diff --git a/src/name_analysis/gather.rs b/src/name_analysis/gather.rs index be51957..a5e9ce1 100644 --- a/src/name_analysis/gather.rs +++ b/src/name_analysis/gather.rs @@ -1,24 +1,20 @@ use crate::ast::ast_node::{AstNode, AstNodeRef}; -use crate::ast::node::{ - Class, CompilationUnit, Function, FunctionBody, Identifier, Interface, - InterfaceDefaultFunction, InterfaceDefaultOperatorFunction, InterfaceFunction, - InterfaceOperatorFunction, Member, Module, Namespace, OperatorFunction, PlatformFunction, - PlatformOperatorFunction, UseStatement, UseStatementSuffix, VariableDeclaration, VariableUse, -}; +use crate::ast::node::{Class, Closure, ClosureParameter, CompilationUnit, ForStatement, FullyQualifiedName, Function, FunctionBody, GenericArguments, GenericParameters, Identifier, IfClause, Interface, InterfaceDefaultFunction, InterfaceDefaultOperatorFunction, InterfaceFunction, InterfaceOperatorFunction, Member, Module, Namespace, OperatorFunction, Parameter, PlatformFunction, PlatformOperatorFunction, PrimitiveType, TernaryExpression, UseStatement, UseStatementSuffix, VariableDeclaration, VariableUse, WhileStatement}; use crate::diagnostic::DmDiagnostic; use crate::name_analysis::fqn_context::FqnContext; +use crate::name_analysis::scope_table::ScopeTable; use crate::name_analysis::symbol::class_member_symbol::ClassMemberSymbol; use crate::name_analysis::symbol::function_symbol::FunctionSymbol; use crate::name_analysis::symbol::module_symbol::ModuleSymbol; +use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol; use crate::name_analysis::symbol::source_definition::SourceDefinition; use crate::name_analysis::symbol::type_symbol::{ - ConcreteTypeSymbol, ConcreteTypeSymbolKind, TypeSymbol, + ConcreteTypeSymbol, ConcreteTypeSymbolKind, GenericTypeSymbol, 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( @@ -57,11 +53,11 @@ fn gather_node_children<'a>( node: &'a impl AstNode, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, - scope_ids: &mut HashMap<&'a VariableUse, usize>, + scope_table: &mut ScopeTable<'a>, diagnostics: &mut Vec, ) { for child in node.children() { - gather_node(child, symbol_table, fqn_context, scope_ids, diagnostics); + gather_node(child, symbol_table, fqn_context, scope_table, diagnostics); } } @@ -69,7 +65,7 @@ fn gather_node<'a>( node: AstNodeRef<'a>, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, - scope_ids: &mut HashMap<&'a VariableUse, usize>, + scope_table: &mut ScopeTable<'a>, diagnostics: &mut Vec, ) { match node { @@ -82,29 +78,87 @@ fn gather_node<'a>( AstNodeRef::Identifier(_) => { unreachable!(); } - 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::FullyQualifiedName(fully_qualified_name) => { + gather_fully_qualified_name(fully_qualified_name, symbol_table, scope_table); + } + AstNodeRef::TypeUseList(type_use_list) => { + gather_node_children( + type_use_list, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::IdentifierList(_) => { + unreachable!(); + } + AstNodeRef::ParenthesesTypeUseList(parentheses_type_useList) => { + gather_node_children( + parentheses_type_useList, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::TypeUse(type_use) => { + gather_node_children( + type_use, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::PrimitiveType(primitive_type) => { + gather_primitive_type(primitive_type, symbol_table, fqn_context, scope_table, diagnostics); + } + AstNodeRef::TypedArray(typed_array) => { + gather_node_children(typed_array, symbol_table, fqn_context, scope_table, diagnostics); + } + AstNodeRef::InterfaceOrClassTypeUse(interface_or_class_type_use) => { + gather_node_children( + interface_or_class_type_use, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::TupleTypeUse(tuple_type_use) => { + gather_node_children(tuple_type_use, symbol_table, fqn_context, scope_table, diagnostics); + } + AstNodeRef::FunctionTypeUse(function_type_use) => { + gather_node_children(function_type_use, symbol_table, fqn_context, scope_table, diagnostics); + } + AstNodeRef::GenericArguments(generic_arguments) => { + gather_node_children(generic_arguments, symbol_table, fqn_context, scope_table, diagnostics); + } + AstNodeRef::GenericParameters(generic_parameters) => { + gather_generic_parameters(generic_parameters, symbol_table, diagnostics); + } + AstNodeRef::TupleArguments(tuple_arguments) => { + gather_node_children(tuple_arguments, symbol_table, fqn_context, scope_table, diagnostics); + } + AstNodeRef::ImplementsList(implements_list) => { + gather_node_children(implements_list, symbol_table, fqn_context, scope_table, diagnostics); + } + AstNodeRef::Parameters(parameters) => { + gather_node_children(parameters, symbol_table, fqn_context, scope_table, diagnostics); + } + AstNodeRef::Parameter(parameter) => { + gather_parameter(parameter, symbol_table, diagnostics); + } + AstNodeRef::ReturnType(return_type) => { + gather_node_children(return_type, symbol_table, fqn_context, scope_table, diagnostics); + } AstNodeRef::CompilationUnit(compilation_unit) => { gather_node_children( compilation_unit, symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); } @@ -128,7 +182,7 @@ fn gather_node<'a>( module_level_declaration, symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); } @@ -137,7 +191,7 @@ fn gather_node<'a>( interface_level_declaration, symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); } @@ -146,28 +200,40 @@ fn gather_node<'a>( class_level_declaration, symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); } AstNodeRef::Module(module) => { - gather_module(module, symbol_table, fqn_context, scope_ids, diagnostics); + gather_module(module, symbol_table, fqn_context, scope_table, diagnostics); } AstNodeRef::Interface(interface) => { - gather_interface(interface, symbol_table, fqn_context, scope_ids, diagnostics); + gather_interface( + interface, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); } AstNodeRef::Class(class) => { - gather_class(class, symbol_table, fqn_context, scope_ids, diagnostics); + gather_class(class, symbol_table, fqn_context, scope_table, diagnostics); } AstNodeRef::Function(function) => { - gather_function(function, symbol_table, fqn_context, scope_ids, diagnostics); + gather_function( + function, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); } AstNodeRef::OperatorFunction(operator_function) => { gather_operator_function( operator_function, symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); } @@ -176,7 +242,7 @@ fn gather_node<'a>( platform_function, symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); } @@ -185,7 +251,7 @@ fn gather_node<'a>( platform_operator_function, symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); } @@ -194,7 +260,7 @@ fn gather_node<'a>( interface_function, symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); } @@ -203,7 +269,7 @@ fn gather_node<'a>( interface_default_function, symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); } @@ -212,7 +278,7 @@ fn gather_node<'a>( interface_operator_function, symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); } @@ -221,7 +287,7 @@ fn gather_node<'a>( interface_default_operator_function, symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); } @@ -230,7 +296,7 @@ fn gather_node<'a>( function_body, symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); } @@ -239,7 +305,7 @@ fn gather_node<'a>( function_equals_body, symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); } @@ -251,7 +317,7 @@ fn gather_node<'a>( function_block_body, symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); } @@ -260,76 +326,449 @@ fn gather_node<'a>( class_constructor, symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); } AstNodeRef::Member(member) => { - gather_member(member, symbol_table, fqn_context, scope_ids, diagnostics); + gather_member(member, symbol_table, fqn_context, scope_table, diagnostics); } AstNodeRef::Statement(statement) => { - gather_node_children(statement, symbol_table, fqn_context, scope_ids, diagnostics); + gather_node_children( + statement, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); } AstNodeRef::VariableDeclaration(variable_declaration) => { gather_variable_declaration( variable_declaration, symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); } - AstNodeRef::AssignmentStatement(_) => {} - AstNodeRef::ExpressionStatement(_) => {} - AstNodeRef::IfStatement(_) => {} - AstNodeRef::IfClause(_) => {} - AstNodeRef::IfElseIf(_) => {} - AstNodeRef::IfElse(_) => {} - AstNodeRef::WhileStatement(_) => {} - AstNodeRef::ForStatement(_) => {} - AstNodeRef::LValue(_) => {} - AstNodeRef::LValueSuffix(_) => {} - AstNodeRef::VariableUse(variable_use) => { - gather_variable_use(variable_use, symbol_table, scope_ids); + AstNodeRef::AssignmentStatement(assignment_statement) => { + gather_node_children( + assignment_statement, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); } - 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(_) => {} + AstNodeRef::ExpressionStatement(expression_statement) => { + gather_node_children( + expression_statement, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::IfStatement(if_statement) => { + gather_node_children( + if_statement, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::IfClause(if_clause) => { + gather_if_clause( + if_clause, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::IfElseIf(if_else_if) => { + gather_node_children( + if_else_if, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::IfElse(if_else) => { + gather_node_children(if_else, symbol_table, fqn_context, scope_table, diagnostics); + } + AstNodeRef::WhileStatement(while_statement) => { + gather_while_statement( + while_statement, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::ForStatement(for_statement) => { + gather_for_statement( + for_statement, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::LValue(l_value) => { + gather_node_children(l_value, symbol_table, fqn_context, scope_table, diagnostics); + } + AstNodeRef::LValueSuffix(l_value_suffix) => { + gather_node_children( + l_value_suffix, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::VariableUse(variable_use) => { + gather_variable_use(variable_use, symbol_table, scope_table); + } + AstNodeRef::Expression(expression) => { + gather_node_children( + expression, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::TernaryExpression(ternary_expression) => { + gather_ternary_expression( + ternary_expression, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::TernaryRhs(ternary_rhs) => { + gather_node_children( + ternary_rhs, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::OrExpression(or_expression) => { + gather_node_children( + or_expression, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::OrRhs(or_rhs) => { + gather_node_children(or_rhs, symbol_table, fqn_context, scope_table, diagnostics); + } + AstNodeRef::AndExpression(and_expression) => { + gather_node_children( + and_expression, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::AndRhs(and_rhs) => { + gather_node_children(and_rhs, symbol_table, fqn_context, scope_table, diagnostics); + } + AstNodeRef::ComparisonExpression(comparison_expression) => { + gather_node_children( + comparison_expression, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::ComparisonRhs(comparison_rhs) => { + gather_node_children( + comparison_rhs, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::ComparisonOperator(_) => { + // no-op + } + AstNodeRef::ShiftExpression(shift_expression) => { + gather_node_children( + shift_expression, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::ShiftRhs(shift_rhs) => { + gather_node_children( + shift_rhs, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::ShiftOperator(_) => { + // no-op + } + AstNodeRef::AdditiveExpression(additive_expression) => { + gather_node_children( + additive_expression, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::AdditiveRhs(additive_rhs) => { + gather_node_children( + additive_rhs, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::AdditiveOperator(_) => { + // no-op + } + AstNodeRef::MultiplicativeExpression(multiplicative_expression) => { + gather_node_children( + multiplicative_expression, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::MultiplicativeRhs(multiplicative_rhs) => { + gather_node_children( + multiplicative_rhs, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::MultiplicativeOperator(_) => { + // no-op + } + AstNodeRef::PrefixExpression(prefix_expression) => { + gather_node_children( + prefix_expression, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::PrefixOperator(_) => { + // no-op + } + AstNodeRef::SuffixExpression(suffix_expression) => { + gather_node_children( + suffix_expression, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::SuffixOperator(_) => { + // no-op + } + AstNodeRef::ObjectProperty(_) => { + // no-op + } + AstNodeRef::ObjectIndex(object_index) => { + gather_node_children( + object_index, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::ListExpression(list_expression) => { + gather_node_children( + list_expression, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::Call(call) => { + gather_node_children(call, symbol_table, fqn_context, scope_table, diagnostics); + } + AstNodeRef::ParenthesesCall(parentheses_call) => { + gather_node_children( + parentheses_call, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::NonParenthesesCall(non_parentheses_call) => { + gather_node_children( + non_parentheses_call, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::TurboFish(turbo_fish) => { + gather_node_children( + turbo_fish, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::ExpressionList(expression_list) => { + gather_node_children( + expression_list, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::Closure(closure) => { + gather_closure(closure, symbol_table, fqn_context, scope_table, diagnostics); + } + AstNodeRef::ClosureParameters(closure_parameters) => { + gather_node_children( + closure_parameters, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::ClosureParameter(closure_parameter) => { + gather_closure_parameter( + closure_parameter, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::Literal(literal) => { + gather_node_children(literal, symbol_table, fqn_context, scope_table, diagnostics); + } + AstNodeRef::DString(d_string) => { + gather_node_children( + d_string, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::DStringExpression(d_string_expression) => { + gather_node_children( + d_string_expression, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + AstNodeRef::BacktickString(backtick_string) => { + gather_node_children( + backtick_string, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + } +} + +fn gather_fully_qualified_name<'a>( + fully_qualified_name: &'a FullyQualifiedName, + symbol_table: &mut SymbolTable, + scope_table: &mut ScopeTable<'a>, +) { + scope_table.insert_fqn_scope(fully_qualified_name, symbol_table.current_scope_id()); +} + +fn gather_primitive_type<'a>( + primitive_type: &'a PrimitiveType, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + scope_table: &mut ScopeTable<'a>, + diagnostics: &mut Vec +) { + match primitive_type { + PrimitiveType::TypedArray(typed_array) => { + gather_node(typed_array.as_node_ref(), symbol_table, fqn_context, scope_table, diagnostics); + } + _ => {} + } +} + +fn gather_generic_parameters<'a>( + generic_parameters: &'a GenericParameters, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + for identifier in generic_parameters.identifier_list().identifiers() { + let type_symbol = TypeSymbol::Generic(GenericTypeSymbol::new( + identifier.name(), + Some(SourceDefinition::from_identifier(identifier)), + )); + if let Err(insert_error) = symbol_table.insert_type_symbol(type_symbol) { + handle_insert_error( + insert_error, + identifier.name(), + identifier.file_id(), + identifier.range(), + "Type", + diagnostics, + ); + } + } +} + +fn gather_parameter<'a>( + parameter: &'a Parameter, + symbol_table: &mut SymbolTable, + diagnostics: &mut Vec, +) { + let parameter_symbol = ParameterSymbol::new( + parameter.identifier().name(), + Some(SourceDefinition::from_identifier(parameter.identifier())), + ); + if let Err(insert_error) = symbol_table.insert_parameter_symbol(parameter_symbol) { + handle_insert_error( + insert_error, + parameter.identifier().name(), + parameter.identifier().file_id(), + parameter.identifier().range(), + "Parameter", + diagnostics, + ); } } @@ -337,7 +776,7 @@ pub fn gather_compilation_unit<'a>( compilation_unit: &'a CompilationUnit, file_name: &str, symbol_table: &mut SymbolTable, - scope_ids: &mut HashMap<&'a VariableUse, usize>, + scope_table: &mut ScopeTable<'a>, diagnostics: &mut Vec, ) { let mut fqn_context = FqnContext::new(); @@ -346,7 +785,7 @@ pub fn gather_compilation_unit<'a>( compilation_unit.as_node_ref(), symbol_table, &mut fqn_context, - scope_ids, + scope_table, diagnostics, ); symbol_table.pop_scope(); @@ -425,7 +864,7 @@ fn gather_module<'a>( module: &'a Module, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, - scope_ids: &mut HashMap<&'a VariableUse, usize>, + scope_table: &mut ScopeTable<'a>, diagnostics: &mut Vec, ) { let module_symbol = ModuleSymbol::new( @@ -453,7 +892,7 @@ fn gather_module<'a>( declaration.as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); } @@ -466,7 +905,7 @@ fn gather_interface<'a>( interface: &'a Interface, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, - scope_ids: &mut HashMap<&'a VariableUse, usize>, + scope_table: &mut ScopeTable<'a>, diagnostics: &mut Vec, ) { let type_symbol = ConcreteTypeSymbol::new( @@ -497,7 +936,7 @@ fn gather_interface<'a>( declaration.as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); } @@ -510,7 +949,7 @@ fn gather_class<'a>( class: &'a Class, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, - scope_ids: &mut HashMap<&'a VariableUse, usize>, + scope_table: &mut ScopeTable<'a>, diagnostics: &mut Vec, ) { let class_symbol = ConcreteTypeSymbol::new( @@ -540,7 +979,7 @@ fn gather_class<'a>( class.class_constructor().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); for declaration in class.class_level_declarations() { @@ -548,7 +987,7 @@ fn gather_class<'a>( declaration.as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); } @@ -561,7 +1000,7 @@ fn gather_function<'a>( function: &'a Function, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, - scope_ids: &mut HashMap<&'a VariableUse, usize>, + scope_table: &mut ScopeTable<'a>, diagnostics: &mut Vec, ) { let function_symbol = FunctionSymbol::without_parameters_or_return_type( @@ -586,28 +1025,28 @@ fn gather_function<'a>( function.generics().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); gather_node( function.parameters().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); gather_node( function.return_type().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); gather_node( function.function_body().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); symbol_table.pop_scope(); @@ -617,7 +1056,7 @@ fn gather_operator_function<'a>( operator_function: &'a OperatorFunction, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, - scope_ids: &mut HashMap<&'a VariableUse, usize>, + scope_table: &mut ScopeTable<'a>, diagnostics: &mut Vec, ) { let function_symbol = FunctionSymbol::without_parameters_or_return_type( @@ -647,28 +1086,28 @@ fn gather_operator_function<'a>( operator_function.generics().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); gather_node( operator_function.parameters().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); gather_node( operator_function.return_type().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); gather_node( operator_function.function_body().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); symbol_table.pop_scope(); @@ -678,7 +1117,7 @@ fn gather_platform_function<'a>( platform_function: &'a PlatformFunction, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, - scope_ids: &mut HashMap<&'a VariableUse, usize>, + scope_table: &mut ScopeTable<'a>, diagnostics: &mut Vec, ) { let function_symbol = FunctionSymbol::without_parameters_or_return_type( @@ -708,21 +1147,21 @@ fn gather_platform_function<'a>( platform_function.generics().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); gather_node( platform_function.parameters().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); gather_node( platform_function.return_type().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); symbol_table.pop_scope(); @@ -732,7 +1171,7 @@ fn gather_platform_operator_function<'a>( platform_operator_function: &'a PlatformOperatorFunction, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, - scope_ids: &mut HashMap<&'a VariableUse, usize>, + scope_table: &mut ScopeTable<'a>, diagnostics: &mut Vec, ) { let function_symbol = FunctionSymbol::without_parameters_or_return_type( @@ -762,21 +1201,21 @@ fn gather_platform_operator_function<'a>( platform_operator_function.generics().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); gather_node( platform_operator_function.parameters().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); gather_node( platform_operator_function.return_type().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); symbol_table.pop_scope(); @@ -786,7 +1225,7 @@ fn gather_interface_function<'a>( interface_function: &'a InterfaceFunction, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, - scope_ids: &mut HashMap<&'a VariableUse, usize>, + scope_table: &mut ScopeTable<'a>, diagnostics: &mut Vec, ) { let function_symbol = FunctionSymbol::without_parameters_or_return_type( @@ -816,21 +1255,21 @@ fn gather_interface_function<'a>( interface_function.generics().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); gather_node( interface_function.parameters().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); gather_node( interface_function.return_type().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); symbol_table.pop_scope(); @@ -840,7 +1279,7 @@ fn gather_interface_default_function<'a>( interface_default_function: &'a InterfaceDefaultFunction, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, - scope_ids: &mut HashMap<&'a VariableUse, usize>, + scope_table: &mut ScopeTable<'a>, diagnostics: &mut Vec, ) { let function_symbol = FunctionSymbol::without_parameters_or_return_type( @@ -870,28 +1309,28 @@ fn gather_interface_default_function<'a>( interface_default_function.generics().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); gather_node( interface_default_function.parameters().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); gather_node( interface_default_function.return_type().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); gather_node( interface_default_function.function_body().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); symbol_table.pop_scope(); @@ -901,7 +1340,7 @@ fn gather_interface_operator_function<'a>( interface_operator_function: &'a InterfaceOperatorFunction, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, - scope_ids: &mut HashMap<&'a VariableUse, usize>, + scope_table: &mut ScopeTable<'a>, diagnostics: &mut Vec, ) { let function_symbol = FunctionSymbol::without_parameters_or_return_type( @@ -931,21 +1370,21 @@ fn gather_interface_operator_function<'a>( interface_operator_function.generics().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); gather_node( interface_operator_function.parameters().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); gather_node( interface_operator_function.return_type().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); symbol_table.pop_scope(); @@ -955,7 +1394,7 @@ fn gather_interface_default_operator_function<'a>( interface_default_operator_function: &'a InterfaceDefaultOperatorFunction, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, - scope_ids: &mut HashMap<&'a VariableUse, usize>, + scope_table: &mut ScopeTable<'a>, diagnostics: &mut Vec, ) { let function_symbol = FunctionSymbol::without_parameters_or_return_type( @@ -999,7 +1438,7 @@ fn gather_interface_default_operator_function<'a>( interface_default_operator_function.generics().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); gather_node( @@ -1008,7 +1447,7 @@ fn gather_interface_default_operator_function<'a>( .as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); gather_node( @@ -1017,7 +1456,7 @@ fn gather_interface_default_operator_function<'a>( .as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); gather_node( @@ -1026,7 +1465,7 @@ fn gather_interface_default_operator_function<'a>( .as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); symbol_table.pop_scope(); @@ -1036,7 +1475,7 @@ fn gather_function_body<'a>( function_body: &'a FunctionBody, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, - scope_ids: &mut HashMap<&'a VariableUse, usize>, + scope_table: &mut ScopeTable<'a>, diagnostics: &mut Vec, ) { symbol_table.push_scope("FunctionBodyScope"); @@ -1044,7 +1483,7 @@ fn gather_function_body<'a>( function_body, symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); symbol_table.pop_scope(); @@ -1054,7 +1493,7 @@ fn gather_member<'a>( member: &'a Member, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, - scope_ids: &mut HashMap<&'a VariableUse, usize>, + scope_table: &mut ScopeTable<'a>, diagnostics: &mut Vec, ) { let member_symbol = ClassMemberSymbol::new( @@ -1077,7 +1516,7 @@ fn gather_member<'a>( member.type_use().as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); } @@ -1086,7 +1525,7 @@ fn gather_variable_declaration<'a>( variable_declaration: &'a VariableDeclaration, symbol_table: &mut SymbolTable, fqn_context: &mut FqnContext, - scope_ids: &mut HashMap<&'a VariableUse, usize>, + scope_table: &mut ScopeTable<'a>, diagnostics: &mut Vec, ) { let variable_symbol = VariableSymbol::new( @@ -1111,16 +1550,201 @@ fn gather_variable_declaration<'a>( expression.as_node_ref(), symbol_table, fqn_context, - scope_ids, + scope_table, diagnostics, ); } } +fn gather_if_clause<'a>( + if_clause: &'a IfClause, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + scope_table: &mut ScopeTable<'a>, + diagnostics: &mut Vec, +) { + symbol_table.push_scope("IfClauseScope"); + gather_node( + if_clause.expression().as_node_ref(), + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + symbol_table.push_scope("IfClauseStatementsScope"); + for statement in if_clause.statements() { + gather_node( + statement.as_node_ref(), + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + symbol_table.pop_scope(); + symbol_table.pop_scope(); +} + +fn gather_while_statement<'a>( + while_statement: &'a WhileStatement, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + scope_table: &mut ScopeTable<'a>, + diagnostics: &mut Vec, +) { + symbol_table.push_scope("WhileStatementScope"); + gather_node( + while_statement.expression().as_node_ref(), + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + symbol_table.push_scope("WhileStatementStatementsScope"); + for statement in while_statement.statements() { + gather_node( + statement.as_node_ref(), + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + symbol_table.pop_scope(); + symbol_table.pop_scope(); +} + +fn gather_for_statement<'a>( + for_statement: &'a ForStatement, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + scope_table: &mut ScopeTable<'a>, + diagnostics: &mut Vec, +) { + gather_node( + for_statement.expression().as_node_ref(), + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + symbol_table.push_scope("ForStatementScope"); + let identifier_symbol = VariableSymbol::new( + for_statement.identifier().name(), + false, + Some(SourceDefinition::from_identifier( + for_statement.identifier(), + )), + ); + if let Err(insert_error) = symbol_table.insert_variable_symbol(identifier_symbol) { + handle_insert_error( + insert_error, + for_statement.identifier().name(), + for_statement.identifier().file_id(), + for_statement.identifier().range(), + "Variable", + diagnostics, + ); + } + symbol_table.push_scope("ForStatementStatementsScope"); + for statement in for_statement.statements() { + gather_node( + statement.as_node_ref(), + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + symbol_table.pop_scope(); + symbol_table.pop_scope(); +} + fn gather_variable_use<'a>( variable_use: &'a VariableUse, symbol_table: &mut SymbolTable, - scope_ids: &mut HashMap<&'a VariableUse, usize>, + scope_table: &mut ScopeTable<'a>, ) { - scope_ids.insert(variable_use, symbol_table.current_scope_id()); + scope_table.insert_variable_use_scope(variable_use, symbol_table.current_scope_id()); +} + +fn gather_ternary_expression<'a>( + ternary_expression: &'a TernaryExpression, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + scope_table: &mut ScopeTable<'a>, + diagnostics: &mut Vec, +) { + symbol_table.push_scope("TernaryExpressionScope"); + gather_node_children( + ternary_expression, + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + symbol_table.pop_scope(); +} + +fn gather_closure<'a>( + closure: &'a Closure, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + scope_table: &mut ScopeTable<'a>, + diagnostics: &mut Vec, +) { + symbol_table.push_scope("ClosureScope"); + gather_node( + closure.closure_parameters().as_node_ref(), + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + symbol_table.push_scope("ClosureStatementsScope"); + for statement in closure.statements() { + gather_node( + statement.as_node_ref(), + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } + symbol_table.pop_scope(); + symbol_table.pop_scope(); +} + +fn gather_closure_parameter<'a>( + closure_parameter: &'a ClosureParameter, + symbol_table: &mut SymbolTable, + fqn_context: &mut FqnContext, + scope_table: &mut ScopeTable<'a>, + diagnostics: &mut Vec, +) { + let parameter_symbol = ParameterSymbol::new( + closure_parameter.identifier().name(), + Some(SourceDefinition::from_identifier( + closure_parameter.identifier(), + )), + ); + if let Err(insert_err) = symbol_table.insert_parameter_symbol(parameter_symbol) { + handle_insert_error( + insert_err, + closure_parameter.identifier().name(), + closure_parameter.identifier().file_id(), + closure_parameter.identifier().range(), + "Parameter", + diagnostics, + ); + } + if let Some(type_use) = closure_parameter.type_use() { + gather_node( + type_use.as_node_ref(), + symbol_table, + fqn_context, + scope_table, + diagnostics, + ); + } } diff --git a/src/name_analysis/mod.rs b/src/name_analysis/mod.rs index 878a2f0..dc80048 100644 --- a/src/name_analysis/mod.rs +++ b/src/name_analysis/mod.rs @@ -19,19 +19,23 @@ The resolve phase has one main responsibility: resolve all references based on t `scope_id` property. */ -use crate::ast::node::{CompilationUnit, VariableUse}; +// use crate::name_analysis::resolve::resolve_compilation_unit; +use crate::ast::ast_node::AstNode; +use crate::ast::node::CompilationUnit; use crate::diagnostic::DmDiagnostic; use crate::name_analysis::gather::gather_compilation_unit; -// use crate::name_analysis::resolve::resolve_compilation_unit; use crate::name_analysis::symbol_table::SymbolTable; use codespan_reporting::files::Files; use std::collections::HashMap; +use std::hash::Hash; +use crate::name_analysis::scope_table::ScopeTable; pub(self) mod fqn_context; mod gather; // mod resolve; pub mod symbol; pub mod symbol_table; +mod scope_table; pub fn analyze_names<'a, F: Files<'a, FileId = usize, Name = String>>( compilation_units: &[Box], @@ -39,7 +43,7 @@ pub fn analyze_names<'a, F: Files<'a, FileId = usize, Name = String>>( symbol_table: &mut SymbolTable, ) -> Vec { let mut diagnostics = vec![]; - let mut scope_ids: HashMap<&VariableUse, usize> = HashMap::new(); + let mut scope_table = ScopeTable::new(); // gather symbols for compilation_unit in compilation_units { @@ -48,7 +52,7 @@ pub fn analyze_names<'a, F: Files<'a, FileId = usize, Name = String>>( compilation_unit, &file_name, symbol_table, - &mut scope_ids, + &mut scope_table, &mut diagnostics, ); } diff --git a/src/name_analysis/scope_table/mod.rs b/src/name_analysis/scope_table/mod.rs new file mode 100644 index 0000000..cfa3665 --- /dev/null +++ b/src/name_analysis/scope_table/mod.rs @@ -0,0 +1,32 @@ +use crate::ast::node::{FullyQualifiedName, VariableUse}; +use std::collections::HashMap; + +pub struct ScopeTable<'a> { + variable_use_scopes: HashMap<&'a VariableUse, usize>, + fqn_scopes: HashMap<&'a FullyQualifiedName, usize>, +} + +impl<'a> ScopeTable<'a> { + pub fn new() -> Self { + Self { + variable_use_scopes: HashMap::new(), + fqn_scopes: HashMap::new(), + } + } + + pub fn insert_variable_use_scope(&mut self, variable_use: &'a VariableUse, scope_id: usize) { + self.variable_use_scopes.insert(variable_use, scope_id); + } + + pub fn insert_fqn_scope(&mut self, fqn: &'a FullyQualifiedName, scope_id: usize) { + self.fqn_scopes.insert(fqn, scope_id); + } + + pub fn variable_use_scope(&self, variable_use: &'a VariableUse) -> Option { + self.variable_use_scopes.get(&variable_use).copied() + } + + pub fn fqn_scope(&self, fqn: &'a FullyQualifiedName) -> Option { + self.fqn_scopes.get(&fqn).copied() + } +} diff --git a/src/parser/ast.yaml b/src/parser/ast.yaml index 604299e..4b86b91 100644 --- a/src/parser/ast.yaml +++ b/src/parser/ast.yaml @@ -50,7 +50,6 @@ Identifier: - range: kind: range derive: - - Clone - PartialEq - Eq - Hash @@ -60,6 +59,10 @@ FullyQualifiedName: - identifiers: vec: rule: Identifier + derive: + - PartialEq + - Eq + - Hash # Lists TypeUseList: @@ -74,7 +77,7 @@ IdentifierList: - identifiers: vec: rule: Identifier -ParenthesesOptionalTypeUseList: +ParenthesesTypeUseList: struct: children: - type_use_list: @@ -90,19 +93,29 @@ TypeUse: - TupleTypeUse - FunctionTypeUse PrimitiveType: - leaf_enum: + tree_enum: rules: - - Byte - - Short - - Char - - Int - - Long - - Double - - Bool - - String + - Byte: + child: false + - Short: + child: false + - Char: + child: false + - Int: + child: false + - Long: + child: false + - Double: + child: false + - Bool: + child: false + - String: + child: false - TypedArray - - Any - - Void + - Any: + child: false + - Void: + child: false TypedArray: struct: children: @@ -160,7 +173,7 @@ GenericParameters: TupleArguments: struct: children: - - parentheses_optional_type_use_list + - parentheses_type_use_list # Implements List ImplementsList: @@ -656,7 +669,7 @@ IfClause: skip: rule: Then - statements: - skip: + vec: rule: Statement IfElseIf: struct: @@ -704,7 +717,7 @@ ForStatement: - do_kw: skip: rule: Do - - statement: + - statements: vec: rule: Statement - end_kw: @@ -731,7 +744,6 @@ VariableUse: children: - identifier derive: - - Clone - PartialEq - Eq - Hash diff --git a/src/parser/deimos.pest b/src/parser/deimos.pest index 4694984..6872bf0 100644 --- a/src/parser/deimos.pest +++ b/src/parser/deimos.pest @@ -199,7 +199,7 @@ IdentifierList = { ~ ( "," ~ Identifier )* } -ParenthesesOptionalTypeUseList = { +ParenthesesTypeUseList = { "(" ~ TypeUseList? ~ ")" @@ -272,7 +272,7 @@ GenericParameters = { // Tuple Arguments TupleArguments = { - ParenthesesOptionalTypeUseList + ParenthesesTypeUseList } // Implements list