schala/schala-lang/language/src/symbol_table/test.rs

234 lines
4.9 KiB
Rust
Raw Normal View History

2019-10-16 19:51:43 -07:00
#![cfg(test)]
use super::*;
2021-10-19 19:19:21 -07:00
use assert_matches::assert_matches;
2019-10-16 19:51:43 -07:00
use crate::util::quick_ast;
2021-10-19 19:19:21 -07:00
fn add_symbols(src: &str) -> (SymbolTable, Result<(), Vec<SymbolError>>) {
let ast = quick_ast(src);
let mut symbol_table = SymbolTable::new();
2021-10-18 22:51:36 -07:00
let result = symbol_table.process_ast(&ast);
2019-10-23 14:02:27 -07:00
(symbol_table, result)
}
2021-10-18 22:51:36 -07:00
fn make_fqsn(strs: &[&str]) -> FQSN {
2021-10-19 17:22:35 -07:00
FQSN::from_strs(strs)
2019-10-16 19:51:43 -07:00
}
2021-10-18 22:51:36 -07:00
2019-10-16 19:51:43 -07:00
#[test]
fn basic_symbol_table() {
2021-10-18 22:51:36 -07:00
let src = "let a = 10; fn b() { 20 }";
let (symbols, _) = add_symbols(src);
2021-10-19 17:22:35 -07:00
fn make_fqsn(strs: &[&str]) -> FQSN {
FQSN::from_strs(strs)
}
2021-10-18 22:51:36 -07:00
symbols.fq_names.table.get(&make_fqsn(&["b"])).unwrap();
let src = "type Option<T> = Some(T) | None";
let (symbols, _) = add_symbols(src);
symbols.types.table.get(&make_fqsn(&["Option"])).unwrap();
symbols.types.table.get(&make_fqsn(&["Option", "Some"])).unwrap();
symbols.types.table.get(&make_fqsn(&["Option", "None"])).unwrap();
2019-10-16 19:51:43 -07:00
}
#[test]
fn no_function_definition_duplicates() {
2019-10-16 19:51:43 -07:00
let source = r#"
fn a() { 1 }
fn b() { 2 }
fn a() { 3 }
"#;
2021-10-18 22:51:36 -07:00
let (_, output) = add_symbols(source);
2021-10-19 19:19:21 -07:00
let errs = output.unwrap_err();
assert_matches!(&errs[..], [
SymbolError::DuplicateName { prev_name, ..}
] if prev_name == &FQSN::from_strs(&["a"])
);
2019-10-16 19:51:43 -07:00
}
#[test]
fn no_variable_definition_duplicates() {
2019-10-16 19:51:43 -07:00
let source = r#"
let x = 9
let a = 20
let q = 39
let a = 30
2021-10-19 19:19:21 -07:00
let x = 34
2019-10-16 19:51:43 -07:00
"#;
2021-10-18 22:51:36 -07:00
let (_, output) = add_symbols(source);
2021-10-19 19:19:21 -07:00
let errs = output.unwrap_err();
assert_matches!(&errs[..], [
SymbolError::DuplicateName { prev_name: pn1, ..},
SymbolError::DuplicateName { prev_name: pn2, ..}
] if pn1 == &FQSN::from_strs(&["a"]) && pn2 == &FQSN::from_strs(&["x"])
);
2019-10-16 19:51:43 -07:00
}
#[test]
fn no_variable_definition_duplicates_in_function() {
2019-10-16 19:51:43 -07:00
let source = r#"
fn a() {
let a = 20
let b = 40
a + b
}
fn q() {
let a = 29
2019-10-16 19:51:43 -07:00
let x = 30
let x = 33
}
"#;
2021-10-18 22:51:36 -07:00
let (_, output) = add_symbols(source);
2021-10-19 19:19:21 -07:00
let errs = output.unwrap_err();
assert_matches!(&errs[..], [
SymbolError::DuplicateName { prev_name: pn1, ..},
] if pn1 == &FQSN::from_strs(&["q", "x"])
);
2019-10-16 19:51:43 -07:00
}
#[test]
fn dont_falsely_detect_duplicates() {
let source = r#"
let a = 20;
fn some_func() {
let a = 40;
77
}
let q = 39;
"#;
2021-10-18 22:51:36 -07:00
let (symbols, _) = add_symbols(source);
assert!(symbols.fq_names.table.get(&make_fqsn(&["a"])).is_some());
assert!(symbols.fq_names.table.get(&make_fqsn(&["some_func", "a"])).is_some());
2019-10-16 19:51:43 -07:00
}
#[test]
fn enclosing_scopes() {
let source = r#"
fn outer_func(x) {
fn inner_func(arg) {
arg
}
x + inner_func(x)
}"#;
2021-10-18 22:51:36 -07:00
let (symbols, _) = add_symbols(source);
assert!(symbols.fq_names.table.get(&make_fqsn(&["outer_func"])).is_some());
assert!(symbols.fq_names.table.get(&make_fqsn(&["outer_func", "inner_func"])).is_some());
2019-10-16 19:51:43 -07:00
}
#[test]
fn enclosing_scopes_2() {
let source = r#"
fn outer_func(x) {
fn inner_func(arg) {
arg
}
fn second_inner_func() {
fn another_inner_func() {
}
}
inner_func(x)
}"#;
2021-10-18 22:51:36 -07:00
let (symbols, _) = add_symbols(source);
assert!(symbols.fq_names.table.get(&make_fqsn(&["outer_func"])).is_some());
assert!(symbols.fq_names.table.get(&make_fqsn(&["outer_func", "inner_func"])).is_some());
assert!(symbols.fq_names.table.get(&make_fqsn(&["outer_func", "second_inner_func"])).is_some());
assert!(symbols.fq_names.table.get(&make_fqsn(&["outer_func", "second_inner_func", "another_inner_func"])).is_some());
2019-10-16 19:51:43 -07:00
}
#[test]
fn enclosing_scopes_3() {
let source = r#"
fn outer_func(x) {
fn inner_func(arg) {
arg
}
fn second_inner_func() {
fn another_inner_func() {
}
fn another_inner_func() {
}
}
inner_func(x)
}"#;
2021-10-18 22:51:36 -07:00
let (_, output) = add_symbols(source);
let _err = output.unwrap_err();
2019-10-16 19:51:43 -07:00
}
2019-10-24 03:02:52 -07:00
#[test]
fn modules() {
let source = r#"
module stuff {
fn item() {
}
}
fn item()
"#;
2021-10-18 22:51:36 -07:00
let (symbols, _) = add_symbols(source);
symbols.fq_names.table.get(&make_fqsn(&["stuff"])).unwrap();
symbols.fq_names.table.get(&make_fqsn(&["item"])).unwrap();
symbols.fq_names.table.get(&make_fqsn(&["stuff", "item"])).unwrap();
2019-10-24 03:02:52 -07:00
}
#[test]
2019-10-24 02:13:07 -07:00
fn duplicate_modules() {
let source = r#"
2019-10-24 02:13:07 -07:00
module q {
fn foo() { 4 }
}
module a {
2019-10-24 02:13:07 -07:00
fn foo() { 334 }
}
module a {
2021-10-19 19:19:21 -07:00
fn sarat() { 39 }
2019-10-24 02:13:07 -07:00
fn foo() { 256.1 }
}
"#;
2021-10-18 22:51:36 -07:00
let (_, output) = add_symbols(source);
2021-10-19 19:19:21 -07:00
let errs = output.unwrap_err();
assert_matches!(&errs[..], [
SymbolError::DuplicateName { prev_name: pn1, ..},
] if pn1 == &FQSN::from_strs(&["a"])
);
}
2021-10-19 20:35:53 -07:00
#[test]
fn duplicate_struct_members() {
//TODO this is a parser error
/*
let source = r#"
type Tarak = Tarak {
loujet: i32,
mets: i32,
mets: i32,
}
"#;
*/
let source = r#" type Tarak = Tarak { loujet: i32, mets: i32, mets: i32 } "#;
let (_, output) = add_symbols(source);
let errs = output.unwrap_err();
assert_matches!(&errs[..], [
SymbolError::DuplicateRecord {
type_name, member, ..},
] if type_name == &FQSN::from_strs(&["Tarak", "Tarak"]) && member == "mets"
);
}