diff --git a/dmc-lib/src/lowering/mod.rs b/dmc-lib/src/lowering/mod.rs index 0e877f8..42bb745 100644 --- a/dmc-lib/src/lowering/mod.rs +++ b/dmc-lib/src/lowering/mod.rs @@ -17,7 +17,7 @@ use crate::ir::ir_call::IrCall; use crate::ir::ir_expression::IrExpression; use crate::ir::ir_function::IrFunction; use crate::ir::ir_operation::IrOperation; -use crate::ir::ir_parameter::IrParameter; +use crate::ir::ir_parameter::{IrParameter, IrParameterId}; use crate::ir::ir_return::IrReturn; use crate::ir::ir_statement::IrStatement; use crate::ir::ir_type_info::IrTypeInfo; @@ -27,7 +27,6 @@ use crate::semantic_analysis::symbol::{Symbol, SymbolId}; use crate::semantic_analysis::type_info::{TypeInfo, TypeInfoId}; use std::collections::HashMap; use std::ops::Neg; -use std::rc::Rc; pub struct LowerToIrResult { pub functions: Vec, @@ -72,6 +71,8 @@ struct LowerToIrFunctionContext { blocks: Vec, ir_variables: Vec, symbols_to_variables: HashMap, + ir_parameters: Vec, + symbols_to_parameters: HashMap, current_block_statements: Vec, t_var_counter: usize, } @@ -82,6 +83,8 @@ impl LowerToIrFunctionContext { blocks: Vec::new(), ir_variables: Vec::new(), symbols_to_variables: HashMap::new(), + ir_parameters: Vec::new(), + symbols_to_parameters: HashMap::new(), current_block_statements: Vec::new(), t_var_counter: 0, } @@ -101,6 +104,20 @@ impl LowerToIrFunctionContext { self.blocks.push(ir_block); } + fn insert_ir_parameter( + &mut self, + ir_parameter: IrParameter, + maybe_associated_symbol_id: Option, + ) -> IrParameterId { + self.ir_parameters.push(ir_parameter); + let ir_parameter_id = self.ir_parameters.len() - 1; + if let Some(associated_symbol_id) = maybe_associated_symbol_id { + self.symbols_to_parameters + .insert(associated_symbol_id, ir_parameter_id); + } + ir_parameter_id + } + fn insert_ir_variable( &mut self, ir_variable: IrVariable, @@ -124,24 +141,10 @@ impl LowerToIrFunctionContext { } fn lower_to_ir_function(function: &Function, ctx: &mut LowerToIrContext) { - fn lower_to_ir_parameters(function: &Function, ctx: &mut LowerToIrContext) -> Vec { - let mut ir_parameters = Vec::new(); - let n_parameters = function.parameters().len() as isize; - for (i, parameter) in function.parameters().iter().enumerate() { - let parameter_type_info_id = ctx.nodes_to_type_infos[¶meter.node_id()]; - let parameter_type_info = &ctx.type_infos[parameter_type_info_id]; - let ir_parameter = IrParameter::new( - parameter.declared_name(), - to_ir_type_info(parameter_type_info), - n_parameters.neg() + (i as isize), - ); - ir_parameters.push(ir_parameter); - } - ir_parameters - } - let mut fn_ctx = LowerToIrFunctionContext::new(); + lower_to_ir_parameters(function, ctx, &mut fn_ctx); + let n_statements = function.statements().len(); for (i, statement) in function.statements().iter().enumerate() { let can_return_value = i == n_statements - 1; @@ -156,12 +159,16 @@ fn lower_to_ir_function(function: &Function, ctx: &mut LowerToIrContext) { _ => panic!("Expected function symbol"), }; - let return_type_info_id = ctx.symbols_to_type_infos[&function_symbol_id]; - let return_type_info = &ctx.type_infos[return_type_info_id]; + let function_type_info_id = ctx.symbols_to_type_infos[&function_symbol_id]; + let function_type_info = match &ctx.type_infos[function_type_info_id] { + TypeInfo::Function(function_type_info) => function_type_info, + _ => panic!("Expected FunctionTypeInfo"), + }; + let return_type_info = &ctx.type_infos[function_type_info.return_type_id()]; let ir_function = IrFunction::new( function_symbol.fqn_owned(), - lower_to_ir_parameters(function, ctx), + fn_ctx.ir_parameters, fn_ctx.ir_variables, return_type_info_to_ir_type_info(return_type_info), fn_ctx.blocks, @@ -170,6 +177,27 @@ fn lower_to_ir_function(function: &Function, ctx: &mut LowerToIrContext) { ctx.ir_functions.push(ir_function); } +fn lower_to_ir_parameters( + function: &Function, + ctx: &LowerToIrContext, + fn_ctx: &mut LowerToIrFunctionContext, +) { + let n_parameters = function.parameters().len() as isize; + for (i, parameter) in function.parameters().iter().enumerate() { + let parameter_type_info_id = ctx.nodes_to_type_infos[¶meter.node_id()]; + let parameter_type_info = &ctx.type_infos[parameter_type_info_id]; + let ir_parameter = IrParameter::new( + parameter.declared_name(), + to_ir_type_info(parameter_type_info), + n_parameters.neg() + (i as isize), + ); + fn_ctx.insert_ir_parameter( + ir_parameter, + Some(ctx.nodes_to_symbols[¶meter.node_id()]), + ); + } +} + fn lower_to_ir_statement( statement: &Statement, ctx: &LowerToIrContext, @@ -389,8 +417,18 @@ fn lower_expression_to_ir_expression( } Expression::Identifier(identifier) => { let rhs_symbol_id = ctx.nodes_to_symbols[&identifier.node_id()]; - let rhs_ir_variable_id = fn_ctx.symbols_to_variables[&rhs_symbol_id]; - IrExpression::Variable(rhs_ir_variable_id) + if let Some(rhs_ir_variable_id) = fn_ctx.symbols_to_variables.get(&rhs_symbol_id) { + IrExpression::Variable(*rhs_ir_variable_id) + } else if let Some(rhs_ir_parameter_id) = + fn_ctx.symbols_to_parameters.get(&rhs_symbol_id) + { + IrExpression::Parameter(*rhs_ir_parameter_id) + } else { + panic!( + "Could not find parameter or variable for symbol_id {}", + rhs_symbol_id + ); + } } Expression::Integer(integer_literal) => IrExpression::Int(integer_literal.value()), Expression::Double(double_literal) => IrExpression::Double(double_literal.value()), diff --git a/dmc-lib/src/semantic_analysis/collect_types.rs b/dmc-lib/src/semantic_analysis/collect_types.rs index 6f38f9e..5bead2c 100644 --- a/dmc-lib/src/semantic_analysis/collect_types.rs +++ b/dmc-lib/src/semantic_analysis/collect_types.rs @@ -53,7 +53,8 @@ pub fn collect_types( } fn collect_types_function(function: &Function, ctx: &mut CollectTypesContext) { - let parameter_type_info_ids = get_parameter_type_info_ids(function.parameters(), ctx); + let parameter_type_info_ids = + collect_and_get_parameter_type_info_ids(function.parameters(), ctx); let return_type_info = match function.return_type() { None => TypeInfo::Void, @@ -83,7 +84,7 @@ fn declared_name_to_type_info(declared_name: &str) -> TypeInfo { } } -fn get_parameter_type_info_ids( +fn collect_and_get_parameter_type_info_ids( parameters: &[Parameter], ctx: &mut CollectTypesContext, ) -> Vec { @@ -92,12 +93,17 @@ fn get_parameter_type_info_ids( let type_info = declared_name_to_type_info(parameter.type_use().declared_name()); let type_info_id = ctx.insert_type_info(type_info); parameter_type_info_ids.push(type_info_id); + + // also associate the parameter symbol with the type info + let symbol_id = ctx.nodes_to_symbols[¶meter.node_id()]; + ctx.symbols_to_type_infos.insert(symbol_id, type_info_id); } parameter_type_info_ids } fn collect_types_extern_function(extern_function: &ExternFunction, ctx: &mut CollectTypesContext) { - let parameter_type_info_ids = get_parameter_type_info_ids(extern_function.parameters(), ctx); + let parameter_type_info_ids = + collect_and_get_parameter_type_info_ids(extern_function.parameters(), ctx); let return_type_info = declared_name_to_type_info(extern_function.return_type().declared_name()); diff --git a/dmc-lib/src/semantic_analysis/resolve_names.rs b/dmc-lib/src/semantic_analysis/resolve_names.rs index e413605..cf04f6c 100644 --- a/dmc-lib/src/semantic_analysis/resolve_names.rs +++ b/dmc-lib/src/semantic_analysis/resolve_names.rs @@ -9,11 +9,12 @@ use crate::ast::function::Function; use crate::ast::identifier::Identifier; use crate::ast::let_statement::LetStatement; use crate::ast::negative_expression::NegativeExpression; +use crate::ast::parameter::Parameter; use crate::ast::statement::Statement; use crate::diagnostic::Diagnostics; use crate::diagnostic_factories::symbol_not_found; use crate::semantic_analysis::scope::{Scope, ScopeId}; -use crate::semantic_analysis::symbol::{Symbol, SymbolId, VariableSymbol}; +use crate::semantic_analysis::symbol::{ParameterSymbol, Symbol, SymbolId, VariableSymbol}; use std::collections::HashMap; pub struct NameResolutionResult { @@ -105,9 +106,27 @@ pub fn resolve_names( } fn resolve_names_function(function: &Function, ctx: &mut NameResolutionContext) { + for parameter in function.parameters() { + resolve_names_parameter(parameter, ctx); + } + for statement in function.statements() { resolve_names_statement(statement, ctx, StatementResolutionPhase::Static); } + + // point this function's node_id to the symbol_id for the function symbol + let scope_id = ctx.nodes_to_scopes[&function.node_id()]; + let scope = &ctx.scopes[scope_id]; + let symbol_id = scope.symbols()[function.declared_name()]; + ctx.nodes_to_symbols.insert(function.node_id(), symbol_id); +} + +fn resolve_names_parameter(parameter: &Parameter, ctx: &mut NameResolutionContext) { + // point this parameter's node_id to the symbol_id for the parameter symbol + let scope_id = ctx.nodes_to_scopes[¶meter.node_id()]; + let scope = &ctx.scopes[scope_id]; + let symbol_id = scope.symbols()[parameter.declared_name()]; + ctx.nodes_to_symbols.insert(parameter.node_id(), symbol_id); } fn resolve_names_statement( diff --git a/dmc-lib/src/semantic_analysis/resolve_types/mod.rs b/dmc-lib/src/semantic_analysis/resolve_types/mod.rs index d46a302..19cf64c 100644 --- a/dmc-lib/src/semantic_analysis/resolve_types/mod.rs +++ b/dmc-lib/src/semantic_analysis/resolve_types/mod.rs @@ -10,6 +10,7 @@ use crate::ast::function::Function; use crate::ast::identifier::Identifier; use crate::ast::let_statement::LetStatement; use crate::ast::negative_expression::NegativeExpression; +use crate::ast::parameter::Parameter; use crate::ast::statement::Statement; use crate::diagnostic::{Diagnostic, Diagnostics}; use crate::error_codes::BINARY_INCOMPATIBLE_TYPES; @@ -67,11 +68,23 @@ pub fn resolve_types( } fn resolve_types_function(function: &Function, ctx: &mut ResolveTypesContext) { + for parameter in function.parameters() { + resolve_types_parameter(parameter, ctx); + } + for statement in function.statements() { resolve_types_statement(statement, ctx); } } +fn resolve_types_parameter(parameter: &Parameter, ctx: &mut ResolveTypesContext) { + // point the parameter's node_id to the associated type_info + let symbol_id = ctx.nodes_to_symbols[¶meter.node_id()]; + let type_info_id = ctx.symbols_to_type_infos[&symbol_id]; + ctx.nodes_to_type_infos + .insert(parameter.node_id(), type_info_id); +} + fn resolve_types_statement(statement: &Statement, ctx: &mut ResolveTypesContext) { match statement { Statement::Let(let_statement) => { @@ -300,7 +313,7 @@ fn resolve_types_call(call: &Call, ctx: &mut ResolveTypesContext) { // set return type as type of call expression let return_type_info_id = function_type_info.return_type_id(); ctx.nodes_to_type_infos - .insert(call.node_id(), *return_type_info_id); + .insert(call.node_id(), return_type_info_id); } TypeInfo::__Error => { // bubble it up diff --git a/dmc-lib/src/semantic_analysis/type_info.rs b/dmc-lib/src/semantic_analysis/type_info.rs index 0a0588f..dbaaeb7 100644 --- a/dmc-lib/src/semantic_analysis/type_info.rs +++ b/dmc-lib/src/semantic_analysis/type_info.rs @@ -49,7 +49,7 @@ impl FunctionTypeInfo { &self.parameter_type_info_ids } - pub fn return_type_id(&self) -> &TypeInfoId { - &self.return_type_info_id + pub fn return_type_id(&self) -> TypeInfoId { + self.return_type_info_id } }