Reduce number of tables in symbol table

This commit is contained in:
Greg Shuflin 2021-10-18 22:24:04 -07:00
parent db6c9bb162
commit 9d89440a6d
1 changed files with 35 additions and 23 deletions

View File

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