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(2)

View File

@ -2,7 +2,7 @@ extern crate take_mut;
use std::collections::HashMap;
use std::collections::VecDeque;
use parser::{AST, Statement, Expression, Function};
use parser::{AST, Statement, Expression, Function, Callable};
use std::rc::Rc;
use std::io::{Write, Stdout, BufWriter};
use std::convert::From;
@ -12,7 +12,6 @@ use parser::Statement::*;
type Reduction<T> = (T, Option<SideEffect>);
#[derive(Debug, Clone)]
enum ReducedValue {
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
}
}
Call(name, mut args) => {
Call(callable, mut args) => {
let mut f = true;
for arg in args.iter_mut() {
if arg.is_reducible() {
@ -269,9 +268,9 @@ impl<'a> Evaluator<'a> {
}
}
if f {
self.reduce_call(name, args)
self.reduce_call(callable, args)
} else {
(Call(name, args), None)
(Call(callable, args), None)
}
}
While(test, body) => {
@ -327,7 +326,7 @@ impl<'a> Evaluator<'a> {
("+", Number(l), StringLiteral(s1)) => StringLiteral(Rc::new(format!("{}{}", l, *s1))),
("-", Number(l), Number(r)) => Number(l - r),
("*", Number(l), Number(r)) => Number(l * r),
("/", Number(l), Number(r)) if r != 0.0 => Number(l / r),
("/", Number(l), Number(r)) if r != 0.0 => Number(l / r),
("%", Number(l), Number(r)) => Number(l % r),
("<", Number(l), Number(r)) => if l < r { truthy } else { falsy },
("<=", Number(l), Number(r)) => if l <= r { truthy } else { falsy },
@ -341,18 +340,22 @@ impl<'a> Evaluator<'a> {
}
}
fn reduce_call(&mut self, name: Rc<String>, arguments: Vec<Expression>) -> Reduction<Expression> {
if let Some(res) = handle_builtin(&*name, &arguments) {
fn reduce_call(&mut self, callable: Callable, arguments: Vec<Expression>) -> Reduction<Expression> {
if let Some(res) = handle_builtin(&callable, &arguments) {
return res;
}
println!("Reduce call, name {} args: {:?}", name, arguments);
println!("Reduce call, callable {:?} args: {:?}", callable, arguments);
let function = match self.lookup_binding(&*name) {
Some(ReducedValue::Lambda(func)) => func,
_ => return (Null, None),
let function = match callable {
Callable::Lambda(func) => func.clone(),
Callable::NamedFunction(name) => {
match self.lookup_binding(&*name) {
Some(ReducedValue::Lambda(func)) => func,
_ => return (Null, None),
}
}
};
if function.prototype.parameters.len() != arguments.len() {
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 {
"print" => {
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 |
// while_expr | lambda_expr
// identifier_expr := call_expression | Variable
// call_expr := Identifier LParen exprlist RParen
// while_expr := WHILE primary_expression LCurlyBrace (expression delimiter)* RCurlyBrace
// paren_expr := LParen expression RParen
// call_expr := Identifier LParen exprlist RParen
// conditional_expr := IF expression LCurlyBrace (expression delimiter)* RCurlyBrace (LCurlyBrace (expresion delimiter)* RCurlyBrace)?
// lambda_expr := FN LParen identlist RParen LCurlyBrace (expression delimiter)* RCurlyBrace
// lambda_call
// lambda_call := ε | LParen exprlist RParen
// op := '+', '-', etc.
//
@ -63,13 +65,19 @@ pub enum Expression {
Number(f64),
Variable(Rc<String>),
BinExp(Rc<String>, Box<Expression>, Box<Expression>),
Call(Rc<String>, Vec<Expression>),
Call(Callable, Vec<Expression>),
Conditional(Box<Expression>, Box<Expression>, Option<Box<Expression>>),
Lambda(Function),
Block(VecDeque<Expression>),
While(Box<Expression>, Vec<Expression>),
}
#[derive(Clone, Debug)]
pub enum Callable {
NamedFunction(Rc<String>),
Lambda(Function),
}
impl fmt::Display for Expression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::Expression::*;
@ -426,7 +434,14 @@ impl Parser {
prototype: prototype,
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> {
@ -481,7 +496,7 @@ impl Parser {
let expr = match self.peek() {
Some(LParen) => {
let args = try!(self.call_expr());
Expression::Call(name, args)
Expression::Call(Callable::NamedFunction(name), args)
}
__ => Expression::Variable(name),
};