Add Lambda type

And change name FuncNode -> FuncDefNode

Now function definition nodes reduce to a Lambda, which is not
reducible.
This commit is contained in:
greg 2017-01-02 18:41:46 -08:00
parent ad994c38ae
commit 84fbe73cf6
3 changed files with 24 additions and 12 deletions

View File

@ -100,7 +100,7 @@ impl CodeGen for ASTNode {
use self::ASTNode::*;
match self {
&ExprNode(ref expr) => expr.codegen(data),
&FuncNode(ref func) => func.codegen(data),
&FuncDefNode(ref func) => func.codegen(data),
}
}
}

View File

@ -86,7 +86,7 @@ impl Evaluable for ASTNode {
use parser::ASTNode::*;
match self {
&ExprNode(ref expr) => expr.is_reducible(),
&FuncNode(_) => true,
&FuncDefNode(_) => true,
}
}
}
@ -97,6 +97,7 @@ impl Evaluable for Expression {
match *self {
Null => false,
StringLiteral(_) => false,
Lambda(_) => false,
Number(_) => false,
_ => true,
}
@ -156,10 +157,11 @@ impl Evaluator {
(ExprNode(expr), None)
}
}
FuncNode(func) => {
FuncDefNode(func) => {
let fn_name = func.prototype.name.clone();
self.add_function(fn_name, func);
(ExprNode(Expression::Null), None)
//TODO get rid of this clone
self.add_function(fn_name, func.clone());
(ExprNode(Expression::Lambda(func)), None)
}
}
}
@ -170,6 +172,7 @@ impl Evaluator {
Null => (Null, None),
e @ StringLiteral(_) => (e, None),
e @ Number(_) => (e, None),
e @ Lambda(_) => (e, None),
Variable(var) => {
match self.lookup_binding(var) {
None => (Null, None),

View File

@ -23,7 +23,7 @@ use std::collections::VecDeque;
#[derive(Debug, Clone)]
pub enum ASTNode {
ExprNode(Expression),
FuncNode(Function),
FuncDefNode(Function),
}
#[derive(Debug, Clone)]
@ -47,15 +47,16 @@ pub enum Expression {
BinExp(String, Box<Expression>, Box<Expression>),
Call(String, Vec<Expression>),
Conditional(Box<Expression>, Box<Expression>, Option<Box<Expression>>),
Lambda(Function),
Block(VecDeque<Expression>),
}
impl fmt::Display for ASTNode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::ASTNode::*;
match self {
&ExprNode(ref expr) => write!(f, "{}", expr),
&FuncNode(_) => write!(f, "UNIMPLEMENTED"),
match *self {
ExprNode(ref expr) => write!(f, "{}", expr),
FuncDefNode(_) => write!(f, "UNIMPLEMENTED"),
}
}
}
@ -67,6 +68,14 @@ impl fmt::Display for Expression {
&Null => write!(f, "null"),
&StringLiteral(ref s) => write!(f, "\"{}\"", s),
&Number(n) => write!(f, "{}", n),
&Lambda(Function {
prototype: Prototype {
ref name,
ref parameters,
..
},
..
}) => write!(f, "«function: {}, {} arg(s)»", name, parameters.len()),
_ => write!(f, "UNIMPLEMENTED"),
}
}
@ -203,7 +212,7 @@ impl Parser {
let prototype = try!(self.prototype());
let body: Vec<Expression> = try!(self.body());
expect!(self, Keyword(Kw::End));
Ok(ASTNode::FuncNode(Function {
Ok(ASTNode::FuncDefNode(Function {
prototype: prototype,
body: body,
}))
@ -444,14 +453,14 @@ mod tests {
parsetest!(
"fn a() 1 + 2 end",
&[FuncNode(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 }
&& name == "a" && match &parameters[..] { &[] => true, _ => false }
);
parsetest!(
"fn a(x,y) 1 + 2 end",
&[FuncNode(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 }
&& name == "a" && *parameters == ["x","y"]
);