use crate::{
Environment,
FALSE_SYMBOL,
TRUE_SYMBOL,
builtin::ValueType,
eval::apply::eval_apply,
is_number_eq,
value::Value,
};
pub(crate) fn builtin(
args: &[Value],
value_type: ValueType,
env: &Environment,
) -> Option<(Value, Environment)> {
if let [v] = &args[..] {
match eval_apply(v, env) {
Some((e, new_env)) => Some((
Value::Atom(String::from(match (e, value_type) {
(Value::Atom(_), ValueType::Atom)
| (Value::Builtin(_), ValueType::Builtin)
| (Value::Lambda(_, _, _), ValueType::Lambda)
| (Value::Number(_), ValueType::Number)
| (Value::Object(_, _), ValueType::Object)
| (Value::Plugin(_, _), ValueType::Plugin)
| (Value::String(_), ValueType::String) => TRUE_SYMBOL,
(Value::Number(n), ValueType::Integer) if is_number_eq(n.round(), n) => {
TRUE_SYMBOL
}
(Value::List(_), ValueType::List) | (Value::Unit, ValueType::Unit) => {
TRUE_SYMBOL
}
_ => FALSE_SYMBOL,
})),
new_env,
)),
None => {
eprintln!(
concat!(
"Error[ksl::builtin::is<{:?}>]: ",
"Cannot evaluate expression {:?}."
),
value_type, v
);
None
}
}
} else {
eprintln!(
concat!(
"Error[ksl::builtin::is<{:?}>]: ",
"Only accepts 1 argument, but {} were passed."
),
value_type,
args.len()
);
None
}
}