diff --git a/schala-lang/language/src/symbol_table/mod.rs b/schala-lang/language/src/symbol_table/mod.rs index 75a3b56..7c5f25a 100644 --- a/schala-lang/language/src/symbol_table/mod.rs +++ b/schala-lang/language/src/symbol_table/mod.rs @@ -68,25 +68,39 @@ struct DuplicateName { location: Location } -//TODO should map to a Spec* type that has Location and Kind of namespace entry -//tht way I don't need as many tables -/// Keeps track of what names were used in a given namespace. -struct NameTable { - table: HashMap +#[derive(Debug)] +struct NameSpec { + location: Location, + kind: K } -impl NameTable { +#[derive(Debug)] +enum NameKind { + Module, + Function, + Binding, +} + +#[derive(Debug)] +struct TypeKind; + +/// Keeps track of what names were used in a given namespace. +struct NameTable { + table: HashMap> +} + +impl NameTable { fn new() -> Self { Self { table: HashMap::new() } } - fn register(&mut self, name: FQSN, location: Location) -> Result<(), DuplicateName> { + fn register(&mut self, name: FQSN, spec: NameSpec) -> Result<(), DuplicateName> { match self.table.entry(name.clone()) { Entry::Occupied(o) => { - Err(DuplicateName { prev_name: name, location: *o.get() }) + Err(DuplicateName { prev_name: name, location: o.get().location }) }, Entry::Vacant(v) => { - v.insert(location); + v.insert(spec); Ok(()) } } @@ -162,9 +176,8 @@ pub struct SymbolTable { symbol_path_to_symbol: HashMap, id_to_fqsn: HashMap, symbol_trie: SymbolTrie, - functions: NameTable, //TODO maybe bindings and functions should be the same table? - types: NameTable, - bindings: NameTable, //TODO NameTable should be a trie to facilitate quick lookups + fq_names: NameTable, + types: NameTable, } impl SymbolTable { @@ -174,9 +187,8 @@ impl SymbolTable { symbol_path_to_symbol: HashMap::new(), id_to_fqsn: HashMap::new(), symbol_trie: SymbolTrie::new(), - functions: NameTable::new(), + fq_names: NameTable::new(), types: NameTable::new(), - bindings: NameTable::new(), } } @@ -263,7 +275,6 @@ impl SymbolTable { /// checks for dupicate definitions (and returns errors if discovered), and sets /// up name tables that will be used by further parts of the compiler pub fn process_ast(&mut self, ast: &ast::AST) -> Result<(), String> { - let mut scope_stack = vec![Scope::Top]; self.add_from_scope(ast.statements.as_ref(), &mut scope_stack) .map_err(|err| format!("{:?}", err))?; @@ -279,15 +290,15 @@ impl SymbolTable { StatementKind::Declaration(Declaration::FuncSig(signature)) => { let fn_name: String = signature.name.as_str().to_owned(); let fq_function = FQSN::from_scope_stack(scope_stack.as_ref(), fn_name); - self.functions.register(fq_function.clone(), location)?; - self.types.register(fq_function, location)?; + self.fq_names.register(fq_function.clone(), NameSpec { location, kind: NameKind::Function })?; + self.types.register(fq_function, NameSpec { location, kind: TypeKind } )?; } StatementKind::Declaration(Declaration::FuncDecl(signature, body)) => { let fn_name: String = signature.name.as_str().to_owned(); let new_scope = Scope::Name(fn_name.clone()); let fq_function = FQSN::from_scope_stack(scope_stack.as_ref(), fn_name); - self.functions.register(fq_function.clone(), location)?; - self.types.register(fq_function, location)?; + self.fq_names.register(fq_function.clone(), NameSpec { location, kind: NameKind::Function })?; + self.types.register(fq_function, NameSpec { location, kind: TypeKind } )?; scope_stack.push(new_scope); let output = self.add_from_scope(body.as_ref(), scope_stack); scope_stack.pop(); @@ -295,20 +306,20 @@ impl SymbolTable { }, StatementKind::Declaration(Declaration::TypeDecl { name, body, mutable }) => { let fq_type = FQSN::from_scope_stack(scope_stack.as_ref(), name.name.as_ref().to_owned()); - self.types.register(fq_type, location)?; + self.types.register(fq_type, NameSpec { location, kind: TypeKind } )?; if let Err(errors) = self.add_type_members(name, body, mutable, location, scope_stack) { return Err(errors[0].clone()); } }, StatementKind::Declaration(Declaration::Binding { name, .. }) => { let fq_binding = FQSN::from_scope_stack(scope_stack.as_ref(), name.as_str().to_owned()); - self.bindings.register(fq_binding, location)?; + self.fq_names.register(fq_binding, NameSpec { location, kind: NameKind::Binding })?; } StatementKind::Module(ModuleSpecifier { name, contents }) => { let mod_name = name.as_str().to_owned(); let fq_module = FQSN::from_scope_stack(scope_stack.as_ref(), mod_name.clone()); let new_scope = Scope::Name(mod_name); - self.bindings.register(fq_module, location)?; + self.fq_names.register(fq_module, NameSpec { location, kind: NameKind::Module })?; scope_stack.push(new_scope); let output = self.add_from_scope(contents.as_ref(), scope_stack); scope_stack.pop(); @@ -324,7 +335,8 @@ impl SymbolTable { let mut errors = vec![]; let mut register = |fqsn: FQSN| { - if let Err(err) = self.types.register(fqsn, location) { + let spec = NameSpec { location, kind: TypeKind }; + if let Err(err) = self.types.register(fqsn, spec) { errors.push(err); } };