Implement lambda application

This commit is contained in:
greg 2017-12-29 03:57:27 -08:00
parent 339e3464e3
commit 0d2a0e3536

View File

@ -33,6 +33,7 @@ impl EvaluatorState {
binding.insert(var, value); binding.insert(var, value);
} }
fn get_var(&self, var: &str) -> Option<&Sexp> { fn get_var(&self, var: &str) -> Option<&Sexp> {
println!("Var: {}", var);
for bindings in self.binding_stack.iter().rev() { for bindings in self.binding_stack.iter().rev() {
match bindings.get(var) { match bindings.get(var) {
Some(x) => return Some(x), Some(x) => return Some(x),
@ -41,6 +42,13 @@ impl EvaluatorState {
} }
None None
} }
fn push_env(&mut self) {
self.binding_stack.push(HashMap::new());
}
fn pop_env(&mut self) {
self.binding_stack.pop();
}
} }
pub struct Rukka { pub struct Rukka {
@ -206,7 +214,22 @@ impl EvaluatorState {
use self::Sexp::*; use self::Sexp::*;
match function { match function {
FnLiteral { formal_params, body } => { FnLiteral { formal_params, body } => {
Err(format!("unimplementd")) self.push_env();
let mut cur = operands;
for param in formal_params {
match cur {
Cons(box arg, box rest) => {
cur = rest;
self.set_var(param, arg);
},
_ => return Err(format!("Bad argument for function application")),
}
}
println!("Body: {:?}", body);
let result = self.eval(*body);
self.pop_env();
result
}, },
Builtin(builtin) => self.apply_builtin(builtin, operands), Builtin(builtin) => self.apply_builtin(builtin, operands),
_ => return Err(format!("Bad type to apply")), _ => return Err(format!("Bad type to apply")),
@ -216,31 +239,37 @@ impl EvaluatorState {
fn apply_builtin(&mut self, op: BuiltinFn, operands: Sexp) -> Result<Sexp, String> { fn apply_builtin(&mut self, op: BuiltinFn, operands: Sexp) -> Result<Sexp, String> {
use self::Sexp::*; use self::Sexp::*;
use self::BuiltinFn::*; use self::BuiltinFn::*;
let mut evaled_operands = Vec::new();
let mut cur_operand = operands;
loop {
match cur_operand {
Nil => break,
Cons(box l, box rest) => {
evaled_operands.push(self.eval(l)?);
cur_operand = rest;
},
_ => return Err(format!("Bad operands list"))
}
}
Ok(match op { Ok(match op {
Plus | Mult => { Plus | Mult => {
let mut result = match op { Plus => 0, Mult => 1, _ => unreachable!() }; let mut result = match op { Plus => 0, Mult => 1, _ => unreachable!() };
let mut operand = &operands; for arg in evaled_operands {
loop { if let NumberAtom(n) = arg {
match operand { if let Plus = op {
&Nil => break, result += n;
&Cons(ref l, ref r) => { } else if let Mult = op {
if let NumberAtom(ref n) = **l { result *= n;
if let Plus = op { }
result += n; } else {
} else if let Mult = op { return Err(format!("Bad operand: {:?}", arg));
result *= n;
}
operand = r as &Sexp;
} else {
return Err(format!("Bad operand"));
}
},
_ => return Err(format!("Bad operands list"))
} }
} }
NumberAtom(result) NumberAtom(result)
}, },
_ => return Err(format!("Not implemented")), op => return Err(format!("Builtin op {:?} not implemented", op)),
}) })
} }
} }