Finish evaluating conditionals

This commit is contained in:
greg 2016-12-31 03:35:46 -08:00
parent 7f52b20d97
commit 82c52ede48
2 changed files with 46 additions and 10 deletions

View File

@ -103,6 +103,18 @@ impl Evaluable for Expression {
} }
} }
impl Expression {
fn is_truthy(&self) -> bool {
use parser::Expression::*;
match *self {
Null => false,
StringLiteral(ref s) if s == "" => false,
Number(0.0) => false,
_ => true,
}
}
}
impl Evaluator { impl Evaluator {
fn reduce(&mut self, mut node: ASTNode) -> String { fn reduce(&mut self, mut node: ASTNode) -> String {
loop { loop {
@ -208,10 +220,32 @@ impl Evaluator {
let (new_test, new_effect) = self.reduce_expr(test); let (new_test, new_effect) = self.reduce_expr(test);
(Conditional(Box::new(new_test), then_block, else_block), new_effect) (Conditional(Box::new(new_test), then_block, else_block), new_effect)
} else { } else {
if let Number(0.0) = test { if test.is_truthy() {
unimplemented!() (*then_block, None)
} else { } else {
unimplemented!() match else_block {
Some(box expr) => (expr, None),
None => (Null, None)
}
}
}
}
Block(mut exprs) => {
let first = exprs.pop_front();
match first {
None => (Null, None),
Some(expr) => {
if exprs.len() == 0 {
(expr, None)
} else {
if expr.is_reducible() {
let (new, side_effect) = self.reduce_expr(expr);
exprs.push_front(new);
(Block(exprs), side_effect)
} else {
(Block(exprs), None)
}
}
} }
} }
} }

View File

@ -1,5 +1,6 @@
use std::fmt; use std::fmt;
use tokenizer::{Token, Kw, Op}; use tokenizer::{Token, Kw, Op};
use std::collections::VecDeque;
// Grammar // Grammar
// program := (statement delimiter ?)* // program := (statement delimiter ?)*
@ -45,7 +46,8 @@ pub enum Expression {
Variable(String), Variable(String),
BinExp(String, Box<Expression>, Box<Expression>), BinExp(String, Box<Expression>, Box<Expression>),
Call(String, Vec<Expression>), Call(String, Vec<Expression>),
Conditional(Box<Expression>, Vec<Expression>, Option<Vec<Expression>>), Conditional(Box<Expression>, Box<Expression>, Option<Box<Expression>>),
Block(VecDeque<Expression>),
} }
impl fmt::Display for ASTNode { impl fmt::Display for ASTNode {
@ -315,7 +317,6 @@ impl Parser {
Some(Identifier(_)) => try!(self.identifier_expr()), Some(Identifier(_)) => try!(self.identifier_expr()),
Some(Token::LParen) => try!(self.paren_expr()), Some(Token::LParen) => try!(self.paren_expr()),
Some(e) => { Some(e) => {
panic!();
return ParseError::result_from_str("Expected primary expression"); return ParseError::result_from_str("Expected primary expression");
} }
None => return ParseError::result_from_str("Expected primary expression received EoI"), None => return ParseError::result_from_str("Expected primary expression received EoI"),
@ -324,28 +325,29 @@ impl Parser {
fn conditional_expr(&mut self) -> ParseResult<Expression> { fn conditional_expr(&mut self) -> ParseResult<Expression> {
use tokenizer::Token::*; use tokenizer::Token::*;
use self::Expression::*;
expect!(self, Keyword(Kw::If)); expect!(self, Keyword(Kw::If));
let test = try!(self.expression()); let test = try!(self.expression());
expect!(self, Keyword(Kw::Then)); expect!(self, Keyword(Kw::Then));
let mut then_block = Vec::new(); let mut then_block = VecDeque::new();
loop { loop {
match self.peek() { match self.peek() {
None | Some(Keyword(Kw::Else)) | Some(Keyword(Kw::End)) => break, None | Some(Keyword(Kw::Else)) | Some(Keyword(Kw::End)) => break,
_ => { _ => {
let exp = try!(self.expression()); let exp = try!(self.expression());
then_block.push(exp); then_block.push_back(exp);
} }
} }
} }
let else_block = if let Some(Keyword(Kw::Else)) = self.peek() { let else_block = if let Some(Keyword(Kw::Else)) = self.peek() {
self.next(); self.next();
let mut else_exprs = Vec::new(); let mut else_exprs = VecDeque::new();
loop { loop {
match self.peek() { match self.peek() {
None | Some(Keyword(Kw::End)) => break, None | Some(Keyword(Kw::End)) => break,
_ => { _ => {
let exp = try!(self.expression()); let exp = try!(self.expression());
else_exprs.push(exp); else_exprs.push_back(exp);
} }
} }
} }
@ -355,7 +357,7 @@ impl Parser {
}; };
expect!(self, Keyword(Kw::End)); expect!(self, Keyword(Kw::End));
Ok(Expression::Conditional(Box::new(test), then_block, else_block)) Ok(Conditional(Box::new(test), Box::new(Block(then_block)), else_block.map(|list| Box::new(Block(list)))))
} }
fn identifier_expr(&mut self) -> ParseResult<Expression> { fn identifier_expr(&mut self) -> ParseResult<Expression> {