Conditionals

This commit is contained in:
greg 2018-05-12 13:51:12 -07:00
parent 3f836eb74f
commit 44e585fca2
3 changed files with 34 additions and 5 deletions

View File

@ -1,6 +1,8 @@
# TODO Items
- Next priorities: - get ADTs working, get matches working
- inclusive/exclusive range syntax like .. vs ..=
- sketch of an idea for the REPL:

View File

@ -31,6 +31,11 @@ pub enum Expr {
val: Box<Expr>,
expr: Box<Expr>,
},
Conditional {
cond: Box<Expr>,
then_clause: Vec<Stmt>,
else_clause: Vec<Stmt>,
},
UnimplementedSigilValue
}
@ -90,6 +95,14 @@ impl Expression {
args: arguments.iter().map(|arg| arg.reduce()).collect(),
},
TupleLiteral(exprs) => Expr::Tuple(exprs.iter().map(|e| e.reduce()).collect()),
IfExpression(cond, then_clause, else_clause) => Expr::Conditional {
cond: Box::new((**cond).reduce()),
then_clause: then_clause.iter().map(|expr| expr.reduce()).collect(),
else_clause: match else_clause {
None => vec![],
Some(stmts) => stmts.iter().map(|expr| expr.reduce()).collect(),
}
},
_ => Expr::UnimplementedSigilValue,
}
}

View File

@ -342,6 +342,14 @@ impl<'a> State<'a> {
}
}
fn block(&mut self, stmts: Vec<Stmt>) -> EvalResult<Expr> {
let mut ret = None;
for stmt in stmts {
ret = self.statement(stmt)?;
}
Ok(ret.unwrap_or(Expr::Unit))
}
fn expression(&mut self, expr: Expr) -> EvalResult<Expr> {
use self::Expr::*;
match expr {
@ -356,6 +364,7 @@ impl<'a> State<'a> {
Val(v) => self.value(v),
func @ Func(_) => Ok(func),
Tuple(exprs) => Ok(Tuple(exprs.into_iter().map(|expr| self.expression(expr)).collect::<Result<Vec<Expr>,_>>()?)),
Conditional { box cond, then_clause, else_clause } => self.conditional(cond, then_clause, else_clause),
Assign { box val, box expr } => {
let name = match val {
Expr::Val(name) => name,
@ -390,11 +399,7 @@ impl<'a> State<'a> {
func_state.values.insert(param, ValueEntry::Binding { constant: true, val });
}
// TODO figure out function return semantics
let mut ret = None;
for stmt in body {
ret = func_state.statement(stmt)?;
}
Ok(ret.unwrap_or(Expr::Unit))
func_state.block(body)
}
}
}
@ -449,6 +454,15 @@ impl<'a> State<'a> {
})
}
fn conditional(&mut self, cond: Expr, then_clause: Vec<Stmt>, else_clause: Vec<Stmt>) -> EvalResult<Expr> {
let cond = self.expression(cond)?;
Ok(match cond {
Expr::Lit(Lit::Bool(true)) => self.block(then_clause)?,
Expr::Lit(Lit::Bool(false)) => self.block(else_clause)?,
_ => return Err(format!("Conditional with non-boolean condition"))
})
}
fn value(&mut self, name: Rc<String>) -> EvalResult<Expr> {
use self::ValueEntry::*;
match self.values.lookup(&name) {