summaryrefslogtreecommitdiff
path: root/src/lib/eval/mod.rs
blob: b582397222466f66f170ce6894fc03e8b2dcbcab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
use std::collections::HashMap;
use super::types::Op;
use super::types::Op::*;
use super::types::SEXP;
use super::types::SEXP::*;
use super::types::Type::*;
use super::types::Number;

pub mod arith;

pub type Env = HashMap<String, SEXP>;

pub fn eval(expr: &SEXP, env: &mut Env) -> Result<SEXP, String> {
    match expr {
        Atom(ref x) => Ok(Atom((*x).clone())),
        Sexpr(ref s) => seval(s, env)
    }
}

fn seval(sexpr: &[SEXP], env: &mut Env) -> Result<SEXP, String> {
    if sexpr.is_empty() {
        return Err("Empty S Expression".to_string())
    }

    let op = match &sexpr[0] {
        Atom(Operator(x)) => *x,
        Atom(Symbol(_s)) => return Err("Not yet implemented".to_string()),
        x => return Err(format!("{:?} is not a procedure", x))
    };

    op_eval(op, &sexpr[1..], env)
}

fn op_eval(op: Op, expr: &[SEXP], env: &mut Env) -> Result<SEXP, String> {
    match op {
        Add => op_add(expr, env),
        //Define => define(expr, env),
        _ => Err("Not yet implemented".to_string())
    }
}

fn op_add(expr: &[SEXP], env: &mut Env) -> Result<SEXP, String> {
    let mut acc = Number(Number::Int(0));
    let mut i = 0;
    while i < expr.len() {
        let b = match eval(&expr[i], env)? {
            Atom(x) => x,
            Sexpr(_) => panic!("This should have evaluated to an atom")
        };
        acc = (acc + b)?;
        i += 1;
    }
    Ok(SEXP::Atom(acc))
}