Fix some analysis/lowering bugs. WIP.
This commit is contained in:
parent
01df9a708f
commit
c59fbe4033
@ -17,7 +17,7 @@ use crate::ir::ir_call::IrCall;
|
|||||||
use crate::ir::ir_expression::IrExpression;
|
use crate::ir::ir_expression::IrExpression;
|
||||||
use crate::ir::ir_function::IrFunction;
|
use crate::ir::ir_function::IrFunction;
|
||||||
use crate::ir::ir_operation::IrOperation;
|
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_return::IrReturn;
|
||||||
use crate::ir::ir_statement::IrStatement;
|
use crate::ir::ir_statement::IrStatement;
|
||||||
use crate::ir::ir_type_info::IrTypeInfo;
|
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 crate::semantic_analysis::type_info::{TypeInfo, TypeInfoId};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ops::Neg;
|
use std::ops::Neg;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
pub struct LowerToIrResult {
|
pub struct LowerToIrResult {
|
||||||
pub functions: Vec<IrFunction>,
|
pub functions: Vec<IrFunction>,
|
||||||
@ -72,6 +71,8 @@ struct LowerToIrFunctionContext {
|
|||||||
blocks: Vec<IrBlock>,
|
blocks: Vec<IrBlock>,
|
||||||
ir_variables: Vec<IrVariable>,
|
ir_variables: Vec<IrVariable>,
|
||||||
symbols_to_variables: HashMap<SymbolId, IrVariableId>,
|
symbols_to_variables: HashMap<SymbolId, IrVariableId>,
|
||||||
|
ir_parameters: Vec<IrParameter>,
|
||||||
|
symbols_to_parameters: HashMap<SymbolId, IrParameterId>,
|
||||||
current_block_statements: Vec<IrStatement>,
|
current_block_statements: Vec<IrStatement>,
|
||||||
t_var_counter: usize,
|
t_var_counter: usize,
|
||||||
}
|
}
|
||||||
@ -82,6 +83,8 @@ impl LowerToIrFunctionContext {
|
|||||||
blocks: Vec::new(),
|
blocks: Vec::new(),
|
||||||
ir_variables: Vec::new(),
|
ir_variables: Vec::new(),
|
||||||
symbols_to_variables: HashMap::new(),
|
symbols_to_variables: HashMap::new(),
|
||||||
|
ir_parameters: Vec::new(),
|
||||||
|
symbols_to_parameters: HashMap::new(),
|
||||||
current_block_statements: Vec::new(),
|
current_block_statements: Vec::new(),
|
||||||
t_var_counter: 0,
|
t_var_counter: 0,
|
||||||
}
|
}
|
||||||
@ -101,6 +104,20 @@ impl LowerToIrFunctionContext {
|
|||||||
self.blocks.push(ir_block);
|
self.blocks.push(ir_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn insert_ir_parameter(
|
||||||
|
&mut self,
|
||||||
|
ir_parameter: IrParameter,
|
||||||
|
maybe_associated_symbol_id: Option<SymbolId>,
|
||||||
|
) -> 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(
|
fn insert_ir_variable(
|
||||||
&mut self,
|
&mut self,
|
||||||
ir_variable: IrVariable,
|
ir_variable: IrVariable,
|
||||||
@ -124,24 +141,10 @@ impl LowerToIrFunctionContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn lower_to_ir_function(function: &Function, ctx: &mut LowerToIrContext) {
|
fn lower_to_ir_function(function: &Function, ctx: &mut LowerToIrContext) {
|
||||||
fn lower_to_ir_parameters(function: &Function, ctx: &mut LowerToIrContext) -> Vec<IrParameter> {
|
|
||||||
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();
|
let mut fn_ctx = LowerToIrFunctionContext::new();
|
||||||
|
|
||||||
|
lower_to_ir_parameters(function, ctx, &mut fn_ctx);
|
||||||
|
|
||||||
let n_statements = function.statements().len();
|
let n_statements = function.statements().len();
|
||||||
for (i, statement) in function.statements().iter().enumerate() {
|
for (i, statement) in function.statements().iter().enumerate() {
|
||||||
let can_return_value = i == n_statements - 1;
|
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"),
|
_ => panic!("Expected function symbol"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let return_type_info_id = ctx.symbols_to_type_infos[&function_symbol_id];
|
let function_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 = 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(
|
let ir_function = IrFunction::new(
|
||||||
function_symbol.fqn_owned(),
|
function_symbol.fqn_owned(),
|
||||||
lower_to_ir_parameters(function, ctx),
|
fn_ctx.ir_parameters,
|
||||||
fn_ctx.ir_variables,
|
fn_ctx.ir_variables,
|
||||||
return_type_info_to_ir_type_info(return_type_info),
|
return_type_info_to_ir_type_info(return_type_info),
|
||||||
fn_ctx.blocks,
|
fn_ctx.blocks,
|
||||||
@ -170,6 +177,27 @@ fn lower_to_ir_function(function: &Function, ctx: &mut LowerToIrContext) {
|
|||||||
ctx.ir_functions.push(ir_function);
|
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(
|
fn lower_to_ir_statement(
|
||||||
statement: &Statement,
|
statement: &Statement,
|
||||||
ctx: &LowerToIrContext,
|
ctx: &LowerToIrContext,
|
||||||
@ -389,8 +417,18 @@ fn lower_expression_to_ir_expression(
|
|||||||
}
|
}
|
||||||
Expression::Identifier(identifier) => {
|
Expression::Identifier(identifier) => {
|
||||||
let rhs_symbol_id = ctx.nodes_to_symbols[&identifier.node_id()];
|
let rhs_symbol_id = ctx.nodes_to_symbols[&identifier.node_id()];
|
||||||
let rhs_ir_variable_id = fn_ctx.symbols_to_variables[&rhs_symbol_id];
|
if let Some(rhs_ir_variable_id) = fn_ctx.symbols_to_variables.get(&rhs_symbol_id) {
|
||||||
IrExpression::Variable(rhs_ir_variable_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::Integer(integer_literal) => IrExpression::Int(integer_literal.value()),
|
||||||
Expression::Double(double_literal) => IrExpression::Double(double_literal.value()),
|
Expression::Double(double_literal) => IrExpression::Double(double_literal.value()),
|
||||||
|
|||||||
@ -53,7 +53,8 @@ pub fn collect_types(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn collect_types_function(function: &Function, ctx: &mut CollectTypesContext) {
|
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() {
|
let return_type_info = match function.return_type() {
|
||||||
None => TypeInfo::Void,
|
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],
|
parameters: &[Parameter],
|
||||||
ctx: &mut CollectTypesContext,
|
ctx: &mut CollectTypesContext,
|
||||||
) -> Vec<TypeInfoId> {
|
) -> Vec<TypeInfoId> {
|
||||||
@ -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 = declared_name_to_type_info(parameter.type_use().declared_name());
|
||||||
let type_info_id = ctx.insert_type_info(type_info);
|
let type_info_id = ctx.insert_type_info(type_info);
|
||||||
parameter_type_info_ids.push(type_info_id);
|
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
|
parameter_type_info_ids
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_types_extern_function(extern_function: &ExternFunction, ctx: &mut CollectTypesContext) {
|
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 =
|
let return_type_info =
|
||||||
declared_name_to_type_info(extern_function.return_type().declared_name());
|
declared_name_to_type_info(extern_function.return_type().declared_name());
|
||||||
|
|||||||
@ -9,11 +9,12 @@ use crate::ast::function::Function;
|
|||||||
use crate::ast::identifier::Identifier;
|
use crate::ast::identifier::Identifier;
|
||||||
use crate::ast::let_statement::LetStatement;
|
use crate::ast::let_statement::LetStatement;
|
||||||
use crate::ast::negative_expression::NegativeExpression;
|
use crate::ast::negative_expression::NegativeExpression;
|
||||||
|
use crate::ast::parameter::Parameter;
|
||||||
use crate::ast::statement::Statement;
|
use crate::ast::statement::Statement;
|
||||||
use crate::diagnostic::Diagnostics;
|
use crate::diagnostic::Diagnostics;
|
||||||
use crate::diagnostic_factories::symbol_not_found;
|
use crate::diagnostic_factories::symbol_not_found;
|
||||||
use crate::semantic_analysis::scope::{Scope, ScopeId};
|
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;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub struct NameResolutionResult {
|
pub struct NameResolutionResult {
|
||||||
@ -105,9 +106,27 @@ pub fn resolve_names(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_names_function(function: &Function, ctx: &mut NameResolutionContext) {
|
fn resolve_names_function(function: &Function, ctx: &mut NameResolutionContext) {
|
||||||
|
for parameter in function.parameters() {
|
||||||
|
resolve_names_parameter(parameter, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
for statement in function.statements() {
|
for statement in function.statements() {
|
||||||
resolve_names_statement(statement, ctx, StatementResolutionPhase::Static);
|
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(
|
fn resolve_names_statement(
|
||||||
|
|||||||
@ -10,6 +10,7 @@ use crate::ast::function::Function;
|
|||||||
use crate::ast::identifier::Identifier;
|
use crate::ast::identifier::Identifier;
|
||||||
use crate::ast::let_statement::LetStatement;
|
use crate::ast::let_statement::LetStatement;
|
||||||
use crate::ast::negative_expression::NegativeExpression;
|
use crate::ast::negative_expression::NegativeExpression;
|
||||||
|
use crate::ast::parameter::Parameter;
|
||||||
use crate::ast::statement::Statement;
|
use crate::ast::statement::Statement;
|
||||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||||
use crate::error_codes::BINARY_INCOMPATIBLE_TYPES;
|
use crate::error_codes::BINARY_INCOMPATIBLE_TYPES;
|
||||||
@ -67,11 +68,23 @@ pub fn resolve_types(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_types_function(function: &Function, ctx: &mut ResolveTypesContext) {
|
fn resolve_types_function(function: &Function, ctx: &mut ResolveTypesContext) {
|
||||||
|
for parameter in function.parameters() {
|
||||||
|
resolve_types_parameter(parameter, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
for statement in function.statements() {
|
for statement in function.statements() {
|
||||||
resolve_types_statement(statement, ctx);
|
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) {
|
fn resolve_types_statement(statement: &Statement, ctx: &mut ResolveTypesContext) {
|
||||||
match statement {
|
match statement {
|
||||||
Statement::Let(let_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
|
// set return type as type of call expression
|
||||||
let return_type_info_id = function_type_info.return_type_id();
|
let return_type_info_id = function_type_info.return_type_id();
|
||||||
ctx.nodes_to_type_infos
|
ctx.nodes_to_type_infos
|
||||||
.insert(call.node_id(), *return_type_info_id);
|
.insert(call.node_id(), return_type_info_id);
|
||||||
}
|
}
|
||||||
TypeInfo::__Error => {
|
TypeInfo::__Error => {
|
||||||
// bubble it up
|
// bubble it up
|
||||||
|
|||||||
@ -49,7 +49,7 @@ impl FunctionTypeInfo {
|
|||||||
&self.parameter_type_info_ids
|
&self.parameter_type_info_ids
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn return_type_id(&self) -> &TypeInfoId {
|
pub fn return_type_id(&self) -> TypeInfoId {
|
||||||
&self.return_type_info_id
|
self.return_type_info_id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user