locrian 0.2.1

A simple embeddable functional programming language.
Documentation
use crate::eval::{EvalContext, EvalFn, EvalResult, eval};

pub(crate) fn call<'a>(args: Vec<EvalResult<'a>>) -> EvalResult<'a> {
    if let Some(EvalResult::Quoted(q, ctx)) = args.first() {
        let args_list = if let Some(EvalResult::Object(args_obj)) = args.get(1) {
            args_obj.clone()
        } else if let Some(EvalResult::Array(args_arr)) = args.get(1) {
            args_arr
                .iter()
                .cloned()
                .enumerate()
                .map(|(k, v)| (format!("${k}"), v))
                .collect::<Vec<_>>()
        } else {
            return EvalResult::None;
        };
        let mut new_ctx: EvalContext<'a> = EvalContext {
            fns: ctx.fns.clone(),
            vars: ctx.vars.clone(),
        };
        for arg in args_list {
            new_ctx.vars.insert(arg.0.clone(), arg.1.clone().into());
        }
        eval(q.as_ref().clone(), new_ctx)
            .unwrap_or(EvalResult::None)
            .to_owned()
    } else {
        EvalResult::None
    }
}

pub(crate) const let_: EvalFn = func!("call($1, $0)");

#[cfg(test)]
mod tests {

    use crate::{eval::EvalResult, eval_str, stdlib::STDLIB};

    #[test]
    fn test_let_call() {
        assert_eq!(
            eval_str(r#"let({"a":2,"b":4}, 'num:add(a, b))"#, STDLIB.clone()).unwrap(),
            EvalResult::Number(6_f64)
        );
        assert_eq!(
            eval_str(r#"call('num:add(a, b), {"a": 2, "b": 4})"#, STDLIB.clone()).unwrap(),
            EvalResult::Number(6_f64)
        );
        assert_eq!(
            eval_str(
                r#"
                let({"fn": 'num:add(a, b)},
                    'call(fn, {"a": 2, "b": 4}))
                    "#,
                STDLIB.clone()
            )
            .unwrap(),
            EvalResult::Number(6_f64)
        );

        assert_eq!(
            eval_str(
                r#"
            call('num:add($0, $1), [2, 2])
            "#,
                STDLIB.clone()
            )
            .unwrap(),
            EvalResult::Number(4_f64)
        )
    }
}