Symbol table tests to separate file
This commit is contained in:
parent
92ad4767c8
commit
97b59d7e70
@ -8,6 +8,32 @@ use crate::ast;
|
|||||||
use crate::ast::{ItemId, TypeBody, TypeSingletonName, Signature, Statement, StatementKind};
|
use crate::ast::{ItemId, TypeBody, TypeSingletonName, Signature, Statement, StatementKind};
|
||||||
use crate::typechecking::TypeName;
|
use crate::typechecking::TypeName;
|
||||||
|
|
||||||
|
#[allow(unused_macros)]
|
||||||
|
macro_rules! sym_path_kind {
|
||||||
|
(fn) => { ScopeSegmentKind::Function };
|
||||||
|
(ty) => { ScopeSegmentKind::Type };
|
||||||
|
(tr) => { ScopeSegmentKind::Terminal };
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused_macros)]
|
||||||
|
macro_rules! fqsn {
|
||||||
|
( $( $name:expr ; $kind:tt),* ) => {
|
||||||
|
{
|
||||||
|
let mut vec = vec![];
|
||||||
|
$(
|
||||||
|
vec.push(ScopeSegment::new(
|
||||||
|
Rc::new($name.to_string()),
|
||||||
|
sym_path_kind!($kind),
|
||||||
|
));
|
||||||
|
)*
|
||||||
|
FullyQualifiedSymbolName(vec)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mod test;
|
||||||
|
|
||||||
type LineNumber = u32;
|
type LineNumber = u32;
|
||||||
type SymbolTrackTable = HashMap<Rc<String>, LineNumber>;
|
type SymbolTrackTable = HashMap<Rc<String>, LineNumber>;
|
||||||
|
|
||||||
@ -57,29 +83,6 @@ pub enum ScopeSegmentKind {
|
|||||||
//Module
|
//Module
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_macros)]
|
|
||||||
macro_rules! fqsn {
|
|
||||||
( $( $name:expr ; $kind:tt),* ) => {
|
|
||||||
{
|
|
||||||
let mut vec = vec![];
|
|
||||||
$(
|
|
||||||
vec.push(ScopeSegment::new(
|
|
||||||
Rc::new($name.to_string()),
|
|
||||||
sym_path_kind!($kind),
|
|
||||||
));
|
|
||||||
)*
|
|
||||||
FullyQualifiedSymbolName(vec)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused_macros)]
|
|
||||||
macro_rules! sym_path_kind {
|
|
||||||
(fn) => { ScopeSegmentKind::Function };
|
|
||||||
(ty) => { ScopeSegmentKind::Type };
|
|
||||||
(tr) => { ScopeSegmentKind::Terminal };
|
|
||||||
}
|
|
||||||
|
|
||||||
//cf. p. 150 or so of Language Implementation Patterns
|
//cf. p. 150 or so of Language Implementation Patterns
|
||||||
pub struct SymbolTable {
|
pub struct SymbolTable {
|
||||||
symbol_path_to_symbol: HashMap<FullyQualifiedSymbolName, Symbol>,
|
symbol_path_to_symbol: HashMap<FullyQualifiedSymbolName, Symbol>,
|
||||||
@ -313,156 +316,3 @@ impl LocalTypeContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod symbol_table_tests {
|
|
||||||
use super::*;
|
|
||||||
use crate::util::quick_ast;
|
|
||||||
|
|
||||||
macro_rules! values_in_table {
|
|
||||||
//TODO multiple values
|
|
||||||
($source:expr, $single_value:expr) => {
|
|
||||||
{
|
|
||||||
let mut symbol_table = SymbolTable::new();
|
|
||||||
let ast = quick_ast($source);
|
|
||||||
symbol_table.add_top_level_symbols(&ast).unwrap();
|
|
||||||
match symbol_table.lookup_by_fqsn($single_value) {
|
|
||||||
Some(_spec) => (),
|
|
||||||
None => panic!(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn basic_symbol_table() {
|
|
||||||
values_in_table! { "let a = 10; fn b() { 20 }", &fqsn!("b"; tr) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn no_duplicates() {
|
|
||||||
let source = r#"
|
|
||||||
fn a() { 1 }
|
|
||||||
fn b() { 2 }
|
|
||||||
fn a() { 3 }
|
|
||||||
"#;
|
|
||||||
let mut symbol_table = SymbolTable::new();
|
|
||||||
let ast = quick_ast(source);
|
|
||||||
let output = symbol_table.add_top_level_symbols(&ast).unwrap_err();
|
|
||||||
assert!(output.contains("Duplicate"))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn no_duplicates_2() {
|
|
||||||
let source = r#"
|
|
||||||
let a = 20;
|
|
||||||
let q = 39;
|
|
||||||
let a = 30;
|
|
||||||
"#;
|
|
||||||
let mut symbol_table = SymbolTable::new();
|
|
||||||
let ast = quick_ast(source);
|
|
||||||
let output = symbol_table.add_top_level_symbols(&ast).unwrap_err();
|
|
||||||
assert!(output.contains("Duplicate"))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn no_duplicates_3() {
|
|
||||||
let source = r#"
|
|
||||||
fn a() {
|
|
||||||
let a = 20
|
|
||||||
let b = 40
|
|
||||||
a + b
|
|
||||||
}
|
|
||||||
|
|
||||||
fn q() {
|
|
||||||
let x = 30
|
|
||||||
let x = 33
|
|
||||||
}
|
|
||||||
"#;
|
|
||||||
let mut symbol_table = SymbolTable::new();
|
|
||||||
let ast = quick_ast(source);
|
|
||||||
let output = symbol_table.add_top_level_symbols(&ast).unwrap_err();
|
|
||||||
assert!(output.contains("Duplicate"))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn dont_falsely_detect_duplicates() {
|
|
||||||
let source = r#"
|
|
||||||
let a = 20;
|
|
||||||
fn some_func() {
|
|
||||||
let a = 40;
|
|
||||||
77
|
|
||||||
}
|
|
||||||
let q = 39;
|
|
||||||
"#;
|
|
||||||
let mut symbol_table = SymbolTable::new();
|
|
||||||
let ast = quick_ast(source);
|
|
||||||
symbol_table.add_top_level_symbols(&ast).unwrap();
|
|
||||||
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)
|
|
||||||
}"#;
|
|
||||||
let mut symbol_table = SymbolTable::new();
|
|
||||||
let ast = quick_ast(source);
|
|
||||||
symbol_table.add_top_level_symbols(&ast).unwrap();
|
|
||||||
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)
|
|
||||||
}"#;
|
|
||||||
let mut symbol_table = SymbolTable::new();
|
|
||||||
let ast = quick_ast(source);
|
|
||||||
symbol_table.add_top_level_symbols(&ast).unwrap();
|
|
||||||
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)
|
|
||||||
}"#;
|
|
||||||
let mut symbol_table = SymbolTable::new();
|
|
||||||
let ast = quick_ast(source);
|
|
||||||
let output = symbol_table.add_top_level_symbols(&ast).unwrap_err();
|
|
||||||
assert!(output.contains("Duplicate"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
151
schala-lang/language/src/symbol_table/test.rs
Normal file
151
schala-lang/language/src/symbol_table/test.rs
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
#![cfg(test)]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
use super::*;
|
||||||
|
use crate::util::quick_ast;
|
||||||
|
|
||||||
|
macro_rules! values_in_table {
|
||||||
|
//TODO multiple values
|
||||||
|
($source:expr, $single_value:expr) => {
|
||||||
|
{
|
||||||
|
let mut symbol_table = SymbolTable::new();
|
||||||
|
let ast = quick_ast($source);
|
||||||
|
symbol_table.add_top_level_symbols(&ast).unwrap();
|
||||||
|
match symbol_table.lookup_by_fqsn($single_value) {
|
||||||
|
Some(_spec) => (),
|
||||||
|
None => panic!(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn basic_symbol_table() {
|
||||||
|
values_in_table! { "let a = 10; fn b() { 20 }", &fqsn!("b"; tr) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_duplicates() {
|
||||||
|
let source = r#"
|
||||||
|
fn a() { 1 }
|
||||||
|
fn b() { 2 }
|
||||||
|
fn a() { 3 }
|
||||||
|
"#;
|
||||||
|
let mut symbol_table = SymbolTable::new();
|
||||||
|
let ast = quick_ast(source);
|
||||||
|
let output = symbol_table.add_top_level_symbols(&ast).unwrap_err();
|
||||||
|
assert!(output.contains("Duplicate"))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_duplicates_2() {
|
||||||
|
let source = r#"
|
||||||
|
let a = 20;
|
||||||
|
let q = 39;
|
||||||
|
let a = 30;
|
||||||
|
"#;
|
||||||
|
let mut symbol_table = SymbolTable::new();
|
||||||
|
let ast = quick_ast(source);
|
||||||
|
let output = symbol_table.add_top_level_symbols(&ast).unwrap_err();
|
||||||
|
assert!(output.contains("Duplicate"))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_duplicates_3() {
|
||||||
|
let source = r#"
|
||||||
|
fn a() {
|
||||||
|
let a = 20
|
||||||
|
let b = 40
|
||||||
|
a + b
|
||||||
|
}
|
||||||
|
|
||||||
|
fn q() {
|
||||||
|
let x = 30
|
||||||
|
let x = 33
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
let mut symbol_table = SymbolTable::new();
|
||||||
|
let ast = quick_ast(source);
|
||||||
|
let output = symbol_table.add_top_level_symbols(&ast).unwrap_err();
|
||||||
|
assert!(output.contains("Duplicate"))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn dont_falsely_detect_duplicates() {
|
||||||
|
let source = r#"
|
||||||
|
let a = 20;
|
||||||
|
fn some_func() {
|
||||||
|
let a = 40;
|
||||||
|
77
|
||||||
|
}
|
||||||
|
let q = 39;
|
||||||
|
"#;
|
||||||
|
let mut symbol_table = SymbolTable::new();
|
||||||
|
let ast = quick_ast(source);
|
||||||
|
symbol_table.add_top_level_symbols(&ast).unwrap();
|
||||||
|
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)
|
||||||
|
}"#;
|
||||||
|
let mut symbol_table = SymbolTable::new();
|
||||||
|
let ast = quick_ast(source);
|
||||||
|
symbol_table.add_top_level_symbols(&ast).unwrap();
|
||||||
|
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)
|
||||||
|
}"#;
|
||||||
|
let mut symbol_table = SymbolTable::new();
|
||||||
|
let ast = quick_ast(source);
|
||||||
|
symbol_table.add_top_level_symbols(&ast).unwrap();
|
||||||
|
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)
|
||||||
|
}"#;
|
||||||
|
let mut symbol_table = SymbolTable::new();
|
||||||
|
let ast = quick_ast(source);
|
||||||
|
let output = symbol_table.add_top_level_symbols(&ast).unwrap_err();
|
||||||
|
assert!(output.contains("Duplicate"))
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user