Function bodies can contain statements now

This commit is contained in:
greg 2017-01-03 02:11:59 -08:00
parent f158b6c712
commit 06771979df
3 changed files with 31 additions and 20 deletions

11
closure.schala Normal file
View File

@ -0,0 +1,11 @@
fn outer()
fn inner(a)
a + 10
end
inner(20) + 8.3
end
outer()

View File

@ -29,7 +29,7 @@ impl<'a> Evaluator<'a> {
pub fn run(&mut self, ast: AST) -> Vec<String> {
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!")
}
}
}

View File

@ -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<Expression>,
pub body: Vec<ASTNode>,
}
#[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<Expression> = try!(self.body());
let body: Vec<ASTNode> = 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<Vec<Expression>> {
fn body(&mut self) -> ParseResult<Vec<ASTNode>> {
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<Expression> {
@ -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 &parameters[..] { &[] => 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"]
);
}