diff --git a/src/name_analysis/fqn_context.rs b/src/name_analysis/fqn_context.rs index 7589f3a..fd3ef36 100644 --- a/src/name_analysis/fqn_context.rs +++ b/src/name_analysis/fqn_context.rs @@ -1,4 +1,4 @@ -pub(super) struct FqnContext { +pub struct FqnContext { stack: Vec, } diff --git a/src/name_analysis/gather.rs b/src/name_analysis/gather.rs index 082035b..3a2d75b 100644 --- a/src/name_analysis/gather.rs +++ b/src/name_analysis/gather.rs @@ -1,16 +1,20 @@ use crate::ast::ast_node::{AstNode, AstNodeRef}; use crate::ast::node::{ - CompilationUnit, Function, FunctionBlockBody, FunctionBody, Identifier, Statement, - UseStatement, UseStatementSuffix, VariableDeclaration, + Class, CompilationUnit, Function, FunctionBlockBody, FunctionBody, Identifier, Interface, + Module, Namespace, Statement, UseStatement, UseStatementSuffix, VariableDeclaration, }; use crate::diagnostic::DmDiagnostic; +use crate::name_analysis::fqn_context::FqnContext; use crate::name_analysis::symbol::function_symbol::FunctionSymbol; +use crate::name_analysis::symbol::module_symbol::ModuleSymbol; use crate::name_analysis::symbol::source_definition::SourceDefinition; +use crate::name_analysis::symbol::type_symbol::{ + ConcreteTypeSymbol, ConcreteTypeSymbolKind, TypeSymbol, +}; use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol}; use crate::name_analysis::symbol::variable_symbol::VariableSymbol; use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable}; use codespan_reporting::diagnostic::{Diagnostic, Label}; -use std::collections::HashMap; use std::range::Range; fn handle_insert_error( @@ -45,165 +49,28 @@ fn handle_insert_error( } } -fn gather_identifier( - identifier: &Identifier, - symbol_table: &SymbolTable, - identifier_scope_ids: &mut HashMap, -) { - identifier_scope_ids.insert(identifier.clone(), symbol_table.current_scope_id()); -} - -fn gather_concrete_use_symbol( - base_fqn: &str, - identifier: &Identifier, - symbol_table: &mut SymbolTable, - diagnostics: &mut Vec, -) { - let symbol = ConcreteUseSymbol::new( - base_fqn, - identifier.name(), - Some(SourceDefinition::from_identifier(identifier)), - ); - if let Err(insert_error) = symbol_table.insert_concrete_use_symbol(symbol) { - handle_insert_error( - insert_error, - &base_fqn, - identifier.file_id(), - identifier.range(), - "Use Statement", - diagnostics, - ); - } -} - -fn gather_use_statement( - use_statement: &UseStatement, - symbol_table: &mut SymbolTable, - diagnostics: &mut Vec, -) { - let base_fqn = use_statement - .prefixes() - .map(|prefix| prefix.identifier().name()) - .collect::>() - .join("::"); - - match use_statement.suffix() { - UseStatementSuffix::Identifier(identifier) => { - gather_concrete_use_symbol(&base_fqn, identifier, symbol_table, diagnostics); - } - UseStatementSuffix::Star => { - let symbol = StarUseSymbol::new( - &base_fqn, - Some(SourceDefinition::from_use_statement(use_statement)), - ); - let insert_result = symbol_table.insert_star_use_symbol(symbol); - if let Err(error) = insert_result { - handle_insert_error( - error, - &base_fqn, - use_statement.file_id(), - use_statement.range(), - "Use Statement", - diagnostics, - ); - } - } - UseStatementSuffix::UseList(use_list) => { - for identifier in use_list.identifiers() { - gather_concrete_use_symbol(&base_fqn, identifier, symbol_table, diagnostics); - } - } - } -} - -fn gather_function( - function: &Function, - symbol_table: &mut SymbolTable, - diagnostics: &mut Vec, -) { - let function_symbol = FunctionSymbol::without_parameters_or_return_type( - "", - function.identifier().name(), - function.is_public(), - false, - Some(SourceDefinition::from_identifier(function.identifier())), - ); - if let Err(insert_error) = symbol_table.insert_function_symbol(function_symbol) { - handle_insert_error( - insert_error, - function.identifier().name(), - function.identifier().file_id(), - function.identifier().range(), - "Function", - diagnostics, - ); - } - gather_node( - AstNodeRef::FunctionBody(function.function_body()), - symbol_table, - diagnostics, - ); -} - -fn gather_function_block_body( - function_block_body: &FunctionBlockBody, - symbol_table: &mut SymbolTable, - diagnostics: &mut Vec, -) { - symbol_table.push_scope("FunctionBlockBody"); - gather_node_children(function_block_body, symbol_table, diagnostics); - symbol_table.pop_scope(); -} - -fn gather_variable_declaration( - variable_declaration: &VariableDeclaration, - symbol_table: &mut SymbolTable, - diagnostics: &mut Vec, -) { - let variable_symbol = VariableSymbol::new( - variable_declaration.identifier().name(), - variable_declaration.is_mut(), - Some(SourceDefinition::from_identifier( - variable_declaration.identifier(), - )), - ); - if let Err(insert_error) = symbol_table.insert_variable_symbol(variable_symbol) { - handle_insert_error( - insert_error, - variable_declaration.identifier().name(), - variable_declaration.identifier().file_id(), - variable_declaration.identifier().range(), - "Variable", - diagnostics, - ); - } - if let Some(expression) = variable_declaration.expression() { - gather_node( - AstNodeRef::Expression(expression), - symbol_table, - diagnostics, - ); - } -} - fn gather_node_children( node: &impl AstNode, symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, diagnostics: &mut Vec, ) { for child in node.children() { - gather_node(child, symbol_table, diagnostics); + gather_node(child, symbol_table, fqn_context, diagnostics); } } fn gather_node( node: AstNodeRef, symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, diagnostics: &mut Vec, ) { match node { AstNodeRef::Operator(_) => {} - AstNodeRef::Identifier(_) => {} + AstNodeRef::Identifier(_) => { + unreachable!() + } AstNodeRef::FullyQualifiedName(_) => {} AstNodeRef::TypeUseList(_) => {} AstNodeRef::IdentifierList(_) => {} @@ -222,26 +89,58 @@ fn gather_node( AstNodeRef::Parameter(_) => {} AstNodeRef::ReturnType(_) => {} AstNodeRef::CompilationUnit(compilation_unit) => { - gather_node_children(compilation_unit, symbol_table, diagnostics); + gather_node_children(compilation_unit, symbol_table, fqn_context, diagnostics); + } + AstNodeRef::Namespace(namespace) => { + gather_namespace(namespace, fqn_context); } - AstNodeRef::ParentMod(_) => {} AstNodeRef::UseStatement(use_statement) => { gather_use_statement(use_statement, symbol_table, diagnostics); } - AstNodeRef::UseStatementPrefix(_) => {} - AstNodeRef::UseStatementSuffix(_) => {} - AstNodeRef::UseList(_) => {} - AstNodeRef::ModuleLevelDeclaration(module_level_declaration) => { - gather_node_children(module_level_declaration, symbol_table, diagnostics); + AstNodeRef::UseStatementPrefix(_) => { + unreachable!() + } + AstNodeRef::UseStatementSuffix(_) => { + unreachable!() + } + AstNodeRef::UseList(_) => { + unreachable!() + } + AstNodeRef::ModuleLevelDeclaration(module_level_declaration) => { + gather_node_children( + module_level_declaration, + symbol_table, + fqn_context, + diagnostics, + ); + } + AstNodeRef::InterfaceLevelDeclaration(interface_level_declaration) => { + gather_node_children( + interface_level_declaration, + symbol_table, + fqn_context, + diagnostics, + ); + } + AstNodeRef::ClassLevelDeclaration(class_level_declaration) => { + gather_node_children( + class_level_declaration, + symbol_table, + fqn_context, + diagnostics, + ); + } + AstNodeRef::Module(module) => { + gather_module(module, symbol_table, fqn_context, diagnostics); + } + AstNodeRef::Interface(interface) => { + gather_interface(interface, symbol_table, fqn_context, diagnostics); + } + AstNodeRef::Class(class) => { + gather_class(class, symbol_table, fqn_context, diagnostics); } - AstNodeRef::InterfaceLevelDeclaration(_) => {} - AstNodeRef::ClassLevelDeclaration(_) => {} - AstNodeRef::Module(_) => {} - AstNodeRef::CompanionModule(_) => {} - AstNodeRef::Interface(_) => {} - AstNodeRef::Class(_) => {} AstNodeRef::Function(function) => { - gather_function(function, symbol_table, diagnostics); + gather_function(function, symbol_table, fqn_context, diagnostics); } AstNodeRef::OperatorFunction(_) => {} AstNodeRef::PlatformFunction(_) => {} @@ -251,25 +150,45 @@ fn gather_node( AstNodeRef::InterfaceDefaultOperatorFunction(_) => {} AstNodeRef::FunctionBody(function_body) => match function_body { FunctionBody::FunctionAliasBody(alias_body) => { - gather_node(alias_body.as_node_ref(), symbol_table, diagnostics); + gather_node( + alias_body.as_node_ref(), + symbol_table, + fqn_context, + diagnostics, + ); } FunctionBody::FunctionEqualsBody(equals_body) => { - gather_node(equals_body.as_node_ref(), symbol_table, diagnostics); + gather_node( + equals_body.as_node_ref(), + symbol_table, + fqn_context, + diagnostics, + ); } FunctionBody::FunctionBlockBody(block_body) => { - gather_node(block_body.as_node_ref(), symbol_table, diagnostics); + gather_node( + block_body.as_node_ref(), + symbol_table, + fqn_context, + diagnostics, + ); } }, AstNodeRef::FunctionEqualsBody(_) => {} AstNodeRef::FunctionAliasBody(_) => {} AstNodeRef::FunctionBlockBody(block_body) => { - gather_function_block_body(block_body, symbol_table, diagnostics); + gather_function_block_body(block_body, symbol_table, fqn_context, diagnostics); } AstNodeRef::ClassConstructor(_) => {} AstNodeRef::Member(_) => {} AstNodeRef::Statement(statement) => match statement { Statement::VariableDeclaration(variable_declaration) => { - gather_variable_declaration(variable_declaration, symbol_table, diagnostics); + gather_node( + variable_declaration.as_node_ref(), + symbol_table, + fqn_context, + diagnostics, + ); } Statement::AssignmentStatement(_) => {} Statement::ExpressionStatement(_) => {} @@ -332,10 +251,282 @@ pub fn gather_compilation_unit( compilation_unit: &mut CompilationUnit, file_name: &str, symbol_table: &mut SymbolTable, - identifier_scope_ids: &mut HashMap, diagnostics: &mut Vec, ) { + let mut fqn_context = FqnContext::new(); symbol_table.push_scope(&format!("FileScope {}", file_name)); - gather_node(compilation_unit.as_node_ref(), symbol_table, diagnostics); + gather_node( + compilation_unit.as_node_ref(), + symbol_table, + &mut fqn_context, + diagnostics, + ); symbol_table.pop_scope(); } + +fn gather_namespace(namespace: &Namespace, fqn_context: &mut FqnContext) { + for identifier in namespace.fqn().identifiers() { + fqn_context.push(identifier.name()); + } +} + +fn gather_use_statement( + use_statement: &UseStatement, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + let base_fqn = use_statement + .prefixes() + .map(|prefix| prefix.identifier().name()) + .collect::>() + .join("::"); + + match use_statement.suffix() { + UseStatementSuffix::Identifier(identifier) => { + gather_concrete_use_symbol(&base_fqn, identifier, symbol_table, diagnostics); + } + UseStatementSuffix::Star => { + let symbol = StarUseSymbol::new( + &base_fqn, + Some(SourceDefinition::from_use_statement(use_statement)), + ); + let insert_result = symbol_table.insert_star_use_symbol(symbol); + if let Err(error) = insert_result { + handle_insert_error( + error, + &base_fqn, + use_statement.file_id(), + use_statement.range(), + "Use Statement", + diagnostics, + ); + } + } + UseStatementSuffix::UseList(use_list) => { + for identifier in use_list.identifiers() { + gather_concrete_use_symbol(&base_fqn, identifier, symbol_table, diagnostics); + } + } + } +} + +fn gather_concrete_use_symbol( + base_fqn: &str, + identifier: &Identifier, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + let symbol = ConcreteUseSymbol::new( + base_fqn, + identifier.name(), + Some(SourceDefinition::from_identifier(identifier)), + ); + if let Err(insert_error) = symbol_table.insert_concrete_use_symbol(symbol) { + handle_insert_error( + insert_error, + &base_fqn, + identifier.file_id(), + identifier.range(), + "Use Statement", + diagnostics, + ); + } +} + +fn gather_module( + module: &Module, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + let module_symbol = ModuleSymbol::new( + &fqn_context.resolve(module.identifier().name()), + module.identifier().name(), + module.is_public(), + Some(SourceDefinition::from_identifier(module.identifier())), + ); + if let Err(symbol_insert_error) = symbol_table.insert_module_symbol(module_symbol) { + handle_insert_error( + symbol_insert_error, + module.identifier().name(), + module.identifier().file_id(), + module.identifier().range(), + "Module", + diagnostics, + ); + } + + fqn_context.push(module.identifier().name()); + symbol_table.push_scope(&format!("ModuleScope {}", module.identifier().name())); + + for declaration in module.declarations() { + gather_node( + declaration.as_node_ref(), + symbol_table, + fqn_context, + diagnostics, + ); + } + + symbol_table.pop_scope(); + fqn_context.pop(); +} + +fn gather_interface( + interface: &Interface, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + let type_symbol = ConcreteTypeSymbol::new( + &fqn_context.resolve(interface.identifier().name()), + interface.identifier().name(), + interface.is_public(), + ConcreteTypeSymbolKind::Interface, + Some(SourceDefinition::from_identifier(interface.identifier())), + ); + if let Err(symbol_insert_error) = + symbol_table.insert_type_symbol(TypeSymbol::Concrete(type_symbol)) + { + handle_insert_error( + symbol_insert_error, + interface.identifier().name(), + interface.identifier().file_id(), + interface.identifier().range(), + "Interface", + diagnostics, + ); + } + + fqn_context.push(interface.identifier().name()); + symbol_table.push_scope(&format!("InterfaceScope {}", interface.identifier().name())); + + for declaration in interface.declarations() { + gather_node( + declaration.as_node_ref(), + symbol_table, + fqn_context, + diagnostics, + ); + } + + symbol_table.pop_scope(); + fqn_context.pop(); +} + +fn gather_class( + class: &Class, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + let class_symbol = ConcreteTypeSymbol::new( + &fqn_context.resolve(class.identifier().name()), + class.identifier().name(), + class.is_public(), + ConcreteTypeSymbolKind::Class, + Some(SourceDefinition::from_identifier(class.identifier())), + ); + if let Err(symbol_insert_error) = + symbol_table.insert_type_symbol(TypeSymbol::Concrete(class_symbol)) + { + handle_insert_error( + symbol_insert_error, + class.identifier().name(), + class.identifier().file_id(), + class.identifier().range(), + "Class", + diagnostics, + ); + } + + fqn_context.push(class.identifier().name()); + symbol_table.push_scope(&format!("ClassScope {}", class.identifier().name())); + + for declaration in class.class_level_declarations() { + gather_node( + declaration.as_node_ref(), + symbol_table, + fqn_context, + diagnostics, + ); + } + + symbol_table.pop_scope(); + fqn_context.pop(); +} + +fn gather_function( + function: &Function, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + let function_symbol = FunctionSymbol::without_parameters_or_return_type( + &fqn_context.resolve(function.identifier().name()), + function.identifier().name(), + function.is_public(), + false, + Some(SourceDefinition::from_identifier(function.identifier())), + ); + if let Err(insert_error) = symbol_table.insert_function_symbol(function_symbol) { + handle_insert_error( + insert_error, + function.identifier().name(), + function.identifier().file_id(), + function.identifier().range(), + "Function", + diagnostics, + ); + } + gather_node( + function.function_body().as_node_ref(), + symbol_table, + fqn_context, + diagnostics, + ); +} + +fn gather_function_block_body( + function_block_body: &FunctionBlockBody, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + symbol_table.push_scope("FunctionBlockBody"); + gather_node_children(function_block_body, symbol_table, fqn_context, diagnostics); + symbol_table.pop_scope(); +} + +fn gather_variable_declaration( + variable_declaration: &VariableDeclaration, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + let variable_symbol = VariableSymbol::new( + variable_declaration.identifier().name(), + variable_declaration.is_mut(), + Some(SourceDefinition::from_identifier( + variable_declaration.identifier(), + )), + ); + if let Err(insert_error) = symbol_table.insert_variable_symbol(variable_symbol) { + handle_insert_error( + insert_error, + variable_declaration.identifier().name(), + variable_declaration.identifier().file_id(), + variable_declaration.identifier().range(), + "Variable", + diagnostics, + ); + } + if let Some(expression) = variable_declaration.expression() { + gather_node( + expression.as_node_ref(), + symbol_table, + fqn_context, + diagnostics, + ); + } +} diff --git a/src/name_analysis/mod.rs b/src/name_analysis/mod.rs index 3a951a1..08fa285 100644 --- a/src/name_analysis/mod.rs +++ b/src/name_analysis/mod.rs @@ -27,7 +27,7 @@ use crate::name_analysis::symbol_table::SymbolTable; use codespan_reporting::files::Files; use std::collections::HashMap; -mod fqn_context; +pub(self) mod fqn_context; mod gather; // mod resolve; pub mod symbol; @@ -44,13 +44,7 @@ pub fn analyze_names<'a, F: Files<'a, FileId = usize, Name = String>>( // gather symbols for compilation_unit in compilation_units.iter_mut() { let file_name = files.name(compilation_unit.file_id()).unwrap(); - gather_compilation_unit( - compilation_unit, - &file_name, - symbol_table, - &mut identifier_scope_ids, - &mut diagnostics, - ); + gather_compilation_unit(compilation_unit, &file_name, symbol_table, &mut diagnostics); } // resolve symbols diff --git a/src/name_analysis/symbol/type_symbol.rs b/src/name_analysis/symbol/type_symbol.rs index 4ae5d2e..9a0cb5b 100644 --- a/src/name_analysis/symbol/type_symbol.rs +++ b/src/name_analysis/symbol/type_symbol.rs @@ -28,6 +28,7 @@ pub struct ConcreteTypeSymbol { fqn: String, declared_name: String, is_public: bool, + kind: ConcreteTypeSymbolKind, source_definition: Option, } @@ -36,12 +37,14 @@ impl ConcreteTypeSymbol { 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 } } @@ -54,6 +57,10 @@ impl ConcreteTypeSymbol { self.is_public } + pub fn kind(&self) -> &ConcreteTypeSymbolKind { + &self.kind + } + pub fn declared_name(&self) -> &str { &self.declared_name } @@ -69,11 +76,18 @@ impl Debug for ConcreteTypeSymbol { .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, diff --git a/src/parser/ast.yaml b/src/parser/ast.yaml index 202edcf..ca177fc 100644 --- a/src/parser/ast.yaml +++ b/src/parser/ast.yaml @@ -181,7 +181,7 @@ ReturnType: CompilationUnit: struct: children: - - parent_mod: + - namespace: member: optional: true - use_statements: @@ -196,12 +196,12 @@ CompilationUnit: - file_id: special: kind: file_id -ParentMod: +Namespace: struct: children: - - mod_kw: + - ns_kw: skip: - rule: Mod + rule: Ns - fqn: member: rule: FullyQualifiedName @@ -253,7 +253,6 @@ ModuleLevelDeclaration: InterfaceLevelDeclaration: tree_enum: rules: - - CompanionModule - Interface - Class - InterfaceFunction @@ -263,7 +262,6 @@ InterfaceLevelDeclaration: ClassLevelDeclaration: tree_enum: rules: - - CompanionModule - Interface - Class - Function @@ -290,21 +288,6 @@ Module: - end_kw: skip: rule: End -CompanionModule: - struct: - children: - - companion_kw: - skip: - rule: Companion - - mod_kw: - skip: - rule: Mod - - declarations: - vec: - rule: ModuleLevelDeclaration - - end_kw: - skip: - rule: End Interface: struct: children: diff --git a/src/parser/deimos.pest b/src/parser/deimos.pest index aba0983..4c65760 100644 --- a/src/parser/deimos.pest +++ b/src/parser/deimos.pest @@ -307,13 +307,13 @@ ReturnType = { CompilationUnit = { SOI - ~ ParentMod? + ~ Namespace? ~ ( UseStatement | ModuleLevelDeclaration )* ~ EOI } -ParentMod = { - Mod +Namespace = { + Ns ~ FullyQualifiedName } @@ -352,8 +352,7 @@ ModuleLevelDeclaration = { } InterfaceLevelDeclaration = { - CompanionModule - | Interface + Interface | Class | InterfaceFunction | InterfaceDefaultFunction @@ -362,8 +361,7 @@ InterfaceLevelDeclaration = { } ClassLevelDeclaration = { - CompanionModule - | Interface + Interface | Class | Function | OperatorFunction @@ -380,13 +378,6 @@ Module = { ~ End } -CompanionModule = { - Companion - ~ Mod - ~ ModuleLevelDeclaration* - ~ End -} - Interface = { Pub? ~ IntKw