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 {
fn reduce(&mut self, mut node: ASTNode) -> String {
loop {
@ -208,10 +220,32 @@ impl Evaluator {
let (new_test, new_effect) = self.reduce_expr(test);
(Conditional(Box::new(new_test), then_block, else_block), new_effect)
} else {
if let Number(0.0) = test {
unimplemented!()
if test.is_truthy() {
(*then_block, None)
} 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 tokenizer::{Token, Kw, Op};
use std::collections::VecDeque;
// Grammar
// program := (statement delimiter ?)*
@ -45,7 +46,8 @@ pub enum Expression {
Variable(String),
BinExp(String, Box<Expression>, Box<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 {
@ -315,7 +317,6 @@ impl Parser {
Some(Identifier(_)) => try!(self.identifier_expr()),
Some(Token::LParen) => try!(self.paren_expr()),
Some(e) => {
panic!();
return ParseError::result_from_str("Expected primary expression");
}
None => return ParseError::result_from_str("Expected primary expression received EoI"),
@ -324,28 +325,29 @@ impl Parser {
fn conditional_expr(&mut self) -> ParseResult<Expression> {
use tokenizer::Token::*;
use self::Expression::*;
expect!(self, Keyword(Kw::If));
let test = try!(self.expression());
expect!(self, Keyword(Kw::Then));
let mut then_block = Vec::new();
let mut then_block = VecDeque::new();
loop {
match self.peek() {
None | Some(Keyword(Kw::Else)) | Some(Keyword(Kw::End)) => break,
_ => {
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() {
self.next();
let mut else_exprs = Vec::new();
let mut else_exprs = VecDeque::new();
loop {
match self.peek() {
None | Some(Keyword(Kw::End)) => break,
_ => {
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));
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> {