Inline parsing of lambdas like half-works

This commit is contained in:
greg 2017-01-12 02:58:36 -08:00
parent 26bc6e90f3
commit 5911a07f4f
3 changed files with 42 additions and 19 deletions

View File

@ -1,5 +1,5 @@
(fn(q) { q * 2 })(25) (fn(q) { q * 2 }(25))
a = fn(x) { x + 5 } a = fn(x) { x + 5 }
a(2) a(2)

View File

@ -2,7 +2,7 @@ extern crate take_mut;
use std::collections::HashMap; use std::collections::HashMap;
use std::collections::VecDeque; use std::collections::VecDeque;
use parser::{AST, Statement, Expression, Function}; use parser::{AST, Statement, Expression, Function, Callable};
use std::rc::Rc; use std::rc::Rc;
use std::io::{Write, Stdout, BufWriter}; use std::io::{Write, Stdout, BufWriter};
use std::convert::From; use std::convert::From;
@ -12,7 +12,6 @@ use parser::Statement::*;
type Reduction<T> = (T, Option<SideEffect>); type Reduction<T> = (T, Option<SideEffect>);
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
enum ReducedValue { enum ReducedValue {
StringLiteral(Rc<String>), StringLiteral(Rc<String>),
@ -259,7 +258,7 @@ impl<'a> Evaluator<'a> {
(self.reduce_binop(op, *left, *right), None) //can assume both arguments are maximally reduced (self.reduce_binop(op, *left, *right), None) //can assume both arguments are maximally reduced
} }
} }
Call(name, mut args) => { Call(callable, mut args) => {
let mut f = true; let mut f = true;
for arg in args.iter_mut() { for arg in args.iter_mut() {
if arg.is_reducible() { if arg.is_reducible() {
@ -269,9 +268,9 @@ impl<'a> Evaluator<'a> {
} }
} }
if f { if f {
self.reduce_call(name, args) self.reduce_call(callable, args)
} else { } else {
(Call(name, args), None) (Call(callable, args), None)
} }
} }
While(test, body) => { While(test, body) => {
@ -341,18 +340,22 @@ impl<'a> Evaluator<'a> {
} }
} }
fn reduce_call(&mut self, name: Rc<String>, arguments: Vec<Expression>) -> Reduction<Expression> { fn reduce_call(&mut self, callable: Callable, arguments: Vec<Expression>) -> Reduction<Expression> {
if let Some(res) = handle_builtin(&*name, &arguments) { if let Some(res) = handle_builtin(&callable, &arguments) {
return res; return res;
} }
println!("Reduce call, name {} args: {:?}", name, arguments); println!("Reduce call, callable {:?} args: {:?}", callable, arguments);
let function = match self.lookup_binding(&*name) { let function = match callable {
Some(ReducedValue::Lambda(func)) => func, Callable::Lambda(func) => func.clone(),
_ => return (Null, None), Callable::NamedFunction(name) => {
match self.lookup_binding(&*name) {
Some(ReducedValue::Lambda(func)) => func,
_ => return (Null, None),
}
}
}; };
if function.prototype.parameters.len() != arguments.len() { if function.prototype.parameters.len() != arguments.len() {
return (Null, None); return (Null, None);
} }
@ -376,7 +379,12 @@ impl<'a> Evaluator<'a> {
} }
} }
fn handle_builtin(name: &str, arguments: &Vec<Expression>) -> Option<Reduction<Expression>> { fn handle_builtin(callable: &Callable, arguments: &Vec<Expression>) -> Option<Reduction<Expression>> {
let name: &str = match *callable {
Callable::NamedFunction(ref name) => *&name,
_ => return None,
};
match name { match name {
"print" => { "print" => {
let mut s = String::new(); let mut s = String::new();

View File

@ -18,11 +18,13 @@ use std::convert::From;
// primary_expression := Number | String | identifier_expr | paren_expr | conditional_expr | // primary_expression := Number | String | identifier_expr | paren_expr | conditional_expr |
// while_expr | lambda_expr // while_expr | lambda_expr
// identifier_expr := call_expression | Variable // identifier_expr := call_expression | Variable
// call_expr := Identifier LParen exprlist RParen
// while_expr := WHILE primary_expression LCurlyBrace (expression delimiter)* RCurlyBrace // while_expr := WHILE primary_expression LCurlyBrace (expression delimiter)* RCurlyBrace
// paren_expr := LParen expression RParen // paren_expr := LParen expression RParen
// call_expr := Identifier LParen exprlist RParen
// conditional_expr := IF expression LCurlyBrace (expression delimiter)* RCurlyBrace (LCurlyBrace (expresion delimiter)* RCurlyBrace)? // conditional_expr := IF expression LCurlyBrace (expression delimiter)* RCurlyBrace (LCurlyBrace (expresion delimiter)* RCurlyBrace)?
// lambda_expr := FN LParen identlist RParen LCurlyBrace (expression delimiter)* RCurlyBrace // lambda_expr := FN LParen identlist RParen LCurlyBrace (expression delimiter)* RCurlyBrace
// lambda_call
// lambda_call := ε | LParen exprlist RParen
// op := '+', '-', etc. // op := '+', '-', etc.
// //
@ -63,13 +65,19 @@ pub enum Expression {
Number(f64), Number(f64),
Variable(Rc<String>), Variable(Rc<String>),
BinExp(Rc<String>, Box<Expression>, Box<Expression>), BinExp(Rc<String>, Box<Expression>, Box<Expression>),
Call(Rc<String>, Vec<Expression>), Call(Callable, Vec<Expression>),
Conditional(Box<Expression>, Box<Expression>, Option<Box<Expression>>), Conditional(Box<Expression>, Box<Expression>, Option<Box<Expression>>),
Lambda(Function), Lambda(Function),
Block(VecDeque<Expression>), Block(VecDeque<Expression>),
While(Box<Expression>, Vec<Expression>), While(Box<Expression>, Vec<Expression>),
} }
#[derive(Clone, Debug)]
pub enum Callable {
NamedFunction(Rc<String>),
Lambda(Function),
}
impl fmt::Display for Expression { impl fmt::Display for Expression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::Expression::*; use self::Expression::*;
@ -426,7 +434,14 @@ impl Parser {
prototype: prototype, prototype: prototype,
body: body, body: body,
}; };
Ok(Lambda(function))
match self.peek() {
Some(LParen) => {
let args = try!(self.call_expr());
Ok(Call(Callable::Lambda(function), args))
},
_ => Ok(Lambda(function))
}
} }
fn while_expr(&mut self) -> ParseResult<Expression> { fn while_expr(&mut self) -> ParseResult<Expression> {
@ -481,7 +496,7 @@ impl Parser {
let expr = match self.peek() { let expr = match self.peek() {
Some(LParen) => { Some(LParen) => {
let args = try!(self.call_expr()); let args = try!(self.call_expr());
Expression::Call(name, args) Expression::Call(Callable::NamedFunction(name), args)
} }
__ => Expression::Variable(name), __ => Expression::Variable(name),
}; };