WIP name analysis, more symbol types, add symbol tree abstraction.

This commit is contained in:
Jesse Brault 2025-10-21 12:41:14 -05:00
parent b5c0e44eeb
commit bdbc2543b8
11 changed files with 255 additions and 136 deletions

View File

@ -8,6 +8,7 @@ use deimos::parser::{DeimosParser, Rule};
use deimos::std_core::add_std_core_symbols; use deimos::std_core::add_std_core_symbols;
use pest::Parser; use pest::Parser;
use std::path::PathBuf; use std::path::PathBuf;
use deimos::name_analysis::symbol_tree::SymbolTree;
pub fn name_analysis(paths: &Vec<PathBuf>) -> Result<(), Box<dyn std::error::Error>> { pub fn name_analysis(paths: &Vec<PathBuf>) -> Result<(), Box<dyn std::error::Error>> {
let mut compilation_units = vec![]; let mut compilation_units = vec![];
@ -29,9 +30,10 @@ pub fn name_analysis(paths: &Vec<PathBuf>) -> Result<(), Box<dyn std::error::Err
} }
let mut symbol_table = SymbolTable::new(); let mut symbol_table = SymbolTable::new();
let mut symbol_tree = SymbolTree::new();
add_std_core_symbols(&mut symbol_table).expect("Failed to add std::core symbols."); add_std_core_symbols(&mut symbol_table).expect("Failed to add std::core symbols.");
let diagnostics = analyze_names(&mut compilation_units, &files, &mut symbol_table); let diagnostics = analyze_names(&mut compilation_units, &files, &mut symbol_table, &mut symbol_tree);
if diagnostics.is_empty() { if diagnostics.is_empty() {
println!("Name analysis complete."); println!("Name analysis complete.");
println!("{}", symbol_table); println!("{}", symbol_table);

View File

@ -1,12 +1,13 @@
use std::cell::RefCell;
use crate::ast::node::{CompilationUnit, Identifier, UseStatement, UseStatementSuffix}; use crate::ast::node::{CompilationUnit, Identifier, UseStatement, UseStatementSuffix};
use crate::diagnostic::DmDiagnostic; use crate::diagnostic::DmDiagnostic;
use crate::name_analysis::fqn_context::FqnContext; use crate::name_analysis::fqn_context::FqnContext;
use crate::name_analysis::symbol::source_definition::SourceDefinition; use crate::name_analysis::symbol::source_definition::SourceDefinition;
use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol, UseSymbol}; use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol, UseSymbol};
use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable}; use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable};
use crate::name_analysis::symbol_tree::SymbolTree;
use crate::name_analysis::util::use_statement_base_fqn; use crate::name_analysis::util::use_statement_base_fqn;
use codespan_reporting::diagnostic::{Diagnostic, Label}; use codespan_reporting::diagnostic::{Diagnostic, Label};
use std::cell::RefCell;
use std::range::Range; use std::range::Range;
use std::rc::Rc; use std::rc::Rc;
@ -75,6 +76,7 @@ pub fn nap1_compilation_unit(
file_name: &str, file_name: &str,
compilation_unit: &mut CompilationUnit, compilation_unit: &mut CompilationUnit,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
symbol_tree: &mut SymbolTree,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
let mut fqn_context = FqnContext::new(); let mut fqn_context = FqnContext::new();
@ -103,7 +105,7 @@ fn handle_concrete_use_statement(
let to_insert = ConcreteUseSymbol::new( let to_insert = ConcreteUseSymbol::new(
&base_fqn, &base_fqn,
identifier.name(), identifier.name(),
Some(SourceDefinition::from_identifier(identifier)) Some(SourceDefinition::from_identifier(identifier)),
); );
match symbol_table.insert_concrete_use_symbol(to_insert) { match symbol_table.insert_concrete_use_symbol(to_insert) {
Ok(inserted) => { Ok(inserted) => {
@ -116,7 +118,7 @@ fn handle_concrete_use_statement(
identifier.file_id(), identifier.file_id(),
identifier.range(), identifier.range(),
"Use Symbol", "Use Symbol",
diagnostics diagnostics,
); );
} }
} }
@ -142,7 +144,14 @@ fn nap1_use_statement(
identifier, identifier,
"Use Statement", "Use Statement",
diagnostics diagnostics
) );
use_statement.set_use_symbol(Rc::new(RefCell::new(UseSymbol::Concrete(Rc::new(
RefCell::new(ConcreteUseSymbol::new(
&base_fqn,
identifier.name(),
Some(SourceDefinition::from_use_statement(use_statement)),
)),
)))));
} }
UseStatementSuffix::Star => { UseStatementSuffix::Star => {
insert_symbol!( insert_symbol!(

View File

@ -28,6 +28,7 @@ use crate::name_analysis::second_pass::nap2_compilation_unit;
use crate::name_analysis::symbol_table::SymbolTable; use crate::name_analysis::symbol_table::SymbolTable;
use codespan_reporting::files::Files; use codespan_reporting::files::Files;
use std::hash::Hash; use std::hash::Hash;
use crate::name_analysis::symbol_tree::SymbolTree;
pub(self) mod fqn_context; pub(self) mod fqn_context;
// mod resolve; // mod resolve;
@ -36,24 +37,26 @@ mod scope_table;
mod second_pass; mod second_pass;
pub mod symbol; pub mod symbol;
pub mod symbol_table; pub mod symbol_table;
pub mod symbol_tree;
mod util; mod util;
pub fn analyze_names<'a, F: Files<'a, FileId = usize, Name = String>>( pub fn analyze_names<'a, F: Files<'a, FileId = usize, Name = String>>(
compilation_units: &mut Vec<Box<CompilationUnit>>, compilation_units: &mut Vec<Box<CompilationUnit>>,
files: &'a F, files: &'a F,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
symbol_tree: &mut SymbolTree,
) -> Vec<DmDiagnostic> { ) -> Vec<DmDiagnostic> {
let mut diagnostics = vec![]; let mut diagnostics = vec![];
// gather symbols // gather symbols
for compilation_unit in compilation_units.iter_mut() { for compilation_unit in compilation_units.iter_mut() {
let file_name = files.name(compilation_unit.file_id()).unwrap(); let file_name = files.name(compilation_unit.file_id()).unwrap();
nap1_compilation_unit(&file_name, compilation_unit, symbol_table, &mut diagnostics); nap1_compilation_unit(&file_name, compilation_unit, symbol_table, symbol_tree, &mut diagnostics);
} }
// resolve symbols // resolve symbols
for compilation_unit in compilation_units { for compilation_unit in compilation_units {
nap2_compilation_unit(compilation_unit, symbol_table, &mut diagnostics); nap2_compilation_unit(compilation_unit, symbol_table, symbol_tree, &mut diagnostics);
} }
diagnostics.into() diagnostics.into()

View File

@ -1,8 +1,9 @@
use crate::ast::node::{CompilationUnit, Identifier, UseStatement, UseStatementSuffix}; use crate::ast::node::{CompilationUnit, Identifier, UseStatement, UseStatementSuffix};
use crate::diagnostic::DmDiagnostic; use crate::diagnostic::DmDiagnostic;
use crate::name_analysis::symbol::usable_symbol::ConcreteUsableSymbol;
use crate::name_analysis::symbol::use_symbol::UseSymbol; use crate::name_analysis::symbol::use_symbol::UseSymbol;
use crate::name_analysis::symbol_table::{SymbolLookupError, SymbolTable}; use crate::name_analysis::symbol_table::{SymbolLookupError, SymbolTable};
use crate::name_analysis::util::use_statement_base_fqn; use crate::name_analysis::symbol_tree::SymbolTree;
use codespan_reporting::diagnostic::{Diagnostic, Label}; use codespan_reporting::diagnostic::{Diagnostic, Label};
use std::range::Range; use std::range::Range;
@ -32,66 +33,84 @@ fn handle_lookup_error(
pub fn nap2_compilation_unit( pub fn nap2_compilation_unit(
compilation_unit: &mut CompilationUnit, compilation_unit: &mut CompilationUnit,
symbol_table: &SymbolTable, symbol_table: &SymbolTable,
symbol_tree: &SymbolTree,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
// TODO: check namespace for proper file name // TODO: check namespace for proper file name
for use_statement in compilation_unit.use_statements_mut() { for use_statement in compilation_unit.use_statements_mut() {
nap2_use_statement(use_statement, symbol_table, diagnostics); nap2_use_statement(use_statement, symbol_tree, diagnostics);
} }
// TODO: declarations // TODO: declarations
} }
fn nap2_use_statement( fn handle_concrete_use_symbol(
use_statement: &mut UseStatement, use_statement: &UseStatement,
symbol_table: &SymbolTable, identifier: &Identifier,
symbol_tree: &SymbolTree,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
let base_fqn = use_statement_base_fqn(use_statement); let mut fqn_parts: Vec<&str> = {
let mut base: Vec<&str> = use_statement
let mut handle_concrete_use_symbol = |identifier: &Identifier| { .prefixes()
let fqn = format!("{}::{}", base_fqn, identifier.name()); .map(|prefix| prefix.identifier().name())
match symbol_table.resolve_concrete_usable_by_fqn(&fqn) { .collect();
Ok(resolved_symbol) => match *use_statement.use_symbol().unwrap().borrow() { base.push(identifier.name());
UseSymbol::Concrete(ref concrete_use_symbol) => { base
concrete_use_symbol
.borrow_mut()
.set_resolved_symbol(resolved_symbol);
}
_ => panic!("Unexpected symbol type"),
},
Err(lookup_error) => {
handle_lookup_error(
lookup_error,
&fqn,
use_statement.file_id(),
use_statement.range(),
"Usable Symbol",
diagnostics,
);
}
}
}; };
let found = symbol_tree
.find_interface(&fqn_parts)
.map(|interface_symbol| ConcreteUsableSymbol::Interface(interface_symbol))
.or_else(|| {
symbol_tree
.find_class(&fqn_parts)
.map(|class_symbol| ConcreteUsableSymbol::Class(class_symbol))
})
.or_else(|| {
symbol_tree
.find_function(&fqn_parts)
.map(|function_symbol| ConcreteUsableSymbol::Function(function_symbol))
});
if let Some(concrete_usable_symbol) = found {
let use_symbol_ref = use_statement.use_symbol().unwrap().borrow();
match *use_symbol_ref {
UseSymbol::Concrete(ref concrete_use_symbol) => {
concrete_use_symbol
.borrow_mut()
.set_resolved_symbol(concrete_usable_symbol);
}
_ => panic!(
"Unexpected UseSymbol type (expected Concrete, found: {:?}",
*use_symbol_ref
),
}
} else {
handle_lookup_error(
SymbolLookupError::NoDefinition,
&fqn_parts.join("::"),
use_statement.file_id(),
use_statement.range(),
"Usable Symbol",
diagnostics,
);
}
}
fn nap2_use_statement(
use_statement: &mut UseStatement,
symbol_tree: &SymbolTree,
diagnostics: &mut Vec<DmDiagnostic>,
) {
match use_statement.suffix() { match use_statement.suffix() {
UseStatementSuffix::Identifier(identifier) => { UseStatementSuffix::Identifier(identifier) => {
handle_concrete_use_symbol(identifier); handle_concrete_use_symbol(use_statement, identifier, symbol_tree, diagnostics);
} }
UseStatementSuffix::Star => { UseStatementSuffix::Star => {
if let Err(error) = symbol_table.resolve_usable_star(&base_fqn) { todo!("Resolve star symbols")
handle_lookup_error(
error,
&base_fqn,
use_statement.file_id(),
use_statement.range(),
"Star Usable Symbol",
diagnostics,
);
}
} }
UseStatementSuffix::UseList(use_list) => { UseStatementSuffix::UseList(use_list) => {
for identifier in use_list.identifiers() { for identifier in use_list.identifiers() {
handle_concrete_use_symbol(identifier); handle_concrete_use_symbol(use_statement, identifier, symbol_tree, diagnostics);
} }
} }
} }

View File

@ -0,0 +1,40 @@
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
use crate::name_analysis::symbol::class_member_symbol::ClassMemberSymbol;
use crate::name_analysis::symbol::function_symbol::FunctionSymbol;
#[derive(Debug)]
pub struct ClassSymbol {
declared_name: Rc<String>,
fqn: Rc<String>,
members: HashMap<Rc<String>, Rc<RefCell<ClassMemberSymbol>>>,
functions: HashMap<Rc<String>, Rc<RefCell<FunctionSymbol>>>
}
impl ClassSymbol {
pub fn new(declared_name: &str, fqn: &str) -> Self {
Self {
declared_name: Rc::new(declared_name.to_string()),
fqn: Rc::new(fqn.to_string()),
members: HashMap::new(),
functions: HashMap::new(),
}
}
pub fn declared_name(&self) -> &str {
&self.declared_name
}
pub fn declared_name_owned(&self) -> Rc<String> {
self.declared_name.clone()
}
pub fn fqn(&self) -> &str {
&self.fqn
}
pub fn fqn_owned(&self) -> Rc<String> {
self.fqn.clone()
}
}

View File

@ -0,0 +1,36 @@
use std::collections::HashMap;
use std::rc::Rc;
use crate::name_analysis::symbol::function_symbol::FunctionSymbol;
#[derive(Debug)]
pub struct InterfaceSymbol {
declared_name: Rc<String>,
fqn: Rc<String>,
functions: HashMap<String, FunctionSymbol>,
}
impl InterfaceSymbol {
pub fn new(declared_name: &str, fqn: &str) -> Self {
Self {
declared_name: Rc::new(declared_name.to_string()),
fqn: Rc::new(fqn.to_string()),
functions: HashMap::new(),
}
}
pub fn declared_name(&self) -> &str {
&self.declared_name
}
pub fn declared_name_owned(&self) -> Rc<String> {
self.declared_name.clone()
}
pub fn fqn(&self) -> &str {
&self.fqn
}
pub fn fqn_owned(&self) -> Rc<String> {
self.fqn.clone()
}
}

View File

@ -1,12 +1,14 @@
pub(crate) mod class_member_symbol; pub mod class_member_symbol;
pub(crate) mod function_symbol; pub mod class_symbol;
pub(crate) mod module_symbol; pub mod function_symbol;
pub(crate) mod parameter_symbol; pub mod interface_symbol;
pub(crate) mod source_definition; pub mod module_symbol;
pub(crate) mod type_symbol; pub mod parameter_symbol;
pub(crate) mod usable_symbol; pub mod source_definition;
pub(crate) mod use_symbol; pub mod type_symbol;
pub(crate) mod variable_symbol; pub mod usable_symbol;
pub mod use_symbol;
pub mod variable_symbol;
use crate::name_analysis::symbol::type_symbol::ConcreteTypeSymbol; use crate::name_analysis::symbol::type_symbol::ConcreteTypeSymbol;
use crate::name_analysis::symbol::use_symbol::UseSymbol; use crate::name_analysis::symbol::use_symbol::UseSymbol;
@ -40,7 +42,9 @@ impl Symbol {
Symbol::Use(use_symbol) => use_symbol.source_definition(), Symbol::Use(use_symbol) => use_symbol.source_definition(),
Symbol::Module(module) => module.source_definition().cloned(), Symbol::Module(module) => module.source_definition().cloned(),
Symbol::Type(type_symbol) => type_symbol.source_definition().cloned(), Symbol::Type(type_symbol) => type_symbol.source_definition().cloned(),
Symbol::ConcreteType(concrete_type_symbol) => concrete_type_symbol.borrow().source_definition().cloned(), Symbol::ConcreteType(concrete_type_symbol) => {
concrete_type_symbol.borrow().source_definition().cloned()
}
Symbol::Function(function_symbol) => function_symbol.source_definition().cloned(), Symbol::Function(function_symbol) => function_symbol.source_definition().cloned(),
Symbol::Parameter(parameter_symbol) => parameter_symbol.source_definition().cloned(), Symbol::Parameter(parameter_symbol) => parameter_symbol.source_definition().cloned(),
Symbol::Variable(variable_symbol) => variable_symbol.source_definition().cloned(), Symbol::Variable(variable_symbol) => variable_symbol.source_definition().cloned(),

View File

@ -1,10 +1,12 @@
use crate::name_analysis::symbol::class_symbol::ClassSymbol;
use crate::name_analysis::symbol::function_symbol::FunctionSymbol; use crate::name_analysis::symbol::function_symbol::FunctionSymbol;
use crate::name_analysis::symbol::type_symbol::{ConcreteTypeSymbol, TypeSymbol}; use crate::name_analysis::symbol::interface_symbol::InterfaceSymbol;
use std::cell::RefCell; use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum ConcreteUsableSymbol { pub enum ConcreteUsableSymbol {
Type(Rc<RefCell<ConcreteTypeSymbol>>), Interface(Rc<RefCell<InterfaceSymbol>>),
Class(Rc<RefCell<ClassSymbol>>),
Function(Rc<RefCell<FunctionSymbol>>), Function(Rc<RefCell<FunctionSymbol>>),
} }

View File

@ -2,7 +2,6 @@ use crate::name_analysis::symbol::class_member_symbol::ClassMemberSymbol;
use crate::name_analysis::symbol::function_symbol::FunctionSymbol; use crate::name_analysis::symbol::function_symbol::FunctionSymbol;
use crate::name_analysis::symbol::module_symbol::ModuleSymbol; use crate::name_analysis::symbol::module_symbol::ModuleSymbol;
use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol; use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol;
use crate::name_analysis::symbol::type_symbol::ConcreteTypeSymbol;
use crate::name_analysis::symbol::usable_symbol::ConcreteUsableSymbol; use crate::name_analysis::symbol::usable_symbol::ConcreteUsableSymbol;
use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol, UseSymbol}; use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol, UseSymbol};
use crate::name_analysis::symbol::variable_symbol::VariableSymbol; use crate::name_analysis::symbol::variable_symbol::VariableSymbol;
@ -190,27 +189,6 @@ impl SymbolTable {
} }
} }
fn find_current_scope_concrete_type_symbol(
&self,
declared_name: &str,
) -> Option<Rc<RefCell<ConcreteTypeSymbol>>> {
self.current_scope().get_concrete_type_symbol(declared_name)
}
pub fn insert_concrete_type_symbol(
&mut self,
symbol: ConcreteTypeSymbol,
) -> Result<(), SymbolInsertError> {
if let Some(defined_type) =
self.find_current_scope_concrete_type_symbol(symbol.declared_name())
{
Err(SymbolAlreadyDefined(Symbol::ConcreteType(defined_type)))
} else {
self.current_scope_mut().insert_concrete_type_symbol(symbol);
Ok(())
}
}
pub fn insert_function_symbol( pub fn insert_function_symbol(
&mut self, &mut self,
function_symbol: FunctionSymbol, function_symbol: FunctionSymbol,
@ -334,39 +312,6 @@ impl SymbolTable {
} }
Err(NoDefinition) Err(NoDefinition)
} }
pub fn resolve_concrete_usable_by_fqn(
&self,
fqn: &str,
) -> Result<ConcreteUsableSymbol, SymbolLookupError> {
// breadth-first search, use a queue
let mut search_stack: VecDeque<usize> = VecDeque::new();
search_stack.push_back(0); // global scope
while let Some(scope_id) = search_stack.pop_front() {
let scope = &self.scopes[scope_id];
for child_id in scope.children() {
search_stack.push_back(child_id);
}
if let Some(concrete_type_symbol) = scope.get_concrete_type_symbol_by_fqn(fqn) {
return Ok(ConcreteUsableSymbol::Type(concrete_type_symbol));
}
// TODO: this is inefficient. Use a (cached) hash table of Fqn => Rc<RefCell<symbol>>
for function_symbol in scope.function_symbols().values() {
if function_symbol.fqn() == fqn {
return Ok(ConcreteUsableSymbol::Function(todo!()));
}
}
}
Err(NoDefinition)
}
pub fn resolve_usable_star(&self, base_fqn: &str) -> Result<(), SymbolLookupError> {
todo!()
}
} }
impl Display for SymbolTable { impl Display for SymbolTable {

View File

@ -1,8 +1,9 @@
use crate::name_analysis::symbol::class_member_symbol::ClassMemberSymbol; use crate::name_analysis::symbol::class_member_symbol::ClassMemberSymbol;
use crate::name_analysis::symbol::class_symbol::ClassSymbol;
use crate::name_analysis::symbol::function_symbol::FunctionSymbol; use crate::name_analysis::symbol::function_symbol::FunctionSymbol;
use crate::name_analysis::symbol::interface_symbol::InterfaceSymbol;
use crate::name_analysis::symbol::module_symbol::ModuleSymbol; use crate::name_analysis::symbol::module_symbol::ModuleSymbol;
use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol; use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol;
use crate::name_analysis::symbol::type_symbol::{ConcreteTypeSymbol, TypeSymbol};
use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol}; use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol};
use crate::name_analysis::symbol::variable_symbol::VariableSymbol; use crate::name_analysis::symbol::variable_symbol::VariableSymbol;
use std::cell::RefCell; use std::cell::RefCell;
@ -18,8 +19,8 @@ pub struct Scope {
concrete_use_symbols: HashMap<String, Rc<RefCell<ConcreteUseSymbol>>>, concrete_use_symbols: HashMap<String, Rc<RefCell<ConcreteUseSymbol>>>,
star_use_symbols: HashMap<String, StarUseSymbol>, star_use_symbols: HashMap<String, StarUseSymbol>,
module_symbols: HashMap<String, ModuleSymbol>, module_symbols: HashMap<String, ModuleSymbol>,
concrete_type_symbols: HashMap<String, Rc<RefCell<ConcreteTypeSymbol>>>, interface_symbols: HashMap<Rc<String>, Rc<RefCell<InterfaceSymbol>>>,
concrete_type_symbols_by_fqn: HashMap<String, Rc<RefCell<ConcreteTypeSymbol>>>, class_symbols: HashMap<Rc<String>, Rc<RefCell<ClassSymbol>>>,
function_symbols: HashMap<String, FunctionSymbol>, function_symbols: HashMap<String, FunctionSymbol>,
parameter_symbols: HashMap<String, ParameterSymbol>, parameter_symbols: HashMap<String, ParameterSymbol>,
variable_symbols: HashMap<String, VariableSymbol>, variable_symbols: HashMap<String, VariableSymbol>,
@ -36,8 +37,8 @@ impl Scope {
concrete_use_symbols: HashMap::new(), concrete_use_symbols: HashMap::new(),
star_use_symbols: HashMap::new(), star_use_symbols: HashMap::new(),
module_symbols: HashMap::new(), module_symbols: HashMap::new(),
concrete_type_symbols: HashMap::new(), interface_symbols: HashMap::new(),
concrete_type_symbols_by_fqn: HashMap::new(), class_symbols: HashMap::new(),
function_symbols: HashMap::new(), function_symbols: HashMap::new(),
parameter_symbols: HashMap::new(), parameter_symbols: HashMap::new(),
variable_symbols: HashMap::new(), variable_symbols: HashMap::new(),
@ -88,24 +89,25 @@ impl Scope {
&mut self.module_symbols &mut self.module_symbols
} }
pub fn insert_concrete_type_symbol(&mut self, symbol: ConcreteTypeSymbol) { pub fn insert_interface_symbol(&mut self, symbol: InterfaceSymbol) {
let as_rc = Rc::new(RefCell::new(symbol)); self.interface_symbols
self.concrete_type_symbols.insert( .insert(symbol.declared_name_owned(), Rc::new(RefCell::new(symbol)));
as_rc.borrow().declared_name().to_string(),
as_rc.clone(),
);
self.concrete_type_symbols_by_fqn.insert(
as_rc.borrow().fqn().to_string(),
as_rc.clone(),
);
} }
pub fn get_concrete_type_symbol(&self, declared_name: &str) -> Option<Rc<RefCell<ConcreteTypeSymbol>>> { pub fn get_interface_symbol(
self.concrete_type_symbols.get(declared_name).cloned() &self,
declared_name: Rc<String>,
) -> Option<Rc<RefCell<InterfaceSymbol>>> {
self.interface_symbols.get(&declared_name).cloned()
} }
pub fn get_concrete_type_symbol_by_fqn(&self, fqn: &str) -> Option<Rc<RefCell<ConcreteTypeSymbol>>> { pub fn insert_class_symbol(&mut self, symbol: ClassSymbol) {
self.concrete_type_symbols_by_fqn.get(fqn).cloned() self.class_symbols
.insert(symbol.declared_name_owned(), Rc::new(RefCell::new(symbol)));
}
pub fn get_class_symbol(&self, declared_name: Rc<String>) -> Option<Rc<RefCell<ClassSymbol>>> {
self.class_symbols.get(&declared_name).cloned()
} }
pub fn function_symbols(&self) -> &HashMap<String, FunctionSymbol> { pub fn function_symbols(&self) -> &HashMap<String, FunctionSymbol> {

View File

@ -0,0 +1,57 @@
use std::cell::RefCell;
use crate::name_analysis::symbol::class_symbol::ClassSymbol;
use crate::name_analysis::symbol::function_symbol::FunctionSymbol;
use crate::name_analysis::symbol::interface_symbol::InterfaceSymbol;
use std::collections::HashMap;
use std::rc::Rc;
pub struct SymbolTree {
children: Box<HashMap<String, SymbolTree>>,
classes: Box<HashMap<String, Rc<RefCell<ClassSymbol>>>>,
interfaces: Box<HashMap<String, Rc<RefCell<InterfaceSymbol>>>>,
functions: Box<HashMap<String, Rc<RefCell<FunctionSymbol>>>>,
}
impl SymbolTree {
pub fn new() -> Self {
Self {
children: Box::new(HashMap::new()),
classes: Box::new(HashMap::new()),
interfaces: Box::new(HashMap::new()),
functions: Box::new(HashMap::new()),
}
}
pub fn find_class(&self, fqn_parts: &[&str]) -> Option<Rc<RefCell<ClassSymbol>>> {
match fqn_parts.len() {
0 => None,
1 => self.classes.get(fqn_parts[0]).cloned(),
_ => self
.children
.get(fqn_parts[0])
.and_then(|child_tree| child_tree.find_class(&fqn_parts[1..])),
}
}
pub fn find_interface(&self, fqn_parts: &[&str]) -> Option<Rc<RefCell<InterfaceSymbol>>> {
match fqn_parts.len() {
0 => None,
1 => self.interfaces.get(fqn_parts[0]).cloned(),
_ => self
.children
.get(fqn_parts[0])
.and_then(|child_tree| child_tree.find_interface(&fqn_parts[1..])),
}
}
pub fn find_function(&self, fqn_parts: &[&str]) -> Option<Rc<RefCell<FunctionSymbol>>> {
match fqn_parts.len() {
0 => None,
1 => self.functions.get(fqn_parts[0]).cloned(),
_ => self
.children
.get(fqn_parts[0])
.and_then(|child_tree| child_tree.find_function(&fqn_parts[1..])),
}
}
}