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

View File

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