<commit_before>use datum::*;
use primitive::*;
use numeric::LNumeric;
use core::hashmap::linear::LinearMap;

struct Runtime {
    stdin: @io::Reader,
    stdout: @io::Writer,
    stderr: @io::Writer,
    global: LinearMap<~str, @LDatum>
}

#[deriving(Eq)]
enum RuntimeError {
    UnknownLocalVariable(~str),
    NotImplemented,
    NotCallable,
    NotList,
    ArgNumError,
    TypeError,
    DivideByZeroError,
}

impl ToStr for RuntimeError {
    fn to_str(&self) -> ~str {
        err_to_str(self)
    }
}

priv fn err_to_str(&err: &RuntimeError) -> ~str {
    match err {
        UnknownLocalVariable(name) => ~"unknown local variable: " + copy name,
        NotImplemented => ~"not implemented",
        NotCallable => ~"not callable",
        NotList => ~"not list",
        ArgNumError => ~"bad number of arguments",
        TypeError => ~"type error",
        DivideByZeroError => ~"divide by zero",
    }
}

fn load_prelude() -> LinearMap<~str, @LDatum> {
    let mut map = LinearMap::new();
    for vec::each(prelude()) |&pair| {
        let (key, func) = pair;
        map.insert(key, @LPrim(func));
    }
    map
}

priv fn call_prim1(args: &[@LDatum],
                op: &fn(@LDatum) -> Result<@LDatum, RuntimeError>)
    -> Result<@LDatum, RuntimeError>
{
    if args.len() == 1 {
        op(args[0])
    } else {
        Err(ArgNumError)
    }
}

priv fn call_num_prim2(args: &[@LDatum],
                    op: &fn(&LNumeric, &LNumeric) -> Result<@LDatum, RuntimeError>)
    -> Result<@LDatum, RuntimeError>
{
    if args.len() == 2 {
        match *args[0] {
            LNum(lhs) => match *args[1] {
                LNum(rhs) => op(&lhs, &rhs),
                _ => Err(TypeError),
            },
            _ => Err(TypeError),
        }
    } else {
        Err(ArgNumError)
    }
}

pub impl Runtime {
    fn new_std() -> Runtime {
        Runtime {
            stdin: io::stdin(),
            stdout: io::stdout(),
            stderr: io::stderr(),
            global: load_prelude(),
        }
    }

    fn eval(&mut self, val: @LDatum) -> Result<@LDatum, RuntimeError> {
        match copy *val {
            LIdent(name) => 
                match self.global.find(&name) {
                    Some(&datum) => Ok(datum),
                    None => Err(UnknownLocalVariable(name)),
                },
            LCons(fexpr, aexpr) =>
                match aexpr.to_list() {
                    None => Err(NotList),
                    Some(aexprs) => {
                        match self.eval(fexpr) {
                            Ok(@LPrim(f)) => {
                                match result::map_vec(aexprs, |&expr| self.eval(expr)) {
                                    Ok(args) => self.call_prim(f, args),
                                    Err(e) => Err(e),<commit_msg>rename UnknownLocalVariable to UnboundVariable<commit_after>use datum::*;
use primitive::*;
use numeric::LNumeric;
use core::hashmap::linear::LinearMap;

struct Runtime {
    stdin: @io::Reader,
    stdout: @io::Writer,
    stderr: @io::Writer,
    global: LinearMap<~str, @LDatum>
}

#[deriving(Eq)]
enum RuntimeError {
    UnboundVariable(~str),
    NotImplemented,
    NotCallable,
    NotList,
    ArgNumError,
    TypeError,
    DivideByZeroError,
}

impl ToStr for RuntimeError {
    fn to_str(&self) -> ~str {
        err_to_str(self)
    }
}

priv fn err_to_str(&err: &RuntimeError) -> ~str {
    match err {
        UnboundVariable(name) => ~"unbound variable: " + copy name,
        NotImplemented => ~"not implemented",
        NotCallable => ~"not callable",
        NotList => ~"not list",
        ArgNumError => ~"bad number of arguments",
        TypeError => ~"type error",
        DivideByZeroError => ~"divide by zero",
    }
}

fn load_prelude() -> LinearMap<~str, @LDatum> {
    let mut map = LinearMap::new();
    for vec::each(prelude()) |&pair| {
        let (key, func) = pair;
        map.insert(key, @LPrim(func));
    }
    map
}

priv fn call_prim1(args: &[@LDatum],
                op: &fn(@LDatum) -> Result<@LDatum, RuntimeError>)
    -> Result<@LDatum, RuntimeError>
{
    if args.len() == 1 {
        op(args[0])
    } else {
        Err(ArgNumError)
    }
}

priv fn call_num_prim2(args: &[@LDatum],
                    op: &fn(&LNumeric, &LNumeric) -> Result<@LDatum, RuntimeError>)
    -> Result<@LDatum, RuntimeError>
{
    if args.len() == 2 {
        match *args[0] {
            LNum(lhs) => match *args[1] {
                LNum(rhs) => op(&lhs, &rhs),
                _ => Err(TypeError),
            },
            _ => Err(TypeError),
        }
    } else {
        Err(ArgNumError)
    }
}

pub impl Runtime {
    fn new_std() -> Runtime {
        Runtime {
            stdin: io::stdin(),
            stdout: io::stdout(),
            stderr: io::stderr(),
            global: load_prelude(),
        }
    }

    fn eval(&mut self, val: @LDatum) -> Result<@LDatum, RuntimeError> {
        match copy *val {
            LIdent(name) => 
                match self.global.find(&name) {
                    Some(&datum) => Ok(datum),
                    None => Err(UnboundVariable(name)),
                },
            LCons(fexpr, aexpr) =>
                match aexpr.to_list() {
                    None => Err(NotList),
                    Some(aexprs) => {
                        match self.eval(fexpr) {
                            Ok(@LPrim(f)) => {
                                match result::map_vec(aexprs, |&expr| self.eval(expr)) {
                                    Ok(args) => self.call_prim(f, args),
                                    Err(e) => Err(e),
{'fraction_non_alphanumeric': 0.1496622822609314, 'fraction_numerical': 0.002488446498400284, 'mean_word_length': 1.7651105651105652, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 75, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3977780', 'n_tokens_mistral': 1857, 'n_tokens_neox': 1784, 'n_words': 365}