From c32ae72bebc7276d8c0a9d302935cda992dca048 Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Mon, 29 Sep 2025 09:39:13 -0500 Subject: [PATCH] WIP redoing name analysis. --- ast-generator/src/ast_node/mod.rs | 29 +- src/name_analysis/gather.rs | 1417 ++--------------- src/name_analysis/gather.rs.bak | 1320 +++++++++++++++ src/name_analysis/mod.rs | 69 +- .../{resolve.rs => resolve.rs.bak} | 0 5 files changed, 1489 insertions(+), 1346 deletions(-) create mode 100644 src/name_analysis/gather.rs.bak rename src/name_analysis/{resolve.rs => resolve.rs.bak} (100%) diff --git a/ast-generator/src/ast_node/mod.rs b/ast-generator/src/ast_node/mod.rs index 5c9464a..f09cf79 100644 --- a/ast-generator/src/ast_node/mod.rs +++ b/ast-generator/src/ast_node/mod.rs @@ -41,12 +41,33 @@ pub fn make_ast_node_impl(build_spec: &BuildSpec) -> Option { } } -pub fn make_ast_enum_member(build_spec: &BuildSpec) -> Option { +pub fn make_ast_enum_member(build_spec: &BuildSpec) -> Option { match build_spec { BuildSpec::Struct(struct_spec) => { - let type_ident = format_ident!("{}", struct_spec.build()); - Some(quote! { #type_ident(#type_ident) }) + Some(format_ident!("{}", struct_spec.build())) } - _ => None, + BuildSpec::LeafStruct(leaf_struct) => { + Some(format_ident!("{}", leaf_struct.build())) + } + BuildSpec::Enum(enum_spec) => { + Some(format_ident!("{}", enum_spec.build())) + } + BuildSpec::LeafEnum(leaf_enum) => { + Some(format_ident!("{}", leaf_enum.build())) + } + BuildSpec::PolymorphicType(polymorphic_type) => { + Some(format_ident!("{}", polymorphic_type.name())) + }, + BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => { + Some(format_ident!("{}", polymorphic_enum_loop.name())) + } + BuildSpec::PolymorphicPassThrough(_) => None, + BuildSpec::Production(_) => None, + BuildSpec::NodeProduction(_) => None, } + .map(|type_ident| { + quote! { + #type_ident(#type_ident) + } + }) } \ No newline at end of file diff --git a/src/name_analysis/gather.rs b/src/name_analysis/gather.rs index e73145e..aa85608 100644 --- a/src/name_analysis/gather.rs +++ b/src/name_analysis/gather.rs @@ -1,1320 +1,115 @@ -use crate::ast::node::*; +use std::collections::HashMap; +use crate::ast::ast_node::AstNodeRef; +use crate::ast::node::{CompilationUnit, Identifier}; +use crate::ast::walk::walk_depth_first; use crate::diagnostic::DmDiagnostic; -use crate::name_analysis::fqn_context::FqnContext; -use crate::name_analysis::symbol::*; -use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable}; -use codespan_reporting::diagnostic::{Diagnostic, Label}; -use std::ops::DerefMut; -use std::range::Range; -use std::rc::Rc; +use crate::name_analysis::symbol_table::SymbolTable; -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, - )) - .with_label( - Label::primary(error_file_id, error_range) - .with_message("Symbol duplicated here."), - ); - - if let Some(source_definition) = s.definition() { - diagnostic = diagnostic.with_label( - Label::secondary(source_definition.file_id(), source_definition.range()) - .with_message("Symbol defined here."), - ); - } - - diagnostics.push(diagnostic); - } - } +fn gather_identifier(identifier: &Identifier, symbol_table: &SymbolTable, identifier_scope_ids: &mut HashMap<&Identifier, usize>) { + identifier_scope_ids[identifier] = symbol_table.current_scope_id(); } -/* Names */ - -fn gather_identifier(identifier: &mut Identifier, symbol_table: &mut SymbolTable) { - identifier.set_scope_id(symbol_table.current_scope_id()); -} - -fn gather_fully_qualified_name( - fully_qualified_name: &mut FullyQualifiedName, - symbol_table: &mut SymbolTable, -) { - gather_identifier(fully_qualified_name.last_mut(), symbol_table); -} - -/* Type Use */ - -fn gather_type_use( - type_use: &mut TypeUse, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - match type_use { - TypeUse::Primitive(primitive_type_use) => { - gather_primitive_type_use(primitive_type_use, symbol_table, fqn_context, diagnostics) - } - TypeUse::InterfaceOrClass(interface_or_class_type_use) => { - gather_interface_or_class_type_use( - interface_or_class_type_use, - symbol_table, - fqn_context, - diagnostics, - ); - } - TypeUse::Tuple(tuple_type_use) => { - gather_tuple_type_use(tuple_type_use, symbol_table, fqn_context, diagnostics); - } - TypeUse::Function(function_type_use) => { - gather_function_type_use(function_type_use, symbol_table, fqn_context, diagnostics); - } - } -} - -fn gather_primitive_type_use( - primitive_type_use: &mut PrimitiveTypeUse, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - match primitive_type_use { - PrimitiveTypeUse::Array(generic_arguments_opt) => { - if let Some(generic_arguments) = generic_arguments_opt { - gather_generic_arguments(generic_arguments, symbol_table, fqn_context, diagnostics); - } - } - _ => {} - } -} - -fn gather_interface_or_class_type_use( - interface_or_class_type_use: &mut InterfaceOrClassTypeUse, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - gather_fully_qualified_name(interface_or_class_type_use.fqn_mut(), symbol_table); - gather_generic_arguments( - interface_or_class_type_use.generics_mut(), - symbol_table, - fqn_context, - diagnostics, - ); -} - -fn gather_tuple_type_use( - tuple_type_use: &mut TupleTypeUse, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - for generic_argument in tuple_type_use.arguments_mut().type_uses_mut() { - gather_type_use(generic_argument, symbol_table, fqn_context, diagnostics); - } -} - -fn gather_function_type_use( - function_type_use: &mut FunctionTypeUse, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - symbol_table.push_scope("FunctionTypeUseScope"); - gather_generic_parameters(function_type_use.generics_mut(), symbol_table, diagnostics); - gather_parameters( - function_type_use.parameters_mut(), - symbol_table, - fqn_context, - diagnostics, - ); - gather_return_type( - function_type_use.return_type_mut(), - symbol_table, - fqn_context, - diagnostics, - ); - symbol_table.pop_scope(); -} - -/* Generic Arguments */ - -fn gather_generic_arguments( - generic_arguments: &mut GenericArguments, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - for argument in generic_arguments.arguments_mut() { - gather_type_use(argument, symbol_table, fqn_context, diagnostics); - } -} - -/* Generic Parameters */ - -fn gather_generic_parameters( - generic_parameters: &mut GenericParameters, - symbol_table: &mut SymbolTable, - diagnostics: &mut Vec, -) { - for identifier in generic_parameters.identifiers_mut() { - let insert_result = - symbol_table.insert_type_symbol(TypeSymbol::Generic(GenericTypeSymbol::new( - &identifier.name(), - SourceDefinition::from_identifier(identifier), - ))); - match insert_result { - Ok(_) => {} - Err(insert_error) => { - handle_insert_error( - insert_error, - &identifier.name(), - identifier.file_id(), - identifier.range(), - "Type", - diagnostics, - ); - } - } - } -} - -/* Implements List */ - -fn gather_implements_list( - implements_list: &mut ImplementsList, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - for type_use in implements_list.type_uses_mut() { - gather_type_use(type_use, symbol_table, fqn_context, diagnostics); - } -} - -/* Function Parameters */ - -fn gather_parameters( - parameters: &mut Parameters, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) -> Option>> { - parameters - .parameters_mut() - .iter_mut() - .map(|parameter| gather_parameter(parameter, symbol_table, fqn_context, diagnostics)) - .collect() -} - -fn gather_parameter( - parameter: &mut Parameter, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) -> Option> { - let parameter_name = parameter.identifier().name(); - - let insert_result = symbol_table.insert_parameter_symbol(ParameterSymbol::new( - ¶meter_name, - Some(¶meter.identifier()), - )); - - match insert_result { - Ok(parameter_symbol) => { - let mut identifier = parameter.identifier_mut(); - identifier.set_scope_id(symbol_table.current_scope_id()); - identifier.set_saved_symbol(Symbol::Parameter(parameter_symbol.clone())); - - gather_type_use( - parameter.type_use_mut(), - symbol_table, - fqn_context, - diagnostics, - ); - Some(parameter_symbol) - } - Err(err) => { - handle_insert_error( - err, - ¶meter_name, - parameter.identifier().file_id(), - parameter.identifier().range(), - "function/variable", - diagnostics, - ); - None - } - } -} - -/* Return Type */ - -fn gather_return_type( - return_type: &mut ReturnType, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - gather_type_use( - return_type.declared_type_mut(), - symbol_table, - fqn_context, - diagnostics, - ); - gather_references(return_type.references_mut(), symbol_table); -} - -/* References */ - -fn gather_references(references: &mut References, symbol_table: &mut SymbolTable) { - for identifier in references.identifiers_mut() { - gather_identifier(identifier, symbol_table); - } -} - -/* Compilation Unit/Top-level construct */ - -pub(super) fn gather_compilation_unit( +pub fn gather_compilation_unit( compilation_unit: &mut CompilationUnit, symbol_table: &mut SymbolTable, + identifier_scope_ids: &mut HashMap<&Identifier, usize>, diagnostics: &mut Vec, ) { - let mut fqn_context = FqnContext::new(); - if let Some(namespace) = compilation_unit.namespace() { - fqn_context.push(&namespace.name()); - } - - symbol_table.push_scope(&format!("FileScope({})", compilation_unit.file_name())); - for use_statement in compilation_unit.use_statements_mut() { - gather_use_statement(use_statement, symbol_table, &mut fqn_context, diagnostics) - } - for declaration in compilation_unit.declarations_mut() { - gather_module_level_declaration(declaration, symbol_table, &mut fqn_context, diagnostics); - } - symbol_table.pop_scope(); - assert_eq!(symbol_table.current_scope_id(), 0); -} - -/* Use Statement */ - -fn handle_use_statement_import( - symbol_table: &mut SymbolTable, - base_name: &str, - identifier: &mut Identifier, - diagnostics: &mut Vec, -) { - let declared_name = identifier.name().to_string(); - let insert_result = symbol_table.insert_use_statement_symbol(UseStatementSymbol::new( - &format!("{}::{}", base_name, &declared_name), - &declared_name, - Some(identifier), - )); - - match insert_result { - Ok(use_statement_symbol) => { - gather_identifier(identifier, symbol_table); - - identifier.set_saved_symbol(Symbol::UseStatement(use_statement_symbol)); - } - Err(err) => { - handle_insert_error( - err, - &declared_name, - identifier.file_id(), - identifier.range(), - "Use statement", - diagnostics, - ); - } - } -} - -fn gather_use_statement( - use_statement: &mut UseStatement, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - todo!() -} - -/* Declarations allowed in each level */ - -fn gather_module_level_declaration( - declaration: &mut ModuleLevelDeclaration, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - use crate::ast::node::level::ModuleLevelDeclaration::*; - match declaration { - Module(module_declaration) => { - gather_module_declaration(module_declaration, symbol_table, fqn_context, diagnostics); - } - Interface(interface_declaration) => { - gather_interface_declaration( - interface_declaration, - symbol_table, - fqn_context, - diagnostics, - ); - } - Class(class_declaration) => { - gather_class_declaration(class_declaration, symbol_table, fqn_context, diagnostics) - } - Function(function_definition) => { - gather_function_definition(function_definition, symbol_table, fqn_context, diagnostics) - } - PlatformFunction(platform_function_definition) => { - gather_platform_function_definition( - platform_function_definition, - symbol_table, - fqn_context, - diagnostics, - ); - } - } -} - -fn gather_interface_level_declaration( - declaration: &mut InterfaceLevelDeclaration, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - use crate::ast::node::level::InterfaceLevelDeclaration::*; - match declaration { - Module(module_declaration) => { - gather_module_declaration(module_declaration, symbol_table, fqn_context, diagnostics); - } - Interface(interface_declaration) => { - gather_interface_declaration( - interface_declaration, - symbol_table, - fqn_context, - diagnostics, - ); - } - Class(class_declaration) => { - gather_class_declaration(class_declaration, symbol_table, fqn_context, diagnostics) - } - Function(interface_function_declaration) => { - gather_interface_function_declaration( - interface_function_declaration, - symbol_table, - fqn_context, - diagnostics, - ); - } - OperatorFunction(interface_operator_function_declaration) => { - gather_interface_operator_function_declaration( - interface_operator_function_declaration, - symbol_table, - fqn_context, - diagnostics, - ); - } - } -} - -fn gather_class_level_declaration( - declaration: &mut ClassLevelDeclaration, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - use crate::ast::node::level::ClassLevelDeclaration::*; - match declaration { - Module(module_declaration) => { - gather_module_declaration(module_declaration, symbol_table, fqn_context, diagnostics); - } - Interface(interface_declaration) => { - gather_interface_declaration( - interface_declaration, - symbol_table, - fqn_context, - diagnostics, - ); - } - Class(class_declaration) => { - gather_class_declaration(class_declaration, symbol_table, fqn_context, diagnostics); - } - Function(function_definition) => { - gather_function_definition(function_definition, symbol_table, fqn_context, diagnostics); - } - OperatorFunction(operator_function_definition) => { - gather_operator_function_definition( - operator_function_definition, - symbol_table, - fqn_context, - diagnostics, - ); - } - PlatformFunction(platform_function_declaration) => { - gather_platform_function_definition( - platform_function_declaration, - symbol_table, - fqn_context, - diagnostics, - ); - } - Property(property_declaration) => { - gather_property_declaration( - property_declaration, - symbol_table, - fqn_context, - diagnostics, - ); - } - Field(field_declaration) => { - gather_field_declaration(field_declaration, symbol_table, fqn_context, diagnostics); - } - } -} - -/* Main Declarations */ - -fn gather_module_declaration( - declaration: &mut ModuleDeclaration, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - // 1. Add mod identifier symbol - // 2. Push identifier on fqn_context - // 3. Push scope - // 4. Process declarations - // 5. Pop scope - // 6. Pop fqn_context - - let module_name = declaration.identifier().name(); - - let insert_result = symbol_table.insert_module_symbol(ModuleSymbol::new( - &fqn_context.resolve(&module_name), - &module_name, - declaration.is_public(), - Some(declaration.identifier()), - )); - - match insert_result { - Ok(_) => { - fqn_context.push(&module_name); - symbol_table.push_scope(&format!("ModuleScope({})", module_name)); - - for inner_declaration in declaration.declarations_mut() { - gather_module_level_declaration( - inner_declaration, - symbol_table, - fqn_context, - diagnostics, - ); - } - - symbol_table.pop_scope(); - fqn_context.pop(); - } - Err(insert_error) => handle_insert_error( - insert_error, - &module_name, - declaration.identifier().file_id(), - declaration.identifier().range(), - "Module", - diagnostics, - ), - } -} - -fn gather_interface_declaration( - declaration: &mut InterfaceDeclaration, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - let interface_name = declaration.identifier().name(); - - let insert_result = - symbol_table.insert_type_symbol(TypeSymbol::Concrete(ConcreteTypeSymbol::new( - &fqn_context.resolve(&interface_name), - &interface_name, - declaration.is_public(), - Some(declaration.identifier()), - ))); - - match insert_result { - Ok(_) => { - fqn_context.push(&interface_name); - symbol_table.push_scope(&format!("InterfaceScope({})", interface_name)); - - for inner_declaration in declaration.declarations_mut() { - gather_interface_level_declaration( - inner_declaration, - symbol_table, - fqn_context, - diagnostics, - ); - } - - symbol_table.pop_scope(); - fqn_context.pop(); - } - Err(insert_error) => { - handle_insert_error( - insert_error, - &interface_name, - declaration.identifier().file_id(), - declaration.identifier().range(), - "Interface", - diagnostics, - ); - } - } -} - -fn gather_class_declaration( - class_declaration: &mut ClassDeclaration, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - let class_name = class_declaration.identifier().name().to_string(); - - let insert_result = - symbol_table.insert_type_symbol(TypeSymbol::Concrete(ConcreteTypeSymbol::new( - &fqn_context.resolve(&class_name), - &class_name, - class_declaration.is_public(), - Some(class_declaration.identifier()), - ))); - - match insert_result { - Ok(_) => { - // Do this first so we can't implement generic parameters! - gather_implements_list( - class_declaration.implements_mut(), - symbol_table, - fqn_context, - diagnostics, - ); - - fqn_context.push(&class_name); - symbol_table.push_scope(&format!("ClassScope({})", class_name)); - - gather_generic_parameters(class_declaration.generics_mut(), symbol_table, diagnostics); - - if let Some(class_constructor) = class_declaration.class_constructor_mut() { - gather_class_constructor(class_constructor, symbol_table, fqn_context, diagnostics); - } - - for inner_declaration in class_declaration.declarations_mut() { - gather_class_level_declaration( - inner_declaration, - symbol_table, - fqn_context, - diagnostics, - ); - } - - symbol_table.pop_scope(); - fqn_context.pop(); - } - Err(insert_error) => { - handle_insert_error( - insert_error, - &class_name, - class_declaration.identifier().file_id(), - class_declaration.identifier().range(), - "interface/class", - diagnostics, - ); - } - } -} - -/* Function declarations and components */ - -fn gather_function_definition( - function: &mut FunctionDefinition, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - let declared_name = function.identifier().name(); - let resolved_name = fqn_context.resolve(&declared_name); - - let insert_result = symbol_table.insert_function_symbol(FunctionSymbol::new( - &resolved_name, - &declared_name, - function.is_public(), - false, - Some(function.identifier()), - )); - - match insert_result { - Ok(function_symbol) => { - let mut identifier = function.identifier_mut(); - identifier.set_saved_symbol(Symbol::Function(function_symbol.clone())); - identifier.set_scope_id(symbol_table.current_scope_id()); - - symbol_table.push_scope(&format!("FunctionParameterScope({})", resolved_name)); - - let parameters_result = gather_parameters( - function.parameters_mut(), - symbol_table, - fqn_context, - diagnostics, - ); - - match parameters_result { - Some(parameter_symbols) => { - function_symbol - .borrow_mut() - .set_parameters(parameter_symbols); - } - None => {} - } - - gather_return_type( - function.return_type_mut(), - symbol_table, - fqn_context, - diagnostics, - ); - - symbol_table.push_scope(&format!("FunctionBodyScope({})", resolved_name)); - - gather_function_body(function.body_mut(), symbol_table, fqn_context, diagnostics); - - symbol_table.pop_scope(); // body - symbol_table.pop_scope(); // parameters - } - Err(err) => { - handle_insert_error( - err, - &declared_name, - function.identifier().file_id(), - function.identifier().range(), - "function/variable", - diagnostics, - ); - } - } -} - -fn gather_operator_function_definition( - operator_function_definition: &mut OperatorFunctionDefinition, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - todo!() -} - -fn gather_platform_function_definition( - platform_function_declaration: &mut PlatformFunctionDeclaration, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - let declared_name = platform_function_declaration.identifier().name(); - let fully_qualified_name = fqn_context.resolve(&declared_name); - - let insert_result = symbol_table.insert_function_symbol(FunctionSymbol::new( - &fully_qualified_name, - &declared_name, - platform_function_declaration.is_public(), - true, - Some(platform_function_declaration.identifier()), - )); - - match insert_result { - Ok(function_symbol) => { - let declared_name_as_string = platform_function_declaration - .identifier() - .name() - .to_string(); - - platform_function_declaration - .identifier_mut() - .set_scope_id(symbol_table.current_scope_id()); - - symbol_table.push_scope(&format!( - "FunctionParameterScope({})", - declared_name_as_string - )); - - let parameter_symbols_result = gather_parameters( - platform_function_declaration.parameters_mut(), - symbol_table, - fqn_context, - diagnostics, - ); - - match parameter_symbols_result { - Some(parameter_symbols) => { - function_symbol - .borrow_mut() - .set_parameters(parameter_symbols); - } - None => {} - } - - gather_return_type( - platform_function_declaration.return_type_mut(), - symbol_table, - fqn_context, - diagnostics, - ); - - symbol_table.pop_scope(); - } - Err(err) => { - handle_insert_error( - err, - &declared_name, - platform_function_declaration.identifier().file_id(), - platform_function_declaration.identifier().range(), - "(Platform-) Function", - diagnostics, - ); - } - } -} - -fn gather_interface_function_declaration( - declaration: &mut InterfaceFunctionDeclaration, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - let name = declaration.identifier().name(); - let insert_result = symbol_table.insert_function_symbol(FunctionSymbol::new( - &fqn_context.resolve(&name), - &name, - true, - false, - Some(declaration.identifier()), - )); - - match insert_result { - Ok(function_symbol) => { - symbol_table.push_scope(&format!("FunctionParameterScope({})", &name)); - - gather_generic_parameters(declaration.generics_mut(), symbol_table, diagnostics); - - let parameters = gather_parameters( - declaration.parameters_mut(), - symbol_table, - fqn_context, - diagnostics, - ); - if let Some(parameter_symbols) = parameters { - function_symbol - .borrow_mut() - .set_parameters(parameter_symbols); - } - - gather_return_type( - declaration.return_type_mut(), - symbol_table, - fqn_context, - diagnostics, - ); - - if let Some(body) = declaration.body_mut() { - gather_function_body(body, symbol_table, fqn_context, diagnostics); - } - - symbol_table.pop_scope(); - } - Err(insert_error) => { - handle_insert_error( - insert_error, - &name, - declaration.identifier().file_id(), - declaration.identifier().range(), - "Interface Function", - diagnostics, - ); - } - } -} - -fn gather_interface_operator_function_declaration( - declaration: &mut InterfaceOperatorFunctionDeclaration, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - todo!() -} - -fn gather_function_body( - function_body: &mut FunctionBody, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - use crate::ast::node::function::FunctionBody::*; - match function_body { - Equals(expression) => gather_expression(expression, symbol_table, diagnostics), - Block(block) => gather_block_statement_inner(block, symbol_table, fqn_context, diagnostics), - _ => todo!(), - } -} - -/* Class Components */ - -fn gather_class_constructor( - class_constructor: &mut ClassConstructor, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - for parameter in class_constructor.parameters_mut() { - match parameter { - ClassConstructorParameter::Property(property) => { - gather_property_declaration( - property.deref_mut(), - symbol_table, - fqn_context, - diagnostics, - ); - } - ClassConstructorParameter::Field(field) => { - gather_field_declaration(field.deref_mut(), symbol_table, fqn_context, diagnostics); - } - } - } -} - -fn gather_property_declaration( - property_declaration: &mut PropertyDeclaration, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - let identifier = property_declaration.identifier(); - let insert_result = symbol_table.insert_class_member_symbol(ClassMemberSymbol::new( - &identifier.name(), - false, - Some(SourceDefinition::from_identifier(identifier)), - )); - if let Err(insert_error) = insert_result { - handle_insert_error( - insert_error, - &identifier.name(), - identifier.file_id(), - identifier.range(), - "Data Member", - diagnostics, - ); - } -} - -fn gather_field_declaration( - field_declaration: &mut FieldDeclaration, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - let identifier = field_declaration.identifier(); - let insert_result = symbol_table.insert_class_member_symbol(ClassMemberSymbol::new( - &identifier.name(), - true, - Some(SourceDefinition::from_identifier(identifier)), - )); - if let Err(insert_error) = insert_result { - handle_insert_error( - insert_error, - &identifier.name(), - identifier.file_id(), - identifier.range(), - "Data Member", - diagnostics, - ); - } -} - -/* Statements */ - -fn gather_block_statement( - block: &mut BlockStatement, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - symbol_table.push_scope("BlockStatementScope"); - gather_block_statement_inner(block, symbol_table, fqn_context, diagnostics); - symbol_table.pop_scope(); -} - -fn gather_block_statement_inner( - block: &mut BlockStatement, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - for statement in block.statements_mut() { - gather_statement(statement, symbol_table, fqn_context, diagnostics); - } - if let Some(expression) = block.expression_mut() { - gather_expression(expression, symbol_table, diagnostics); - } -} - -fn gather_statement( - statement: &mut Statement, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - use crate::ast::node::statement::Statement::*; - match statement { - BlockStatement(block) => { - gather_block_statement(block, symbol_table, fqn_context, diagnostics) - } - VariableDeclarationStatement(variable_declaration) => { - gather_variable_declaration(variable_declaration, symbol_table, diagnostics) - } - AssignStatement(assign_statement) => { - gather_assign_statement(assign_statement, symbol_table, fqn_context, diagnostics) - } - CallStatement(call_statement) => { - gather_call_statement(call_statement, symbol_table, diagnostics) - } - _ => todo!(), - } -} - -fn gather_variable_declaration( - variable_declaration: &mut VariableDeclarationStatement, - symbol_table: &mut SymbolTable, - diagnostics: &mut Vec, -) { - let identifier = variable_declaration.identifier(); - let variable_name = identifier.name(); - - let insert_result = symbol_table.insert_variable_symbol(VariableSymbol::new( - &variable_name, - variable_declaration.is_mutable(), - Some(identifier), - )); - - match insert_result { - Ok(variable_symbol) => { - let mut identifier = variable_declaration.identifier_mut(); - identifier.set_saved_symbol(Symbol::Variable(variable_symbol)); - identifier.set_scope_id(symbol_table.current_scope_id()); - } - Err(err) => handle_insert_error( - err, - &variable_name, - identifier.file_id(), - identifier.range(), - "function/variable", - diagnostics, - ), - } - - if let Some(initializer) = variable_declaration.initializer_mut() { - gather_expression(initializer, symbol_table, diagnostics); - } -} - -fn gather_assign_statement( - assign_statement: &mut AssignStatement, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - gather_expression(assign_statement.lhs_mut(), symbol_table, diagnostics); - gather_expression(assign_statement.rhs_mut(), symbol_table, diagnostics); -} - -fn gather_call_statement( - call_statement: &mut CallStatement, - symbol_table: &mut SymbolTable, - diagnostics: &mut Vec, -) { - gather_expression(call_statement.expression_mut(), symbol_table, diagnostics); -} - -fn gather_return_statement( - return_statement: &mut ReturnStatement, - symbol_table: &mut SymbolTable, - diagnostics: &mut Vec, -) { - if let Some(expression) = return_statement.expression_mut() { - gather_expression(expression, symbol_table, diagnostics); - } -} - -fn gather_if_statement( - if_statement: &mut IfStatement, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - gather_expression(if_statement.condition_mut(), symbol_table, diagnostics); - gather_block_statement( - if_statement.then_block_mut(), - symbol_table, - fqn_context, - diagnostics, - ); -} - -fn gather_if_else_statement( - if_else_statement: &mut IfElseStatement, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - gather_if_statement( - if_else_statement.if_statement_mut(), - symbol_table, - fqn_context, - diagnostics, - ); - for if_statement in if_else_statement.else_ifs_mut().if_statements_mut() { - gather_if_statement(if_statement, symbol_table, fqn_context, diagnostics); - } - if let Some(else_block) = if_else_statement.else_block_mut() { - gather_block_statement( - else_block.block_statement_mut(), - symbol_table, - fqn_context, - diagnostics, - ); - } -} - -fn gather_while_statement( - while_statement: &mut WhileStatement, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - gather_expression(while_statement.condition_mut(), symbol_table, diagnostics); - gather_block_statement( - while_statement.body_mut(), - symbol_table, - fqn_context, - diagnostics, - ); -} - -fn gather_for_statement( - for_statement: &mut ForStatement, - symbol_table: &mut SymbolTable, - fqn_context: &mut FqnContext, - diagnostics: &mut Vec, -) { - gather_expression(for_statement.iterator_mut(), symbol_table, diagnostics); - symbol_table.push_scope("ForStatementScope"); - let variable_identifier = for_statement.variable_mut(); - let insert_result = symbol_table.insert_variable_symbol(VariableSymbol::new( - &variable_identifier.name(), - false, - Some(variable_identifier), - )); - - match insert_result { - Ok(_) => { - gather_block_statement_inner( - for_statement.body_mut(), - symbol_table, - fqn_context, - diagnostics, - ); - } - Err(insert_error) => { - handle_insert_error( - insert_error, - &variable_identifier.name(), - variable_identifier.file_id(), - variable_identifier.range(), - "variable", - diagnostics, - ); - } - } - - symbol_table.pop_scope(); -} - -/* Expressions */ - -fn gather_expression( - expression: &mut Expression, - symbol_table: &mut SymbolTable, - diagnostics: &mut Vec, -) { - use crate::ast::node::expression::Expression::*; - match expression { - Ternary(ternary_expression) => { - gather_ternary_expression(ternary_expression, symbol_table, diagnostics); - } - Binary(binary_expression) => { - gather_binary_expression(binary_expression, symbol_table, diagnostics); - } - UnaryPrefix(prefix_expression) => { - gather_prefix_expression(prefix_expression, symbol_table, diagnostics); - } - UnarySuffix(suffix_expression) => { - gather_suffix_expression(suffix_expression, symbol_table, diagnostics); - } - Call(call_expression) => { - gather_call_expression(call_expression, symbol_table, diagnostics); - } - ObjectAccess(object_access) => { - gather_object_access(object_access, symbol_table, diagnostics); - } - Literal(literal) => { - gather_literal(literal, symbol_table, diagnostics); - } - FullyQualifiedName(fully_qualified_name) => { - gather_fully_qualified_name(fully_qualified_name, symbol_table); - } - Closure(closure) => { - gather_closure(closure, symbol_table, diagnostics); - } - } -} - -fn gather_ternary_expression( - ternary_expression: &mut TernaryExpression, - symbol_table: &mut SymbolTable, - diagnostics: &mut Vec, -) { - gather_expression( - ternary_expression.condition_mut(), - symbol_table, - diagnostics, - ); - gather_expression( - ternary_expression.true_expression_mut(), - symbol_table, - diagnostics, - ); - gather_expression( - ternary_expression.false_expression_mut(), - symbol_table, - diagnostics, - ); -} - -fn gather_binary_expression( - binary_expression: &mut BinaryExpression, - symbol_table: &mut SymbolTable, - diagnostics: &mut Vec, -) { - gather_expression(binary_expression.left_mut(), symbol_table, diagnostics); - gather_expression(binary_expression.right_mut(), symbol_table, diagnostics); -} - -fn gather_prefix_expression( - prefix_expression: &mut PrefixExpression, - symbol_table: &mut SymbolTable, - diagnostics: &mut Vec, -) { - gather_expression( - prefix_expression.expression_mut(), - symbol_table, - diagnostics, - ); -} - -fn gather_suffix_expression( - suffix_expression: &mut SuffixExpression, - symbol_table: &mut SymbolTable, - diagnostics: &mut Vec, -) { - gather_expression( - suffix_expression.expression_mut(), - symbol_table, - diagnostics, - ); -} - -fn gather_call_expression( - call_expression: &mut CallExpression, - symbol_table: &mut SymbolTable, - diagnostics: &mut Vec, -) { - gather_expression(call_expression.callee_mut(), symbol_table, diagnostics); - if let Some(turbo_fish) = call_expression.turbo_fish_mut() { - gather_turbo_fish(turbo_fish, symbol_table, diagnostics); - } - for call_argument in call_expression.arguments_mut().arguments_mut() { - gather_expression(call_argument.expression_mut(), symbol_table, diagnostics); - } -} - -fn gather_turbo_fish( - turbo_fish: &mut TurboFish, - symbol_table: &mut SymbolTable, - diagnostics: &mut Vec, -) { - todo!() -} - -fn gather_closure( - closure: &mut Closure, - symbol_table: &mut SymbolTable, - diagnostics: &mut Vec, -) { - todo!() -} - -fn gather_object_access( - object_access: &mut ObjectAccess, - symbol_table: &mut SymbolTable, - diagnostics: &mut Vec, -) { - gather_expression(object_access.receiver_mut(), symbol_table, diagnostics); - for object_navigation in object_access.navigations_mut().navigations_mut() { - match object_navigation { - ObjectNavigation::Index(index_expression) => { - gather_expression(index_expression, symbol_table, diagnostics); - } - ObjectNavigation::Identifier(identifier) => { - // TODO: use a special gather for names belonging to a struct - gather_identifier(identifier, symbol_table); - } - } - } -} - -fn gather_literal( - literal: &mut Literal, - symbol_table: &mut SymbolTable, - diagnostics: &mut Vec, -) { - match literal { - Literal::DString(d_string) => gather_d_string(d_string, symbol_table, diagnostics), - Literal::BacktickString(backtick_string) => { - gather_d_string(backtick_string, symbol_table, diagnostics) - } - _ => {} - } -} - -fn gather_d_string( - d_string: &mut DString, - symbol_table: &mut SymbolTable, - diagnostics: &mut Vec, -) { - todo!() + walk_depth_first(compilation_unit, &mut |child| match child { + AstNodeRef::Operator(_) => {} + AstNodeRef::Identifier(identifier) => { + gather_identifier(&identifier, symbol_table, identifier_scope_ids); + } + AstNodeRef::FullyQualifiedName(_) => {} + AstNodeRef::TypeUseList(_) => {} + AstNodeRef::IdentifierList(_) => {} + AstNodeRef::ParenthesesOptionalTypeUseList(_) => {} + AstNodeRef::TypeUse(_) => {} + AstNodeRef::PrimitiveType(_) => {} + AstNodeRef::TypedArray(_) => {} + AstNodeRef::InterfaceOrClassTypeUse(_) => {} + AstNodeRef::TupleTypeUse(_) => {} + AstNodeRef::FunctionTypeUse(_) => {} + AstNodeRef::GenericArguments(_) => {} + AstNodeRef::GenericParameters(_) => {} + AstNodeRef::TupleArguments(_) => {} + AstNodeRef::ImplementsList(_) => {} + AstNodeRef::Parameters(_) => {} + AstNodeRef::Parameter(_) => {} + AstNodeRef::ReturnType(_) => {} + AstNodeRef::CompilationUnit(_) => {} + AstNodeRef::ParentMod(_) => {} + AstNodeRef::UseStatement(_) => {} + AstNodeRef::UseStatementPrefix(_) => {} + AstNodeRef::UseStatementSuffix(_) => {} + AstNodeRef::UseList(_) => {} + AstNodeRef::ModuleLevelDeclaration(_) => {} + AstNodeRef::InterfaceLevelDeclaration(_) => {} + AstNodeRef::ClassLevelDeclaration(_) => {} + AstNodeRef::Module(_) => {} + AstNodeRef::CompanionModule(_) => {} + AstNodeRef::Interface(_) => {} + AstNodeRef::Class(_) => {} + AstNodeRef::Function(_) => {} + AstNodeRef::OperatorFunction(_) => {} + AstNodeRef::PlatformFunction(_) => {} + AstNodeRef::InterfaceFunction(_) => {} + AstNodeRef::InterfaceDefaultFunction(_) => {} + AstNodeRef::InterfaceOperatorFunction(_) => {} + AstNodeRef::InterfaceDefaultOperatorFunction(_) => {} + AstNodeRef::FunctionBody(_) => {} + AstNodeRef::FunctionEqualsBody(_) => {} + AstNodeRef::FunctionAliasBody(_) => {} + AstNodeRef::FunctionBlockBody(_) => {} + AstNodeRef::ClassConstructor(_) => {} + AstNodeRef::Member(_) => {} + AstNodeRef::Statement(_) => {} + AstNodeRef::VariableDeclaration(_) => {} + AstNodeRef::AssignmentStatement(_) => {} + AstNodeRef::ExpressionStatement(_) => {} + AstNodeRef::IfStatement(_) => {} + AstNodeRef::IfClause(_) => {} + AstNodeRef::IfElseIf(_) => {} + AstNodeRef::IfElse(_) => {} + AstNodeRef::WhileStatement(_) => {} + AstNodeRef::ForStatement(_) => {} + AstNodeRef::Expression(_) => {} + AstNodeRef::TernaryExpression(_) => {} + AstNodeRef::TernaryRhs(_) => {} + AstNodeRef::OrExpression(_) => {} + AstNodeRef::OrRhs(_) => {} + AstNodeRef::AndExpression(_) => {} + AstNodeRef::AndRhs(_) => {} + AstNodeRef::ComparisonExpression(_) => {} + AstNodeRef::ComparisonRhs(_) => {} + AstNodeRef::ComparisonOperator(_) => {} + AstNodeRef::ShiftExpression(_) => {} + AstNodeRef::ShiftRhs(_) => {} + AstNodeRef::ShiftOperator(_) => {} + AstNodeRef::AdditiveExpression(_) => {} + AstNodeRef::AdditiveRhs(_) => {} + AstNodeRef::AdditiveOperator(_) => {} + AstNodeRef::MultiplicativeExpression(_) => {} + AstNodeRef::MultiplicativeRhs(_) => {} + AstNodeRef::MultiplicativeOperator(_) => {} + AstNodeRef::PrefixExpression(_) => {} + AstNodeRef::PrefixOperator(_) => {} + AstNodeRef::SuffixExpression(_) => {} + AstNodeRef::SuffixOperator(_) => {} + AstNodeRef::ObjectProperty(_) => {} + AstNodeRef::ObjectIndex(_) => {} + AstNodeRef::ListExpression(_) => {} + AstNodeRef::Call(_) => {} + AstNodeRef::ParenthesesCall(_) => {} + AstNodeRef::NonParenthesesCall(_) => {} + AstNodeRef::TurboFish(_) => {} + AstNodeRef::ExpressionList(_) => {} + AstNodeRef::Closure(_) => {} + AstNodeRef::ClosureParameters(_) => {} + AstNodeRef::ClosureParameter(_) => {} + AstNodeRef::Literal(_) => {} + AstNodeRef::DString(_) => {} + AstNodeRef::DStringExpression(_) => {} + AstNodeRef::BacktickString(_) => {} + }); } diff --git a/src/name_analysis/gather.rs.bak b/src/name_analysis/gather.rs.bak new file mode 100644 index 0000000..e73145e --- /dev/null +++ b/src/name_analysis/gather.rs.bak @@ -0,0 +1,1320 @@ +use crate::ast::node::*; +use crate::diagnostic::DmDiagnostic; +use crate::name_analysis::fqn_context::FqnContext; +use crate::name_analysis::symbol::*; +use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable}; +use codespan_reporting::diagnostic::{Diagnostic, Label}; +use std::ops::DerefMut; +use std::range::Range; +use std::rc::Rc; + +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, + )) + .with_label( + Label::primary(error_file_id, error_range) + .with_message("Symbol duplicated here."), + ); + + if let Some(source_definition) = s.definition() { + diagnostic = diagnostic.with_label( + Label::secondary(source_definition.file_id(), source_definition.range()) + .with_message("Symbol defined here."), + ); + } + + diagnostics.push(diagnostic); + } + } +} + +/* Names */ + +fn gather_identifier(identifier: &mut Identifier, symbol_table: &mut SymbolTable) { + identifier.set_scope_id(symbol_table.current_scope_id()); +} + +fn gather_fully_qualified_name( + fully_qualified_name: &mut FullyQualifiedName, + symbol_table: &mut SymbolTable, +) { + gather_identifier(fully_qualified_name.last_mut(), symbol_table); +} + +/* Type Use */ + +fn gather_type_use( + type_use: &mut TypeUse, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + match type_use { + TypeUse::Primitive(primitive_type_use) => { + gather_primitive_type_use(primitive_type_use, symbol_table, fqn_context, diagnostics) + } + TypeUse::InterfaceOrClass(interface_or_class_type_use) => { + gather_interface_or_class_type_use( + interface_or_class_type_use, + symbol_table, + fqn_context, + diagnostics, + ); + } + TypeUse::Tuple(tuple_type_use) => { + gather_tuple_type_use(tuple_type_use, symbol_table, fqn_context, diagnostics); + } + TypeUse::Function(function_type_use) => { + gather_function_type_use(function_type_use, symbol_table, fqn_context, diagnostics); + } + } +} + +fn gather_primitive_type_use( + primitive_type_use: &mut PrimitiveTypeUse, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + match primitive_type_use { + PrimitiveTypeUse::Array(generic_arguments_opt) => { + if let Some(generic_arguments) = generic_arguments_opt { + gather_generic_arguments(generic_arguments, symbol_table, fqn_context, diagnostics); + } + } + _ => {} + } +} + +fn gather_interface_or_class_type_use( + interface_or_class_type_use: &mut InterfaceOrClassTypeUse, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + gather_fully_qualified_name(interface_or_class_type_use.fqn_mut(), symbol_table); + gather_generic_arguments( + interface_or_class_type_use.generics_mut(), + symbol_table, + fqn_context, + diagnostics, + ); +} + +fn gather_tuple_type_use( + tuple_type_use: &mut TupleTypeUse, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + for generic_argument in tuple_type_use.arguments_mut().type_uses_mut() { + gather_type_use(generic_argument, symbol_table, fqn_context, diagnostics); + } +} + +fn gather_function_type_use( + function_type_use: &mut FunctionTypeUse, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + symbol_table.push_scope("FunctionTypeUseScope"); + gather_generic_parameters(function_type_use.generics_mut(), symbol_table, diagnostics); + gather_parameters( + function_type_use.parameters_mut(), + symbol_table, + fqn_context, + diagnostics, + ); + gather_return_type( + function_type_use.return_type_mut(), + symbol_table, + fqn_context, + diagnostics, + ); + symbol_table.pop_scope(); +} + +/* Generic Arguments */ + +fn gather_generic_arguments( + generic_arguments: &mut GenericArguments, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + for argument in generic_arguments.arguments_mut() { + gather_type_use(argument, symbol_table, fqn_context, diagnostics); + } +} + +/* Generic Parameters */ + +fn gather_generic_parameters( + generic_parameters: &mut GenericParameters, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + for identifier in generic_parameters.identifiers_mut() { + let insert_result = + symbol_table.insert_type_symbol(TypeSymbol::Generic(GenericTypeSymbol::new( + &identifier.name(), + SourceDefinition::from_identifier(identifier), + ))); + match insert_result { + Ok(_) => {} + Err(insert_error) => { + handle_insert_error( + insert_error, + &identifier.name(), + identifier.file_id(), + identifier.range(), + "Type", + diagnostics, + ); + } + } + } +} + +/* Implements List */ + +fn gather_implements_list( + implements_list: &mut ImplementsList, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + for type_use in implements_list.type_uses_mut() { + gather_type_use(type_use, symbol_table, fqn_context, diagnostics); + } +} + +/* Function Parameters */ + +fn gather_parameters( + parameters: &mut Parameters, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) -> Option>> { + parameters + .parameters_mut() + .iter_mut() + .map(|parameter| gather_parameter(parameter, symbol_table, fqn_context, diagnostics)) + .collect() +} + +fn gather_parameter( + parameter: &mut Parameter, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) -> Option> { + let parameter_name = parameter.identifier().name(); + + let insert_result = symbol_table.insert_parameter_symbol(ParameterSymbol::new( + ¶meter_name, + Some(¶meter.identifier()), + )); + + match insert_result { + Ok(parameter_symbol) => { + let mut identifier = parameter.identifier_mut(); + identifier.set_scope_id(symbol_table.current_scope_id()); + identifier.set_saved_symbol(Symbol::Parameter(parameter_symbol.clone())); + + gather_type_use( + parameter.type_use_mut(), + symbol_table, + fqn_context, + diagnostics, + ); + Some(parameter_symbol) + } + Err(err) => { + handle_insert_error( + err, + ¶meter_name, + parameter.identifier().file_id(), + parameter.identifier().range(), + "function/variable", + diagnostics, + ); + None + } + } +} + +/* Return Type */ + +fn gather_return_type( + return_type: &mut ReturnType, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + gather_type_use( + return_type.declared_type_mut(), + symbol_table, + fqn_context, + diagnostics, + ); + gather_references(return_type.references_mut(), symbol_table); +} + +/* References */ + +fn gather_references(references: &mut References, symbol_table: &mut SymbolTable) { + for identifier in references.identifiers_mut() { + gather_identifier(identifier, symbol_table); + } +} + +/* Compilation Unit/Top-level construct */ + +pub(super) fn gather_compilation_unit( + compilation_unit: &mut CompilationUnit, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + let mut fqn_context = FqnContext::new(); + if let Some(namespace) = compilation_unit.namespace() { + fqn_context.push(&namespace.name()); + } + + symbol_table.push_scope(&format!("FileScope({})", compilation_unit.file_name())); + for use_statement in compilation_unit.use_statements_mut() { + gather_use_statement(use_statement, symbol_table, &mut fqn_context, diagnostics) + } + for declaration in compilation_unit.declarations_mut() { + gather_module_level_declaration(declaration, symbol_table, &mut fqn_context, diagnostics); + } + symbol_table.pop_scope(); + assert_eq!(symbol_table.current_scope_id(), 0); +} + +/* Use Statement */ + +fn handle_use_statement_import( + symbol_table: &mut SymbolTable, + base_name: &str, + identifier: &mut Identifier, + diagnostics: &mut Vec, +) { + let declared_name = identifier.name().to_string(); + let insert_result = symbol_table.insert_use_statement_symbol(UseStatementSymbol::new( + &format!("{}::{}", base_name, &declared_name), + &declared_name, + Some(identifier), + )); + + match insert_result { + Ok(use_statement_symbol) => { + gather_identifier(identifier, symbol_table); + + identifier.set_saved_symbol(Symbol::UseStatement(use_statement_symbol)); + } + Err(err) => { + handle_insert_error( + err, + &declared_name, + identifier.file_id(), + identifier.range(), + "Use statement", + diagnostics, + ); + } + } +} + +fn gather_use_statement( + use_statement: &mut UseStatement, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + todo!() +} + +/* Declarations allowed in each level */ + +fn gather_module_level_declaration( + declaration: &mut ModuleLevelDeclaration, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + use crate::ast::node::level::ModuleLevelDeclaration::*; + match declaration { + Module(module_declaration) => { + gather_module_declaration(module_declaration, symbol_table, fqn_context, diagnostics); + } + Interface(interface_declaration) => { + gather_interface_declaration( + interface_declaration, + symbol_table, + fqn_context, + diagnostics, + ); + } + Class(class_declaration) => { + gather_class_declaration(class_declaration, symbol_table, fqn_context, diagnostics) + } + Function(function_definition) => { + gather_function_definition(function_definition, symbol_table, fqn_context, diagnostics) + } + PlatformFunction(platform_function_definition) => { + gather_platform_function_definition( + platform_function_definition, + symbol_table, + fqn_context, + diagnostics, + ); + } + } +} + +fn gather_interface_level_declaration( + declaration: &mut InterfaceLevelDeclaration, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + use crate::ast::node::level::InterfaceLevelDeclaration::*; + match declaration { + Module(module_declaration) => { + gather_module_declaration(module_declaration, symbol_table, fqn_context, diagnostics); + } + Interface(interface_declaration) => { + gather_interface_declaration( + interface_declaration, + symbol_table, + fqn_context, + diagnostics, + ); + } + Class(class_declaration) => { + gather_class_declaration(class_declaration, symbol_table, fqn_context, diagnostics) + } + Function(interface_function_declaration) => { + gather_interface_function_declaration( + interface_function_declaration, + symbol_table, + fqn_context, + diagnostics, + ); + } + OperatorFunction(interface_operator_function_declaration) => { + gather_interface_operator_function_declaration( + interface_operator_function_declaration, + symbol_table, + fqn_context, + diagnostics, + ); + } + } +} + +fn gather_class_level_declaration( + declaration: &mut ClassLevelDeclaration, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + use crate::ast::node::level::ClassLevelDeclaration::*; + match declaration { + Module(module_declaration) => { + gather_module_declaration(module_declaration, symbol_table, fqn_context, diagnostics); + } + Interface(interface_declaration) => { + gather_interface_declaration( + interface_declaration, + symbol_table, + fqn_context, + diagnostics, + ); + } + Class(class_declaration) => { + gather_class_declaration(class_declaration, symbol_table, fqn_context, diagnostics); + } + Function(function_definition) => { + gather_function_definition(function_definition, symbol_table, fqn_context, diagnostics); + } + OperatorFunction(operator_function_definition) => { + gather_operator_function_definition( + operator_function_definition, + symbol_table, + fqn_context, + diagnostics, + ); + } + PlatformFunction(platform_function_declaration) => { + gather_platform_function_definition( + platform_function_declaration, + symbol_table, + fqn_context, + diagnostics, + ); + } + Property(property_declaration) => { + gather_property_declaration( + property_declaration, + symbol_table, + fqn_context, + diagnostics, + ); + } + Field(field_declaration) => { + gather_field_declaration(field_declaration, symbol_table, fqn_context, diagnostics); + } + } +} + +/* Main Declarations */ + +fn gather_module_declaration( + declaration: &mut ModuleDeclaration, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + // 1. Add mod identifier symbol + // 2. Push identifier on fqn_context + // 3. Push scope + // 4. Process declarations + // 5. Pop scope + // 6. Pop fqn_context + + let module_name = declaration.identifier().name(); + + let insert_result = symbol_table.insert_module_symbol(ModuleSymbol::new( + &fqn_context.resolve(&module_name), + &module_name, + declaration.is_public(), + Some(declaration.identifier()), + )); + + match insert_result { + Ok(_) => { + fqn_context.push(&module_name); + symbol_table.push_scope(&format!("ModuleScope({})", module_name)); + + for inner_declaration in declaration.declarations_mut() { + gather_module_level_declaration( + inner_declaration, + symbol_table, + fqn_context, + diagnostics, + ); + } + + symbol_table.pop_scope(); + fqn_context.pop(); + } + Err(insert_error) => handle_insert_error( + insert_error, + &module_name, + declaration.identifier().file_id(), + declaration.identifier().range(), + "Module", + diagnostics, + ), + } +} + +fn gather_interface_declaration( + declaration: &mut InterfaceDeclaration, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + let interface_name = declaration.identifier().name(); + + let insert_result = + symbol_table.insert_type_symbol(TypeSymbol::Concrete(ConcreteTypeSymbol::new( + &fqn_context.resolve(&interface_name), + &interface_name, + declaration.is_public(), + Some(declaration.identifier()), + ))); + + match insert_result { + Ok(_) => { + fqn_context.push(&interface_name); + symbol_table.push_scope(&format!("InterfaceScope({})", interface_name)); + + for inner_declaration in declaration.declarations_mut() { + gather_interface_level_declaration( + inner_declaration, + symbol_table, + fqn_context, + diagnostics, + ); + } + + symbol_table.pop_scope(); + fqn_context.pop(); + } + Err(insert_error) => { + handle_insert_error( + insert_error, + &interface_name, + declaration.identifier().file_id(), + declaration.identifier().range(), + "Interface", + diagnostics, + ); + } + } +} + +fn gather_class_declaration( + class_declaration: &mut ClassDeclaration, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + let class_name = class_declaration.identifier().name().to_string(); + + let insert_result = + symbol_table.insert_type_symbol(TypeSymbol::Concrete(ConcreteTypeSymbol::new( + &fqn_context.resolve(&class_name), + &class_name, + class_declaration.is_public(), + Some(class_declaration.identifier()), + ))); + + match insert_result { + Ok(_) => { + // Do this first so we can't implement generic parameters! + gather_implements_list( + class_declaration.implements_mut(), + symbol_table, + fqn_context, + diagnostics, + ); + + fqn_context.push(&class_name); + symbol_table.push_scope(&format!("ClassScope({})", class_name)); + + gather_generic_parameters(class_declaration.generics_mut(), symbol_table, diagnostics); + + if let Some(class_constructor) = class_declaration.class_constructor_mut() { + gather_class_constructor(class_constructor, symbol_table, fqn_context, diagnostics); + } + + for inner_declaration in class_declaration.declarations_mut() { + gather_class_level_declaration( + inner_declaration, + symbol_table, + fqn_context, + diagnostics, + ); + } + + symbol_table.pop_scope(); + fqn_context.pop(); + } + Err(insert_error) => { + handle_insert_error( + insert_error, + &class_name, + class_declaration.identifier().file_id(), + class_declaration.identifier().range(), + "interface/class", + diagnostics, + ); + } + } +} + +/* Function declarations and components */ + +fn gather_function_definition( + function: &mut FunctionDefinition, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + let declared_name = function.identifier().name(); + let resolved_name = fqn_context.resolve(&declared_name); + + let insert_result = symbol_table.insert_function_symbol(FunctionSymbol::new( + &resolved_name, + &declared_name, + function.is_public(), + false, + Some(function.identifier()), + )); + + match insert_result { + Ok(function_symbol) => { + let mut identifier = function.identifier_mut(); + identifier.set_saved_symbol(Symbol::Function(function_symbol.clone())); + identifier.set_scope_id(symbol_table.current_scope_id()); + + symbol_table.push_scope(&format!("FunctionParameterScope({})", resolved_name)); + + let parameters_result = gather_parameters( + function.parameters_mut(), + symbol_table, + fqn_context, + diagnostics, + ); + + match parameters_result { + Some(parameter_symbols) => { + function_symbol + .borrow_mut() + .set_parameters(parameter_symbols); + } + None => {} + } + + gather_return_type( + function.return_type_mut(), + symbol_table, + fqn_context, + diagnostics, + ); + + symbol_table.push_scope(&format!("FunctionBodyScope({})", resolved_name)); + + gather_function_body(function.body_mut(), symbol_table, fqn_context, diagnostics); + + symbol_table.pop_scope(); // body + symbol_table.pop_scope(); // parameters + } + Err(err) => { + handle_insert_error( + err, + &declared_name, + function.identifier().file_id(), + function.identifier().range(), + "function/variable", + diagnostics, + ); + } + } +} + +fn gather_operator_function_definition( + operator_function_definition: &mut OperatorFunctionDefinition, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + todo!() +} + +fn gather_platform_function_definition( + platform_function_declaration: &mut PlatformFunctionDeclaration, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + let declared_name = platform_function_declaration.identifier().name(); + let fully_qualified_name = fqn_context.resolve(&declared_name); + + let insert_result = symbol_table.insert_function_symbol(FunctionSymbol::new( + &fully_qualified_name, + &declared_name, + platform_function_declaration.is_public(), + true, + Some(platform_function_declaration.identifier()), + )); + + match insert_result { + Ok(function_symbol) => { + let declared_name_as_string = platform_function_declaration + .identifier() + .name() + .to_string(); + + platform_function_declaration + .identifier_mut() + .set_scope_id(symbol_table.current_scope_id()); + + symbol_table.push_scope(&format!( + "FunctionParameterScope({})", + declared_name_as_string + )); + + let parameter_symbols_result = gather_parameters( + platform_function_declaration.parameters_mut(), + symbol_table, + fqn_context, + diagnostics, + ); + + match parameter_symbols_result { + Some(parameter_symbols) => { + function_symbol + .borrow_mut() + .set_parameters(parameter_symbols); + } + None => {} + } + + gather_return_type( + platform_function_declaration.return_type_mut(), + symbol_table, + fqn_context, + diagnostics, + ); + + symbol_table.pop_scope(); + } + Err(err) => { + handle_insert_error( + err, + &declared_name, + platform_function_declaration.identifier().file_id(), + platform_function_declaration.identifier().range(), + "(Platform-) Function", + diagnostics, + ); + } + } +} + +fn gather_interface_function_declaration( + declaration: &mut InterfaceFunctionDeclaration, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + let name = declaration.identifier().name(); + let insert_result = symbol_table.insert_function_symbol(FunctionSymbol::new( + &fqn_context.resolve(&name), + &name, + true, + false, + Some(declaration.identifier()), + )); + + match insert_result { + Ok(function_symbol) => { + symbol_table.push_scope(&format!("FunctionParameterScope({})", &name)); + + gather_generic_parameters(declaration.generics_mut(), symbol_table, diagnostics); + + let parameters = gather_parameters( + declaration.parameters_mut(), + symbol_table, + fqn_context, + diagnostics, + ); + if let Some(parameter_symbols) = parameters { + function_symbol + .borrow_mut() + .set_parameters(parameter_symbols); + } + + gather_return_type( + declaration.return_type_mut(), + symbol_table, + fqn_context, + diagnostics, + ); + + if let Some(body) = declaration.body_mut() { + gather_function_body(body, symbol_table, fqn_context, diagnostics); + } + + symbol_table.pop_scope(); + } + Err(insert_error) => { + handle_insert_error( + insert_error, + &name, + declaration.identifier().file_id(), + declaration.identifier().range(), + "Interface Function", + diagnostics, + ); + } + } +} + +fn gather_interface_operator_function_declaration( + declaration: &mut InterfaceOperatorFunctionDeclaration, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + todo!() +} + +fn gather_function_body( + function_body: &mut FunctionBody, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + use crate::ast::node::function::FunctionBody::*; + match function_body { + Equals(expression) => gather_expression(expression, symbol_table, diagnostics), + Block(block) => gather_block_statement_inner(block, symbol_table, fqn_context, diagnostics), + _ => todo!(), + } +} + +/* Class Components */ + +fn gather_class_constructor( + class_constructor: &mut ClassConstructor, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + for parameter in class_constructor.parameters_mut() { + match parameter { + ClassConstructorParameter::Property(property) => { + gather_property_declaration( + property.deref_mut(), + symbol_table, + fqn_context, + diagnostics, + ); + } + ClassConstructorParameter::Field(field) => { + gather_field_declaration(field.deref_mut(), symbol_table, fqn_context, diagnostics); + } + } + } +} + +fn gather_property_declaration( + property_declaration: &mut PropertyDeclaration, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + let identifier = property_declaration.identifier(); + let insert_result = symbol_table.insert_class_member_symbol(ClassMemberSymbol::new( + &identifier.name(), + false, + Some(SourceDefinition::from_identifier(identifier)), + )); + if let Err(insert_error) = insert_result { + handle_insert_error( + insert_error, + &identifier.name(), + identifier.file_id(), + identifier.range(), + "Data Member", + diagnostics, + ); + } +} + +fn gather_field_declaration( + field_declaration: &mut FieldDeclaration, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + let identifier = field_declaration.identifier(); + let insert_result = symbol_table.insert_class_member_symbol(ClassMemberSymbol::new( + &identifier.name(), + true, + Some(SourceDefinition::from_identifier(identifier)), + )); + if let Err(insert_error) = insert_result { + handle_insert_error( + insert_error, + &identifier.name(), + identifier.file_id(), + identifier.range(), + "Data Member", + diagnostics, + ); + } +} + +/* Statements */ + +fn gather_block_statement( + block: &mut BlockStatement, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + symbol_table.push_scope("BlockStatementScope"); + gather_block_statement_inner(block, symbol_table, fqn_context, diagnostics); + symbol_table.pop_scope(); +} + +fn gather_block_statement_inner( + block: &mut BlockStatement, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + for statement in block.statements_mut() { + gather_statement(statement, symbol_table, fqn_context, diagnostics); + } + if let Some(expression) = block.expression_mut() { + gather_expression(expression, symbol_table, diagnostics); + } +} + +fn gather_statement( + statement: &mut Statement, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + use crate::ast::node::statement::Statement::*; + match statement { + BlockStatement(block) => { + gather_block_statement(block, symbol_table, fqn_context, diagnostics) + } + VariableDeclarationStatement(variable_declaration) => { + gather_variable_declaration(variable_declaration, symbol_table, diagnostics) + } + AssignStatement(assign_statement) => { + gather_assign_statement(assign_statement, symbol_table, fqn_context, diagnostics) + } + CallStatement(call_statement) => { + gather_call_statement(call_statement, symbol_table, diagnostics) + } + _ => todo!(), + } +} + +fn gather_variable_declaration( + variable_declaration: &mut VariableDeclarationStatement, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + let identifier = variable_declaration.identifier(); + let variable_name = identifier.name(); + + let insert_result = symbol_table.insert_variable_symbol(VariableSymbol::new( + &variable_name, + variable_declaration.is_mutable(), + Some(identifier), + )); + + match insert_result { + Ok(variable_symbol) => { + let mut identifier = variable_declaration.identifier_mut(); + identifier.set_saved_symbol(Symbol::Variable(variable_symbol)); + identifier.set_scope_id(symbol_table.current_scope_id()); + } + Err(err) => handle_insert_error( + err, + &variable_name, + identifier.file_id(), + identifier.range(), + "function/variable", + diagnostics, + ), + } + + if let Some(initializer) = variable_declaration.initializer_mut() { + gather_expression(initializer, symbol_table, diagnostics); + } +} + +fn gather_assign_statement( + assign_statement: &mut AssignStatement, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + gather_expression(assign_statement.lhs_mut(), symbol_table, diagnostics); + gather_expression(assign_statement.rhs_mut(), symbol_table, diagnostics); +} + +fn gather_call_statement( + call_statement: &mut CallStatement, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + gather_expression(call_statement.expression_mut(), symbol_table, diagnostics); +} + +fn gather_return_statement( + return_statement: &mut ReturnStatement, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + if let Some(expression) = return_statement.expression_mut() { + gather_expression(expression, symbol_table, diagnostics); + } +} + +fn gather_if_statement( + if_statement: &mut IfStatement, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + gather_expression(if_statement.condition_mut(), symbol_table, diagnostics); + gather_block_statement( + if_statement.then_block_mut(), + symbol_table, + fqn_context, + diagnostics, + ); +} + +fn gather_if_else_statement( + if_else_statement: &mut IfElseStatement, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + gather_if_statement( + if_else_statement.if_statement_mut(), + symbol_table, + fqn_context, + diagnostics, + ); + for if_statement in if_else_statement.else_ifs_mut().if_statements_mut() { + gather_if_statement(if_statement, symbol_table, fqn_context, diagnostics); + } + if let Some(else_block) = if_else_statement.else_block_mut() { + gather_block_statement( + else_block.block_statement_mut(), + symbol_table, + fqn_context, + diagnostics, + ); + } +} + +fn gather_while_statement( + while_statement: &mut WhileStatement, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + gather_expression(while_statement.condition_mut(), symbol_table, diagnostics); + gather_block_statement( + while_statement.body_mut(), + symbol_table, + fqn_context, + diagnostics, + ); +} + +fn gather_for_statement( + for_statement: &mut ForStatement, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + diagnostics: &mut Vec, +) { + gather_expression(for_statement.iterator_mut(), symbol_table, diagnostics); + symbol_table.push_scope("ForStatementScope"); + let variable_identifier = for_statement.variable_mut(); + let insert_result = symbol_table.insert_variable_symbol(VariableSymbol::new( + &variable_identifier.name(), + false, + Some(variable_identifier), + )); + + match insert_result { + Ok(_) => { + gather_block_statement_inner( + for_statement.body_mut(), + symbol_table, + fqn_context, + diagnostics, + ); + } + Err(insert_error) => { + handle_insert_error( + insert_error, + &variable_identifier.name(), + variable_identifier.file_id(), + variable_identifier.range(), + "variable", + diagnostics, + ); + } + } + + symbol_table.pop_scope(); +} + +/* Expressions */ + +fn gather_expression( + expression: &mut Expression, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + use crate::ast::node::expression::Expression::*; + match expression { + Ternary(ternary_expression) => { + gather_ternary_expression(ternary_expression, symbol_table, diagnostics); + } + Binary(binary_expression) => { + gather_binary_expression(binary_expression, symbol_table, diagnostics); + } + UnaryPrefix(prefix_expression) => { + gather_prefix_expression(prefix_expression, symbol_table, diagnostics); + } + UnarySuffix(suffix_expression) => { + gather_suffix_expression(suffix_expression, symbol_table, diagnostics); + } + Call(call_expression) => { + gather_call_expression(call_expression, symbol_table, diagnostics); + } + ObjectAccess(object_access) => { + gather_object_access(object_access, symbol_table, diagnostics); + } + Literal(literal) => { + gather_literal(literal, symbol_table, diagnostics); + } + FullyQualifiedName(fully_qualified_name) => { + gather_fully_qualified_name(fully_qualified_name, symbol_table); + } + Closure(closure) => { + gather_closure(closure, symbol_table, diagnostics); + } + } +} + +fn gather_ternary_expression( + ternary_expression: &mut TernaryExpression, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + gather_expression( + ternary_expression.condition_mut(), + symbol_table, + diagnostics, + ); + gather_expression( + ternary_expression.true_expression_mut(), + symbol_table, + diagnostics, + ); + gather_expression( + ternary_expression.false_expression_mut(), + symbol_table, + diagnostics, + ); +} + +fn gather_binary_expression( + binary_expression: &mut BinaryExpression, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + gather_expression(binary_expression.left_mut(), symbol_table, diagnostics); + gather_expression(binary_expression.right_mut(), symbol_table, diagnostics); +} + +fn gather_prefix_expression( + prefix_expression: &mut PrefixExpression, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + gather_expression( + prefix_expression.expression_mut(), + symbol_table, + diagnostics, + ); +} + +fn gather_suffix_expression( + suffix_expression: &mut SuffixExpression, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + gather_expression( + suffix_expression.expression_mut(), + symbol_table, + diagnostics, + ); +} + +fn gather_call_expression( + call_expression: &mut CallExpression, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + gather_expression(call_expression.callee_mut(), symbol_table, diagnostics); + if let Some(turbo_fish) = call_expression.turbo_fish_mut() { + gather_turbo_fish(turbo_fish, symbol_table, diagnostics); + } + for call_argument in call_expression.arguments_mut().arguments_mut() { + gather_expression(call_argument.expression_mut(), symbol_table, diagnostics); + } +} + +fn gather_turbo_fish( + turbo_fish: &mut TurboFish, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + todo!() +} + +fn gather_closure( + closure: &mut Closure, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + todo!() +} + +fn gather_object_access( + object_access: &mut ObjectAccess, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + gather_expression(object_access.receiver_mut(), symbol_table, diagnostics); + for object_navigation in object_access.navigations_mut().navigations_mut() { + match object_navigation { + ObjectNavigation::Index(index_expression) => { + gather_expression(index_expression, symbol_table, diagnostics); + } + ObjectNavigation::Identifier(identifier) => { + // TODO: use a special gather for names belonging to a struct + gather_identifier(identifier, symbol_table); + } + } + } +} + +fn gather_literal( + literal: &mut Literal, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + match literal { + Literal::DString(d_string) => gather_d_string(d_string, symbol_table, diagnostics), + Literal::BacktickString(backtick_string) => { + gather_d_string(backtick_string, symbol_table, diagnostics) + } + _ => {} + } +} + +fn gather_d_string( + d_string: &mut DString, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + todo!() +} diff --git a/src/name_analysis/mod.rs b/src/name_analysis/mod.rs index 929fae0..6e8a645 100644 --- a/src/name_analysis/mod.rs +++ b/src/name_analysis/mod.rs @@ -19,15 +19,16 @@ The resolve phase has one main responsibility: resolve all references based on t `scope_id` property. */ -use crate::ast::node::CompilationUnit; +use crate::ast::node::{CompilationUnit, Identifier}; use crate::diagnostic::DmDiagnostic; use crate::name_analysis::gather::gather_compilation_unit; -use crate::name_analysis::resolve::resolve_compilation_unit; +// use crate::name_analysis::resolve::resolve_compilation_unit; use crate::name_analysis::symbol_table::SymbolTable; +use std::collections::HashMap; mod fqn_context; mod gather; -mod resolve; +// mod resolve; pub mod symbol; pub mod symbol_table; @@ -36,15 +37,21 @@ pub fn analyze_names( symbol_table: &mut SymbolTable, ) -> Vec { let mut diagnostics = vec![]; + let mut identifier_scope_ids: HashMap<&Identifier, usize> = HashMap::new(); // gather symbols for compilation_unit in compilation_units.iter_mut() { - gather_compilation_unit(compilation_unit, symbol_table, &mut diagnostics); + gather_compilation_unit( + compilation_unit, + symbol_table, + &mut identifier_scope_ids, + &mut diagnostics, + ); } // resolve symbols for compilation_unit in compilation_units.iter_mut() { - resolve_compilation_unit(compilation_unit, symbol_table, &mut diagnostics); + // resolve_compilation_unit(compilation_unit, symbol_table, &mut diagnostics); } diagnostics.into() @@ -64,7 +71,7 @@ pub fn analyze_names( // use indoc::indoc; // use pest::Parser; // use std::collections::HashMap; -// +// // fn assert_number_of_diagnostics( // sources: HashMap<&str, &str>, // symbol_table: &mut SymbolTable, @@ -72,7 +79,7 @@ pub fn analyze_names( // ) -> Vec { // let mut files = SimpleFiles::new(); // let mut compilation_units = vec![]; -// +// // for (file_name, source) in sources { // let file_id = files.add(file_name, source); // let parse_result = DeimosParser::parse(Rule::CompilationUnit, source); @@ -83,35 +90,35 @@ pub fn analyze_names( // if pairs.as_str().trim() != source.trim() { // panic!("Parsing did not consume entire input."); // } -// +// // compilation_units.push(build_ast(file_name, file_id, pairs.next().unwrap())); // } -// +// // let diagnostics = analyze_names(&mut compilation_units, symbol_table); -// +// // if diagnostics.len() != n_diagnostics { // let writer = StandardStream::stderr(ColorChoice::Always); // let config = term::Config::default(); -// +// // for diagnostic in &diagnostics { // term::emit(&mut writer.lock(), &config, &files, &diagnostic).unwrap(); // } -// +// // eprintln!("{}", symbol_table); // } -// +// // assert_eq!(n_diagnostics, diagnostics.len()); -// +// // compilation_units // } -// +// // fn assert_no_diagnostics( // sources: HashMap<&str, &str>, // symbol_table: &mut SymbolTable, // ) -> Vec { // assert_number_of_diagnostics(sources, symbol_table, 0) // } -// +// // fn assert_saved_symbols(compilation_unit: &CompilationUnit) { // walk_depth_first(compilation_unit, &mut |node_ref| match node_ref { // NodeRef::Identifier(identifier) => { @@ -130,7 +137,7 @@ pub fn analyze_names( // _ => {} // }) // } -// +// // fn assert_resolved_symbols(compilation_unit: &CompilationUnit) { // walk_depth_first(compilation_unit, &mut |node_ref| match node_ref { // NodeRef::UseStatement(use_statement) => match use_statement { @@ -139,7 +146,7 @@ pub fn analyze_names( // _ => {} // }) // } -// +// // #[test] // fn params_seen() { // let sources: HashMap<&str, &str> = HashMap::from([( @@ -149,13 +156,13 @@ pub fn analyze_names( // let x = args; // }"}, // )]); -// +// // let cus = assert_no_diagnostics(sources, &mut SymbolTable::new()); // for ref cu in cus { // assert_saved_symbols(cu); // } // } -// +// // #[test] // fn two_files() { // let sources: HashMap<&str, &str> = HashMap::from([ @@ -169,19 +176,19 @@ pub fn analyze_names( // "deps.dm", // indoc! {" // ns test; -// +// // pub class Greeter {} // "}, // ), // ]); -// +// // let cus = assert_no_diagnostics(sources, &mut SymbolTable::new()); // for ref cu in cus { // assert_saved_symbols(cu); // assert_resolved_symbols(cu); // } // } -// +// // #[test] // fn sees_std_core_println() { // let sources: HashMap<&str, &str> = HashMap::from([( @@ -192,7 +199,7 @@ pub fn analyze_names( // } // "}, // )]); -// +// // let mut symbol_table = SymbolTable::new(); // add_std_core_symbols(&mut symbol_table).expect("Failed to add std::core symbols."); // let cus = assert_no_diagnostics(sources, &mut symbol_table); @@ -201,7 +208,7 @@ pub fn analyze_names( // assert_resolved_symbols(cu); // } // } -// +// // #[test] // fn sees_duplicate_fn() { // let sources: HashMap<&str, &str> = HashMap::from([( @@ -213,7 +220,7 @@ pub fn analyze_names( // )]); // assert_number_of_diagnostics(sources, &mut SymbolTable::new(), 1); // } -// +// // #[test] // fn use_class_from_other_file() { // let sources: HashMap<&str, &str> = HashMap::from([ @@ -221,7 +228,7 @@ pub fn analyze_names( // "main.dm", // indoc! {" // use greeter::Greeter; -// +// // fn test(greeter: Greeter) {} // "}, // ), @@ -229,7 +236,7 @@ pub fn analyze_names( // "greeter.dm", // indoc! {" // ns greeter; -// +// // class Greeter {} // "}, // ), @@ -241,7 +248,7 @@ pub fn analyze_names( // assert_resolved_symbols(cu); // } // } -// +// // #[test] // fn shadow_import() { // let sources: HashMap<&str, &str> = HashMap::from([ @@ -249,7 +256,7 @@ pub fn analyze_names( // "main.dm", // indoc! {" // use greeter::Greeter; -// +// // class Greeter {} // "}, // ), @@ -257,7 +264,7 @@ pub fn analyze_names( // "greeter.dm", // indoc! {" // ns greeter; -// +// // class Greeter {} // "}, // ), diff --git a/src/name_analysis/resolve.rs b/src/name_analysis/resolve.rs.bak similarity index 100% rename from src/name_analysis/resolve.rs rename to src/name_analysis/resolve.rs.bak