diff options
Diffstat (limited to 'src/builtins/numbers.rs')
| -rw-r--r-- | src/builtins/numbers.rs | 227 |
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)) +} |
