ksl 0.1.7

KSL core library and interpreter
Documentation
//! # ksl::builtin::do_
//!
//! Built-in function `Do`.

use crate::{Environment, eval::apply::eval_apply, value::Value};

pub(crate) fn builtin(args: &[Value], env: &Environment) -> Option<(Value, Environment)> {
    let mut local_environment = Environment::new();

    if let [func, Value::Identity(id), lst] = &args[..] {
        let mut final_result = Value::Unit;
        match eval_apply(lst, env) {
            Some((Value::List(vals), new_env)) => {
                let mut local_env = env.clone();
                local_env.extend(new_env);
                for val in vals.iter() {
                    match eval_apply(val, &local_env) {
                        Some((element, new_env1)) => {
                            local_env.extend(new_env1);
                            let _ = local_env.insert(id.clone(), element);
                            match eval_apply(func, &local_env) {
                                Some((result, new_env2)) => {
                                    local_env.extend(new_env2.clone());
                                    local_environment.extend(new_env2);
                                    final_result = result;
                                }
                                None => {
                                    eprintln!(
                                        concat!(
                                            "Error[ksl::builtin::do]: ",
                                            "Cannot evaluate expression {:?}."
                                        ),
                                        func
                                    );
                                    return None;
                                }
                            }
                        }
                        None => {
                            eprintln!(
                                concat!(
                                    "Error[ksl::builtin::do]: ",
                                    "Cannot evaluate expression {:?}."
                                ),
                                val
                            );
                            return None;
                        }
                    }
                }
                // clear leak entry
                let _ = local_environment.remove(id);
                Some((final_result, local_environment))
            }
            Some((e, _)) => {
                eprintln!(
                    concat!(
                        "Error[ksl::builtin::do]: ",
                        "Expected a list, but got `{:?}`."
                    ),
                    e
                );
                None
            }
            None => {
                eprintln!(
                    concat!(
                        "Error[ksl::builtin::do]: ",
                        "Cannot evaluate expression {:?}."
                    ),
                    lst
                );
                None
            }
        }
    } else {
        eprintln!(
            concat!(
                "Error[ksl::builtin::do]: ",
                "Only accepts an expression, a symbol, ",
                "and a list as arguments, but got {:?}.",
            ),
            args
        );
        None
    }
}