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

190 lines
4.0 KiB
Rust
Raw Normal View History

2019-10-16 19:51:43 -07:00
#![cfg(test)]
use super::*;
use crate::util::quick_ast;
2019-10-23 14:02:27 -07:00
fn add_symbols_from_source(src: &str) -> (SymbolTable, Result<(), String>) {
let ast = quick_ast(src);
let mut symbol_table = SymbolTable::new();
2019-10-23 14:02:27 -07:00
let result = symbol_table.add_top_level_symbols(&ast);
(symbol_table, result)
}
2019-10-16 19:51:43 -07:00
macro_rules! values_in_table {
2019-10-24 03:02:52 -07:00
($source:expr, $single_value:expr) => {
values_in_table!($source => $single_value);
2019-10-16 22:46:58 -07:00
};
2019-10-24 03:02:52 -07:00
($source:expr => $( $value:expr ),* ) => {
2019-10-16 19:51:43 -07:00
{
2019-10-23 14:02:27 -07:00
let (symbol_table, _) = add_symbols_from_source($source);
2019-10-16 22:46:58 -07:00
$(
match symbol_table.lookup_by_fqsn($value) {
Some(_spec) => (),
None => panic!(),
};
)*
2019-10-16 19:51:43 -07:00
}
2019-10-16 22:46:58 -07:00
};
2019-10-16 19:51:43 -07:00
}
#[test]
fn basic_symbol_table() {
2019-10-16 20:22:40 -07:00
values_in_table! { "let a = 10; fn b() { 20 }", &fqsn!("b"; tr) };
2019-10-24 03:02:52 -07:00
values_in_table! { "type Option<T> = Some(T) | None" =>
2019-10-16 22:46:58 -07:00
&fqsn!("Option"; tr),
&fqsn!("Option"; ty, "Some"; tr),
&fqsn!("Option"; ty, "None"; tr) };
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 }
"#;
2019-10-23 14:02:27 -07:00
let (_, output) = add_symbols_from_source(source);
assert!(output.unwrap_err().contains("Duplicate function definition: 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
2019-10-16 19:51:43 -07:00
"#;
2019-10-23 14:02:27 -07:00
let (_, output) = add_symbols_from_source(source);
let output = output.unwrap_err();
assert!(output.contains("Duplicate variable definition: a"));
assert!(output.contains("already defined at 2"));
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
}
"#;
2019-10-23 14:02:27 -07:00
let (_, output) = add_symbols_from_source(source);
assert!(output.unwrap_err().contains("Duplicate variable definition: 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;
"#;
2019-10-23 14:02:27 -07:00
let (symbol_table, _) = add_symbols_from_source(source);
2019-10-16 19:51:43 -07:00
assert!(symbol_table.lookup_by_fqsn(&fqsn!["a"; tr]).is_some());
assert!(symbol_table.lookup_by_fqsn(&fqsn!["some_func"; fn, "a";tr]).is_some());
}
#[test]
fn enclosing_scopes() {
let source = r#"
fn outer_func(x) {
fn inner_func(arg) {
arg
}
x + inner_func(x)
}"#;
2019-10-23 14:02:27 -07:00
let (symbol_table, _) = add_symbols_from_source(source);
2019-10-16 19:51:43 -07:00
assert!(symbol_table.lookup_by_fqsn(&fqsn!("outer_func"; tr)).is_some());
assert!(symbol_table.lookup_by_fqsn(&fqsn!("outer_func"; fn, "inner_func"; tr)).is_some());
}
#[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)
}"#;
2019-10-23 14:02:27 -07:00
let (symbol_table, _) = add_symbols_from_source(source);
2019-10-16 19:51:43 -07:00
assert!(symbol_table.lookup_by_fqsn(&fqsn!("outer_func"; tr)).is_some());
assert!(symbol_table.lookup_by_fqsn(&fqsn!("outer_func"; fn, "inner_func"; tr)).is_some());
assert!(symbol_table.lookup_by_fqsn(&fqsn!("outer_func"; fn, "second_inner_func"; tr)).is_some());
assert!(symbol_table.lookup_by_fqsn(&fqsn!("outer_func"; fn, "second_inner_func"; fn, "another_inner_func"; tr)).is_some());
}
#[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)
}"#;
2019-10-23 14:02:27 -07:00
let (_, output) = add_symbols_from_source(source);
assert!(output.unwrap_err().contains("Duplicate"))
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()
"#;
values_in_table! { source =>
&fqsn!("item"; tr),
&fqsn!("stuff"; tr, "item"; tr)
};
}
#[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 {
2019-10-24 02:13:07 -07:00
fn foo() { 256.1 }
}
"#;
let (_, output) = add_symbols_from_source(source);
2019-10-24 02:13:07 -07:00
let output = output.unwrap_err();
assert!(output.contains("Duplicate module"));
assert!(output.contains("already defined at 5"));
}