summaryrefslogtreecommitdiff
path: root/src/builtins/numbers.rs
blob: 86e159aa7947dc719fabcf7dc1dcc65be760682a (plain)
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))
}