Implement lambda application
This commit is contained in:
parent
339e3464e3
commit
0d2a0e3536
@ -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)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user