Conditionals
This commit is contained in:
parent
3f836eb74f
commit
44e585fca2
2
TODO.md
2
TODO.md
@ -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:
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user