More pattern-matching

This commit is contained in:
greg 2018-11-05 04:02:04 -08:00
parent ec29077247
commit c394b81746
2 changed files with 27 additions and 27 deletions

View File

@ -387,37 +387,38 @@ impl<'a> State<'a> {
Ok(Node::Expr(Expr::Unit)) Ok(Node::Expr(Expr::Unit))
} }
fn case_match_expression(&mut self, cond: Expr, alternatives: Vec<Alternative>) -> EvalResult<Node> { fn guard_passes(&mut self, guard: &Option<Expr>, cond: &Node) -> EvalResult<bool> {
let cond = self.expression(Node::Expr(cond))?; if let Some(ref guard_expr) = guard {
for alt in alternatives { let guard_expr = match cond {
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), Node::Expr(ref e) => guard_expr.clone().replace_conditional_target_sigil(e),
_ => guard_expr.clone() _ => guard_expr.clone()
}; };
Ok(self.expression(guard_expr.to_node())?.is_true())
if !self.expression(guard_expr.to_node())?.is_true() { } else {
continue; Ok(true)
} }
} }
fn all_subpatterns_pass(state: &mut State, subpatterns: &Vec<Option<Subpattern>>, items: &Vec<Node>) -> EvalResult<bool> { fn case_match_expression(&mut self, cond: Expr, alternatives: Vec<Alternative>) -> EvalResult<Node> {
//TODO need to handle recursive subpatterns
let all_subpatterns_pass = |state: &mut State, subpatterns: &Vec<Option<Subpattern>>, items: &Vec<Node>| -> EvalResult<bool> {
for (maybe_subp, cond) in subpatterns.iter().zip(items.iter()) { for (maybe_subp, cond) in subpatterns.iter().zip(items.iter()) {
if let Some(subp) = maybe_subp { if let Some(subp) = maybe_subp {
if let Some(ref guard) = subp.guard { if !state.guard_passes(&subp.guard, &cond)? {
let guard_expr = match &cond { return Ok(false)
Node::Expr(ref e) => guard.clone().replace_conditional_target_sigil(e),
_ => guard.clone()
};
if !state.expression(guard_expr.to_node())?.is_true() {
return Ok(false);
}
} }
} }
} }
Ok(true) Ok(true)
};
let cond = self.expression(Node::Expr(cond))?;
for alt in alternatives {
println!("ALTERNATIVE: {:?}", alt);
// no matter what type of condition we have, ignore alternative if the guard evaluates false
if !self.guard_passes(&alt.guard, &cond)? {
continue;
} }
match cond { match cond {

View File

@ -244,7 +244,6 @@ fn handle_symbol(symbol: Option<&Symbol>, inner_patterns: &Vec<Pattern>, symbol_
impl Pattern { impl Pattern {
fn to_alternative(&self, item: Vec<Stmt>, symbol_table: &SymbolTable) -> Alternative { fn to_alternative(&self, item: Vec<Stmt>, symbol_table: &SymbolTable) -> Alternative {
use self::Pattern::*;
let s = self.to_subpattern(symbol_table); let s = self.to_subpattern(symbol_table);
Alternative { Alternative {
tag: s.tag, tag: s.tag,