use crate::{Environment, builtin::MultiFunctionType, eval::apply::eval_apply, value::Value};
pub(crate) fn builtin(args: &[Value], func_type: MultiFunctionType, env: &Environment) -> Option<(Value, Environment)> {
let mut init: f64 = match func_type {
MultiFunctionType::Mul => 1.0,
_ => 0.0,
};
let mut cat_string = String::new();
for arg in args.iter() {
match (eval_apply(arg, env), &func_type) {
(Some((Value::Number(n), _)), MultiFunctionType::Add) => {
init += n;
}
(Some((Value::String(s), _)), MultiFunctionType::Concat) => {
cat_string.extend(s.chars());
}
(Some((Value::Number(n), _)), MultiFunctionType::Mul) => {
init *= n;
}
(Some((e, _)), _) => {
eprintln!(
concat!(
"Error[ksl::builtin::<{:?}>]: ",
"Expected a number, but got `{:?}`."
),
func_type, e
);
return None;
}
(None, _) => {
eprintln!(
concat!(
"Error[ksl::builtin::<{:?}>]: ",
"Cannot evaluate expression {:?}."
),
func_type, arg
);
return None;
}
}
}
Some((
match func_type {
MultiFunctionType::Concat => Value::String(cat_string),
_ => Value::Number(init),
},
Environment::new(),
))
}