From 8b374e1066a475c1640f0ed22a92256aaae22caa Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Mon, 27 Oct 2025 08:48:08 -0500 Subject: [PATCH] WIP seemingly endless name analysis refactoring. --- src/name_analysis/first_pass.rs | 189 ++++++++++++- src/name_analysis/mod.rs | 1 + src/name_analysis/second_pass.rs | 1 - src/name_analysis/symbol/class_symbol.rs | 40 +-- src/name_analysis/symbol/function_symbol.rs | 90 +++--- .../symbol/generic_type_symbol.rs | 34 +++ src/name_analysis/symbol/interface_symbol.rs | 37 +-- src/name_analysis/symbol/mod.rs | 49 +--- .../symbol/module_level_symbol.rs | 30 ++ src/name_analysis/symbol/module_symbol.rs | 38 ++- src/name_analysis/symbol/parameter_symbol.rs | 14 +- .../symbol/primitive_type_symbol.rs | 12 + src/name_analysis/symbol/type_symbol.rs | 130 +-------- src/name_analysis/symbol/usable_symbol.rs | 15 +- src/name_analysis/symbol/use_symbol.rs | 48 ++-- src/name_analysis/symbol_table/fqn_context.rs | 31 +-- src/name_analysis/symbol_table/mod.rs | 258 ++++-------------- src/name_analysis/symbol_table/scope.rs | 158 ++++++----- src/name_analysis/symbol_table/symbol_tree.rs | 60 +++- src/name_analysis/type_use_container.rs | 20 ++ src/name_analysis/util.rs | 22 +- src/std_core/mod.rs | 40 +-- 22 files changed, 684 insertions(+), 633 deletions(-) create mode 100644 src/name_analysis/symbol/generic_type_symbol.rs create mode 100644 src/name_analysis/symbol/module_level_symbol.rs create mode 100644 src/name_analysis/symbol/primitive_type_symbol.rs create mode 100644 src/name_analysis/type_use_container.rs diff --git a/src/name_analysis/first_pass.rs b/src/name_analysis/first_pass.rs index 0fb8f1f..a26de26 100644 --- a/src/name_analysis/first_pass.rs +++ b/src/name_analysis/first_pass.rs @@ -1,12 +1,20 @@ use crate::ast::node::{ - CompilationUnit, ConcreteUseStatement, ConcreteUseStatementSuffix, Identifier, UseStatement, + CompilationUnit, ConcreteUseStatement, ConcreteUseStatementSuffix, Function, FunctionBody, + Identifier, Module, ModuleLevelDeclaration, Parameters, ReturnType, TypeUse, UseStatement, UseStatementIdentifier, UseStatementPrefix, }; use crate::diagnostic::DmDiagnostic; +use crate::name_analysis::symbol::function_symbol::FunctionSymbol; +use crate::name_analysis::symbol::module_level_symbol::ModuleLevelSymbol; +use crate::name_analysis::symbol::module_symbol::ModuleSymbol; +use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol; use crate::name_analysis::symbol::source_definition::SourceDefinition; use crate::name_analysis::symbol::use_symbol::ConcreteUseSymbol; use crate::name_analysis::symbol_table::SymbolTable; +use crate::name_analysis::type_use_container::TypeUseContainer; use crate::name_analysis::util::handle_insert_error; +use std::cell::RefCell; +use std::rc::Rc; pub fn na_p1_compilation_unit( file_name: &str, @@ -30,6 +38,10 @@ pub fn na_p1_compilation_unit( na_p1_use_statement(use_statement, symbol_table, diagnostics); } + for module_level_declaration in compilation_unit.module_level_declarations_mut() { + na_p1_module_level_declaration(module_level_declaration, symbol_table, diagnostics); + } + symbol_table.pop_scope(); } @@ -53,12 +65,12 @@ fn na_p1_concrete_use_statement( symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { - let prefixes: Vec = concrete_use_statement + let prefixes: Vec> = concrete_use_statement .prefixes() .map(UseStatementPrefix::identifier) .map(Identifier::name) - .map(ToString::to_string) - .collect::>(); + .map(Rc::from) + .collect(); match concrete_use_statement.suffix_mut() { ConcreteUseStatementSuffix::UseStatementIdentifier(use_statement_identifier) => { @@ -83,16 +95,16 @@ fn na_p1_concrete_use_statement( } fn handle_concrete_use_statement_identifier( - prefixes: &Vec, + prefixes: &Vec>, use_statement_identifier: &mut UseStatementIdentifier, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { - let mut fqn_parts: Vec<&str> = vec![]; + let mut fqn_parts: Vec> = vec![]; for prefix in prefixes { - fqn_parts.push(prefix); + fqn_parts.push(prefix.clone()); } - fqn_parts.push(use_statement_identifier.identifier().name()); + fqn_parts.push(Rc::from(use_statement_identifier.identifier().name())); let to_insert = ConcreteUseSymbol::new( &fqn_parts, @@ -111,9 +123,168 @@ fn handle_concrete_use_statement_identifier( use_statement_identifier.identifier().name(), use_statement_identifier.identifier().file_id(), use_statement_identifier.identifier().range(), - "Use Symbol", diagnostics, ); } } } + +fn na_p1_module_level_declaration( + module_level_declaration: &mut ModuleLevelDeclaration, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) -> Option { + match module_level_declaration { + ModuleLevelDeclaration::Module(module) => na_p1_module(module, symbol_table, diagnostics) + .map(|module_symbol| ModuleLevelSymbol::Module(module_symbol)), + ModuleLevelDeclaration::Interface(interface) => { + todo!() + } + ModuleLevelDeclaration::Class(class) => { + todo!() + } + ModuleLevelDeclaration::Function(function) => { + na_p1_function(function, symbol_table, diagnostics) + .map(|function_symbol| ModuleLevelSymbol::Function(function_symbol)) + } + ModuleLevelDeclaration::PlatformFunction(platform_function) => { + todo!() + } + } +} + +fn na_p1_module( + module: &mut Module, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) -> Option>> { + symbol_table.push_fqn_part(module.identifier().name()); + symbol_table.push_scope(&format!("ModuleScope {}", module.identifier().name())); + + let to_insert = ModuleSymbol::new( + symbol_table.current_fqn_owned(), + module.is_public(), + Some(SourceDefinition::from_identifier(module.identifier())), + ); + let module_symbol = match symbol_table.insert_module_symbol(to_insert) { + Ok(module_symbol) => { + for declaration in module.declarations_mut() { + let declaration_result = + na_p1_module_level_declaration(declaration, symbol_table, diagnostics); + if let Some(module_level_symbol) = declaration_result { + module_symbol + .borrow_mut() + .add_inner_symbol(module_level_symbol); + } + } + Some(module_symbol) + } + Err(symbol_insert_error) => { + handle_insert_error( + symbol_insert_error, + module.identifier().name(), + module.identifier().file_id(), + module.identifier().range(), + diagnostics, + ); + None + } + }; + + symbol_table.pop_scope(); + symbol_table.pop_fqn_part(); + + module_symbol +} + +fn na_p1_function( + function: &mut Function, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) -> Option>> { + symbol_table.push_scope(&format!("FunctionScope {}", function.identifier().name())); + + let to_insert = FunctionSymbol::new( + &symbol_table.resolve_fqn(Rc::from(function.identifier().name())), + function.is_public(), + false, + Some(SourceDefinition::from_identifier(function.identifier())), + ); + let function_symbol = match symbol_table.insert_function_symbol(to_insert) { + Ok(function_symbol) => { + { + let mut as_ref_mut = function_symbol.borrow_mut(); + as_ref_mut.set_parameter_symbols(na_p1_parameters( + function.parameters_mut(), + symbol_table, + diagnostics, + )); + as_ref_mut.set_return_type(na_p1_return_type( + function.return_type_mut(), + symbol_table, + diagnostics, + )) + } + Some(function_symbol) + } + Err(symbol_insert_error) => { + handle_insert_error( + symbol_insert_error, + function.identifier().name(), + function.identifier().file_id(), + function.identifier().range(), + diagnostics, + ); + None + } + }; + + symbol_table.pop_scope(); + + function_symbol +} + +fn na_p1_parameters( + parameters: &mut Parameters, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) -> Vec>> { + todo!() +} + +fn na_p1_return_type( + return_type: &mut ReturnType, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) -> Rc> { + na_p1_type_use(return_type.type_use_mut(), symbol_table, diagnostics) +} + +fn na_p1_type_use( + type_use: &mut TypeUse, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) -> Rc> { + match type_use { + TypeUse::PrimitiveType(primitive_type) => { + todo!() + } + TypeUse::InterfaceOrClassTypeUse(interface_or_class_type) => { + todo!() + } + TypeUse::TupleTypeUse(tuple_type) => { + todo!() + } + TypeUse::FunctionTypeUse(function_type) => { + todo!() + } + } +} + +fn na_p1_function_body( + function_body: &mut FunctionBody, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + todo!() +} diff --git a/src/name_analysis/mod.rs b/src/name_analysis/mod.rs index 4a1d3c6..ee8bfdb 100644 --- a/src/name_analysis/mod.rs +++ b/src/name_analysis/mod.rs @@ -35,6 +35,7 @@ mod scope_table; mod second_pass; pub mod symbol; pub mod symbol_table; +pub mod type_use_container; mod util; pub fn analyze_names<'a, F: Files<'a, FileId = usize, Name = String>>( diff --git a/src/name_analysis/second_pass.rs b/src/name_analysis/second_pass.rs index 0ab3ed7..a6d2ed8 100644 --- a/src/name_analysis/second_pass.rs +++ b/src/name_analysis/second_pass.rs @@ -96,7 +96,6 @@ fn handle_concrete_use_statement_identifier( &fqn_parts.join("::"), use_statement_identifier.identifier().file_id(), use_statement_identifier.identifier().range(), - "Usable Symbol", diagnostics, ); } diff --git a/src/name_analysis/symbol/class_symbol.rs b/src/name_analysis/symbol/class_symbol.rs index 6697d06..4a076b2 100644 --- a/src/name_analysis/symbol/class_symbol.rs +++ b/src/name_analysis/symbol/class_symbol.rs @@ -1,40 +1,40 @@ +use crate::name_analysis::symbol::class_member_symbol::ClassMemberSymbol; +use crate::name_analysis::symbol::function_symbol::FunctionSymbol; +use crate::name_analysis::symbol::source_definition::SourceDefinition; +use crate::name_analysis::symbol::Symbol; 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, - fqn: Rc, - members: HashMap, Rc>>, - functions: HashMap, Rc>> + fqn_parts: Vec>, + members: HashMap, Rc>>, + functions: HashMap, Rc>>, + source_definition: Option, } impl ClassSymbol { - pub fn new(declared_name: &str, fqn: &str) -> Self { + pub fn new(fqn_parts: &[Rc], source_definition: Option) -> Self { Self { - declared_name: Rc::new(declared_name.to_string()), - fqn: Rc::new(fqn.to_string()), + fqn_parts: fqn_parts.to_vec(), members: HashMap::new(), functions: HashMap::new(), + source_definition, } } pub fn declared_name(&self) -> &str { - &self.declared_name + self.fqn_parts.last().unwrap() } - pub fn declared_name_owned(&self) -> Rc { - self.declared_name.clone() + pub fn declared_name_owned(&self) -> Rc { + self.fqn_parts.last().unwrap().clone() } - - pub fn fqn(&self) -> &str { - &self.fqn +} + +impl Symbol for ClassSymbol { + fn source_definition(&self) -> Option<&SourceDefinition> { + self.source_definition.as_ref() } - - pub fn fqn_owned(&self) -> Rc { - self.fqn.clone() - } -} \ No newline at end of file +} diff --git a/src/name_analysis/symbol/function_symbol.rs b/src/name_analysis/symbol/function_symbol.rs index fd3113f..e7644d6 100644 --- a/src/name_analysis/symbol/function_symbol.rs +++ b/src/name_analysis/symbol/function_symbol.rs @@ -1,30 +1,30 @@ use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol; use crate::name_analysis::symbol::source_definition::SourceDefinition; -use crate::name_analysis::symbol::type_symbol::ConcreteTypeSymbol; +use crate::name_analysis::symbol::Symbol; +use crate::name_analysis::type_use_container::TypeUseContainer; +use crate::name_analysis::util::join_fqn_parts; +use std::cell::RefCell; use std::fmt::{Debug, Formatter}; +use std::rc::Rc; -#[derive(Clone)] pub struct FunctionSymbol { - fqn: String, - declared_name: String, + fqn_parts: Vec>, is_public: bool, is_platform: bool, source_definition: Option, - parameters: Vec, - return_type: Option, // todo: can we use TypeSymbol? + parameters: Vec>>, + return_type: Option>>, // todo: can we use TypeSymbol? } impl FunctionSymbol { - pub fn without_parameters_or_return_type( - fqn: &str, - declared_name: &str, + pub fn new( + fqn_parts: &[Rc], is_public: bool, is_platform: bool, source_definition: Option, ) -> FunctionSymbol { FunctionSymbol { - fqn: fqn.to_string(), - declared_name: declared_name.to_string(), + fqn_parts: fqn_parts.to_vec(), is_public, is_platform, source_definition, @@ -33,36 +33,34 @@ impl FunctionSymbol { } } - pub fn with_parameters(self, parameters: Vec) -> Self { + pub fn with_parameters_and_return_type( + fqn_parts: &[Rc], + is_public: bool, + is_platform: bool, + source_definition: Option, + parameters: &[Rc>], + return_type: Option>>, + ) -> Self { Self { - fqn: self.fqn, - declared_name: self.declared_name, - is_public: self.is_public, - is_platform: self.is_platform, - source_definition: self.source_definition, - parameters, - return_type: self.return_type, + fqn_parts: fqn_parts.to_vec(), + is_public, + is_platform, + source_definition, + parameters: parameters.to_vec(), + return_type, } } - pub fn with_return_type(self, return_type: ConcreteTypeSymbol) -> Self { - Self { - fqn: self.fqn, - declared_name: self.declared_name, - is_public: self.is_public, - is_platform: self.is_platform, - source_definition: self.source_definition, - parameters: self.parameters, - return_type: Some(return_type), - } - } - - pub fn fqn(&self) -> &str { - &self.fqn + pub fn fqn_parts_owned(&self) -> Vec> { + self.fqn_parts.to_vec() } pub fn declared_name(&self) -> &str { - &self.declared_name + self.fqn_parts.last().unwrap().as_ref() + } + + pub fn declared_name_owned(&self) -> Rc { + self.fqn_parts.last().unwrap().clone() } pub fn is_public(&self) -> bool { @@ -73,24 +71,30 @@ impl FunctionSymbol { self.is_platform } - pub fn source_definition(&self) -> Option<&SourceDefinition> { - self.source_definition.as_ref() - } - - pub fn parameters(&self) -> &[ParameterSymbol] { + pub fn parameter_symbols(&self) -> &[Rc>] { &self.parameters } - pub fn return_type(&self) -> Option<&ConcreteTypeSymbol> { - self.return_type.as_ref() + pub fn set_parameter_symbols(&mut self, parameter_symbols: Vec>>) { + self.parameters = parameter_symbols; + } + + pub fn set_return_type(&mut self, type_use_container: Rc>) { + self.return_type = Some(type_use_container); + } +} + +impl Symbol for FunctionSymbol { + fn source_definition(&self) -> Option<&SourceDefinition> { + self.source_definition.as_ref() } } impl Debug for FunctionSymbol { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("FunctionSymbol") - .field("fqn", &self.fqn) - .field("declared_name", &self.declared_name) + .field("fqn", &join_fqn_parts(&self.fqn_parts)) + .field("declared_name", &self.declared_name()) .field("is_public", &self.is_public) .field("is_platform", &self.is_platform) .field("parameters", &self.parameters) diff --git a/src/name_analysis/symbol/generic_type_symbol.rs b/src/name_analysis/symbol/generic_type_symbol.rs new file mode 100644 index 0000000..2e28484 --- /dev/null +++ b/src/name_analysis/symbol/generic_type_symbol.rs @@ -0,0 +1,34 @@ +use crate::name_analysis::symbol::source_definition::SourceDefinition; +use std::fmt::{Debug, Formatter}; + +#[derive(Clone)] +pub struct GenericTypeSymbol { + declared_name: String, + source_definition: Option, +} + +impl GenericTypeSymbol { + pub fn new(declared_name: &str, source_definition: Option) -> Self { + GenericTypeSymbol { + declared_name: declared_name.to_string(), + source_definition, + } + } + + pub fn declared_name(&self) -> &str { + &self.declared_name + } + + pub fn source_definition(&self) -> Option<&SourceDefinition> { + self.source_definition.as_ref() + } +} + +impl Debug for GenericTypeSymbol { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("GenericTypeSymbol") + .field("declared_name", &self.declared_name) + .field("source_definition", &self.source_definition) + .finish() + } +} diff --git a/src/name_analysis/symbol/interface_symbol.rs b/src/name_analysis/symbol/interface_symbol.rs index 6e79a1f..678f42e 100644 --- a/src/name_analysis/symbol/interface_symbol.rs +++ b/src/name_analysis/symbol/interface_symbol.rs @@ -1,36 +1,37 @@ +use crate::name_analysis::symbol::function_symbol::FunctionSymbol; +use crate::name_analysis::symbol::source_definition::SourceDefinition; +use crate::name_analysis::symbol::Symbol; +use std::cell::RefCell; use std::collections::HashMap; use std::rc::Rc; -use crate::name_analysis::symbol::function_symbol::FunctionSymbol; #[derive(Debug)] pub struct InterfaceSymbol { - declared_name: Rc, - fqn: Rc, - functions: HashMap, + fqn_parts: Vec>, + functions: HashMap, Rc>>, + source_definition: Option, } impl InterfaceSymbol { - pub fn new(declared_name: &str, fqn: &str) -> Self { + pub fn new(fqn_parts: &[Rc], source_definition: Option) -> Self { Self { - declared_name: Rc::new(declared_name.to_string()), - fqn: Rc::new(fqn.to_string()), + fqn_parts: fqn_parts.to_vec(), functions: HashMap::new(), + source_definition, } } pub fn declared_name(&self) -> &str { - &self.declared_name + self.fqn_parts.last().unwrap().as_ref() } - pub fn declared_name_owned(&self) -> Rc { - self.declared_name.clone() - } - - pub fn fqn(&self) -> &str { - &self.fqn - } - - pub fn fqn_owned(&self) -> Rc { - self.fqn.clone() + pub fn declared_name_owned(&self) -> Rc { + self.fqn_parts.last().unwrap().clone() + } +} + +impl Symbol for InterfaceSymbol { + fn source_definition(&self) -> Option<&SourceDefinition> { + self.source_definition.as_ref() } } diff --git a/src/name_analysis/symbol/mod.rs b/src/name_analysis/symbol/mod.rs index 609493e..e9a090a 100644 --- a/src/name_analysis/symbol/mod.rs +++ b/src/name_analysis/symbol/mod.rs @@ -1,56 +1,21 @@ pub mod class_member_symbol; pub mod class_symbol; pub mod function_symbol; +pub mod generic_type_symbol; pub mod interface_symbol; +pub mod module_level_symbol; pub mod module_symbol; pub mod parameter_symbol; +pub mod primitive_type_symbol; pub mod source_definition; pub mod type_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::use_symbol::UseSymbol; -use class_member_symbol::ClassMemberSymbol; -use function_symbol::FunctionSymbol; -use module_symbol::ModuleSymbol; -use parameter_symbol::ParameterSymbol; -use source_definition::SourceDefinition; -use std::cell::RefCell; -use std::fmt::{Debug, Display}; -use std::ops::Deref; -use std::rc::Rc; -use type_symbol::TypeSymbol; -use variable_symbol::VariableSymbol; +use crate::name_analysis::symbol::source_definition::SourceDefinition; +use std::fmt::Debug; -#[derive(Debug, Clone)] -pub enum Symbol { - Use(UseSymbol), - Module(ModuleSymbol), - Type(TypeSymbol), - ConcreteType(Rc>), - Function(FunctionSymbol), - Parameter(ParameterSymbol), - Variable(VariableSymbol), - ClassMember(ClassMemberSymbol), -} - -impl Symbol { - pub fn definition(&self) -> Option { - match self { - Symbol::Use(use_symbol) => use_symbol.source_definition(), - Symbol::Module(module) => module.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::Function(function_symbol) => function_symbol.source_definition().cloned(), - Symbol::Parameter(parameter_symbol) => parameter_symbol.source_definition().cloned(), - Symbol::Variable(variable_symbol) => variable_symbol.source_definition().cloned(), - Symbol::ClassMember(class_member_symbol) => { - class_member_symbol.source_definition().cloned() - } - } - } +pub trait Symbol: Debug { + fn source_definition(&self) -> Option<&SourceDefinition>; } diff --git a/src/name_analysis/symbol/module_level_symbol.rs b/src/name_analysis/symbol/module_level_symbol.rs new file mode 100644 index 0000000..6d6d07e --- /dev/null +++ b/src/name_analysis/symbol/module_level_symbol.rs @@ -0,0 +1,30 @@ +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 crate::name_analysis::symbol::module_symbol::ModuleSymbol; +use crate::name_analysis::symbol::Symbol; +use std::cell::RefCell; +use std::rc::Rc; + +#[derive(Debug)] +pub enum ModuleLevelSymbol { + Module(Rc>), + Interface(Rc>), + Class(Rc>), + Function(Rc>), +} + +impl ModuleLevelSymbol { + pub fn to_symbol(self) -> Rc> { + match self { + ModuleLevelSymbol::Module(module_symbol) => module_symbol as Rc>, + ModuleLevelSymbol::Interface(interface_symbol) => { + interface_symbol as Rc> + } + ModuleLevelSymbol::Class(class_symbol) => class_symbol as Rc>, + ModuleLevelSymbol::Function(function_symbol) => { + function_symbol as Rc> + } + } + } +} diff --git a/src/name_analysis/symbol/module_symbol.rs b/src/name_analysis/symbol/module_symbol.rs index b733f49..28ca68a 100644 --- a/src/name_analysis/symbol/module_symbol.rs +++ b/src/name_analysis/symbol/module_symbol.rs @@ -1,42 +1,54 @@ +use crate::name_analysis::symbol::module_level_symbol::ModuleLevelSymbol; use crate::name_analysis::symbol::source_definition::SourceDefinition; +use crate::name_analysis::symbol::Symbol; +use crate::name_analysis::util::join_fqn_parts; use std::fmt::{Debug, Formatter}; +use std::rc::Rc; -#[derive(Clone)] pub struct ModuleSymbol { - fqn: String, - declared_name: String, + fqn_parts: Vec>, is_public: bool, source_definition: Option, + inner_symbols: Vec, } impl ModuleSymbol { pub fn new( - fqn: &str, - declared_name: &str, + fqn_parts: Vec>, is_public: bool, source_definition: Option, ) -> Self { Self { - fqn: fqn.to_string(), - declared_name: declared_name.to_string(), + fqn_parts, is_public, source_definition, + inner_symbols: Vec::new(), } } - pub fn fqn(&self) -> &str { - &self.fqn + pub fn fqn_parts(&self) -> &[Rc] { + &self.fqn_parts } pub fn declared_name(&self) -> &str { - &self.declared_name + self.fqn_parts.last().unwrap() + } + + pub fn declared_name_owned(&self) -> Rc { + self.fqn_parts.last().unwrap().clone() } pub fn is_public(&self) -> bool { self.is_public } - pub fn source_definition(&self) -> Option<&SourceDefinition> { + pub fn add_inner_symbol(&mut self, module_level_symbol: ModuleLevelSymbol) { + self.inner_symbols.push(module_level_symbol); + } +} + +impl Symbol for ModuleSymbol { + fn source_definition(&self) -> Option<&SourceDefinition> { self.source_definition.as_ref() } } @@ -44,10 +56,10 @@ impl ModuleSymbol { impl Debug for ModuleSymbol { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("ModuleSymbol") - .field("fqn", &self.fqn) - .field("declared_name", &self.declared_name) + .field("fqn", &join_fqn_parts(&self.fqn_parts)) .field("is_public", &self.is_public) .field("source_definition", &self.source_definition) + .field("inner_symbols", &self.inner_symbols) .finish() } } diff --git a/src/name_analysis/symbol/parameter_symbol.rs b/src/name_analysis/symbol/parameter_symbol.rs index 5024f8d..8bfb058 100644 --- a/src/name_analysis/symbol/parameter_symbol.rs +++ b/src/name_analysis/symbol/parameter_symbol.rs @@ -1,24 +1,30 @@ use crate::name_analysis::symbol::source_definition::SourceDefinition; +use crate::name_analysis::type_use_container::TypeUseContainer; use std::fmt::{Debug, Formatter}; -#[derive(Clone)] pub struct ParameterSymbol { declared_name: String, source_definition: Option, + type_use_symbol: Option, } impl ParameterSymbol { - pub fn new(declared_name: &str, source_definition: Option) -> Self { + pub fn new( + declared_name: &str, + source_definition: Option, + type_use_symbol: Option, + ) -> Self { ParameterSymbol { declared_name: declared_name.to_string(), source_definition, + type_use_symbol, } } - + pub fn declared_name(&self) -> &str { &self.declared_name } - + pub fn source_definition(&self) -> Option<&SourceDefinition> { self.source_definition.as_ref() } diff --git a/src/name_analysis/symbol/primitive_type_symbol.rs b/src/name_analysis/symbol/primitive_type_symbol.rs new file mode 100644 index 0000000..b6df32d --- /dev/null +++ b/src/name_analysis/symbol/primitive_type_symbol.rs @@ -0,0 +1,12 @@ +#[derive(Debug)] +pub enum PrimitiveTypeSymbol { + Byte, + Char, + Short, + Int, + Long, + Float, + Double, + Boolean, + String, +} diff --git a/src/name_analysis/symbol/type_symbol.rs b/src/name_analysis/symbol/type_symbol.rs index 9a0cb5b..eb9d622 100644 --- a/src/name_analysis/symbol/type_symbol.rs +++ b/src/name_analysis/symbol/type_symbol.rs @@ -1,121 +1,15 @@ -use crate::name_analysis::symbol::source_definition::SourceDefinition; -use std::fmt::{Debug, Formatter}; +use std::cell::RefCell; +use crate::name_analysis::symbol::class_symbol::ClassSymbol; +use crate::name_analysis::symbol::generic_type_symbol::GenericTypeSymbol; +use crate::name_analysis::symbol::interface_symbol::InterfaceSymbol; +use crate::name_analysis::symbol::primitive_type_symbol::PrimitiveTypeSymbol; +use std::fmt::Debug; +use std::rc::Rc; -#[derive(Clone, Debug)] +#[derive(Debug)] pub enum TypeSymbol { - Concrete(ConcreteTypeSymbol), - Generic(GenericTypeSymbol), -} - -impl TypeSymbol { - pub fn declared_name(&self) -> &str { - match self { - TypeSymbol::Concrete(t) => t.declared_name(), - TypeSymbol::Generic(t) => t.declared_name(), - } - } - - pub fn source_definition(&self) -> Option<&SourceDefinition> { - match self { - TypeSymbol::Concrete(t) => t.source_definition(), - TypeSymbol::Generic(t) => t.source_definition(), - } - } -} - -#[derive(Clone)] -pub struct ConcreteTypeSymbol { - fqn: String, - declared_name: String, - is_public: bool, - kind: ConcreteTypeSymbolKind, - source_definition: Option, -} - -impl ConcreteTypeSymbol { - pub fn new( - fqn: &str, - declared_name: &str, - is_public: bool, - kind: ConcreteTypeSymbolKind, - source_definition: Option, - ) -> Self { - Self { - fqn: fqn.to_string(), - declared_name: declared_name.to_string(), - is_public, - kind, - source_definition - } - } - - pub fn fqn(&self) -> &str { - &self.fqn - } - - pub fn is_public(&self) -> bool { - self.is_public - } - - pub fn kind(&self) -> &ConcreteTypeSymbolKind { - &self.kind - } - - pub fn declared_name(&self) -> &str { - &self.declared_name - } - - pub fn source_definition(&self) -> Option<&SourceDefinition> { - self.source_definition.as_ref() - } -} - -impl Debug for ConcreteTypeSymbol { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.debug_struct("TypeSymbol") - .field("fqn", &self.fqn) - .field("declared_name", &self.declared_name) - .field("is_public", &self.is_public) - .field("kind", &self.kind) - .field("source_definition", &self.source_definition) - .finish() - } -} - -#[derive(Clone, Debug)] -pub enum ConcreteTypeSymbolKind { - Interface, - Class -} - -#[derive(Clone)] -pub struct GenericTypeSymbol { - declared_name: String, - source_definition: Option, -} - -impl GenericTypeSymbol { - pub fn new(declared_name: &str, source_definition: Option) -> Self { - GenericTypeSymbol { - declared_name: declared_name.to_string(), - source_definition, - } - } - - pub fn declared_name(&self) -> &str { - &self.declared_name - } - - pub fn source_definition(&self) -> Option<&SourceDefinition> { - self.source_definition.as_ref() - } -} - -impl Debug for GenericTypeSymbol { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.debug_struct("GenericTypeSymbol") - .field("declared_name", &self.declared_name) - .field("source_definition", &self.source_definition) - .finish() - } + Primitive(PrimitiveTypeSymbol), + Class(Rc>), + Interface(Rc>), + Generic(Rc>), } diff --git a/src/name_analysis/symbol/usable_symbol.rs b/src/name_analysis/symbol/usable_symbol.rs index ccc7c77..62de51d 100644 --- a/src/name_analysis/symbol/usable_symbol.rs +++ b/src/name_analysis/symbol/usable_symbol.rs @@ -1,12 +1,25 @@ 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 crate::name_analysis::symbol::Symbol; use std::cell::RefCell; use std::rc::Rc; -#[derive(Clone, Debug)] +#[derive(Debug)] pub enum UsableSymbol { Interface(Rc>), Class(Rc>), Function(Rc>), } + +impl UsableSymbol { + pub fn to_symbol(self) -> Rc> { + match self { + UsableSymbol::Interface(interface_symbol) => { + interface_symbol as Rc> + } + UsableSymbol::Class(class_symbol) => class_symbol as Rc>, + UsableSymbol::Function(function_symbol) => function_symbol as Rc>, + } + } +} diff --git a/src/name_analysis/symbol/use_symbol.rs b/src/name_analysis/symbol/use_symbol.rs index 9b1a575..16a950c 100644 --- a/src/name_analysis/symbol/use_symbol.rs +++ b/src/name_analysis/symbol/use_symbol.rs @@ -1,10 +1,12 @@ use crate::name_analysis::symbol::source_definition::SourceDefinition; use crate::name_analysis::symbol::usable_symbol::UsableSymbol; +use crate::name_analysis::symbol::Symbol; +use crate::name_analysis::util::join_fqn_parts; use std::cell::RefCell; use std::fmt::{Debug, Formatter}; use std::rc::Rc; -#[derive(Debug, Clone)] +#[derive(Debug)] pub enum UseSymbol { Concrete(Rc>), Star(StarUseSymbol), @@ -19,35 +21,31 @@ impl UseSymbol { } } -#[derive(Clone)] pub struct ConcreteUseSymbol { - fqn_parts: Vec, + fqn_parts: Vec>, source_definition: Option, resolved_symbol: Option, } impl ConcreteUseSymbol { - pub fn new( - fqn_parts: &[&str], - source_definition: Option, - ) -> Self { + pub fn new(fqn_parts: &[Rc], source_definition: Option) -> Self { Self { - fqn_parts: fqn_parts.iter().map(ToString::to_string).collect(), + fqn_parts: fqn_parts.to_vec(), source_definition, resolved_symbol: None, } } - pub fn fqn_parts(&self) -> &[String] { - self.fqn_parts.as_slice() + pub fn fqn_parts(&self) -> &[Rc] { + &self.fqn_parts } pub fn declared_name(&self) -> &str { self.fqn_parts.last().unwrap() } - - pub fn source_definition(&self) -> Option<&SourceDefinition> { - self.source_definition.as_ref() + + pub fn declared_name_owned(&self) -> Rc { + self.fqn_parts.last().unwrap().clone() } pub fn resolved_symbol(&self) -> Option<&UsableSymbol> { @@ -59,6 +57,12 @@ impl ConcreteUseSymbol { } } +impl Symbol for ConcreteUseSymbol { + fn source_definition(&self) -> Option<&SourceDefinition> { + self.source_definition.as_ref() + } +} + impl Debug for ConcreteUseSymbol { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("ConcreteUseStatementSymbol") @@ -70,23 +74,25 @@ impl Debug for ConcreteUseSymbol { #[derive(Clone)] pub struct StarUseSymbol { - base_fqn: String, + fqn_parts: Vec>, source_definition: Option, } impl StarUseSymbol { - pub fn new(base_fqn: &str, source_definition: Option) -> Self { + pub fn new(fqn_parts: &[Rc], source_definition: Option) -> Self { Self { - base_fqn: base_fqn.to_string(), + fqn_parts: fqn_parts.to_vec(), source_definition, } } - - pub fn base_fqn(&self) -> &str { - &self.base_fqn + + pub fn fqn_parts(&self) -> &[Rc] { + &self.fqn_parts } +} - pub fn source_definition(&self) -> Option<&SourceDefinition> { +impl Symbol for StarUseSymbol { + fn source_definition(&self) -> Option<&SourceDefinition> { self.source_definition.as_ref() } } @@ -94,7 +100,7 @@ impl StarUseSymbol { impl Debug for StarUseSymbol { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("StarUseStatementSymbol") - .field("base_fqn", &self.base_fqn) + .field("fqn", &join_fqn_parts(&self.fqn_parts)) .field("source_definition", &self.source_definition) .finish() } diff --git a/src/name_analysis/symbol_table/fqn_context.rs b/src/name_analysis/symbol_table/fqn_context.rs index 1605b99..2eb19d9 100644 --- a/src/name_analysis/symbol_table/fqn_context.rs +++ b/src/name_analysis/symbol_table/fqn_context.rs @@ -1,6 +1,8 @@ +use std::rc::Rc; + #[derive(Debug)] pub struct FqnContext { - stack: Vec, + stack: Vec>, } impl FqnContext { @@ -9,31 +11,18 @@ impl FqnContext { } pub fn push(&mut self, name: &str) { - self.stack.push(name.to_string()); + self.stack.push(Rc::from(name)); } pub fn pop(&mut self) { self.stack.pop(); } - - pub fn current(&self) -> String { - let mut acc = String::new(); - for (i, name) in self.stack.iter().enumerate() { - acc.push_str(name); - if i != self.stack.len() - 1 { - acc.push_str("::") - } - } - acc + + pub fn current_fqn(&self) -> Vec<&str> { + self.stack.iter().map(|part| part.as_ref()).collect() } - - pub fn resolve(&self, name: &str) -> String { - let mut acc = String::new(); - if !self.stack.is_empty() { - acc.push_str(&self.current()); - acc.push_str("::"); - } - acc.push_str(name); - acc + + pub fn current_fqn_owned(&self) -> Vec> { + self.stack.clone() } } diff --git a/src/name_analysis/symbol_table/mod.rs b/src/name_analysis/symbol_table/mod.rs index 27b4577..e5df189 100644 --- a/src/name_analysis/symbol_table/mod.rs +++ b/src/name_analysis/symbol_table/mod.rs @@ -1,20 +1,16 @@ -use crate::name_analysis::symbol::class_member_symbol::ClassMemberSymbol; use crate::name_analysis::symbol::function_symbol::FunctionSymbol; use crate::name_analysis::symbol::module_symbol::ModuleSymbol; -use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol; -use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol, UseSymbol}; -use crate::name_analysis::symbol::variable_symbol::VariableSymbol; -use crate::name_analysis::symbol::*; +use crate::name_analysis::symbol::usable_symbol::UsableSymbol; +use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol}; +use crate::name_analysis::symbol::Symbol; use crate::name_analysis::symbol_table::fqn_context::FqnContext; use crate::name_analysis::symbol_table::symbol_tree::SymbolTree; use crate::name_analysis::symbol_table::SymbolInsertError::SymbolAlreadyDefined; -use crate::name_analysis::symbol_table::SymbolLookupError::NoDefinition; use scope::Scope; use std::cell::RefCell; use std::fmt::Display; use std::ops::Deref; use std::rc::Rc; -use crate::name_analysis::symbol::usable_symbol::UsableSymbol; pub(self) mod fqn_context; mod scope; @@ -22,10 +18,9 @@ pub mod symbol_tree; #[derive(Debug)] pub enum SymbolInsertError { - SymbolAlreadyDefined(Symbol), + SymbolAlreadyDefined(Rc>), } -#[derive(Debug)] pub enum SymbolLookupError { NoDefinition, } @@ -69,26 +64,36 @@ impl SymbolTable { self.current_scope_id = parent_id; } } - + pub fn set_current_fqn(&mut self, names: &[&str]) { self.fqn_context = Box::new(FqnContext::new()); for name in names { self.fqn_context.push(*name); } } - + pub fn push_fqn_part(&mut self, part: &str) { self.fqn_context.push(part); } - + pub fn pop_fqn_part(&mut self) { self.fqn_context.pop(); } - - pub fn symbol_tree(&self) -> &SymbolTree { - &self.symbol_tree + + pub fn current_fqn(&self) -> Vec<&str> { + self.fqn_context.current_fqn() } - + + pub fn current_fqn_owned(&self) -> Vec> { + self.fqn_context.current_fqn_owned() + } + + pub fn resolve_fqn(&self, part: Rc) -> Vec> { + let mut parts = self.current_fqn_owned(); + parts.push(part); + parts + } + pub fn find_usable_symbol(&self, fqn_parts: &[&str]) -> Option { self.symbol_tree .find_interface(fqn_parts) @@ -113,83 +118,20 @@ impl SymbolTable { &mut self.scopes[self.current_scope_id] } - fn find_current_scope_concrete_use_symbol( - &self, - declared_name: &str, - ) -> Option>> { - self.current_scope() - .concrete_use_symbols() - .get(declared_name) - .cloned() - } - - fn find_current_scope_module_symbol(&self, declared_name: &str) -> Option<&ModuleSymbol> { - self.current_scope().module_symbols().get(declared_name) - } - - fn find_current_scope_parameter_symbol(&self, declared_name: &str) -> Option<&ParameterSymbol> { - self.current_scope().parameter_symbols().get(declared_name) - } - - fn find_current_scope_variable_symbol(&self, declared_name: &str) -> Option<&VariableSymbol> { - self.current_scope().variable_symbols().get(declared_name) - } - - fn find_current_scope_class_member_symbol( - &self, - declared_name: &str, - ) -> Option<&ClassMemberSymbol> { - self.current_scope() - .class_member_symbols() - .get(declared_name) - } - - fn find_current_scope_variable_or_parameter_symbol( - &self, - declared_name: &str, - ) -> Option { - self.find_current_scope_variable_symbol(declared_name) - .map(|variable_symbol| Symbol::Variable(variable_symbol.clone())) - .or_else(|| { - self.find_current_scope_parameter_symbol(declared_name) - .map(|parameter_symbol| Symbol::Parameter(parameter_symbol.clone())) - }) - } - - fn find_current_scope_usable_symbol(&self, declared_name: &str) -> Option { - self.find_current_scope_concrete_use_symbol(declared_name) - .map(|concrete_use_symbol| { - Symbol::Use(UseSymbol::Concrete(concrete_use_symbol.clone())) - }) - // .or_else(|| { - // self.find_current_scope_type_symbol(declared_name) - // .map(|type_symbol| Symbol::Type(type_symbol.clone())) - // }) - .or_else(|| { - self.find_current_scope_module_symbol(declared_name) - .map(|module_symbol| Symbol::Module(module_symbol.clone())) - }) - } - pub fn insert_concrete_use_symbol( &mut self, concrete_use_symbol: ConcreteUseSymbol, ) -> Result>, SymbolInsertError> { - if let Some(defined_symbol) = - self.find_current_scope_usable_symbol(concrete_use_symbol.declared_name()) + if let Some(defined_symbol) = self + .current_scope() + .find_module_level_symbol(concrete_use_symbol.declared_name()) { - Err(SymbolAlreadyDefined(defined_symbol)) + Err(SymbolAlreadyDefined(defined_symbol.to_symbol())) } else { - let name = concrete_use_symbol.declared_name().to_string(); - self.current_scope_mut() - .concrete_use_symbols_mut() - .insert(name.clone(), Rc::new(RefCell::new(concrete_use_symbol))); - Ok(self - .current_scope() - .concrete_use_symbols() - .get(&name) - .cloned() - .unwrap()) + let inserted = self + .current_scope_mut() + .insert_concrete_use_symbol(concrete_use_symbol); + Ok(inserted) } } @@ -206,142 +148,36 @@ impl SymbolTable { pub fn insert_module_symbol( &mut self, module_symbol: ModuleSymbol, - ) -> Result<(), SymbolInsertError> { - if let Some(defined_symbol) = - self.find_current_scope_usable_symbol(module_symbol.declared_name()) + ) -> Result>, SymbolInsertError> { + if let Some(defined_symbol) = self + .current_scope() + .find_module_level_symbol(module_symbol.declared_name()) { - Err(SymbolAlreadyDefined(defined_symbol)) + Err(SymbolAlreadyDefined(defined_symbol.to_symbol())) } else { - self.current_scope_mut() - .module_symbols_mut() - .insert(module_symbol.declared_name().to_string(), module_symbol); - Ok(()) + let inserted = self.current_scope_mut().insert_module_symbol(module_symbol); + self.symbol_tree.register_module(inserted.clone()); + Ok(inserted) } } pub fn insert_function_symbol( &mut self, function_symbol: FunctionSymbol, - ) -> Result<(), SymbolInsertError> { - if let Some(defined_symbol) = - self.find_current_scope_usable_symbol(function_symbol.declared_name()) + ) -> Result>, SymbolInsertError> { + if let Some(defined_symbol) = self + .current_scope() + .find_module_level_symbol(function_symbol.declared_name()) { - Err(SymbolAlreadyDefined(defined_symbol)) + Err(SymbolAlreadyDefined(defined_symbol.to_symbol())) } else { - self.current_scope_mut() - .function_symbols_mut() - .insert(function_symbol.declared_name().to_string(), function_symbol); - Ok(()) + let inserted = self + .current_scope_mut() + .insert_function_symbol(function_symbol); + self.symbol_tree.register_function(inserted.clone()); + Ok(inserted) } } - - pub fn insert_parameter_symbol( - &mut self, - parameter_symbol: ParameterSymbol, - ) -> Result<(), SymbolInsertError> { - if let Some(defined_symbol) = - self.find_current_scope_parameter_symbol(parameter_symbol.declared_name()) - { - Err(SymbolAlreadyDefined(Symbol::Parameter( - defined_symbol.clone(), - ))) - } else { - self.current_scope_mut().parameter_symbols_mut().insert( - parameter_symbol.declared_name().to_string(), - parameter_symbol, - ); - Ok(()) - } - } - - pub fn insert_variable_symbol( - &mut self, - variable_symbol: VariableSymbol, - ) -> Result<(), SymbolInsertError> { - if let Some(defined_symbol) = - self.find_current_scope_variable_or_parameter_symbol(variable_symbol.declared_name()) - { - Err(SymbolAlreadyDefined(defined_symbol)) - } else { - self.current_scope_mut() - .variable_symbols_mut() - .insert(variable_symbol.declared_name().to_string(), variable_symbol); - Ok(()) - } - } - - pub fn insert_class_member_symbol( - &mut self, - class_member_symbol: ClassMemberSymbol, - ) -> Result<(), SymbolInsertError> { - if let Some(defined_symbol) = - self.find_current_scope_class_member_symbol(class_member_symbol.declared_name()) - { - Err(SymbolAlreadyDefined(Symbol::ClassMember( - defined_symbol.clone(), - ))) - } else { - self.current_scope_mut().class_member_symbols_mut().insert( - class_member_symbol.declared_name().to_string(), - class_member_symbol, - ); - Ok(()) - } - } - - fn lookup_addressable_in_scope_by_identifier( - scope: &Scope, - identifier: &str, - ) -> Option { - scope - .variable_symbols() - .get(identifier) - .map(|variable_symbol| Symbol::Variable(variable_symbol.clone())) - .or_else(|| { - scope - .parameter_symbols() - .get(identifier) - .map(|parameter_symbol| Symbol::Parameter(parameter_symbol.clone())) - }) - .or_else(|| { - scope - .class_member_symbols() - .get(identifier) - .map(|class_member_symbol| Symbol::ClassMember(class_member_symbol.clone())) - }) - .or_else(|| { - scope - .function_symbols() - .get(identifier) - .map(|function_symbol| Symbol::Function(function_symbol.clone())) - }) - // .or_else(|| { - // scope - // .type_symbols() - // .get(identifier) - // .map(|type_symbol| Symbol::Type(type_symbol.clone())) - // }) - } - - pub fn lookup_addressable_by_identifier( - &self, - identifier: &str, - scope_id: usize, - ) -> Result { - let mut scope_opt = Some(&self.scopes[scope_id]); - while let Some(scope) = scope_opt { - if let Some(symbol) = Self::lookup_addressable_in_scope_by_identifier(scope, identifier) - { - return Ok(symbol); - } - scope_opt = if let Some(parent_id) = scope.parent() { - Some(&self.scopes[parent_id]) - } else { - None - }; - } - Err(NoDefinition) - } } impl Display for SymbolTable { diff --git a/src/name_analysis/symbol_table/scope.rs b/src/name_analysis/symbol_table/scope.rs index de8157d..6d07cf8 100644 --- a/src/name_analysis/symbol_table/scope.rs +++ b/src/name_analysis/symbol_table/scope.rs @@ -2,6 +2,7 @@ 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::interface_symbol::InterfaceSymbol; +use crate::name_analysis::symbol::module_level_symbol::ModuleLevelSymbol; use crate::name_analysis::symbol::module_symbol::ModuleSymbol; use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol; use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol}; @@ -16,18 +17,26 @@ pub struct Scope { parent: Option, id: usize, children: Vec, - concrete_use_symbols: HashMap>>, - star_use_symbols: HashMap>>, - module_symbols: HashMap, - interface_symbols: HashMap, Rc>>, - class_symbols: HashMap, Rc>>, - function_symbols: HashMap, - parameter_symbols: HashMap, - variable_symbols: HashMap, - class_member_symbols: HashMap, + concrete_use_symbols: HashMap, Rc>>, + star_use_symbols: HashMap>, Rc>>, + module_symbols: HashMap, Rc>>, + interface_symbols: HashMap, Rc>>, + class_symbols: HashMap, Rc>>, + function_symbols: HashMap, Rc>>, + parameter_symbols: HashMap, ParameterSymbol>, + variable_symbols: HashMap, VariableSymbol>, + class_member_symbols: HashMap, ClassMemberSymbol>, debug_name: String, } +macro_rules! insert_symbol { + ($table:expr, $symbol:expr, $key:expr) => {{ + let as_rc = Rc::new(RefCell::new($symbol)); + $table.insert($key, as_rc.clone()); + as_rc + }}; +} + impl Scope { pub fn new(parent: Option, id: usize, debug_name: String) -> Self { Self { @@ -62,82 +71,81 @@ impl Scope { pub fn children(&self) -> Vec { self.children.clone() } - - pub fn concrete_use_symbols(&self) -> &HashMap>> { - &self.concrete_use_symbols - } - - pub fn concrete_use_symbols_mut( - &mut self, - ) -> &mut HashMap>> { - &mut self.concrete_use_symbols - } + pub fn insert_concrete_use_symbol(&mut self, symbol: ConcreteUseSymbol) -> Rc> { + let key = symbol.declared_name_owned(); + insert_symbol!(self.concrete_use_symbols, symbol, key) + } + pub fn insert_star_use_symbol(&mut self, symbol: StarUseSymbol) -> Rc> { - let as_rc = Rc::new(RefCell::new(symbol)); - self.star_use_symbols.insert(as_rc.borrow().base_fqn().to_string(), as_rc.clone()); - as_rc.clone() + let key = symbol.fqn_parts().to_vec(); + insert_symbol!(self.star_use_symbols, symbol, key) } - pub fn module_symbols(&self) -> &HashMap { - &self.module_symbols + pub fn insert_module_symbol(&mut self, symbol: ModuleSymbol) -> Rc> { + let key = symbol.declared_name_owned(); + insert_symbol!(self.module_symbols, symbol, key) } - pub fn module_symbols_mut(&mut self) -> &mut HashMap { - &mut self.module_symbols + pub fn get_module_symbol(&self, declared_name: &str) -> Option<&Rc>> { + self.module_symbols.get(declared_name) } - pub fn insert_interface_symbol(&mut self, symbol: InterfaceSymbol) { - self.interface_symbols - .insert(symbol.declared_name_owned(), Rc::new(RefCell::new(symbol))); + pub fn insert_function_symbol( + &mut self, + symbol: FunctionSymbol, + ) -> Rc> { + let key = symbol.declared_name_owned(); + insert_symbol!(self.function_symbols, symbol, key) + } + + pub fn get_function_symbol(&self, declared_name: &str) -> Option<&Rc>> { + self.function_symbols.get(declared_name) + } + + pub fn insert_interface_symbol( + &mut self, + symbol: InterfaceSymbol, + ) -> Rc> { + let key = symbol.declared_name_owned(); + insert_symbol!(self.interface_symbols, symbol, key) } pub fn get_interface_symbol( &self, - declared_name: Rc, - ) -> Option>> { - self.interface_symbols.get(&declared_name).cloned() + declared_name: &str, + ) -> Option<&Rc>> { + self.interface_symbols.get(declared_name) } - pub fn insert_class_symbol(&mut self, symbol: ClassSymbol) { - self.class_symbols - .insert(symbol.declared_name_owned(), Rc::new(RefCell::new(symbol))); + pub fn insert_class_symbol(&mut self, symbol: ClassSymbol) -> Rc> { + let key = symbol.declared_name_owned(); + insert_symbol!(self.class_symbols, symbol, key) } - pub fn get_class_symbol(&self, declared_name: Rc) -> Option>> { - self.class_symbols.get(&declared_name).cloned() + pub fn get_class_symbol(&self, declared_name: &str) -> Option<&Rc>> { + self.class_symbols.get(declared_name) } - pub fn function_symbols(&self) -> &HashMap { - &self.function_symbols - } - - pub fn function_symbols_mut(&mut self) -> &mut HashMap { - &mut self.function_symbols - } - - pub fn parameter_symbols(&self) -> &HashMap { - &self.parameter_symbols - } - - pub fn parameter_symbols_mut(&mut self) -> &mut HashMap { - &mut self.parameter_symbols - } - - pub fn variable_symbols(&self) -> &HashMap { - &self.variable_symbols - } - - pub fn variable_symbols_mut(&mut self) -> &mut HashMap { - &mut self.variable_symbols - } - - pub fn class_member_symbols(&self) -> &HashMap { - &self.class_member_symbols - } - - pub fn class_member_symbols_mut(&mut self) -> &mut HashMap { - &mut self.class_member_symbols + pub fn find_module_level_symbol(&self, declared_name: &str) -> Option { + self.module_symbols + .get(declared_name) + .map(|module_symbol| ModuleLevelSymbol::Module(module_symbol.clone())) + .or_else(|| { + self.interface_symbols + .get(declared_name) + .map(|interface_symbol| ModuleLevelSymbol::Interface(interface_symbol.clone())) + }) + .or_else(|| { + self.class_symbols + .get(declared_name) + .map(|class_symbol| ModuleLevelSymbol::Class(class_symbol.clone())) + }) + .or_else(|| { + self.function_symbols + .get(declared_name) + .map(|function_symbol| ModuleLevelSymbol::Function(function_symbol.clone())) + }) } pub fn debug_name(&self) -> &str { @@ -164,14 +172,14 @@ impl Display for Scope { .unwrap_or_else(|| "None".to_string()), self.debug_name() )?; - write_symbols!(f, self.concrete_use_symbols()); - todo!("self.star_use_symbols"); - write_symbols!(f, self.module_symbols()); - todo!("self.concrete_type_symbols"); - write_symbols!(f, self.function_symbols()); - write_symbols!(f, self.parameter_symbols()); - write_symbols!(f, self.variable_symbols()); - write_symbols!(f, self.class_member_symbols()); + write_symbols!(f, self.concrete_use_symbols); + write_symbols!(f, self.star_use_symbols); + write_symbols!(f, self.module_symbols); + write_symbols!(f, self.interface_symbols); + write_symbols!(f, self.function_symbols); + write_symbols!(f, self.parameter_symbols); + write_symbols!(f, self.variable_symbols); + write_symbols!(f, self.class_member_symbols); Ok(()) } } diff --git a/src/name_analysis/symbol_table/symbol_tree.rs b/src/name_analysis/symbol_table/symbol_tree.rs index dadd453..fb624d9 100644 --- a/src/name_analysis/symbol_table/symbol_tree.rs +++ b/src/name_analysis/symbol_table/symbol_tree.rs @@ -1,16 +1,17 @@ -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 crate::name_analysis::symbol::module_symbol::ModuleSymbol; +use std::cell::RefCell; use std::collections::HashMap; use std::rc::Rc; #[derive(Debug)] pub struct SymbolTree { - children: Box>, - classes: Box>>>, - interfaces: Box>>>, - functions: Box>>>, + children: Box, SymbolTree>>, + classes: Box, Rc>>>, + interfaces: Box, Rc>>>, + functions: Box, Rc>>>, } impl SymbolTree { @@ -33,7 +34,7 @@ impl SymbolTree { .and_then(|child_tree| child_tree.find_class(&fqn_parts[1..])), } } - + pub fn find_interface(&self, fqn_parts: &[&str]) -> Option>> { match fqn_parts.len() { 0 => None, @@ -44,7 +45,7 @@ impl SymbolTree { .and_then(|child_tree| child_tree.find_interface(&fqn_parts[1..])), } } - + pub fn find_function(&self, fqn_parts: &[&str]) -> Option>> { match fqn_parts.len() { 0 => None, @@ -55,4 +56,49 @@ impl SymbolTree { .and_then(|child_tree| child_tree.find_function(&fqn_parts[1..])), } } + + pub fn register_module(&mut self, module_symbol: Rc>) { + self.recurse_register_module(&module_symbol.borrow().fqn_parts()); + } + + fn recurse_register_module(&mut self, fqn_parts: &[Rc]) { + if fqn_parts.len() == 0 { + panic!("Unable to register module fqn with no parts.") + } + if fqn_parts.len() == 1 { + self.children + .insert(fqn_parts[0].clone(), SymbolTree::new()); + } else { + if self.children.contains_key(fqn_parts[0].as_ref()) { + let child = self.children.get_mut(fqn_parts[0].as_ref()).unwrap(); + child.recurse_register_module(&fqn_parts[1..]); + } else { + let mut child = SymbolTree::new(); + child.recurse_register_module(&fqn_parts[1..]); + self.children.insert(fqn_parts[0].clone(), child); + } + } + } + + pub fn register_function(&mut self, function_symbol: Rc>) { + let fqn_parts = function_symbol.borrow().fqn_parts_owned(); + self.recurse_register_function(function_symbol, &fqn_parts); + } + + fn recurse_register_function(&mut self, function_symbol: Rc>, fqn_parts: &[Rc]) { + if fqn_parts.len() == 0 { + panic!("Unable to register function fqn with no parts.") + } + if fqn_parts.len() == 1 { + self.functions.insert(fqn_parts[0].clone(), function_symbol); + } else { + if self.children.contains_key(fqn_parts[0].as_ref()) { + let child = self.children.get_mut(fqn_parts[0].as_ref()).unwrap(); + child.recurse_register_function(function_symbol, &fqn_parts[1..]); + } else { + panic!("No such inner module registered: {}", fqn_parts[0]) + } + } + } + } diff --git a/src/name_analysis/type_use_container.rs b/src/name_analysis/type_use_container.rs new file mode 100644 index 0000000..f2f97aa --- /dev/null +++ b/src/name_analysis/type_use_container.rs @@ -0,0 +1,20 @@ +use std::cell::RefCell; +use std::rc::Rc; +use crate::name_analysis::symbol::type_symbol::TypeSymbol; + +#[derive(Debug)] +pub struct TypeUseContainer { + resolved_type: Option>> +} + +impl TypeUseContainer { + pub fn new() -> TypeUseContainer { + Self { + resolved_type: None + } + } + + pub fn set_resolved_type(&mut self, type_symbol: Rc>) { + self.resolved_type = Some(type_symbol) + } +} \ No newline at end of file diff --git a/src/name_analysis/util.rs b/src/name_analysis/util.rs index e3e7ce1..ce24193 100644 --- a/src/name_analysis/util.rs +++ b/src/name_analysis/util.rs @@ -2,28 +2,28 @@ use crate::diagnostic::DmDiagnostic; use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolLookupError}; use codespan_reporting::diagnostic::{Diagnostic, Label}; use std::range::Range; +use std::rc::Rc; pub fn handle_insert_error( err: SymbolInsertError, error_symbol_name: &str, error_file_id: usize, error_range: Range, - symbol_types: &str, diagnostics: &mut Vec, ) { match err { SymbolInsertError::SymbolAlreadyDefined(s) => { let mut diagnostic = Diagnostic::error() .with_message(format!( - "{} symbol '{}' already defined in the current scope.", - symbol_types, error_symbol_name, + "Symbol '{}' already defined in the current scope.", + error_symbol_name, )) .with_label( Label::primary(error_file_id, error_range) .with_message("Symbol duplicated here."), ); - if let Some(source_definition) = s.definition() { + if let Some(source_definition) = s.borrow().source_definition() { diagnostic = diagnostic.with_label( Label::secondary(source_definition.file_id(), source_definition.range()) .with_message("Symbol defined here."), @@ -40,16 +40,12 @@ pub fn handle_lookup_error( error_symbol_name: &str, error_file_id: usize, error_range: Range, - symbol_types: &str, diagnostics: &mut Vec, ) { match err { SymbolLookupError::NoDefinition => { let diagnostic = Diagnostic::error() - .with_message(format!( - "No such {} symbol '{}' in scope.", - symbol_types, error_symbol_name, - )) + .with_message(format!("No such symbol '{}' in scope.", error_symbol_name,)) .with_label( Label::primary(error_file_id, error_range).with_message("Symbol used here."), ); @@ -57,3 +53,11 @@ pub fn handle_lookup_error( } } } + +pub fn format_fqn(parts: &[&str]) -> String { + parts.join("::") +} + +pub fn join_fqn_parts(parts: &[Rc]) -> String { + format_fqn(&parts.iter().map(|part| part.as_ref()).collect::>()) +} diff --git a/src/std_core/mod.rs b/src/std_core/mod.rs index 619e6c3..a245148 100644 --- a/src/std_core/mod.rs +++ b/src/std_core/mod.rs @@ -1,27 +1,27 @@ use crate::name_analysis::symbol::function_symbol::FunctionSymbol; use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol; use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable}; +use crate::name_analysis::type_use_container::TypeUseContainer; +use std::cell::RefCell; +use std::rc::Rc; pub fn add_std_core_symbols(symbol_table: &mut SymbolTable) -> Result<(), SymbolInsertError> { - symbol_table.insert_function_symbol( - FunctionSymbol::without_parameters_or_return_type( - "std::core::println", - "println", - true, - true, - None, - ) - .with_parameters(vec![ParameterSymbol::new("msg", None)]), - )?; - symbol_table.insert_function_symbol( - FunctionSymbol::without_parameters_or_return_type( - "std::core::print", - "print", - true, - true, - None, - ) - .with_parameters(vec![ParameterSymbol::new("msg", None)]), - )?; + symbol_table.set_current_fqn(&vec!["std", "core"]); + + let mut println_msg_symbol_type_use = TypeUseContainer::new(); + println_msg_symbol_type_use.set_resolved_type(todo!()); + + let println_msg_symbol = ParameterSymbol::new("msg", None, Some(TypeUseContainer::new())); + + let println_symbol = FunctionSymbol::with_parameters_and_return_type( + &symbol_table.resolve_fqn(Rc::from("println")), + true, + true, + None, + &vec![Rc::new(RefCell::new(println_msg_symbol))], + None, + ); + symbol_table.insert_function_symbol(println_symbol)?; + Ok(()) }