From f35f1ef701989905ab9451ffd82bac0cd87e2676 Mon Sep 17 00:00:00 2001 From: sofia Date: Tue, 22 Jul 2025 17:32:37 +0300 Subject: [PATCH] Repurpose module map and rename old to ErrorModules --- reid/src/ast/mod.rs | 3 +- reid/src/ast/process.rs | 16 +++++-- reid/src/codegen.rs | 69 +++++++++++++--------------- reid/src/error_raporting.rs | 20 ++++----- reid/src/lib.rs | 21 +++++---- reid/src/mir/fmt.rs | 2 +- reid/src/mir/linker.rs | 89 ++++++++++++++++--------------------- reid/src/mir/mod.rs | 5 ++- reid/src/mir/pass.rs | 2 +- reid/tests/e2e.rs | 7 +-- reid/tests/stdlib.rs | 7 +-- 11 files changed, 116 insertions(+), 125 deletions(-) diff --git a/reid/src/ast/mod.rs b/reid/src/ast/mod.rs index a594164..9acbe9d 100644 --- a/reid/src/ast/mod.rs +++ b/reid/src/ast/mod.rs @@ -3,7 +3,7 @@ //! used for unwrapping syntax sugar, and then be transformed into Reid MIR. use std::path::PathBuf; -use crate::token_stream::TokenRange; +use crate::{lexer::FullToken, token_stream::TokenRange}; pub mod parse; pub mod process; @@ -206,6 +206,7 @@ pub enum TopLevelStatement { #[derive(Debug)] pub struct Module { pub name: String, + pub tokens: Vec, pub top_level_statements: Vec, pub path: Option, pub is_main: bool, diff --git a/reid/src/ast/process.rs b/reid/src/ast/process.rs index 8038734..f0378a7 100644 --- a/reid/src/ast/process.rs +++ b/reid/src/ast/process.rs @@ -1,18 +1,25 @@ -use std::{path::PathBuf, process}; +use std::path::PathBuf; use crate::{ ast::{self}, - mir::{self, NamedVariableRef, SourceModuleId, StmtKind, StructField, StructType, TypeKey}, + mir::{ + self, ModuleMap, NamedVariableRef, SourceModuleId, StmtKind, StructField, StructType, + TypeKey, + }, }; impl mir::Context { pub fn from(modules: Vec, base: PathBuf) -> mir::Context { - mir::Context { modules, base } + let mut map = ModuleMap::new(); + for module in modules { + map.insert(module.module_id, module); + } + mir::Context { modules: map, base } } } impl ast::Module { - pub fn process(&self, module_id: SourceModuleId) -> mir::Module { + pub fn process(self, module_id: SourceModuleId) -> mir::Module { let mut imports = Vec::new(); let mut functions = Vec::new(); let mut typedefs = Vec::new(); @@ -100,6 +107,7 @@ impl ast::Module { functions, path: self.path.clone(), is_main: self.is_main, + tokens: self.tokens, typedefs, } } diff --git a/reid/src/codegen.rs b/reid/src/codegen.rs index 15e39d0..8a67376 100644 --- a/reid/src/codegen.rs +++ b/reid/src/codegen.rs @@ -15,7 +15,7 @@ use reid_lib::{ }; use crate::{ - error_raporting::ModuleMap, + error_raporting::ErrorModules, lexer::{FullToken, Position}, mir::{ self, implement::TypeCategory, Metadata, NamedVariableRef, SourceModuleId, StructField, @@ -40,24 +40,10 @@ impl<'ctx> CodegenContext<'ctx> { impl mir::Context { /// Compile MIR [`Context`] into [`CodegenContext`] containing LLIR. - pub fn codegen<'ctx>( - &self, - context: &'ctx Context, - mod_map: &ModuleMap, - ) -> CodegenContext<'ctx> { + pub fn codegen<'ctx>(&self, context: &'ctx Context) -> CodegenContext<'ctx> { let mut modules = Vec::new(); - for module in &self.modules { - modules.push( - module.codegen( - context, - mod_map - .module(&module.module_id) - .unwrap() - .tokens - .as_ref() - .unwrap(), - ), - ); + for (_, module) in &self.modules { + modules.push(module.codegen(context)); } CodegenContext { context } } @@ -198,12 +184,9 @@ impl Default for State { } impl mir::Module { - fn codegen<'ctx>( - &self, - context: &'ctx Context, - tokens: &Vec, - ) -> ModuleCodegen<'ctx> { + fn codegen<'ctx>(&self, context: &'ctx Context) -> ModuleCodegen<'ctx> { let mut module = context.module(&self.name, self.is_main); + let tokens = &self.tokens; let (debug, compile_unit) = if let Some(path) = &self.path { module.create_debug_info(DebugFileData { @@ -252,19 +235,24 @@ impl mir::Module { insert_debug!(&TypeKind::Char); for typedef in &self.typedefs { - let type_key = TypeKey(typedef.name.clone(), self.module_id); - let type_value = match &typedef.kind { - TypeDefinitionKind::Struct(StructType(fields)) => { - module.custom_type(CustomTypeKind::NamedStruct(NamedStruct( - typedef.name.clone(), - fields - .iter() - // TODO: Reorder custom-type definitions such that - // inner types get evaluated first. Otherwise this - // will cause a panic! - .map(|StructField(_, t, _)| t.get_type(&type_values, &types)) - .collect(), - ))) + let type_key = TypeKey(typedef.name.clone(), typedef.source_module); + + let type_value = if typedef.source_module != self.module_id { + todo!() + } else { + match &typedef.kind { + TypeDefinitionKind::Struct(StructType(fields)) => { + module.custom_type(CustomTypeKind::NamedStruct(NamedStruct( + typedef.name.clone(), + fields + .iter() + // TODO: Reorder custom-type definitions such that + // inner types get evaluated first. Otherwise this + // will cause a panic! + .map(|StructField(_, t, _)| t.get_type(&type_values, &types)) + .collect(), + ))) + } } }; types.insert(type_value, typedef.clone()); @@ -891,6 +879,7 @@ impl mir::Expression { mir::ExprKind::Accessed(expression, type_kind, field) => { let struct_val = expression.codegen(scope, &state.load(false)).unwrap(); + dbg!(&expression); let TypeKind::CodegenPtr(inner) = &struct_val.1 else { panic!("tried accessing non-pointer"); }; @@ -1034,7 +1023,13 @@ impl mir::Expression { panic!("Variable was not a pointer?!?") } } else { - StackValue(v.0.derive(var_ptr_instr), *ptr_inner.clone()) + let TypeKind::Borrow(borrow_inner, mutable) = *ptr_inner.clone() else { + panic!(); + }; + StackValue( + StackValueKind::mutable(mutable, var_ptr_instr), + *borrow_inner.clone(), + ) } }) } diff --git a/reid/src/error_raporting.rs b/reid/src/error_raporting.rs index ef379b5..1a864bc 100644 --- a/reid/src/error_raporting.rs +++ b/reid/src/error_raporting.rs @@ -63,24 +63,24 @@ impl PartialOrd for ErrorKind { } #[derive(Debug, Clone, PartialEq, Eq)] -pub struct Module { +pub struct ErrorModule { pub name: String, pub tokens: Option>, pub source: Option, } #[derive(Debug, Clone, PartialEq, Eq, Default)] -pub struct ModuleMap { - module_map: HashMap, +pub struct ErrorModules { + module_map: HashMap, module_counter: mir::SourceModuleId, } -impl ModuleMap { +impl ErrorModules { pub fn add_module>(&mut self, name: T) -> Option { let id = self.module_counter.increment(); self.module_map.insert( id, - Module { + ErrorModule { name: name.into(), tokens: None, source: None, @@ -101,21 +101,21 @@ impl ModuleMap { } } - pub fn module(&self, id: &mir::SourceModuleId) -> Option<&Module> { + pub fn module(&self, id: &mir::SourceModuleId) -> Option<&ErrorModule> { self.module_map.get(id) } } #[derive(Debug, Clone, PartialEq)] pub struct ReidError { - map: ModuleMap, + map: ErrorModules, errors: Vec, } impl ReidError { pub fn from_lexer( result: Result, - map: ModuleMap, + map: ErrorModules, module: SourceModuleId, ) -> Result { result.map_err(|error| { @@ -136,7 +136,7 @@ impl ReidError { pub fn from_parser( result: Result, - map: ModuleMap, + map: ErrorModules, module: SourceModuleId, ) -> Result { result.map_err(|error| { @@ -155,7 +155,7 @@ impl ReidError { }) } - pub fn from_kind(errors: Vec, map: ModuleMap) -> ReidError { + pub fn from_kind(errors: Vec, map: ErrorModules) -> ReidError { ReidError { map, errors } } } diff --git a/reid/src/lib.rs b/reid/src/lib.rs index 434087d..cd4897f 100644 --- a/reid/src/lib.rs +++ b/reid/src/lib.rs @@ -43,7 +43,7 @@ use std::path::PathBuf; -use error_raporting::{ErrorKind as ErrorRapKind, ModuleMap, ReidError}; +use error_raporting::{ErrorKind as ErrorRapKind, ErrorModules, ReidError}; use lexer::FullToken; use mir::{ linker::LinkerPass, typecheck::TypeCheck, typeinference::TypeInference, typerefs::TypeRefs, @@ -64,7 +64,7 @@ mod util; pub fn parse_module<'map, T: Into>( source: &str, name: T, - map: &'map mut ModuleMap, + map: &'map mut ErrorModules, ) -> Result<(mir::SourceModuleId, Vec), ReidError> { let id = map.add_module(name.into()).unwrap(); map.set_source(id, source.to_owned()); @@ -81,8 +81,8 @@ pub fn parse_module<'map, T: Into>( pub fn compile_module<'map>( module_id: mir::SourceModuleId, - tokens: &Vec, - map: &'map mut ModuleMap, + tokens: Vec, + map: &'map mut ErrorModules, path: Option, is_main: bool, ) -> Result { @@ -101,8 +101,11 @@ pub fn compile_module<'map>( statements.push(statement); } + drop(token_stream); + let ast_module = ast::Module { name: module.name, + tokens: tokens, top_level_statements: statements, path, is_main, @@ -113,7 +116,7 @@ pub fn compile_module<'map>( pub fn perform_all_passes<'map>( context: &mut mir::Context, - module_map: &'map mut ModuleMap, + module_map: &'map mut ErrorModules, ) -> Result<(), ReidError> { #[cfg(debug_assertions)] dbg!(&context); @@ -193,13 +196,13 @@ pub fn perform_all_passes<'map>( pub fn compile_and_pass<'map>( source: &str, path: PathBuf, - module_map: &'map mut ModuleMap, + module_map: &'map mut ErrorModules, ) -> Result { let path = path.canonicalize().unwrap(); let name = path.file_name().unwrap().to_str().unwrap().to_owned(); let (id, tokens) = parse_module(source, name, module_map)?; - let module = compile_module(id, &tokens, module_map, Some(path.clone()), true)?; + let module = compile_module(id, tokens, module_map, Some(path.clone()), true)?; let mut mir_context = mir::Context::from(vec![module], path.parent().unwrap().to_owned()); @@ -211,7 +214,7 @@ pub fn compile_and_pass<'map>( println!("{}", &mir_context); let mut context = Context::new(format!("Reid ({})", env!("CARGO_PKG_VERSION"))); - let codegen_modules = mir_context.codegen(&mut context, &module_map); + let codegen_modules = mir_context.codegen(&mut context); #[cfg(debug_assertions)] println!("{}", &codegen_modules.context); @@ -221,6 +224,6 @@ pub fn compile_and_pass<'map>( } pub fn compile_simple(source: &str, path: PathBuf) -> Result { - let mut map = ModuleMap::default(); + let mut map = ErrorModules::default(); compile_and_pass(source, path, &mut map) } diff --git a/reid/src/mir/fmt.rs b/reid/src/mir/fmt.rs index 28cc797..f125b3b 100644 --- a/reid/src/mir/fmt.rs +++ b/reid/src/mir/fmt.rs @@ -6,7 +6,7 @@ use super::*; impl Display for Context { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - for module in &self.modules { + for (_, module) in &self.modules { Display::fmt(&module, f)?; } Ok(()) diff --git a/reid/src/mir/linker.rs b/reid/src/mir/linker.rs index bb5125b..9bfc562 100644 --- a/reid/src/mir/linker.rs +++ b/reid/src/mir/linker.rs @@ -9,8 +9,7 @@ use std::{ use crate::{ compile_module, - error_raporting::{ModuleMap, ReidError}, - lexer::FullToken, + error_raporting::{ErrorModules, ReidError}, mir::{SourceModuleId, TypeDefinition, TypeKey, TypeKind}, parse_module, }; @@ -47,22 +46,21 @@ pub enum ErrorKind { FunctionIsPrivate(String, String), } -pub fn compile_std( - module_map: &mut ModuleMap, -) -> Result<(super::Module, Vec), ReidError> { +pub fn compile_std(module_map: &mut ErrorModules) -> Result { let (id, tokens) = parse_module(STD_SOURCE, "standard_library", module_map)?; - let module = compile_module(id, &tokens, module_map, None, false)?; + let module = compile_module(id, tokens, module_map, None, false)?; + let module_id = module.module_id; let mut mir_context = super::Context::from(vec![module], Default::default()); - let std_compiled = mir_context.modules.remove(0); - Ok((std_compiled, tokens)) + let std_compiled = mir_context.modules.remove(&module_id).unwrap(); + Ok(std_compiled) } /// Struct used to implement a type-checking pass that can be performed on the /// MIR. pub struct LinkerPass<'map> { - pub module_map: &'map mut ModuleMap, + pub module_map: &'map mut ErrorModules, pub is_lib: bool, } @@ -72,16 +70,15 @@ impl<'map> Pass for LinkerPass<'map> { type Data = (); type TError = ErrorKind; fn context(&mut self, context: &mut Context, mut state: LinkerPassState) -> PassResult { - let mains = context - .modules - .iter_mut() - .filter(|m| m.is_main) + let mains = (&mut context.modules) + .into_iter() + .filter(|(_, module)| module.is_main) .collect::>(); if mains.len() > 1 { state.note_errors(&vec![ErrorKind::MultipleMainsAtStart], Metadata::default()); return Ok(()); } - if let Some(main) = mains.first() { + if let Some((_, main)) = mains.first() { if let None = main.functions.iter().find(|f| f.name == "main") { if !self.is_lib { state.note_errors(&vec![ErrorKind::NoMainFunction], Metadata::default()); @@ -95,26 +92,19 @@ impl<'map> Pass for LinkerPass<'map> { } }; - let mut modules = HashMap::>>::new(); + let mut modules = HashMap::>>::new(); + let mut module_ids = HashMap::::new(); - for module in context.modules.drain(..) { - let tokens = self - .module_map - .module(&module.module_id) - .unwrap() - .tokens - .clone() - .unwrap(); - modules.insert(module.name.clone(), Rc::new(RefCell::new((module, tokens)))); + for (mod_id, module) in context.modules.drain() { + modules.insert(mod_id, Rc::new(RefCell::new(module))); } - let mut modules_to_process: Vec)>>> = - modules.values().cloned().collect(); + let mut modules_to_process: Vec>> = modules.values().cloned().collect(); while let Some(module) = modules_to_process.pop() { let mut importer_module = module.borrow_mut(); - for import in importer_module.0.imports.clone() { + for import in importer_module.imports.clone() { let Import(path, _) = &import; if path.len() != 2 { state.ok::<_, Infallible>( @@ -125,14 +115,18 @@ impl<'map> Pass for LinkerPass<'map> { let module_name = unsafe { path.get_unchecked(0) }; - let mut imported = if let Some(module) = modules.get_mut(module_name) { + let mut imported = if let Some(module) = + modules.get_mut(module_ids.get(module_name).unwrap()) + { module } else if module_name == "std" { + let std = compile_std(&mut self.module_map)?; modules.insert( - "std".to_owned(), + std.module_id, Rc::new(RefCell::new(compile_std(&mut self.module_map)?)), ); - modules.get("std").unwrap() + module_ids.insert(std.name, std.module_id); + modules.get(&std.module_id).unwrap() } else { let file_path = PathBuf::from(&context.base.clone()).join(module_name.to_owned() + ".reid"); @@ -160,8 +154,7 @@ impl<'map> Pass for LinkerPass<'map> { } }; - match compile_module(id, &tokens, &mut self.module_map, Some(file_path), false) - { + match compile_module(id, tokens, &mut self.module_map, Some(file_path), false) { Ok(imported_module) => { if imported_module.is_main { state.ok::<_, Infallible>( @@ -170,12 +163,11 @@ impl<'map> Pass for LinkerPass<'map> { ); continue; } - let module_name = imported_module.name.clone(); - modules.insert( - module_name.clone(), - Rc::new(RefCell::new((imported_module, tokens))), - ); - let imported = modules.get_mut(&module_name).unwrap(); + let module_id = imported_module.module_id; + module_ids + .insert(imported_module.name.clone(), imported_module.module_id); + modules.insert(module_id, Rc::new(RefCell::new(imported_module))); + let imported = modules.get_mut(&module_id).unwrap(); modules_to_process.push(imported.clone()); imported } @@ -194,13 +186,9 @@ impl<'map> Pass for LinkerPass<'map> { .borrow_mut(); let func_name = unsafe { path.get_unchecked(1) }; - let imported_mod_name = imported.0.name.clone(); + let imported_mod_name = imported.name.clone(); - let Some(func) = imported - .0 - .functions - .iter_mut() - .find(|f| f.name == *func_name) + let Some(func) = imported.functions.iter_mut().find(|f| f.name == *func_name) else { state.ok::<_, Infallible>( Err(ErrorKind::NoSuchFunctionInModule( @@ -228,7 +216,6 @@ impl<'map> Pass for LinkerPass<'map> { func.is_imported = true; if let Some(existing) = importer_module - .0 .functions .iter() .find(|f| f.name == *func_name) @@ -304,8 +291,8 @@ impl<'map> Pass for LinkerPass<'map> { let mut seen = HashSet::new(); seen.extend(imported_types.clone()); - let imported_mod_id = imported.0.module_id; - let imported_mod_typedefs = &mut imported.0.typedefs; + let imported_mod_id = imported.module_id; + let imported_mod_typedefs = &mut imported.typedefs; for typekey in imported_types.clone() { let typedef = imported_mod_typedefs @@ -323,10 +310,10 @@ impl<'map> Pass for LinkerPass<'map> { .unwrap() .clone(); - importer_module.0.typedefs.push(typedef.clone()); + importer_module.typedefs.push(typedef.clone()); } - importer_module.0.functions.push(FunctionDefinition { + importer_module.functions.push(FunctionDefinition { name: func_name, is_pub: false, is_imported: false, @@ -337,9 +324,9 @@ impl<'map> Pass for LinkerPass<'map> { } } - context.modules = modules + let modules: Vec = modules .into_values() - .map(|v| Rc::into_inner(v).unwrap().into_inner().0) + .map(|v| Rc::into_inner(v).unwrap().into_inner()) .collect(); Ok(()) diff --git a/reid/src/mir/mod.rs b/reid/src/mir/mod.rs index 77af85c..dc91536 100644 --- a/reid/src/mir/mod.rs +++ b/reid/src/mir/mod.rs @@ -354,11 +354,14 @@ pub struct Module { pub functions: Vec, pub typedefs: Vec, pub path: Option, + pub tokens: Vec, pub is_main: bool, } +pub type ModuleMap = HashMap; + #[derive(Debug)] pub struct Context { - pub modules: Vec, + pub modules: ModuleMap, pub base: PathBuf, } diff --git a/reid/src/mir/pass.rs b/reid/src/mir/pass.rs index 0180cb2..e54115c 100644 --- a/reid/src/mir/pass.rs +++ b/reid/src/mir/pass.rs @@ -277,7 +277,7 @@ impl Context { let mut state = State::new(); let mut scope = Scope::default(); pass.context(self, PassState::from(&mut state, &mut scope, None))?; - for module in &mut self.modules { + for (_, module) in (&mut self.modules).into_iter() { module.pass(pass, &mut state, &mut scope.inner())?; } Ok(state) diff --git a/reid/tests/e2e.rs b/reid/tests/e2e.rs index 814bab8..4502004 100644 --- a/reid/tests/e2e.rs +++ b/reid/tests/e2e.rs @@ -10,13 +10,10 @@ mod util; fn test(source: &str, name: &str) { let mut map = Default::default(); let (id, tokens) = assert_err(parse_module(source, name, &mut map)); - let module = assert_err(compile_module(id, &tokens, &mut map, None, true)); + let module = assert_err(compile_module(id, tokens, &mut map, None, true)); assert_err(perform_all_passes( - &mut mir::Context { - modules: vec![module], - base: Default::default(), - }, + &mut mir::Context::from(vec![module], Default::default()), &mut map, )); } diff --git a/reid/tests/stdlib.rs b/reid/tests/stdlib.rs index 7206083..ba9d3ce 100644 --- a/reid/tests/stdlib.rs +++ b/reid/tests/stdlib.rs @@ -14,7 +14,7 @@ fn compiles() { #[test] fn passes_all_passes() { let mut map = Default::default(); - let Ok((mut std, _)) = compile_std(&mut map) else { + let Ok(mut std) = compile_std(&mut map) else { panic!() }; @@ -22,10 +22,7 @@ fn passes_all_passes() { std.is_main = true; assert_err(perform_all_passes( - &mut mir::Context { - modules: vec![std], - base: Default::default(), - }, + &mut mir::Context::from(vec![std], Default::default()), &mut map, )); }