use crate::{Environment, builtin::MathFunctionType, eval::apply::eval_apply, is_number_eq, value::Value};
pub(crate) fn builtin(args: &[Value], ftype: MathFunctionType, env: Environment) -> Result<Value, std::sync::Arc<str>> {
if let [v] = args {
match eval_apply(v, env)? {
Value::Number(n) => Ok(Value::Number(match ftype {
MathFunctionType::Abs => n.abs(),
MathFunctionType::ArcCos => n.acos(),
MathFunctionType::ArcSin => n.asin(),
MathFunctionType::ArcTan => n.atan(),
MathFunctionType::Ceiling => n.ceil(),
MathFunctionType::Cos => n.cos(),
MathFunctionType::Cosh => n.cosh(),
MathFunctionType::Exp => n.exp(),
MathFunctionType::Floor => n.floor(),
MathFunctionType::Ln => {
if n > 0.0 {
n.ln()
} else {
return Err(std::sync::Arc::from(concat!(
"Error[ksl::builtin::Ln]: ",
"Logarithm of non-positive number.",
)));
}
}
MathFunctionType::Neg => {
if is_number_eq(n, 0.0) {
0.0
} else {
-n
}
}
MathFunctionType::Round => n.round(),
MathFunctionType::Sin => n.sin(),
MathFunctionType::Sinh => n.sinh(),
MathFunctionType::Sqrt => n.sqrt(),
MathFunctionType::Tan => n.tan(),
MathFunctionType::Tanh => n.tanh(),
MathFunctionType::Trunc => n.trunc(),
})),
e => Err(std::sync::Arc::from(format!(
concat!(
"Error[ksl::builtin::{:?}]: ",
"Expected a number, but got: `{}`."
),
ftype, e
))),
}
} else {
Err(std::sync::Arc::from(format!(
concat!(
"Error[ksl::builtin::{:?}]: ",
"Expected 1 parameter, but {} were passed."
),
ftype,
args.len()
)))
}
}