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; pub fn eval(expr: &SEXP, env: &mut Env) -> Result { match expr { Atom(ref x) => Ok(Atom((*x).clone())), Sexpr(ref s) => seval(s, env) } } fn seval(sexpr: &[SEXP], env: &mut Env) -> Result { 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 { 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 { 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)) }