diff --git a/lambda.schala b/lambda.schala index c17e442..85f5d6d 100644 --- a/lambda.schala +++ b/lambda.schala @@ -1,5 +1,5 @@ -(fn(q) { q * 2 })(25) +(fn(q) { q * 2 }(25)) a = fn(x) { x + 5 } a(2) diff --git a/src/eval.rs b/src/eval.rs index b2185dd..5f99faa 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -2,7 +2,7 @@ extern crate take_mut; use std::collections::HashMap; use std::collections::VecDeque; -use parser::{AST, Statement, Expression, Function}; +use parser::{AST, Statement, Expression, Function, Callable}; use std::rc::Rc; use std::io::{Write, Stdout, BufWriter}; use std::convert::From; @@ -12,7 +12,6 @@ use parser::Statement::*; type Reduction = (T, Option); - #[derive(Debug, Clone)] enum ReducedValue { StringLiteral(Rc), @@ -259,7 +258,7 @@ impl<'a> Evaluator<'a> { (self.reduce_binop(op, *left, *right), None) //can assume both arguments are maximally reduced } } - Call(name, mut args) => { + Call(callable, mut args) => { let mut f = true; for arg in args.iter_mut() { if arg.is_reducible() { @@ -269,9 +268,9 @@ impl<'a> Evaluator<'a> { } } if f { - self.reduce_call(name, args) + self.reduce_call(callable, args) } else { - (Call(name, args), None) + (Call(callable, args), None) } } While(test, body) => { @@ -327,7 +326,7 @@ impl<'a> Evaluator<'a> { ("+", Number(l), StringLiteral(s1)) => StringLiteral(Rc::new(format!("{}{}", l, *s1))), ("-", Number(l), Number(r)) => Number(l - r), ("*", Number(l), Number(r)) => Number(l * r), - ("/", Number(l), Number(r)) if r != 0.0 => Number(l / r), + ("/", Number(l), Number(r)) if r != 0.0 => Number(l / r), ("%", Number(l), Number(r)) => Number(l % r), ("<", Number(l), Number(r)) => if l < r { truthy } else { falsy }, ("<=", Number(l), Number(r)) => if l <= r { truthy } else { falsy }, @@ -341,18 +340,22 @@ impl<'a> Evaluator<'a> { } } - fn reduce_call(&mut self, name: Rc, arguments: Vec) -> Reduction { - if let Some(res) = handle_builtin(&*name, &arguments) { + fn reduce_call(&mut self, callable: Callable, arguments: Vec) -> Reduction { + if let Some(res) = handle_builtin(&callable, &arguments) { return res; } - println!("Reduce call, name {} args: {:?}", name, arguments); + println!("Reduce call, callable {:?} args: {:?}", callable, arguments); - let function = match self.lookup_binding(&*name) { - Some(ReducedValue::Lambda(func)) => func, - _ => return (Null, None), + let function = match callable { + Callable::Lambda(func) => func.clone(), + Callable::NamedFunction(name) => { + match self.lookup_binding(&*name) { + Some(ReducedValue::Lambda(func)) => func, + _ => return (Null, None), + } + } }; - if function.prototype.parameters.len() != arguments.len() { return (Null, None); } @@ -376,7 +379,12 @@ impl<'a> Evaluator<'a> { } } -fn handle_builtin(name: &str, arguments: &Vec) -> Option> { +fn handle_builtin(callable: &Callable, arguments: &Vec) -> Option> { + let name: &str = match *callable { + Callable::NamedFunction(ref name) => *&name, + _ => return None, + }; + match name { "print" => { let mut s = String::new(); diff --git a/src/parser.rs b/src/parser.rs index 9ebaa49..5a8e041 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -18,11 +18,13 @@ use std::convert::From; // primary_expression := Number | String | identifier_expr | paren_expr | conditional_expr | // while_expr | lambda_expr // identifier_expr := call_expression | Variable +// call_expr := Identifier LParen exprlist RParen // while_expr := WHILE primary_expression LCurlyBrace (expression delimiter)* RCurlyBrace // paren_expr := LParen expression RParen -// call_expr := Identifier LParen exprlist RParen // conditional_expr := IF expression LCurlyBrace (expression delimiter)* RCurlyBrace (LCurlyBrace (expresion delimiter)* RCurlyBrace)? // lambda_expr := FN LParen identlist RParen LCurlyBrace (expression delimiter)* RCurlyBrace +// lambda_call +// lambda_call := ε | LParen exprlist RParen // op := '+', '-', etc. // @@ -63,13 +65,19 @@ pub enum Expression { Number(f64), Variable(Rc), BinExp(Rc, Box, Box), - Call(Rc, Vec), + Call(Callable, Vec), Conditional(Box, Box, Option>), Lambda(Function), Block(VecDeque), While(Box, Vec), } +#[derive(Clone, Debug)] +pub enum Callable { + NamedFunction(Rc), + Lambda(Function), +} + impl fmt::Display for Expression { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use self::Expression::*; @@ -426,7 +434,14 @@ impl Parser { prototype: prototype, body: body, }; - Ok(Lambda(function)) + + match self.peek() { + Some(LParen) => { + let args = try!(self.call_expr()); + Ok(Call(Callable::Lambda(function), args)) + }, + _ => Ok(Lambda(function)) + } } fn while_expr(&mut self) -> ParseResult { @@ -481,7 +496,7 @@ impl Parser { let expr = match self.peek() { Some(LParen) => { let args = try!(self.call_expr()); - Expression::Call(name, args) + Expression::Call(Callable::NamedFunction(name), args) } __ => Expression::Variable(name), };