full if matching working with basic patterns

This commit is contained in:
greg 2018-10-15 19:54:17 -07:00
parent a99a5f10a4
commit abe2db25b2
2 changed files with 45 additions and 18 deletions

View File

@ -468,7 +468,7 @@ mod eval_tests {
} }
#[test] #[test]
fn basic_patterns() { fn if_is_patterns() {
let source = r#" let source = r#"
type Option<T> = Some(T) | None type Option<T> = Some(T) | None
let x = Some(9); if x is Some(q) then { q } else { 0 }"#; let x = Some(9); if x is Some(q) then { q } else { 0 }"#;
@ -479,4 +479,21 @@ type Option<T> = Some(T) | None
let x = None; if x is Some(q) then { q } else { 0 }"#; let x = None; if x is Some(q) then { q } else { 0 }"#;
fresh_env!(source, "0"); fresh_env!(source, "0");
} }
#[test]
fn full_if_matching() {
let source = r#"
type Option<T> = Some(T) | None
let a = None
if a { is None -> 4, is Some(x) -> x }
"#;
fresh_env!(source, "4");
let source = r#"
type Option<T> = Some(T) | None
let a = Some(99)
if a { is None -> 4, is Some(x) -> x }
"#;
fresh_env!(source, "99");
}
} }

View File

@ -189,24 +189,29 @@ fn reduce_if_expression(discriminator: &Discriminator, body: &IfExpressionBody,
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::*; use self::Pattern::*;
fn handle_symbol(symbol: &Symbol, subpatterns: &Vec<Pattern>, item: Vec<Stmt>) -> Alternative {
let tag = match symbol.spec {
SymbolSpec::DataConstructor { index, .. } => index.clone(),
_ => panic!("Symbol is not a data constructor - this should've been caught in type-checking"),
};
let bound_vars = subpatterns.iter().map(|p| match p {
Literal(PatternLiteral::VarPattern(var)) => Some(var.clone()),
Ignored => None,
_ => None,
}).collect();
Alternative {
tag: Some(tag),
guard: None,
bound_vars,
item,
}
}
match self { match self {
TupleStruct(name, subpatterns) => { TupleStruct(name, subpatterns) => {
let symbol = symbol_table.values.get(name).expect(&format!("Symbol {} not found", name)); let symbol = symbol_table.lookup_by_name(name).expect(&format!("Symbol {} not found", name));
let tag = match symbol.spec { handle_symbol(symbol, subpatterns, item)
SymbolSpec::DataConstructor { index, .. } => index.clone(),
_ => panic!("Bad symbol"),
};
let bound_vars = subpatterns.iter().map(|p| match p {
Literal(PatternLiteral::VarPattern(var)) => Some(var.clone()),
Ignored => None,
_ => None,
}).collect();
Alternative {
tag: Some(tag),
guard: None,
bound_vars,
item,
}
}, },
TuplePattern(_items) => { TuplePattern(_items) => {
unimplemented!() unimplemented!()
@ -219,7 +224,12 @@ impl Pattern {
PatternLiteral::NumPattern { neg, num } => unimplemented!(), PatternLiteral::NumPattern { neg, num } => unimplemented!(),
PatternLiteral::StringPattern(_s) => unimplemented!(), PatternLiteral::StringPattern(_s) => unimplemented!(),
PatternLiteral::BoolPattern(_b) => unimplemented!(), PatternLiteral::BoolPattern(_b) => unimplemented!(),
PatternLiteral::VarPattern(_var) => unimplemented!(), PatternLiteral::VarPattern(var) => match symbol_table.lookup_by_name(var) {
Some(symbol) => handle_symbol(symbol, &vec![], item),
None => {
unimplemented!()
}
}
}, },
} }
} }