Fix bug with pattern matching
This commit is contained in:
parent
df173a0096
commit
b9767d0d7d
@ -27,47 +27,6 @@ macro_rules! test_in_fresh_env {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn if_is_patterns() {
|
|
||||||
let source = r#"
|
|
||||||
type Option<T> = 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<T> = 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<T> = 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<T> = 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]
|
#[test]
|
||||||
fn string_pattern() {
|
fn string_pattern() {
|
||||||
|
@ -344,11 +344,20 @@ impl ast::Pattern {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
ast::Pattern::VarOrName(name) => {
|
ast::Pattern::VarOrName(name) => {
|
||||||
//TODO fix this symbol not existing
|
|
||||||
let symbol = symbol_table.lookup_symbol(&name.id).unwrap();
|
let symbol = symbol_table.lookup_symbol(&name.id).unwrap();
|
||||||
println!("VarOrName symbol: {:?}", symbol);
|
match symbol.spec() {
|
||||||
let def_id = symbol.def_id().unwrap().clone();
|
SymbolSpec::DataConstructor { index: tag, type_id, arity } => {
|
||||||
Pattern::Binding(def_id)
|
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<String>, Pattern)>*/ _) => {
|
ast::Pattern::Record(name, /*Vec<(Rc<String>, Pattern)>*/ _) => {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
|
@ -72,7 +72,8 @@ impl<'a> ScopeResolver<'a> {
|
|||||||
/// mappings.
|
/// mappings.
|
||||||
fn lookup_name_in_scope(&mut self, name: &QualifiedName) {
|
fn lookup_name_in_scope(&mut self, name: &QualifiedName) {
|
||||||
let QualifiedName { id, components } = name;
|
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
|
//TODO some of these if lets that look into the fqsn_to_symbol table should probaby fail
|
||||||
//with an error
|
//with an error
|
||||||
if components.len() == 1 {
|
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
|
//TODO this isn't really the right syntax for a VarOrName
|
||||||
VarOrName(ref name @ QualifiedName { id, components }) => {
|
VarOrName(ref name @ QualifiedName { id, components }) => {
|
||||||
//TODO need a better way to construct a FQSN from a QualifiedName
|
if components.len() == 1 {
|
||||||
let local_name: Rc<String> = components[0].clone();
|
//TODO need a better way to construct a FQSN from a QualifiedName
|
||||||
let lscope = Scope::Name(Rc::new("<local-case-match>".to_string()));
|
let local_name: Rc<String> = components[0].clone();
|
||||||
let fqsn = Fqsn { scopes: vec![lscope, Scope::Name(local_name.clone())] };
|
let lscope = Scope::Name(Rc::new("<local-case-match>".to_string()));
|
||||||
//let local_name = fqsn.local_name();
|
let fqsn = Fqsn { scopes: vec![lscope, Scope::Name(local_name.clone())] };
|
||||||
self.symbol_table.add_symbol(id, fqsn, SymbolSpec::LocalVariable);
|
//let local_name = fqsn.local_name();
|
||||||
self.lexical_scopes.insert(local_name.clone(), NameType::LocalVariable(id.clone()));
|
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
|
Recursion::Continue
|
||||||
|
@ -127,7 +127,6 @@ if x {
|
|||||||
is (_, "panda", _, 2.2) then "yes"
|
is (_, "panda", _, 2.2) then "yes"
|
||||||
is _ then "maybe"
|
is _ then "maybe"
|
||||||
}"#);
|
}"#);
|
||||||
println!("{}", source);
|
|
||||||
|
|
||||||
eval_assert(&source, expected);
|
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");
|
eval_assert(source, "0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn full_if_matching() {
|
||||||
|
let source = r#"
|
||||||
|
type Option<T> = 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<T> = 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]
|
#[test]
|
||||||
fn basic_lambda_evaluation_1() {
|
fn basic_lambda_evaluation_1() {
|
||||||
|
Loading…
Reference in New Issue
Block a user