ksl 0.1.5

KSL core library and interpreter
Documentation
pub mod apply;
mod pair;
mod sentence;

use crate::{
    Environment,
    eval::{apply::eval_apply, sentence::eval_sentence},
    token::{TokenType, source_to_token},
    value::Value,
};

pub fn eval(source: &str, env: &Environment) -> Option<(Value, Environment)> {
    let mut current_val = Value::Unit;
    let mut current_environment = env.clone();
    let mut local_environment = Environment::new();
    if let Some(tokens) = source_to_token(source) {
        for sentence in tokens
            .split(|token| match token.value {
                TokenType::SentenceSeperator => true,
                _ => false,
            })
            .filter(|s| !s.is_empty())
        {
            if let Some((val, new_env)) = eval_sentence(sentence, &current_environment)
                .map(|val| eval_apply(&val, &current_environment))
                .flatten()
            {
                local_environment.extend(new_env.clone());
                current_environment.extend(new_env.clone());
                current_val = val;
            } else {
                return None;
            }
        }
    } else {
        return None;
    }
    Some((current_val, local_environment))
}

pub(crate) fn extract_lambda_env(
    params: &[String],
    body: &Value,
    env: &Environment,
) -> Environment {
    let mut local_environment = Environment::new();
    let mut current_environment = env.clone();
    match body {
        Value::Identity(id) => {
            if !(params.contains(id) || local_environment.contains_key(id)) {
                if let Some(val) = current_environment.get(id) {
                    let _ = local_environment.insert(id.clone(), val.clone());
                }
            }
        }
        Value::List(elements) => {
            for element in elements.iter() {
                let new_env = extract_lambda_env(params, element, &current_environment);
                local_environment.extend(new_env.clone());
                current_environment.extend(new_env);
            }
        }
        Value::Lambda(inner_params, sub_func, inner_env) => {
            let mut capture = current_environment.clone();
            capture.extend(inner_env.clone());
            let mut all_params = params.to_vec();
            all_params.extend(inner_params.clone());
            let new_env = extract_lambda_env(&all_params, sub_func, &capture);
            local_environment.extend(new_env);
        }
        Value::Apply(arguments, sub_func) => {
            for argument in arguments.iter() {
                let new_env = extract_lambda_env(params, argument, &current_environment);
                local_environment.extend(new_env.clone());
                current_environment.extend(new_env);
            }
            let new_env = extract_lambda_env(params, sub_func, &current_environment);
            local_environment.extend(new_env);
        }
        _ => (),
    }
    local_environment
}