From 6fbb26ba88d06fda46af7da750dbf4db80724757 Mon Sep 17 00:00:00 2001 From: sofia Date: Mon, 25 Aug 2025 20:04:30 +0300 Subject: [PATCH] Start adding generics-pass --- examples/generics.reid | 5 +- reid/src/error_raporting.rs | 6 +- reid/src/lib.rs | 21 +++++- reid/src/mir/generics.rs | 144 ++++++++++++++++++++++++++++++++++++ reid/src/mir/mod.rs | 1 + 5 files changed, 171 insertions(+), 6 deletions(-) create mode 100644 reid/src/mir/generics.rs diff --git a/examples/generics.reid b/examples/generics.reid index 3c91fde..c7b4a57 100644 --- a/examples/generics.reid +++ b/examples/generics.reid @@ -5,8 +5,5 @@ fn test(value: T) -> T { } fn main() -> u32 { - let value = 0b110; - let other = 0o17; - - return value * other + 7 * -value; + return test(5); } \ No newline at end of file diff --git a/reid/src/error_raporting.rs b/reid/src/error_raporting.rs index dddaf6d..ebf10de 100644 --- a/reid/src/error_raporting.rs +++ b/reid/src/error_raporting.rs @@ -8,7 +8,7 @@ use crate::{ ast::token_stream::{self, TokenRange}, codegen, lexer::{self, Cursor, FullToken, Position}, - mir::{self, macros, pass, typecheck, Metadata, SourceModuleId}, + mir::{self, generics, macros, pass, typecheck, Metadata, SourceModuleId}, }; use crate::mir::typecheck::ErrorKind as TypecheckError; @@ -36,6 +36,8 @@ pub enum ErrorKind { LinkerError(#[from] mir::pass::Error), #[error("{}{}", label("(Macro) "), .0)] MacroError(#[from] mir::pass::Error), + #[error("{}{}", label("(Generics) "), .0)] + GenericsError(#[from] mir::pass::Error), #[error("{}{}", label("(Codegen) "), .0)] CodegenError(#[from] codegen::ErrorKind), } @@ -62,6 +64,7 @@ impl ErrorKind { codegen::ErrorKind::Null => Default::default(), }, ErrorKind::MacroError(error) => error.metadata, + ErrorKind::GenericsError(error) => error.metadata, } } @@ -74,6 +77,7 @@ impl ErrorKind { ErrorKind::LinkerError(_) => "linker", ErrorKind::MacroError(_) => "macro-pass", ErrorKind::CodegenError(_) => "codegen", + ErrorKind::GenericsError(_) => "generics", } } } diff --git a/reid/src/lib.rs b/reid/src/lib.rs index 3c25513..58fd4bd 100644 --- a/reid/src/lib.rs +++ b/reid/src/lib.rs @@ -70,6 +70,7 @@ use reid_lib::{compile::CompileOutput, Context}; use crate::{ ast::TopLevelStatement, mir::{ + generics::GenericsPass, macros::{form_macros, MacroModule, MacroPass}, SourceModuleId, }, @@ -177,6 +178,24 @@ pub fn perform_all_passes<'map>( is_lib: true, })?; + #[cfg(debug_assertions)] + log::trace!("{:-^100}", "LINKER OUTPUT"); + #[cfg(debug_assertions)] + log::trace!("{:#}", &context); + #[cfg(debug_assertions)] + log::trace!("{:#?}", &state); + + if !state.errors.is_empty() { + return Err(ReidError::from_kind( + state.errors.iter().map(|e| e.clone().into()).collect(), + module_map.clone(), + )); + } + + let state = context.pass(&mut GenericsPass { + function_map: HashMap::new(), + })?; + for module in &mut context.modules { for intrinsic in form_intrinsics() { module.1.functions.insert(0, intrinsic); @@ -184,7 +203,7 @@ pub fn perform_all_passes<'map>( } #[cfg(debug_assertions)] - log::trace!("{:-^100}", "LINKER OUTPUT"); + log::trace!("{:-^100}", "GENERICS OUTPUT"); #[cfg(debug_assertions)] log::trace!("{:#}", &context); #[cfg(debug_assertions)] diff --git a/reid/src/mir/generics.rs b/reid/src/mir/generics.rs new file mode 100644 index 0000000..7c35080 --- /dev/null +++ b/reid/src/mir/generics.rs @@ -0,0 +1,144 @@ +use std::{collections::HashMap, path::PathBuf}; + +use crate::mir::{ + self, FunctionCall, GlobalKind, GlobalValue, IfExpression, Literal, Module, SourceModuleId, TypeKind, + WhileStatement, +}; + +use super::pass::{Pass, PassResult, PassState}; + +#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub enum ErrorKind { + #[error("Should never be encountered!")] + Null, +} + +type Calls = Vec>; + +pub struct GenericsPass { + pub function_map: HashMap>>, +} + +type GenericsPassState<'map, 'st, 'sc> = PassState<'st, 'sc, (), ErrorKind>; + +impl Pass for GenericsPass { + type Data = (); + type TError = ErrorKind; + + fn context(&mut self, context: &mut mir::Context, mut _state: PassState) -> PassResult { + for module in &context.modules { + let mut calls = HashMap::new(); + let mut assoc_calls = HashMap::new(); + for function in &module.1.associated_functions { + match &function.1.kind { + mir::FunctionDefinitionKind::Local(block, _) => block.find_calls(&mut calls, &mut assoc_calls), + mir::FunctionDefinitionKind::Extern(_) => {} + mir::FunctionDefinitionKind::Intrinsic(_) => {} + } + } + for function in &module.1.functions { + match &function.kind { + mir::FunctionDefinitionKind::Local(block, _) => block.find_calls(&mut calls, &mut assoc_calls), + mir::FunctionDefinitionKind::Extern(_) => {} + mir::FunctionDefinitionKind::Intrinsic(_) => {} + } + } + dbg!(&calls); + dbg!(&assoc_calls); + } + + Ok(()) + } + + fn module(&mut self, module: &mut mir::Module, mut state: PassState) -> PassResult { + Ok(()) + } +} + +impl mir::Block { + fn find_calls(&self, calls: &mut HashMap, assoc_calls: &mut HashMap<(TypeKind, String), Calls>) { + for statement in &self.statements { + statement.find_calls(calls, assoc_calls); + } + if let Some((_, Some(e))) = &self.return_expression { + e.find_calls(calls, assoc_calls); + } + } +} + +impl mir::Statement { + fn find_calls(&self, calls: &mut HashMap, assoc_calls: &mut HashMap<(TypeKind, String), Calls>) { + match &self.0 { + mir::StmtKind::Let(_, _, expression) => expression.find_calls(calls, assoc_calls), + mir::StmtKind::Set(expression, expression1) => { + expression.find_calls(calls, assoc_calls); + expression1.find_calls(calls, assoc_calls); + } + mir::StmtKind::Import(_) => {} + mir::StmtKind::Expression(expression) => expression.find_calls(calls, assoc_calls), + mir::StmtKind::While(WhileStatement { condition, block, .. }) => { + condition.find_calls(calls, assoc_calls); + block.find_calls(calls, assoc_calls); + } + } + } +} + +impl mir::Expression { + fn find_calls(&self, calls: &mut HashMap, assoc_calls: &mut HashMap<(TypeKind, String), Calls>) { + match &self.0 { + mir::ExprKind::Variable(_) => {} + mir::ExprKind::Indexed(expression, _, expression1) => { + expression.find_calls(calls, assoc_calls); + expression1.find_calls(calls, assoc_calls); + } + mir::ExprKind::Accessed(expression, _, _, _) => { + expression.find_calls(calls, assoc_calls); + } + mir::ExprKind::Array(expressions) => { + for expression in expressions { + expression.find_calls(calls, assoc_calls); + } + } + mir::ExprKind::Struct(_, items) => { + for item in items { + item.1.find_calls(calls, assoc_calls); + } + } + mir::ExprKind::Literal(_) => todo!(), + mir::ExprKind::BinOp(_, lhs, rhs, _) => { + lhs.find_calls(calls, assoc_calls); + rhs.find_calls(calls, assoc_calls); + } + mir::ExprKind::FunctionCall(function_call) => { + if let Some(calls) = calls.get_mut(&function_call.name) { + calls.push(function_call.generics.clone()); + } else { + calls.insert(function_call.name.clone(), vec![function_call.generics.clone()]); + } + } + mir::ExprKind::AssociatedFunctionCall(ty, function_call) => { + if let Some(calls) = assoc_calls.get_mut(&(ty.clone(), function_call.name.clone())) { + calls.push(function_call.generics.clone()); + } else { + assoc_calls.insert( + (ty.clone(), function_call.name.clone()), + vec![function_call.generics.clone()], + ); + } + } + mir::ExprKind::If(IfExpression(cond, then_e, else_e)) => { + cond.find_calls(calls, assoc_calls); + then_e.find_calls(calls, assoc_calls); + if let Some(else_e) = else_e.as_ref() { + else_e.find_calls(calls, assoc_calls); + } + } + mir::ExprKind::Block(block) => block.find_calls(calls, assoc_calls), + mir::ExprKind::Borrow(expression, _) => expression.find_calls(calls, assoc_calls), + mir::ExprKind::Deref(expression) => expression.find_calls(calls, assoc_calls), + mir::ExprKind::CastTo(expression, _) => expression.find_calls(calls, assoc_calls), + mir::ExprKind::GlobalRef(_, _) => {} + } + } +} diff --git a/reid/src/mir/mod.rs b/reid/src/mir/mod.rs index 34ea57d..3e4f960 100644 --- a/reid/src/mir/mod.rs +++ b/reid/src/mir/mod.rs @@ -11,6 +11,7 @@ use crate::{ }; mod fmt; +pub mod generics; pub mod implement; pub mod linker; pub mod macros;