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 = fn(x) { x + 5 }
|
||||||
a(2)
|
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::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) => {
|
||||||
@ -327,7 +326,7 @@ impl<'a> Evaluator<'a> {
|
|||||||
("+", Number(l), StringLiteral(s1)) => StringLiteral(Rc::new(format!("{}{}", l, *s1))),
|
("+", 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)) => 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)) => Number(l % r),
|
||||||
("<", Number(l), Number(r)) => if l < r { truthy } else { falsy },
|
("<", Number(l), Number(r)) => if l < r { truthy } else { falsy },
|
||||||
("<=", 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> {
|
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();
|
||||||
|
@ -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),
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user