Variable lookup works
Note this introduces a panic - if the AST node inserted into the environment is not reduced, it throws an error when trying to look it up
This commit is contained in:
parent
6ddea790c0
commit
08f1092b69
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
|||||||
use parser::AST;
|
use parser::AST;
|
||||||
use parser::AST::*;
|
use parser::AST::*;
|
||||||
|
|
||||||
pub struct Environment(pub HashMap<String, Box<AST>>);
|
pub struct Environment(pub HashMap<String, AST>);
|
||||||
type EvalResult = (AST, Environment);
|
type EvalResult = (AST, Environment);
|
||||||
|
|
||||||
impl Environment {
|
impl Environment {
|
||||||
@ -11,17 +11,28 @@ impl Environment {
|
|||||||
Environment(HashMap::new())
|
Environment(HashMap::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_binding(&mut self, name: String, binding: Box<AST>) {
|
fn add_binding(&mut self, name: String, binding: AST) {
|
||||||
match *self {
|
match *self {
|
||||||
Environment(ref mut hash_map) => hash_map.insert(name, binding)
|
Environment(ref mut hash_map) => hash_map.insert(name, binding)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_binding(&mut self, name: &String) -> Option<&Box<AST>> {
|
fn lookup_binding(&mut self, name: &String) -> Option<&AST> {
|
||||||
match *self {
|
match *self {
|
||||||
Environment(ref mut hash_map) => hash_map.get(name)
|
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 {
|
pub fn evaluate(ast: AST, env: Environment) -> String {
|
||||||
@ -42,28 +53,38 @@ fn reduce(evr: EvalResult) -> EvalResult {
|
|||||||
|
|
||||||
match ast {
|
match ast {
|
||||||
Name(name) => {
|
Name(name) => {
|
||||||
match env.lookup_binding(&name) {
|
let result = match env.lookup_binding(&name) {
|
||||||
Some(_) => {
|
Some(binding) => match binding {
|
||||||
(Null, env)
|
&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) => {
|
Statements(stmts) => {
|
||||||
let mut reduced_ast = DoNothing;
|
let mut reduced_ast = DoNothing;
|
||||||
let mut reduced_env = env;
|
let mut reduced_env = env;
|
||||||
for stmt in stmts.into_iter() {
|
for stmt in stmts.into_iter() {
|
||||||
let (a, b) = reduce((stmt, reduced_env));
|
let (new_ast, new_env) = reduce((stmt, reduced_env));
|
||||||
reduced_ast = a;
|
reduced_env = new_env;
|
||||||
reduced_env = b;
|
reduced_ast = new_ast;
|
||||||
|
|
||||||
}
|
}
|
||||||
(reduced_ast, reduced_env)
|
(reduced_ast, reduced_env)
|
||||||
},
|
},
|
||||||
|
|
||||||
Binding(name, binding) => {
|
Binding(name, binding) => {
|
||||||
env.add_binding(name, binding);
|
let unboxed_binding = *binding;
|
||||||
(DoNothing, env)
|
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)
|
other_ast => (other_ast, env)
|
||||||
|
Loading…
Reference in New Issue
Block a user