Function bodies can contain statements now
This commit is contained in:
parent
f158b6c712
commit
06771979df
11
closure.schala
Normal file
11
closure.schala
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
|
||||
fn outer()
|
||||
fn inner(a)
|
||||
a + 10
|
||||
end
|
||||
|
||||
inner(20) + 8.3
|
||||
end
|
||||
|
||||
outer()
|
20
src/eval.rs
20
src/eval.rs
@ -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!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 ¶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"]
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user