More work on subpattern matching

This commit is contained in:
greg 2018-11-03 12:53:09 -07:00
parent e71d404071
commit bada386979
2 changed files with 39 additions and 44 deletions

View File

@ -372,6 +372,7 @@ impl<'a> State<'a> {
fn case_match_expression(&mut self, cond: Expr, alternatives: Vec<Alternative>) -> EvalResult<Node> { fn case_match_expression(&mut self, cond: Expr, alternatives: Vec<Alternative>) -> EvalResult<Node> {
let cond = self.expression(Node::Expr(cond))?; let cond = self.expression(Node::Expr(cond))?;
for alt in alternatives { for alt in alternatives {
println!("ALT: {:?}", alt);
// no matter what type of condition we have, ignore alternative if the guard evaluates false // no matter what type of condition we have, ignore alternative if the guard evaluates false
if let Some(ref guard_expr) = alt.guard { if let Some(ref guard_expr) = alt.guard {
let guard_expr = match &cond { let guard_expr = match &cond {
@ -406,7 +407,7 @@ impl<'a> State<'a> {
return inner_state.block(alt.item) return inner_state.block(alt.item)
} }
}, },
Node::PrimTuple { .. } => { Node::PrimTuple { ref items } => {
return Err(format!("Prim tuple not done")) return Err(format!("Prim tuple not done"))
}, },
Node::Expr(ref _e) => { Node::Expr(ref _e) => {

View File

@ -65,12 +65,6 @@ pub struct Alternative {
pub item: Vec<Stmt>, pub item: Vec<Stmt>,
} }
impl Alternative {
fn default(item: Vec<Stmt>) -> Alternative {
Alternative { tag: None, subpatterns: vec![], guard: None, bound_vars: vec![], item }
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Subpattern { pub struct Subpattern {
pub tag: Option<usize>, pub tag: Option<usize>,
@ -172,7 +166,13 @@ fn reduce_if_expression(discriminator: &Discriminator, body: &IfExpressionBody,
let alternatives = vec![ let alternatives = vec![
pat.to_alternative(then_clause, symbol_table), pat.to_alternative(then_clause, symbol_table),
Alternative::default(else_clause), Alternative {
tag: None,
subpatterns: vec![],
bound_vars: vec![],
guard: None,
item: else_clause
},
]; ];
Expr::CaseMatch { Expr::CaseMatch {
@ -202,17 +202,27 @@ fn reduce_if_expression(discriminator: &Discriminator, body: &IfExpressionBody,
* x is SomeBigOldEnum(_, x, Some(t)) * x is SomeBigOldEnum(_, x, Some(t))
*/ */
fn handle_symbol(symbol: Option<&Symbol>, subpatterns: &Vec<Pattern>) -> Subpattern { fn handle_symbol(symbol: Option<&Symbol>, inner_patterns: &Vec<Pattern>, symbol_table: &SymbolTable) -> Subpattern {
use self::Pattern::*; use self::Pattern::*;
let tag = symbol.map(|symbol| match symbol.spec { let tag = symbol.map(|symbol| match symbol.spec {
SymbolSpec::DataConstructor { index, .. } => index.clone(), SymbolSpec::DataConstructor { index, .. } => index.clone(),
_ => panic!("Symbol is not a data constructor - this should've been caught in type-checking"), _ => panic!("Symbol is not a data constructor - this should've been caught in type-checking"),
}); });
let bound_vars = subpatterns.iter().map(|p| match p { let bound_vars = inner_patterns.iter().map(|p| match p {
Literal(PatternLiteral::VarPattern(var)) => Some(var.clone()), Literal(PatternLiteral::VarPattern(var)) => Some(var.clone()),
_ => None, _ => None,
}).collect(); }).collect();
let subpatterns = inner_patterns.iter().map(|p| match p {
Ignored => None,
Literal(PatternLiteral::VarPattern(_)) => None,
Literal(other) => Some(other.to_subpattern(symbol_table)),
tp @ TuplePattern(_) => Some(tp.to_subpattern(symbol_table)),
ts @ TupleStruct(_, _) => Some(ts.to_subpattern(symbol_table)),
Record(..) => unimplemented!(),
}).collect();
let guard = None;
/* /*
let guard_equality_exprs: Vec<Expr> = subpatterns.iter().map(|p| match p { let guard_equality_exprs: Vec<Expr> = subpatterns.iter().map(|p| match p {
Literal(lit) => match lit { Literal(lit) => match lit {
@ -222,9 +232,6 @@ fn handle_symbol(symbol: Option<&Symbol>, subpatterns: &Vec<Pattern>) -> Subpatt
}).collect(); }).collect();
*/ */
let guard = None;
let subpatterns = vec![];
Subpattern { Subpattern {
tag, tag,
subpatterns, subpatterns,
@ -235,43 +242,30 @@ fn handle_symbol(symbol: Option<&Symbol>, subpatterns: &Vec<Pattern>) -> Subpatt
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);
Alternative {
tag: s.tag,
subpatterns: s.subpatterns,
bound_vars: s.bound_vars,
guard: s.guard,
item
}
}
fn to_subpattern(&self, symbol_table: &SymbolTable) -> Subpattern {
use self::Pattern::*; use self::Pattern::*;
match self { match self {
TupleStruct(name, subpatterns) => { TupleStruct(name, inner_patterns) => {
let symbol = symbol_table.lookup_by_name(name).expect(&format!("Symbol {} not found", name)); let symbol = symbol_table.lookup_by_name(name).expect(&format!("Symbol {} not found", name));
let s = handle_symbol(Some(symbol), subpatterns); handle_symbol(Some(symbol), inner_patterns, symbol_table)
Alternative {
tag: s.tag,
subpatterns: s.subpatterns,
guard: s.guard,
bound_vars: s.bound_vars,
item
}
},
TuplePattern(subpatterns) => {
let s = handle_symbol(None, subpatterns);
Alternative {
tag: s.tag,
subpatterns: s.subpatterns,
guard: s.guard,
bound_vars: s.bound_vars,
item
}
}, },
TuplePattern(inner_patterns) => handle_symbol(None, inner_patterns, symbol_table),
Record(_name, _pairs) => { Record(_name, _pairs) => {
unimplemented!() unimplemented!()
}, },
Ignored => Alternative::default(item), Ignored => Subpattern { tag: None, subpatterns: vec![], guard: None, bound_vars: vec![] },
Literal(lit) => { Literal(lit) => lit.to_subpattern(symbol_table),
let s = lit.to_subpattern(symbol_table);
Alternative {
tag: s.tag,
subpatterns: s.subpatterns,
bound_vars: s.bound_vars,
guard: s.guard,
item
}
},
} }
} }
} }
@ -329,7 +323,7 @@ impl PatternLiteral {
} }
}, },
VarPattern(var) => match symbol_table.lookup_by_name(var) { VarPattern(var) => match symbol_table.lookup_by_name(var) {
Some(symbol) => handle_symbol(Some(symbol), &vec![]), Some(symbol) => handle_symbol(Some(symbol), &vec![], symbol_table),
None => Subpattern { None => Subpattern {
tag: None, tag: None,
subpatterns: vec![], subpatterns: vec![],