Lamba calls partially work

This commit is contained in:
greg 2017-01-12 01:33:34 -08:00
parent b0655d7cab
commit 26bc6e90f3
2 changed files with 51 additions and 31 deletions

5
lambda.schala Normal file
View File

@ -0,0 +1,5 @@
(fn(q) { q * 2 })(25)
a = fn(x) { x + 5 }
a(2)

View File

@ -5,23 +5,51 @@ use std::collections::VecDeque;
use parser::{AST, Statement, Expression, Function}; use parser::{AST, Statement, Expression, Function};
use std::rc::Rc; use std::rc::Rc;
use std::io::{Write, Stdout, BufWriter}; use std::io::{Write, Stdout, BufWriter};
use std::convert::From;
use parser::Expression::*; use parser::Expression::*;
use parser::Statement::*; use parser::Statement::*;
type Reduction<T> = (T, Option<SideEffect>); type Reduction<T> = (T, Option<SideEffect>);
#[derive(Debug, Clone)]
enum ReducedValue {
StringLiteral(Rc<String>),
Number(f64),
Lambda(Function),
}
impl From<ReducedValue> 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<Expression> 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)] #[derive(Debug)]
enum SideEffect { enum SideEffect {
Print(String), Print(String),
AddBinding(Rc<String>, Expression), AddBinding(Rc<String>, ReducedValue),
AddFunctionBinding(Function),
} }
pub struct Evaluator<'a> { pub struct Evaluator<'a> {
parent: Option<&'a Evaluator<'a>>, parent: Option<&'a Evaluator<'a>>,
functions: HashMap<String, Function>, variables: HashMap<String, ReducedValue>,
variables: HashMap<String, Expression>,
stdout: BufWriter<Stdout>, stdout: BufWriter<Stdout>,
pub trace_evaluation: bool, pub trace_evaluation: bool,
} }
@ -34,7 +62,6 @@ impl<'a> Evaluator<'a> {
} }
pub fn new(parent: Option<&'a Evaluator>) -> Evaluator<'a> { pub fn new(parent: Option<&'a Evaluator>) -> Evaluator<'a> {
Evaluator { Evaluator {
functions: HashMap::new(),
variables: HashMap::new(), variables: HashMap::new(),
parent: parent, parent: parent,
stdout: BufWriter::new(::std::io::stdout()), stdout: BufWriter::new(::std::io::stdout()),
@ -48,11 +75,11 @@ impl<'a> Evaluator<'a> {
.collect() .collect()
} }
fn add_binding(&mut self, var: String, value: Expression) { fn add_binding(&mut self, var: String, value: ReducedValue) {
self.variables.insert(var, value); self.variables.insert(var, value);
} }
fn lookup_binding(&self, var: &str) -> Option<Expression> { fn lookup_binding(&self, var: &str) -> Option<ReducedValue> {
match self.variables.get(var) { match self.variables.get(var) {
Some(expr) => Some(expr.clone()), Some(expr) => Some(expr.clone()),
None => match self.parent { 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<Function> {
match self.functions.get(name) {
Some(func) => Some(func.clone()),
None => match self.parent {
Some(env) => env.lookup_function(name),
None => None
}
}
}
} }
trait Evaluable { trait Evaluable {
@ -168,9 +181,6 @@ impl<'a> Evaluator<'a> {
AddBinding(var, value) => { AddBinding(var, value) => {
self.add_binding((*var).clone(), 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) => { 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) (ExprNode(Expression::Lambda(func)), binding)
} }
} }
@ -198,7 +210,7 @@ impl<'a> Evaluator<'a> {
e @ Number(_) => (e, None), e @ Number(_) => (e, None),
e @ Lambda(_) => (e, None), e @ Lambda(_) => (e, None),
Variable(ref var) => { Variable(ref var) => {
match self.lookup_binding(var) { match self.lookup_binding(var).map(|x| x.into()) {
None => (Null, None), None => (Null, None),
Some(expr) => (expr, None), Some(expr) => (expr, None),
} }
@ -213,7 +225,8 @@ impl<'a> Evaluator<'a> {
if *op == "=" { if *op == "=" {
return match *left { return match *left {
Variable(var) => { 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, Some(binding))
}, },
_ => (Null, None) _ => (Null, None)
@ -333,9 +346,11 @@ impl<'a> Evaluator<'a> {
return res; return res;
} }
let function = match self.lookup_function(&*name) { println!("Reduce call, name {} args: {:?}", name, arguments);
Some(func) => func,
None => return (Null, None), let function = match self.lookup_binding(&*name) {
Some(ReducedValue::Lambda(func)) => func,
_ => return (Null, None),
}; };
if function.prototype.parameters.len() != arguments.len() { if function.prototype.parameters.len() != arguments.len() {
@ -344,7 +359,7 @@ impl<'a> Evaluator<'a> {
let mut evaluator = Evaluator::new(Some(self)); let mut evaluator = Evaluator::new(Some(self));
for (binding, expr) in function.prototype.parameters.iter().zip(arguments.iter()) { 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()); let nodes = function.body.iter().map(|node| node.clone());