From 44e585fca2adedbd6d0581093be1733aad7b886c Mon Sep 17 00:00:00 2001 From: greg Date: Sat, 12 May 2018 13:51:12 -0700 Subject: [PATCH] Conditionals --- TODO.md | 2 ++ schala-lang/src/ast_reducing.rs | 13 +++++++++++++ schala-lang/src/eval.rs | 24 +++++++++++++++++++----- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/TODO.md b/TODO.md index 2a956a7..5d4eee6 100644 --- a/TODO.md +++ b/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: diff --git a/schala-lang/src/ast_reducing.rs b/schala-lang/src/ast_reducing.rs index 6a30152..4ccf8d6 100644 --- a/schala-lang/src/ast_reducing.rs +++ b/schala-lang/src/ast_reducing.rs @@ -31,6 +31,11 @@ pub enum Expr { val: Box, expr: Box, }, + Conditional { + cond: Box, + then_clause: Vec, + else_clause: Vec, + }, 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, } } diff --git a/schala-lang/src/eval.rs b/schala-lang/src/eval.rs index 34f4252..71d2c97 100644 --- a/schala-lang/src/eval.rs +++ b/schala-lang/src/eval.rs @@ -342,6 +342,14 @@ impl<'a> State<'a> { } } + fn block(&mut self, stmts: Vec) -> EvalResult { + 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 { 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::,_>>()?)), + 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, else_clause: Vec) -> EvalResult { + 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) -> EvalResult { use self::ValueEntry::*; match self.values.lookup(&name) {