From 26bc6e90f31f78882bbe110f2a3b1e3bddb40e10 Mon Sep 17 00:00:00 2001 From: greg Date: Thu, 12 Jan 2017 01:33:34 -0800 Subject: [PATCH] Lamba calls partially work --- lambda.schala | 5 ++++ src/eval.rs | 77 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 51 insertions(+), 31 deletions(-) create mode 100644 lambda.schala diff --git a/lambda.schala b/lambda.schala new file mode 100644 index 0000000..c17e442 --- /dev/null +++ b/lambda.schala @@ -0,0 +1,5 @@ + +(fn(q) { q * 2 })(25) + +a = fn(x) { x + 5 } +a(2) diff --git a/src/eval.rs b/src/eval.rs index 24e274c..b2185dd 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -5,23 +5,51 @@ use std::collections::VecDeque; use parser::{AST, Statement, Expression, Function}; use std::rc::Rc; use std::io::{Write, Stdout, BufWriter}; +use std::convert::From; use parser::Expression::*; use parser::Statement::*; type Reduction = (T, Option); + +#[derive(Debug, Clone)] +enum ReducedValue { + StringLiteral(Rc), + Number(f64), + Lambda(Function), +} + +impl From for Expression { + fn from(rv: ReducedValue) -> Expression { + match rv { + ReducedValue::Number(n) => Expression::Number(n), + ReducedValue::StringLiteral(n) => Expression::StringLiteral(n), + ReducedValue::Lambda(f) => Expression::Lambda(f), + } + } +} + +impl From for ReducedValue { + fn from(rv: Expression) -> ReducedValue { + match rv { + Expression::Number(n) => ReducedValue::Number(n), + Expression::StringLiteral(n) => ReducedValue::StringLiteral(n), + Expression::Lambda(f) => ReducedValue::Lambda(f), + _ => panic!("trying to store a non-fully-reduced variable"), + } + } +} + #[derive(Debug)] enum SideEffect { Print(String), - AddBinding(Rc, Expression), - AddFunctionBinding(Function), + AddBinding(Rc, ReducedValue), } pub struct Evaluator<'a> { parent: Option<&'a Evaluator<'a>>, - functions: HashMap, - variables: HashMap, + variables: HashMap, stdout: BufWriter, pub trace_evaluation: bool, } @@ -34,7 +62,6 @@ impl<'a> Evaluator<'a> { } pub fn new(parent: Option<&'a Evaluator>) -> Evaluator<'a> { Evaluator { - functions: HashMap::new(), variables: HashMap::new(), parent: parent, stdout: BufWriter::new(::std::io::stdout()), @@ -48,11 +75,11 @@ impl<'a> Evaluator<'a> { .collect() } - fn add_binding(&mut self, var: String, value: Expression) { + fn add_binding(&mut self, var: String, value: ReducedValue) { self.variables.insert(var, value); } - fn lookup_binding(&self, var: &str) -> Option { + fn lookup_binding(&self, var: &str) -> Option { match self.variables.get(var) { Some(expr) => Some(expr.clone()), None => match self.parent { @@ -61,20 +88,6 @@ impl<'a> Evaluator<'a> { } } } - - fn add_function(&mut self, name: String, function: Function) { - self.functions.insert(name, function); - } - - fn lookup_function(&self, name: &str) -> Option { - match self.functions.get(name) { - Some(func) => Some(func.clone()), - None => match self.parent { - Some(env) => env.lookup_function(name), - None => None - } - } - } } trait Evaluable { @@ -168,9 +181,6 @@ impl<'a> Evaluator<'a> { AddBinding(var, value) => { self.add_binding((*var).clone(), value); }, - AddFunctionBinding(function) => { - self.add_function((*function.prototype.name).clone(), function); - } } } @@ -185,7 +195,9 @@ impl<'a> Evaluator<'a> { } } FuncDefNode(func) => { - let binding = Some(SideEffect::AddFunctionBinding(func.clone())); + let name = func.prototype.name.clone(); + let reduced_value = ReducedValue::Lambda(func.clone()); + let binding = Some(SideEffect::AddBinding(name, reduced_value)); (ExprNode(Expression::Lambda(func)), binding) } } @@ -198,7 +210,7 @@ impl<'a> Evaluator<'a> { e @ Number(_) => (e, None), e @ Lambda(_) => (e, None), Variable(ref var) => { - match self.lookup_binding(var) { + match self.lookup_binding(var).map(|x| x.into()) { None => (Null, None), Some(expr) => (expr, None), } @@ -213,7 +225,8 @@ impl<'a> Evaluator<'a> { if *op == "=" { return match *left { Variable(var) => { - let binding = SideEffect::AddBinding(var, *right); + let reduced_value: ReducedValue = ReducedValue::from(*right); + let binding = SideEffect::AddBinding(var, reduced_value); (Null, Some(binding)) }, _ => (Null, None) @@ -333,9 +346,11 @@ impl<'a> Evaluator<'a> { return res; } - let function = match self.lookup_function(&*name) { - Some(func) => func, - None => return (Null, None), + println!("Reduce call, name {} args: {:?}", name, arguments); + + let function = match self.lookup_binding(&*name) { + Some(ReducedValue::Lambda(func)) => func, + _ => return (Null, None), }; if function.prototype.parameters.len() != arguments.len() { @@ -344,7 +359,7 @@ impl<'a> Evaluator<'a> { let mut evaluator = Evaluator::new(Some(self)); for (binding, expr) in function.prototype.parameters.iter().zip(arguments.iter()) { - evaluator.add_binding((**binding).clone(), expr.clone()); + evaluator.add_binding((**binding).clone(), expr.clone().into()); } let nodes = function.body.iter().map(|node| node.clone());