diff --git a/src/evaluate.rs b/src/evaluate.rs index b61b4bb..2924930 100644 --- a/src/evaluate.rs +++ b/src/evaluate.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use parser::AST; use parser::AST::*; -pub struct Environment(pub HashMap>); +pub struct Environment(pub HashMap); type EvalResult = (AST, Environment); impl Environment { @@ -11,17 +11,28 @@ impl Environment { Environment(HashMap::new()) } - fn add_binding(&mut self, name: String, binding: Box) { + fn add_binding(&mut self, name: String, binding: AST) { match *self { Environment(ref mut hash_map) => hash_map.insert(name, binding) }; } - fn lookup_binding(&mut self, name: &String) -> Option<&Box> { + fn lookup_binding(&mut self, name: &String) -> Option<&AST> { match *self { Environment(ref mut hash_map) => hash_map.get(name) } } + + fn display(&self) { + match *self { + Environment(ref hash_map) => + for (var, binding) in hash_map { + println!("{} : {:?}", var, binding); + } + } + + println!("----"); + } } pub fn evaluate(ast: AST, env: Environment) -> String { @@ -42,28 +53,38 @@ fn reduce(evr: EvalResult) -> EvalResult { match ast { Name(name) => { - match env.lookup_binding(&name) { - Some(_) => { - (Null, env) + let result = match env.lookup_binding(&name) { + Some(binding) => match binding { + &DoNothing => DoNothing, + &Number(n) => Number(n), + &LangString(ref s) => LangString(s.clone()), + &Null => Null, + _ => panic!("Unreduced ast node for name: {:?}", name) }, - None => (Null, env) - } + None => Null + }; + + (result, env) }, Statements(stmts) => { let mut reduced_ast = DoNothing; let mut reduced_env = env; for stmt in stmts.into_iter() { - let (a, b) = reduce((stmt, reduced_env)); - reduced_ast = a; - reduced_env = b; + let (new_ast, new_env) = reduce((stmt, reduced_env)); + reduced_env = new_env; + reduced_ast = new_ast; + } (reduced_ast, reduced_env) }, Binding(name, binding) => { - env.add_binding(name, binding); - (DoNothing, env) + let unboxed_binding = *binding; + let (evaluated_binding, mut evaluated_env) = reduce((unboxed_binding, env)); + + evaluated_env.add_binding(name, evaluated_binding); + (DoNothing, evaluated_env) }, other_ast => (other_ast, env)