From 06771979df02e738d227fcc01f7ee8115cda4fe4 Mon Sep 17 00:00:00 2001 From: greg Date: Tue, 3 Jan 2017 02:11:59 -0800 Subject: [PATCH] Function bodies can contain statements now --- closure.schala | 11 +++++++++++ src/eval.rs | 20 ++++++++++---------- src/parser.rs | 20 ++++++++++---------- 3 files changed, 31 insertions(+), 20 deletions(-) create mode 100644 closure.schala diff --git a/closure.schala b/closure.schala new file mode 100644 index 0000000..3efce65 --- /dev/null +++ b/closure.schala @@ -0,0 +1,11 @@ + + +fn outer() + fn inner(a) + a + 10 + end + + inner(20) + 8.3 +end + +outer() diff --git a/src/eval.rs b/src/eval.rs index 226199d..9c9f8a2 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -29,7 +29,7 @@ impl<'a> Evaluator<'a> { pub fn run(&mut self, ast: AST) -> Vec { ast.into_iter() - .map(|astnode| format!("{}", self.reduce(astnode))) + .map(|astnode| format!("{}", self.reduction_loop(astnode))) .collect() } @@ -102,7 +102,7 @@ impl Expression { } impl<'a> Evaluator<'a> { - fn reduce(&mut self, mut node: ASTNode) -> ASTNode { + fn reduction_loop(&mut self, mut node: ASTNode) -> ASTNode { loop { node = self.step(node); if !node.is_reducible() { @@ -290,16 +290,16 @@ impl<'a> Evaluator<'a> { evaluator.add_binding(binding.clone(), expr.clone()); } - let nodes = function.body.iter().map(|expr| ASTNode::ExprNode(expr.clone())); - let mut retval = Null; + let nodes = function.body.iter().map(|node| node.clone()); + let mut retval = ExprNode(Null); for n in nodes { - retval = match evaluator.reduce(n) { - ExprNode(expr) => expr, - FuncDefNode(_) => panic!("This should never happen! A maximally-reduced node\ - should never be a function definition!") - }; + retval = evaluator.reduction_loop(n); } - (retval, None) + match retval { + ExprNode(expr) => (expr, None), + FuncDefNode(_) => panic!("This should never happen! A maximally-reduced node\ + should never be a function definition!") + } } } diff --git a/src/parser.rs b/src/parser.rs index 693faaa..440b6d8 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -6,7 +6,7 @@ use std::collections::VecDeque; // program := (statement delimiter ?)* // delimiter := Newline | Semicolon // statement := declaration | expression -// declaraion := Fn prototype (statement)* End +// declaration := Fn prototype (statement)* End // prototype := identifier LParen identlist RParen // identlist := Ident (Comma Ident)* | e // exprlist := Expression (Comma Expression)* | e @@ -29,7 +29,7 @@ pub enum ASTNode { #[derive(Debug, Clone)] pub struct Function { pub prototype: Prototype, - pub body: Vec, + pub body: Vec, } #[derive(Debug, Clone, PartialEq)] @@ -205,7 +205,7 @@ impl Parser { use tokenizer::Token::*; expect!(self, Keyword(Kw::Fn)); let prototype = try!(self.prototype()); - let body: Vec = try!(self.body()); + let body: Vec = try!(self.body()); expect!(self, Keyword(Kw::End)); Ok(ASTNode::FuncDefNode(Function { prototype: prototype, @@ -258,9 +258,9 @@ impl Parser { Ok(args) } - fn body(&mut self) -> ParseResult> { + fn body(&mut self) -> ParseResult> { use tokenizer::Token::*; - let mut exprs = Vec::new(); + let mut statements = Vec::new(); loop { match self.peek() { Some(ref t) if is_delimiter(t) => { @@ -269,12 +269,12 @@ impl Parser { } Some(Keyword(Kw::End)) => break, _ => { - let expr = try!(self.expression()); - exprs.push(expr); + let ast_node = try!(self.statement()); + statements.push(ast_node); } } } - Ok(exprs) + Ok(statements) } fn expression(&mut self) -> ParseResult { @@ -460,14 +460,14 @@ mod tests { parsetest!( "fn a() 1 + 2 end", &[FuncDefNode(Function {prototype: Prototype { ref name, ref parameters }, ref body})], - match &body[..] { &[BinExp(_, box Number(1.0), box Number(2.0))] => true, _ => false } + match &body[..] { &[ExprNode(BinExp(_, box Number(1.0), box Number(2.0)))] => true, _ => false } && name == "a" && match ¶meters[..] { &[] => true, _ => false } ); parsetest!( "fn a(x,y) 1 + 2 end", &[FuncDefNode(Function {prototype: Prototype { ref name, ref parameters }, ref body})], - match &body[..] { &[BinExp(_, box Number(1.0), box Number(2.0))] => true, _ => false } + match &body[..] { &[ExprNode(BinExp(_, box Number(1.0), box Number(2.0)))] => true, _ => false } && name == "a" && *parameters == ["x","y"] ); }