summaryrefslogtreecommitdiff
path: root/src/builtins/numbers.rs
diff options
context:
space:
mode:
authorMica White <botahamec@outlook.com>2025-12-07 14:25:35 -0500
committerMica White <botahamec@outlook.com>2025-12-07 14:25:35 -0500
commitcfa44907065eb10e3b990506881b30c5891f0af2 (patch)
tree90e2b818376a01294c8cc96184171861035c7319 /src/builtins/numbers.rs
First commitHEADmain
Diffstat (limited to 'src/builtins/numbers.rs')
-rw-r--r--src/builtins/numbers.rs227
1 files changed, 227 insertions, 0 deletions
diff --git a/src/builtins/numbers.rs b/src/builtins/numbers.rs
new file mode 100644
index 0000000..86e159a
--- /dev/null
+++ b/src/builtins/numbers.rs
@@ -0,0 +1,227 @@
+use std::sync::Arc;
+
+use rust_decimal::{Decimal, MathematicalOps};
+
+use crate::interpreter::{Interpreter, Value};
+
+use super::{NIL, delsh_bool};
+
+pub fn is_number(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
+ let arg = interpreter.eval(args[0].clone());
+ delsh_bool(arg.number().is_some())
+}
+
+pub fn is_int(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
+ let arg = interpreter.eval(args[0].clone());
+ delsh_bool(arg.number().is_some_and(|num| num.is_integer()))
+}
+
+pub fn is_equal(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
+ let a = interpreter.eval(args[0].clone());
+ let b = interpreter.eval(args[1].clone());
+
+ delsh_bool(a == b)
+}
+
+pub fn is_less(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
+ let a = *interpreter
+ .eval(args[0].clone())
+ .number()
+ .expect("two numbers");
+ let b = *interpreter
+ .eval(args[1].clone())
+ .number()
+ .expect("two numbers");
+
+ delsh_bool(a < b)
+}
+
+pub fn is_greater(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
+ let a = *interpreter
+ .eval(args[0].clone())
+ .number()
+ .expect("two numbers");
+ let b = *interpreter
+ .eval(args[1].clone())
+ .number()
+ .expect("two numbers");
+
+ delsh_bool(a > b)
+}
+
+pub fn is_zero(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
+ let arg = interpreter.eval(args[0].clone());
+ delsh_bool(arg.number().is_some_and(|num| *num == Decimal::ZERO))
+}
+
+pub fn is_one(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
+ let arg = interpreter.eval(args[0].clone());
+ delsh_bool(arg.number().is_some_and(|num| *num == Decimal::ONE))
+}
+
+pub fn is_negative(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
+ let arg = interpreter.eval(args[0].clone());
+ delsh_bool(arg.number().is_some_and(|num| num.is_sign_negative()))
+}
+
+pub fn plus(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
+ let mut total = Decimal::ZERO;
+ for arg in args {
+ let arg = interpreter.eval(arg.clone());
+ match &*arg {
+ Value::Number(num) => total += num,
+ _ => panic!("Expected a number"),
+ }
+ }
+
+ Arc::new(Value::Number(total))
+}
+
+pub fn minus(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
+ if args.len() == 1 {
+ let Value::Number(arg) = &*interpreter.eval(args[0].clone()) else {
+ panic!("expected a number")
+ };
+ Arc::new(Value::Number(-arg))
+ } else if args.len() == 2 {
+ let Value::Number(a) = &*interpreter.eval(args[0].clone()) else {
+ panic!("expected a number")
+ };
+ let Value::Number(b) = &*interpreter.eval(args[1].clone()) else {
+ panic!("expected a number")
+ };
+ return Arc::new(Value::Number(a - b));
+ } else {
+ panic!("expected one or two arguments")
+ }
+}
+
+pub fn negate(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
+ let Value::Number(arg) = &*interpreter.eval(args[0].clone()) else {
+ panic!("expected a number")
+ };
+
+ Arc::new(Value::Number(-arg))
+}
+
+pub fn times(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
+ let mut total = Decimal::ONE;
+
+ for arg in args {
+ let Value::Number(arg) = &*interpreter.eval(arg.clone()) else {
+ panic!("expected a number")
+ };
+
+ total *= arg;
+ }
+
+ Arc::new(Value::Number(total))
+}
+
+pub fn divide(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
+ let Value::Number(arg1) = &*interpreter.eval(args[0].clone()) else {
+ panic!("expected a number")
+ };
+ let Value::Number(arg2) = &*interpreter.eval(args[1].clone()) else {
+ panic!("expected a number")
+ };
+
+ Arc::new(Value::Number(arg1 / arg2))
+}
+
+pub fn quotient(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
+ let numerator = interpreter.eval(args[0].clone());
+ let numerator = numerator.number().expect("two numbers");
+ let denominator = interpreter.eval(args[1].clone());
+ let denominator = denominator.number().expect("two numbers");
+
+ Arc::new(Value::Number((numerator / denominator).floor()))
+}
+
+pub fn remainder(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
+ let Value::Number(arg1) = &*interpreter.eval(args[0].clone()) else {
+ panic!("expected a number")
+ };
+ let Value::Number(arg2) = &*interpreter.eval(args[1].clone()) else {
+ panic!("expected a number")
+ };
+
+ Arc::new(Value::Number(arg1 % arg2))
+}
+
+pub fn add1(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
+ Arc::new(Value::Number(
+ interpreter
+ .eval(args[0].clone())
+ .number()
+ .expect("a number")
+ + Decimal::ONE,
+ ))
+}
+
+pub fn sub1(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
+ Arc::new(Value::Number(
+ interpreter
+ .eval(args[0].clone())
+ .number()
+ .expect("a number")
+ - Decimal::ONE,
+ ))
+}
+
+pub fn max(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
+ let max = interpreter.eval(args[0].clone());
+ let mut max = *max.number().expect("all args to be numbers");
+
+ for arg in &args[1..] {
+ let arg = interpreter.eval(arg.clone());
+ let arg = arg.number().expect("all args to be numbers");
+ max = max.max(*arg);
+ }
+
+ Arc::new(Value::Number(max))
+}
+
+pub fn min(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
+ let min = interpreter.eval(args[0].clone());
+ let mut min = *min.number().expect("all args to be numbers");
+
+ for arg in &args[1..] {
+ let arg = interpreter.eval(arg.clone());
+ let arg = arg.number().expect("all args to be numbers");
+ min = min.min(*arg);
+ }
+
+ Arc::new(Value::Number(min))
+}
+
+pub fn recip(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
+ let number = interpreter.eval(args[0].clone());
+ let number = number.number().expect("a number");
+ Arc::new(Value::Number(Decimal::ONE / number))
+}
+
+pub fn expt(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
+ let x = *interpreter
+ .eval(args[0].clone())
+ .number()
+ .expect("two numbers");
+ let y = *interpreter
+ .eval(args[0].clone())
+ .number()
+ .expect("two numbers");
+
+ Arc::new(Value::Number(x.powd(y)))
+}
+
+pub fn sqrt(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
+ let Value::Number(arg) = &*interpreter.eval(args[0].clone()) else {
+ panic!("expected a number")
+ };
+
+ let Some(sqrt) = arg.sqrt() else {
+ return NIL.clone();
+ };
+
+ Arc::new(Value::Number(sqrt))
+}