Inline parsing of lambdas like half-works
This commit is contained in:
parent
26bc6e90f3
commit
5911a07f4f
@ -1,5 +1,5 @@
|
||||
|
||||
(fn(q) { q * 2 })(25)
|
||||
(fn(q) { q * 2 }(25))
|
||||
|
||||
a = fn(x) { x + 5 }
|
||||
a(2)
|
||||
|
36
src/eval.rs
36
src/eval.rs
@ -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();
|
||||
|
@ -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),
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user