From b9767d0d7d1b2900ff6d5e1dcdb8c824035233e7 Mon Sep 17 00:00:00 2001 From: Greg Shuflin Date: Tue, 26 Oct 2021 13:02:40 -0700 Subject: [PATCH] Fix bug with pattern matching --- schala-lang/language/src/eval/test.rs | 41 ------------------- schala-lang/language/src/reduced_ir/mod.rs | 17 ++++++-- .../language/src/symbol_table/resolver.rs | 25 +++++++---- .../language/src/tree_walk_eval/test.rs | 30 +++++++++++++- 4 files changed, 59 insertions(+), 54 deletions(-) diff --git a/schala-lang/language/src/eval/test.rs b/schala-lang/language/src/eval/test.rs index 89ec254..e13cde8 100644 --- a/schala-lang/language/src/eval/test.rs +++ b/schala-lang/language/src/eval/test.rs @@ -27,47 +27,6 @@ macro_rules! test_in_fresh_env { } } -#[test] -fn if_is_patterns() { - let source = r#" -type Option = Some(T) | None -let x = Option::Some(9); if x is Option::Some(q) then { q } else { 0 }"#; - test_in_fresh_env!(source, "9"); - - let source = r#" -type Option = Some(T) | None -let x = Option::None; if x is Option::Some(q) then { q } else { 0 }"#; - test_in_fresh_env!(source, "0"); -} - -#[test] -fn full_if_matching() { - let source = r#" -type Option = Some(T) | None -let a = Option::None -if a { is Option::None then 4, is Option::Some(x) then x } -"#; -test_in_fresh_env!(source, "4"); - -let source = r#" -type Option = Some(T) | None -let a = Option::Some(99) -if a { is Option::None then 4, is Option::Some(x) then x } -"#; -test_in_fresh_env!(source, "99"); - -let source = r#" -let a = 10 -if a { is 10 then "x", is 4 then "y" } -"#; -test_in_fresh_env!(source, "\"x\""); - -let source = r#" -let a = 10 -if a { is 15 then "x", is 10 then "y" } -"#; -test_in_fresh_env!(source, "\"y\""); -} #[test] fn string_pattern() { diff --git a/schala-lang/language/src/reduced_ir/mod.rs b/schala-lang/language/src/reduced_ir/mod.rs index 4c62a93..03bbfab 100644 --- a/schala-lang/language/src/reduced_ir/mod.rs +++ b/schala-lang/language/src/reduced_ir/mod.rs @@ -344,11 +344,20 @@ impl ast::Pattern { } }, ast::Pattern::VarOrName(name) => { - //TODO fix this symbol not existing let symbol = symbol_table.lookup_symbol(&name.id).unwrap(); - println!("VarOrName symbol: {:?}", symbol); - let def_id = symbol.def_id().unwrap().clone(); - Pattern::Binding(def_id) + match symbol.spec() { + SymbolSpec::DataConstructor { index: tag, type_id, arity } => { + Pattern::Tuple { + tag: Some(tag as u32), + subpatterns: vec![] + } + }, + SymbolSpec::LocalVariable => { + let def_id = symbol.def_id().unwrap().clone(); + Pattern::Binding(def_id) + }, + spec => return Err(format!("Unexpected VarOrName symbol: {:?}", spec).into()) + } }, ast::Pattern::Record(name, /*Vec<(Rc, Pattern)>*/ _) => { unimplemented!() diff --git a/schala-lang/language/src/symbol_table/resolver.rs b/schala-lang/language/src/symbol_table/resolver.rs index 8500565..0e7e824 100644 --- a/schala-lang/language/src/symbol_table/resolver.rs +++ b/schala-lang/language/src/symbol_table/resolver.rs @@ -72,7 +72,8 @@ impl<'a> ScopeResolver<'a> { /// mappings. fn lookup_name_in_scope(&mut self, name: &QualifiedName) { let QualifiedName { id, components } = name; - //TODO handle a "partial" qualified name + //TODO handle a "partial" qualified name, and also handle it down in the pattern-matching + //section //TODO some of these if lets that look into the fqsn_to_symbol table should probaby fail //with an error if components.len() == 1 { @@ -298,13 +299,21 @@ impl<'a> ASTVisitor for ScopeResolver<'a> { } //TODO this isn't really the right syntax for a VarOrName VarOrName(ref name @ QualifiedName { id, components }) => { - //TODO need a better way to construct a FQSN from a QualifiedName - let local_name: Rc = components[0].clone(); - let lscope = Scope::Name(Rc::new("".to_string())); - let fqsn = Fqsn { scopes: vec![lscope, Scope::Name(local_name.clone())] }; - //let local_name = fqsn.local_name(); - self.symbol_table.add_symbol(id, fqsn, SymbolSpec::LocalVariable); - self.lexical_scopes.insert(local_name.clone(), NameType::LocalVariable(id.clone())); + if components.len() == 1 { + //TODO need a better way to construct a FQSN from a QualifiedName + let local_name: Rc = components[0].clone(); + let lscope = Scope::Name(Rc::new("".to_string())); + let fqsn = Fqsn { scopes: vec![lscope, Scope::Name(local_name.clone())] }; + //let local_name = fqsn.local_name(); + self.symbol_table.add_symbol(id, fqsn, SymbolSpec::LocalVariable); + self.lexical_scopes.insert(local_name.clone(), NameType::LocalVariable(id.clone())); + } else { + let fqsn = Fqsn { scopes: components.iter().map(|name| Scope::Name(name.clone())).collect() }; + let symbol = self.symbol_table.fqsn_to_symbol.get(&fqsn); + if let Some(symbol) = symbol { + self.symbol_table.id_to_symbol.insert(id.clone(), symbol.clone()); + } + } }, }; Recursion::Continue diff --git a/schala-lang/language/src/tree_walk_eval/test.rs b/schala-lang/language/src/tree_walk_eval/test.rs index c33cf2c..b3d9bd0 100644 --- a/schala-lang/language/src/tree_walk_eval/test.rs +++ b/schala-lang/language/src/tree_walk_eval/test.rs @@ -127,7 +127,6 @@ if x { is (_, "panda", _, 2.2) then "yes" is _ then "maybe" }"#); -println!("{}", source); eval_assert(&source, expected); } @@ -149,6 +148,35 @@ let x = Option::None; if x is Option::Some(q) then { q } else { -2 + outer }"#; eval_assert(source, "0"); } +#[test] +fn full_if_matching() { + let source = r#" +type Option = Some(T) | None +let a = Option::None +if a { is Option::None then 4, is Option::Some(x) then x } + "#; + eval_assert(source, "4"); + + let source = r#" +type Option = Some(T) | None +let sara = Option::Some(99) +if sara { is Option::None then 1 + 3, is Option::Some(x) then x } + "#; + eval_assert(source, "99"); + + let source = r#" +let a = 10 +if a { is 10 then "x", is 4 then "y" } + "#; + eval_assert(source, "\"x\""); + + let source = r#" +let a = 10 +if a { is 15 then "x", is 10 then "y" } + "#; + eval_assert(source, "\"y\""); +} + #[test] fn basic_lambda_evaluation_1() {