diff --git a/schala-lang/language/src/eval.rs b/schala-lang/language/src/eval.rs index 50a51dd..ecbb32a 100644 --- a/schala-lang/language/src/eval.rs +++ b/schala-lang/language/src/eval.rs @@ -72,6 +72,12 @@ impl Node { Node::PrimTuple { items } => format!("{}", paren_wrapped_vec(items.iter().map(|x| x.to_repl()))), } } + fn is_true(&self) -> bool { + match self { + Node::Expr(Expr::Lit(::reduced_ast::Lit::Bool(true))) => true, + _ => false, + } + } } #[derive(Debug)] @@ -372,16 +378,16 @@ impl<'a> State<'a> { fn case_match_expression(&mut self, cond: Expr, alternatives: Vec) -> EvalResult { let cond = self.expression(Node::Expr(cond))?; for alt in alternatives { - println!("ALT: {:?}", alt); + println!("ALTERNATIVE: {:?}", alt); // no matter what type of condition we have, ignore alternative if the guard evaluates false if let Some(ref guard_expr) = alt.guard { let guard_expr = match &cond { Node::Expr(ref e) => guard_expr.clone().replace_conditional_target_sigil(e), _ => guard_expr.clone() }; - match self.expression(guard_expr.to_node())? { - Node::Expr(Expr::Lit(::reduced_ast::Lit::Bool(true))) => (), - _ => continue, + + if !self.expression(guard_expr.to_node())?.is_true() { + continue; } } @@ -398,17 +404,43 @@ impl<'a> State<'a> { } } - if let Some(guard_expr) = alt.guard { - let evaled_guard = inner_state.expression(guard_expr.to_node()); - println!("EVALED GUARD: {:?}", evaled_guard); - //continue - } - return inner_state.block(alt.item) } }, Node::PrimTuple { ref items } => { - return Err(format!("Prim tuple not done")) + if items.len() != alt.subpatterns.len() { + return Err(format!("Subpattern length isn't correct")); + } + + let mut inner_state = State { + values: self.values.new_scope(None), + symbol_table_handle: self.symbol_table_handle.clone(), + }; + for (bound_var, val) in alt.bound_vars.iter().zip(items.iter()) { + if let Some(bv) = bound_var.as_ref() { + inner_state.values.insert(bv.clone(), ValueEntry::Binding { constant: true, val: val.clone() }); + } + } + + let mut passes = true; + for (maybe_subp, cond) in alt.subpatterns.iter().zip(items.iter()) { + if let Some(subp) = maybe_subp { + if let Some(ref guard) = subp.guard { + let guard_expr = match &cond { + Node::Expr(ref e) => guard.clone().replace_conditional_target_sigil(e), + _ => guard.clone() + }; + if !inner_state.expression(guard_expr.to_node())?.is_true() { + passes = false; + break; + } + } + } + } + if !passes { + continue; + } + return inner_state.block(alt.item) }, Node::Expr(ref _e) => { if let None = alt.tag {