use crate::ast::named::Named; use crate::ast::*; use crate::diagnostic::DmDiagnostic; use crate::name_analysis::symbol::Symbol; use crate::name_analysis::symbol_table::{SymbolLookupError, SymbolTable}; use codespan_reporting::diagnostic::{Diagnostic, Label}; use std::ops::DerefMut; use std::range::Range; /* Type Use */ fn resolve_type_use( type_use: &mut TypeUse, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { match type_use { TypeUse::Primitive(primitive_type_use) => { resolve_primitive_type_use(primitive_type_use, symbol_table, diagnostics) } TypeUse::InterfaceOrClass(interface_or_class_type_use) => { resolve_interface_or_class_type_use( interface_or_class_type_use, symbol_table, diagnostics, ); } TypeUse::Tuple(tuple_type_use) => { resolve_tuple_type_use(tuple_type_use, symbol_table, diagnostics); } TypeUse::Function(function_type_use) => { resolve_function_type_use(function_type_use, symbol_table, diagnostics); } } } fn resolve_primitive_type_use( primitive_type_use: &mut PrimitiveTypeUse, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { match primitive_type_use { PrimitiveTypeUse::Array(generic_arguments_opt) => { if let Some(generic_arguments) = generic_arguments_opt { resolve_generic_arguments(generic_arguments, symbol_table, diagnostics); } } _ => {} } } fn resolve_interface_or_class_type_use( interface_or_class_type_use: &mut InterfaceOrClassTypeUse, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { // 1. handle main name let fqn = interface_or_class_type_use.fqn_mut(); let lookup_result = if fqn.is_single_identifier() { let identifier = fqn.last(); symbol_table.lookup_type_by_declared_name( &identifier.name(), identifier .scope_id() .expect("Identifier's scope id not set."), ) } else { todo!("Fully-qualified-name type uses sensitive to imports and so on") }; match lookup_result { Ok(type_symbol) => { fqn.last_mut().set_saved_symbol(Symbol::Type(type_symbol)); } Err(_) => { diagnostics.push( Diagnostic::error() .with_message(&format!( "No type symbol '{}' found in current scope.", fqn.name() )) .with_label(Label::primary(fqn.file_id(), fqn.range())), ); } } // 2. generics resolve_generic_arguments( interface_or_class_type_use.generics_mut(), symbol_table, diagnostics, ); } fn resolve_tuple_type_use( tuple_type_use: &mut TupleTypeUse, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { resolve_tuple_arguments(tuple_type_use.arguments_mut(), symbol_table, diagnostics); } fn resolve_function_type_use( function_type_use: &mut FunctionTypeUse, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { resolve_parameters( function_type_use.parameters_mut(), symbol_table, diagnostics, ); resolve_return_type( function_type_use.return_type_mut(), symbol_table, diagnostics, ); } /* Generic arguments */ fn resolve_generic_arguments( generic_arguments: &mut GenericArguments, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { for generic_argument in generic_arguments.arguments_mut() { resolve_type_use(generic_argument, symbol_table, diagnostics); } } /* Generic parameters: todo: no resolution needed? */ /* Tuple arguments */ fn resolve_tuple_arguments( tuple_type_use: &mut TupleArguments, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { for type_use in tuple_type_use.type_uses_mut() { resolve_type_use(type_use, symbol_table, diagnostics); } } /* Implements list */ fn resolve_implements_list( implements_list: &mut ImplementsList, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { for type_use in implements_list.type_uses_mut() { resolve_type_use(type_use, symbol_table, diagnostics); } } /* Function parameters */ fn resolve_parameters( parameters: &mut Parameters, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { for parameter in parameters.parameters_mut() { resolve_type_use(parameter.type_use_mut(), symbol_table, diagnostics); } } /* Return Type */ fn resolve_return_type( return_type: &mut ReturnType, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { resolve_type_use(return_type.declared_type_mut(), symbol_table, diagnostics); resolve_references(return_type.references_mut(), symbol_table, diagnostics); } /* References */ fn resolve_references( references: &mut References, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { for reference in references.identifiers_mut() { todo!() } } /* Compilation Unit/Top-level construct */ pub(super) fn resolve_compilation_unit( compilation_unit: &mut CompilationUnit, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { for use_statement in compilation_unit.use_statements_mut() { resolve_use_statement(use_statement, symbol_table, diagnostics); } for declaration in compilation_unit.declarations_mut() { resolve_module_level_declaration(declaration, symbol_table, diagnostics); } } /* Use Statement */ fn handle_use_statement_identifier( identifier: &mut Identifier, base_name: &str, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, file_id: usize, error_range: Range, ) { let declared_name = identifier.name().to_string(); let fqn = format!("{}::{}", base_name, &declared_name); let lookup_result = symbol_table.lookup_usable_by_fqn(&fqn, identifier.scope_id().unwrap()); match lookup_result { Ok(referenced_symbol) => { let saved_symbol = identifier .saved_symbol() .expect("Identifier's saved_symbol is not set."); let use_statement_symbol = saved_symbol.unwrap_use_statement_symbol(); use_statement_symbol .borrow_mut() .set_referenced_symbol(referenced_symbol); } Err(_) => { diagnostics.push( Diagnostic::error() .with_message(&format!("Unable to find symbol '{}'.", fqn)) .with_label(Label::primary(file_id, error_range)), ); } } } fn resolve_use_statement( use_statement: &mut UseStatement, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { let file_id = use_statement.file_id(); let use_statement_range = use_statement.range(); let base_name = use_statement.base_name().to_string(); match use_statement.last_mut() { UseStatementLast::Identifier(identifier) => { handle_use_statement_identifier( identifier.deref_mut(), &base_name, symbol_table, diagnostics, file_id, use_statement_range, ); } UseStatementLast::Identifiers(identifiers) => { for identifier in identifiers { let identifier_range = identifier.range(); handle_use_statement_identifier( identifier.deref_mut(), &base_name, symbol_table, diagnostics, file_id, identifier_range, ) } } UseStatementLast::Star => todo!("star imports"), } } /* Declarations allowed in each level */ fn resolve_module_level_declaration( declaration: &mut ModuleLevelDeclaration, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { use crate::ast::ModuleLevelDeclaration::*; match declaration { Module(module_declaration) => { resolve_module_declaration(module_declaration, symbol_table, diagnostics); } Interface(interface_declaration) => { resolve_interface_declaration(interface_declaration, symbol_table, diagnostics); } Function(function_definition) => { resolve_function_definition(function_definition, symbol_table, diagnostics) } Class(class_declaration) => { resolve_class_declaration(class_declaration, symbol_table, diagnostics); } PlatformFunction(platform_function_declaration) => resolve_platform_function_declaration( platform_function_declaration, symbol_table, diagnostics, ), } } fn resolve_interface_level_declaration( declaration: &mut InterfaceLevelDeclaration, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { use crate::ast::InterfaceLevelDeclaration::*; match declaration { Module(module_declaration) => { resolve_module_declaration(module_declaration, symbol_table, diagnostics); } Interface(interface_declaration) => { resolve_interface_declaration(interface_declaration, symbol_table, diagnostics); } Class(class_declaration) => { resolve_class_declaration(class_declaration, symbol_table, diagnostics); } Function(interface_function_declaration) => { resolve_interface_function_declaration( interface_function_declaration, symbol_table, diagnostics, ); } OperatorFunction(interface_operator_function_declaration) => { resolve_interface_operator_function_declaration( interface_operator_function_declaration, symbol_table, diagnostics, ); } } } fn resolve_class_level_declaration( declaration: &mut ClassLevelDeclaration, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { use crate::ast::ClassLevelDeclaration::*; match declaration { Module(module_declaration) => { resolve_module_declaration(module_declaration, symbol_table, diagnostics); } Interface(interface_declaration) => { resolve_interface_declaration(interface_declaration, symbol_table, diagnostics); } Class(class_declaration) => { resolve_class_declaration(class_declaration, symbol_table, diagnostics); } Function(function_definition) => { resolve_function_definition(function_definition, symbol_table, diagnostics); } OperatorFunction(operator_function_definition) => { resolve_operator_function_definition( operator_function_definition, symbol_table, diagnostics, ); } PlatformFunction(platform_function_declaration) => { resolve_platform_function_declaration( platform_function_declaration, symbol_table, diagnostics, ); } Property(property_declaration) => { resolve_property_declaration(property_declaration, symbol_table, diagnostics); } Field(field_declaration) => { resolve_field_declaration(field_declaration, symbol_table, diagnostics); } } } /* Main Declarations */ fn resolve_module_declaration( module_declaration: &mut ModuleDeclaration, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { for declaration in module_declaration.declarations_mut() { resolve_module_level_declaration(declaration, symbol_table, diagnostics); } } fn resolve_interface_declaration( interface_declaration: &mut InterfaceDeclaration, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { resolve_implements_list( interface_declaration.implements_mut(), symbol_table, diagnostics, ); for declaration in interface_declaration.declarations_mut() { resolve_interface_level_declaration(declaration, symbol_table, diagnostics); } } fn resolve_class_declaration( class_declaration: &mut ClassDeclaration, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { if let Some(class_constructor) = class_declaration.class_constructor_mut() { resolve_class_constructor(class_constructor, symbol_table, diagnostics); } resolve_implements_list(class_declaration.implements_mut(), symbol_table, diagnostics); for declaration in class_declaration.declarations_mut() { resolve_class_level_declaration(declaration, symbol_table, diagnostics); } } /* Function declarations and components */ fn resolve_function_definition( function_definition: &mut FunctionDefinition, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { resolve_parameters( function_definition.parameters_mut(), symbol_table, diagnostics, ); resolve_return_type( function_definition.return_type_mut(), symbol_table, diagnostics, ); resolve_function_body(function_definition.body_mut(), symbol_table, diagnostics); } fn resolve_operator_function_definition( operator_function_definition: &mut OperatorFunctionDefinition, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { todo!() } fn resolve_platform_function_declaration( platform_function_declaration: &mut PlatformFunctionDeclaration, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { resolve_parameters( platform_function_declaration.parameters_mut(), symbol_table, diagnostics, ); resolve_return_type( platform_function_declaration.return_type_mut(), symbol_table, diagnostics, ); } fn resolve_interface_function_declaration( interface_function_declaration: &mut InterfaceFunctionDeclaration, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { resolve_parameters( interface_function_declaration.parameters_mut(), symbol_table, diagnostics, ); resolve_return_type( interface_function_declaration.return_type_mut(), symbol_table, diagnostics, ); if let Some(body) = interface_function_declaration.body_mut() { resolve_function_body(body, symbol_table, diagnostics); } } fn resolve_interface_operator_function_declaration( interface_operator_function_declaration: &mut InterfaceOperatorFunctionDeclaration, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { todo!() } fn resolve_function_body( function_body: &mut FunctionBody, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { use crate::ast::FunctionBody::*; match function_body { Equals(expression) => resolve_expression(expression, symbol_table, diagnostics), Block(block) => resolve_block_statement(block, symbol_table, diagnostics), Alias(identifier) => resolve_function_alias(identifier, symbol_table, diagnostics), } } fn resolve_function_alias( identifier: &mut Identifier, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { todo!() } /* Class components */ fn resolve_class_constructor( class_constructor: &mut ClassConstructor, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { use crate::ast::ClassConstructorParameter::*; for parameter in class_constructor.parameters_mut() { match parameter { Property(property) => resolve_property_declaration(property, symbol_table, diagnostics), Field(field) => resolve_field_declaration(field, symbol_table, diagnostics), } } } fn resolve_property_declaration( property_declaration: &mut PropertyDeclaration, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { resolve_type_use( property_declaration.declared_type_mut(), symbol_table, diagnostics, ); } fn resolve_field_declaration( field_declaration: &mut FieldDeclaration, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { resolve_type_use( field_declaration.declared_type_mut(), symbol_table, diagnostics, ); } /* Statements */ fn resolve_block_statement( block_statement: &mut BlockStatement, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { for statement in block_statement.statements_mut() { resolve_statement(statement, symbol_table, diagnostics); } if let Some(expression) = block_statement.expression_mut() { resolve_expression(expression, symbol_table, diagnostics); } } fn resolve_statement( statement: &mut Statement, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { use crate::ast::Statement::*; match statement { BlockStatement(block) => resolve_block_statement(block, symbol_table, diagnostics), VariableDeclarationStatement(variable_declaration) => { resolve_variable_declaration(variable_declaration, symbol_table, diagnostics) } AssignStatement(assign_statement) => { resolve_assign_statement(assign_statement, symbol_table, diagnostics) } CallStatement(call_statement) => { resolve_call_statement(call_statement, symbol_table, diagnostics) } _ => todo!(), } } fn resolve_variable_declaration( variable_declaration: &mut VariableDeclarationStatement, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { if let Some(initializer) = variable_declaration.initializer_mut() { resolve_expression(initializer, symbol_table, diagnostics) } } fn resolve_assign_statement( assign_statement: &mut AssignStatement, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { resolve_expression(assign_statement.lhs_mut(), symbol_table, diagnostics); resolve_expression(assign_statement.rhs_mut(), symbol_table, diagnostics); } fn resolve_call_statement( call_statement: &mut CallStatement, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { resolve_expression(call_statement.expression_mut(), symbol_table, diagnostics) } fn resolve_return_statement( return_statement: &mut ReturnStatement, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { if let Some(expression) = return_statement.expression_mut() { resolve_expression(expression, symbol_table, diagnostics); } } fn resolve_if_statement( if_statement: &mut IfStatement, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { todo!() } fn resolve_while_statement( while_statement: &mut WhileStatement, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { todo!() } fn resolve_for_statement( for_statement: &mut ForStatement, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { todo!() } /* Expressions */ fn resolve_expression( expression: &mut Expression, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { use crate::ast::Expression::*; match expression { Ternary(ternary_expression) => { resolve_ternary_expression(ternary_expression, symbol_table, diagnostics); } Binary(binary_expression) => { resolve_binary_expression(binary_expression, symbol_table, diagnostics); } UnaryPrefix(prefix_expression) => { resolve_prefix_expression(prefix_expression, symbol_table, diagnostics); } UnarySuffix(suffix_expression) => { resolve_suffix_expression(suffix_expression, symbol_table, diagnostics); } Call(call_expression) => { resolve_call_expression(call_expression, symbol_table, diagnostics) } ObjectAccess(object_access) => { resolve_object_access(object_access, symbol_table, diagnostics); } FullyQualifiedName(fqn) => { if fqn.is_single_identifier() { resolve_identifier_expression(fqn.last_mut(), symbol_table, diagnostics); } else { resolve_fqn_expression(fqn, symbol_table, diagnostics); } } Literal(literal) => { resolve_literal(literal, symbol_table, diagnostics); } Closure(closure) => { resolve_closure(closure, symbol_table, diagnostics); } } } fn handle_named_lookup_result( lookup_result: Result, named: &mut impl Named, diagnostics: &mut Vec, ) { match lookup_result { Ok(referenced_symbol) => { named.set_saved_symbol(referenced_symbol); } Err(_) => { diagnostics.push( DmDiagnostic::error() .with_message(&format!( "Unable to find expressible symbol {} in current scope.", named.name() )) .with_label(Label::primary(named.file_id(), named.range())), ); } } } fn resolve_identifier_expression( identifier: &mut Identifier, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { let lookup_result = symbol_table .lookup_expressible_by_declared_name(&identifier.name(), identifier.scope_id().unwrap()); handle_named_lookup_result(lookup_result, identifier, diagnostics); } fn resolve_fqn_expression( fqn: &mut FullyQualifiedName, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { let lookup_result = symbol_table.lookup_expressible_by_fqn(&fqn.name(), fqn.last().scope_id().unwrap()); handle_named_lookup_result(lookup_result, fqn, diagnostics); } fn resolve_ternary_expression( ternary_expression: &mut TernaryExpression, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { resolve_expression(ternary_expression.condition_mut(), symbol_table, diagnostics); resolve_expression( ternary_expression.true_expression_mut(), symbol_table, diagnostics, ); resolve_expression( ternary_expression.false_expression_mut(), symbol_table, diagnostics, ); } fn resolve_binary_expression( binary_expression: &mut BinaryExpression, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { resolve_expression(binary_expression.left_mut(), symbol_table, diagnostics); resolve_expression(binary_expression.right_mut(), symbol_table, diagnostics); } fn resolve_prefix_expression( prefix_expression: &mut PrefixExpression, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { resolve_expression(prefix_expression.expression_mut(), symbol_table, diagnostics); } fn resolve_suffix_expression( suffix_expression: &mut SuffixExpression, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { resolve_expression(suffix_expression.expression_mut(), symbol_table, diagnostics); } fn resolve_call_expression( call_expression: &mut CallExpression, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { resolve_expression(call_expression.callee_mut(), symbol_table, diagnostics); if let Some(turbo_fish) = call_expression.turbo_fish_mut() { resolve_turbo_fish(turbo_fish, symbol_table, diagnostics); } resolve_call_arguments(call_expression.arguments_mut(), symbol_table, diagnostics); } fn resolve_turbo_fish( turbo_fish: &mut TurboFish, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { resolve_generic_arguments(turbo_fish.generics_mut(), symbol_table, diagnostics); } fn resolve_call_arguments( call_arguments: &mut CallArguments, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { for argument in call_arguments.arguments_mut() { resolve_call_argument(argument, symbol_table, diagnostics); } } fn resolve_call_argument( call_argument: &mut CallArgument, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { resolve_expression(call_argument.expression_mut(), symbol_table, diagnostics); } fn resolve_closure( closure: &mut Closure, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { todo!() } fn resolve_object_access( object_access: &mut ObjectAccess, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { todo!() } fn resolve_literal( literal: &mut Literal, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { match literal { Literal::DString(d_string) => resolve_d_string(d_string, symbol_table, diagnostics), Literal::BacktickString(d_string) => resolve_d_string(d_string, symbol_table, diagnostics), _ => {} } } fn resolve_d_string( d_string: &mut DString, symbol_table: &mut SymbolTable, diagnostics: &mut Vec, ) { todo!() }