diff --git a/schala-lang/src/eval.rs b/schala-lang/src/eval.rs index 8315ed9..42880aa 100644 --- a/schala-lang/src/eval.rs +++ b/schala-lang/src/eval.rs @@ -468,7 +468,7 @@ mod eval_tests { } #[test] - fn basic_patterns() { + fn if_is_patterns() { let source = r#" type Option = Some(T) | None let x = Some(9); if x is Some(q) then { q } else { 0 }"#; @@ -479,4 +479,21 @@ type Option = Some(T) | None let x = None; if x is Some(q) then { q } else { 0 }"#; fresh_env!(source, "0"); } + + #[test] + fn full_if_matching() { + let source = r#" +type Option = Some(T) | None +let a = None +if a { is None -> 4, is Some(x) -> x } +"#; + fresh_env!(source, "4"); + + let source = r#" +type Option = Some(T) | None +let a = Some(99) +if a { is None -> 4, is Some(x) -> x } +"#; + fresh_env!(source, "99"); + } } diff --git a/schala-lang/src/reduced_ast.rs b/schala-lang/src/reduced_ast.rs index 3eb7bf2..96a46eb 100644 --- a/schala-lang/src/reduced_ast.rs +++ b/schala-lang/src/reduced_ast.rs @@ -189,24 +189,29 @@ fn reduce_if_expression(discriminator: &Discriminator, body: &IfExpressionBody, impl Pattern { fn to_alternative(&self, item: Vec, symbol_table: &SymbolTable) -> Alternative { use self::Pattern::*; + + fn handle_symbol(symbol: &Symbol, subpatterns: &Vec, item: Vec) -> 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 { TupleStruct(name, subpatterns) => { - let symbol = symbol_table.values.get(name).expect(&format!("Symbol {} not found", name)); - let tag = match symbol.spec { - 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, - } + let symbol = symbol_table.lookup_by_name(name).expect(&format!("Symbol {} not found", name)); + handle_symbol(symbol, subpatterns, item) }, TuplePattern(_items) => { unimplemented!() @@ -219,7 +224,12 @@ impl Pattern { PatternLiteral::NumPattern { neg, num } => unimplemented!(), PatternLiteral::StringPattern(_s) => 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!() + } + } }, } }