use crate::eval::{EvalResult, eval};
pub(crate) fn if_(args: Vec<EvalResult>) -> EvalResult {
if let Some(EvalResult::Boolean(condition)) = args.first()
&& let Some(EvalResult::Quoted(then, ctx)) = args.get(1)
{
if *condition {
eval(then.as_ref().clone(), ctx.clone()).unwrap_or(EvalResult::None)
} else if let Some(EvalResult::Quoted(else_, ctx)) = args.get(2) {
eval(else_.as_ref().clone(), ctx.clone()).unwrap_or(EvalResult::None)
} else {
EvalResult::None
}
} else {
EvalResult::None
}
}
pub(crate) fn not(args: Vec<EvalResult>) -> EvalResult {
if let Some(EvalResult::Boolean(b)) = args.first() {
EvalResult::Boolean(!b)
} else {
EvalResult::None
}
}
pub(crate) fn eq(args: Vec<EvalResult>) -> EvalResult {
EvalResult::Boolean(
args.iter()
.all(|x| args.first().map(|f| x == f).unwrap_or(false)),
)
}
pub(crate) fn gt(args: Vec<EvalResult>) -> EvalResult {
if let Some(EvalResult::Number(n1)) = args.first()
&& let Some(EvalResult::Number(n2)) = args.get(1)
{
EvalResult::Boolean(n1 > n2)
} else {
EvalResult::None
}
}
pub(crate) fn lt(args: Vec<EvalResult>) -> EvalResult {
if let Some(EvalResult::Number(n1)) = args.first()
&& let Some(EvalResult::Number(n2)) = args.get(1)
{
EvalResult::Boolean(n1 < n2)
} else {
EvalResult::None
}
}
#[cfg(test)]
mod tests {
use crate::{eval::EvalResult, eval_str, stdlib::STDLIB};
#[test]
fn test_if() {
assert_eq!(
eval_str(
r#"use(["bool", "num"], 'if(true, 'add(2, 2), 'add(4, 4)))"#,
STDLIB.clone()
)
.unwrap(),
EvalResult::Number(4_f64)
);
assert_eq!(
eval_str(
r#"use(["bool", "num"], 'if(false, 'add(2, 2), 'add(4, 4)))"#,
STDLIB.clone()
)
.unwrap(),
EvalResult::Number(8_f64)
);
assert_eq!(
eval_str(
r#"use(["bool", "num"], 'if(eq(2, 3), 'add(2, 2), 'add(4, 4)))"#,
STDLIB.clone()
)
.unwrap(),
EvalResult::Number(8_f64)
);
assert_eq!(
eval_str(
r#"use(["bool", "num"], 'if(not(lt(2, 3)), 'add(2, 2), 'add(4, 4)))"#,
STDLIB.clone()
)
.unwrap(),
EvalResult::Number(8_f64)
);
assert_eq!(
eval_str(
r#"use(["bool", "num"], 'if(gt(2, 3), 'add(2, 2), 'add(4, 4)))"#,
STDLIB.clone()
)
.unwrap(),
EvalResult::Number(8_f64)
);
}
}