diff --git a/src/protocol/parser/symbol_table2.rs b/src/protocol/parser/symbol_table2.rs new file mode 100644 index 0000000000000000000000000000000000000000..fecb9d079df26a592365855742a6eecb355f8620 --- /dev/null +++ b/src/protocol/parser/symbol_table2.rs @@ -0,0 +1,107 @@ +use std::collections::HashMap; +use std::collections::hash_map::Entry; + +use crate::protocol::input_source2::*; +use crate::protocol::ast::*; +use crate::collections::*; + +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum SymbolScope { + Module(RootId), + Definition(DefinitionId), +} + +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum SymbolClass { + Module, + Struct, + Enum, + Union, + Function, + Component +} + +struct ScopedSymbols { + scope: SymbolScope, + parent_scope: Option, + child_scopes: Vec, + start: usize, + end: usize, +} + +pub struct Symbol { + // Definition location + pub defined_in_module: RootId, + pub defined_in_scope: SymbolScope, + pub definition_span: InputSpan, // full span of definition + // Introduction location (if imported instead of defined) + + // Symbol properties + pub class: SymbolClass, + pub name: StringRef, + pub definition: Option, +} + +impl Symbol { + pub(crate) fn new(root_id: RootId, scope: SymbolScope, span: InputSpan, class: SymbolClass, name: StringRef) -> Self { + Self{ + defined_in_module: root_id, + defined_in_scope: scope, + definition_span: span, + class, + name, + definition: None, + } + } +} + +pub struct SymbolTable { + module_lookup: HashMap, + scope_lookup: HashMap, + symbols: Vec, +} + +impl SymbolTable { + /// Inserts a new module by its name. Upon module naming conflict the + /// previously associated `RootId` will be returned. + pub(crate) fn insert_module(&mut self, module_name: StringRef, root_id: RootId) -> Result<(), RootId> { + match self.module_lookup.entry(module_name) { + Entry::Occupied(v) => { + Err(*v.get()) + }, + Entry::Vacant(v) => { + v.insert(root_id); + Ok(()) + } + } + } + + /// Inserts a new scope with defined symbols. The `parent_scope` must + /// already be added to the symbol table. The symbols are expected to come + /// from a temporary buffer and are copied inside the symbol table. Will + /// return an error if there is a naming conflict. + pub(crate) fn insert_scoped_symbols( + &mut self, parent_scope: Option, within_scope: SymbolScope, symbols: &[Symbol] + ) -> Result<(), ParseError> { + // Add scoped symbols + let old_num_symbols = self.symbols.len(); + + let new_scope = ScopedSymbols { + scope: within_scope, + parent_scope, + child_scopes: Vec::new(), + start: old_num_symbols, + end: old_num_symbols + symbols.len(), + }; + + self.symbols.extend(symbols); + self.scope_lookup.insert(within_scope, new_scope); + + if let Some(parent_scope) = parent_scope.as_ref() { + let parent = self.scope_lookup.get_mut(parent_scope).unwrap(); + parent.child_scopes.push(within_scope); + } + + Ok(()) + } +} \ No newline at end of file