ksl 0.1.7

KSL core library and interpreter
Documentation
//! # ksl::builtin::apply
//!
//! Built-in functions which accept multiple arguments.
//!
//! - Add
//! - Concat
//! - Mul

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(),
    ))
}