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

View File

@ -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<FQSN, Location>
#[derive(Debug)]
struct NameSpec<K> {
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<K> {
table: HashMap<FQSN, NameSpec<K>>
}
impl<K> NameTable<K> {
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<K>) -> 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<FullyQualifiedSymbolName, Symbol>,
id_to_fqsn: HashMap<ItemId, FullyQualifiedSymbolName>,
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<NameKind>,
types: NameTable<TypeKind>,
}
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);
}
};