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> {
|
pub fn run(&mut self, ast: AST) -> Vec<String> {
|
||||||
ast.into_iter()
|
ast.into_iter()
|
||||||
.map(|astnode| format!("{}", self.reduce(astnode)))
|
.map(|astnode| format!("{}", self.reduction_loop(astnode)))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +102,7 @@ impl Expression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Evaluator<'a> {
|
impl<'a> Evaluator<'a> {
|
||||||
fn reduce(&mut self, mut node: ASTNode) -> ASTNode {
|
fn reduction_loop(&mut self, mut node: ASTNode) -> ASTNode {
|
||||||
loop {
|
loop {
|
||||||
node = self.step(node);
|
node = self.step(node);
|
||||||
if !node.is_reducible() {
|
if !node.is_reducible() {
|
||||||
@ -290,16 +290,16 @@ impl<'a> Evaluator<'a> {
|
|||||||
evaluator.add_binding(binding.clone(), expr.clone());
|
evaluator.add_binding(binding.clone(), expr.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let nodes = function.body.iter().map(|expr| ASTNode::ExprNode(expr.clone()));
|
let nodes = function.body.iter().map(|node| node.clone());
|
||||||
let mut retval = Null;
|
let mut retval = ExprNode(Null);
|
||||||
for n in nodes {
|
for n in nodes {
|
||||||
retval = match evaluator.reduce(n) {
|
retval = evaluator.reduction_loop(n);
|
||||||
ExprNode(expr) => expr,
|
|
||||||
FuncDefNode(_) => panic!("This should never happen! A maximally-reduced node\
|
|
||||||
should never be a function definition!")
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(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 ?)*
|
// program := (statement delimiter ?)*
|
||||||
// delimiter := Newline | Semicolon
|
// delimiter := Newline | Semicolon
|
||||||
// statement := declaration | expression
|
// statement := declaration | expression
|
||||||
// declaraion := Fn prototype (statement)* End
|
// declaration := Fn prototype (statement)* End
|
||||||
// prototype := identifier LParen identlist RParen
|
// prototype := identifier LParen identlist RParen
|
||||||
// identlist := Ident (Comma Ident)* | e
|
// identlist := Ident (Comma Ident)* | e
|
||||||
// exprlist := Expression (Comma Expression)* | e
|
// exprlist := Expression (Comma Expression)* | e
|
||||||
@ -29,7 +29,7 @@ pub enum ASTNode {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Function {
|
pub struct Function {
|
||||||
pub prototype: Prototype,
|
pub prototype: Prototype,
|
||||||
pub body: Vec<Expression>,
|
pub body: Vec<ASTNode>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
@ -205,7 +205,7 @@ impl Parser {
|
|||||||
use tokenizer::Token::*;
|
use tokenizer::Token::*;
|
||||||
expect!(self, Keyword(Kw::Fn));
|
expect!(self, Keyword(Kw::Fn));
|
||||||
let prototype = try!(self.prototype());
|
let prototype = try!(self.prototype());
|
||||||
let body: Vec<Expression> = try!(self.body());
|
let body: Vec<ASTNode> = try!(self.body());
|
||||||
expect!(self, Keyword(Kw::End));
|
expect!(self, Keyword(Kw::End));
|
||||||
Ok(ASTNode::FuncDefNode(Function {
|
Ok(ASTNode::FuncDefNode(Function {
|
||||||
prototype: prototype,
|
prototype: prototype,
|
||||||
@ -258,9 +258,9 @@ impl Parser {
|
|||||||
Ok(args)
|
Ok(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn body(&mut self) -> ParseResult<Vec<Expression>> {
|
fn body(&mut self) -> ParseResult<Vec<ASTNode>> {
|
||||||
use tokenizer::Token::*;
|
use tokenizer::Token::*;
|
||||||
let mut exprs = Vec::new();
|
let mut statements = Vec::new();
|
||||||
loop {
|
loop {
|
||||||
match self.peek() {
|
match self.peek() {
|
||||||
Some(ref t) if is_delimiter(t) => {
|
Some(ref t) if is_delimiter(t) => {
|
||||||
@ -269,12 +269,12 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
Some(Keyword(Kw::End)) => break,
|
Some(Keyword(Kw::End)) => break,
|
||||||
_ => {
|
_ => {
|
||||||
let expr = try!(self.expression());
|
let ast_node = try!(self.statement());
|
||||||
exprs.push(expr);
|
statements.push(ast_node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(exprs)
|
Ok(statements)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expression(&mut self) -> ParseResult<Expression> {
|
fn expression(&mut self) -> ParseResult<Expression> {
|
||||||
@ -460,14 +460,14 @@ mod tests {
|
|||||||
parsetest!(
|
parsetest!(
|
||||||
"fn a() 1 + 2 end",
|
"fn a() 1 + 2 end",
|
||||||
&[FuncDefNode(Function {prototype: Prototype { ref name, ref parameters }, ref body})],
|
&[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 }
|
&& name == "a" && match ¶meters[..] { &[] => true, _ => false }
|
||||||
);
|
);
|
||||||
|
|
||||||
parsetest!(
|
parsetest!(
|
||||||
"fn a(x,y) 1 + 2 end",
|
"fn a(x,y) 1 + 2 end",
|
||||||
&[FuncDefNode(Function {prototype: Prototype { ref name, ref parameters }, ref body})],
|
&[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"]
|
&& name == "a" && *parameters == ["x","y"]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user