#![cfg(test)] use super::*; use crate::util::quick_ast; fn add_symbols(src: &str) -> (SymbolTable, Result<(), String>) { let ast = quick_ast(src); let mut symbol_table = SymbolTable::new(); let result = symbol_table.process_ast(&ast); (symbol_table, result) } fn make_fqsn(strs: &[&str]) -> FQSN { FQSN::from_strs(strs) } #[test] fn basic_symbol_table() { let src = "let a = 10; fn b() { 20 }"; let (symbols, _) = add_symbols(src); fn make_fqsn(strs: &[&str]) -> FQSN { FQSN::from_strs(strs) } symbols.fq_names.table.get(&make_fqsn(&["b"])).unwrap(); let src = "type Option = 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(); } #[test] fn no_function_definition_duplicates() { let source = r#" fn a() { 1 } fn b() { 2 } fn a() { 3 } "#; let (_, output) = add_symbols(source); //TODO test for right type of error output.unwrap_err(); } #[test] fn no_variable_definition_duplicates() { let source = r#" let x = 9 let a = 20 let q = 39 let a = 30 "#; let (_, output) = add_symbols(source); let _output = output.unwrap_err(); /* assert!(output.contains("Duplicate variable definition: a")); assert!(output.contains("already defined at 2")); */ } #[test] fn no_variable_definition_duplicates_in_function() { let source = r#" fn a() { let a = 20 let b = 40 a + b } fn q() { let a = 29 let x = 30 let x = 33 } "#; let (_, output) = add_symbols(source); let _err = output.unwrap_err(); //assert!(output.unwrap_err().contains("Duplicate variable definition: x")) } #[test] fn dont_falsely_detect_duplicates() { let source = r#" let a = 20; fn some_func() { let a = 40; 77 } let q = 39; "#; 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()); } #[test] fn enclosing_scopes() { let source = r#" fn outer_func(x) { fn inner_func(arg) { arg } x + inner_func(x) }"#; 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()); } #[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) }"#; 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()); } #[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) }"#; let (_, output) = add_symbols(source); let _err = output.unwrap_err(); } #[test] fn modules() { let source = r#" module stuff { fn item() { } } fn item() "#; 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(); } #[test] fn duplicate_modules() { let source = r#" module q { fn foo() { 4 } } module a { fn foo() { 334 } } module a { fn foo() { 256.1 } } "#; let (_, output) = add_symbols(source); let _output = output.unwrap_err(); }