From 9d1b18f083540dabc18d0b8554e9fa902f049040 Mon Sep 17 00:00:00 2001 From: sofia Date: Thu, 17 Jul 2025 17:44:18 +0300 Subject: [PATCH] Add FullToken array to error raporting --- reid/src/error_raporting.rs | 71 +++++++++++++++++++++++++++---------- reid/src/lexer.rs | 2 +- reid/src/lib.rs | 61 +++++++++++++++++-------------- reid/src/mir/linker.rs | 69 +++++++++++++++++++++-------------- reid/src/mir/mod.rs | 5 ++- reid/tests/e2e.rs | 11 ++---- reid/tests/stdlib.rs | 2 +- 7 files changed, 139 insertions(+), 82 deletions(-) diff --git a/reid/src/error_raporting.rs b/reid/src/error_raporting.rs index bf20403..5874a57 100644 --- a/reid/src/error_raporting.rs +++ b/reid/src/error_raporting.rs @@ -4,7 +4,8 @@ use std::{ }; use crate::{ - ast, lexer, + ast, + lexer::{self, FullToken}, mir::{self, pass, Metadata, SourceModuleId}, token_stream, }; @@ -65,38 +66,66 @@ impl Ord for ErrorKind { } } +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ErrModule { + pub name: String, + pub tokens: Option>, +} + #[derive(Debug, Clone, PartialEq, Eq, Default)] pub struct ModuleMap { - module_map: HashMap, + module_map: HashMap, module_counter: mir::SourceModuleId, } impl ModuleMap { pub fn add_module>(&mut self, name: T) -> Option { let id = self.module_counter.increment(); - self.module_map.insert(id, name.into().clone()); + self.module_map.insert( + id, + ErrModule { + name: name.into(), + tokens: None, + }, + ); Some(id) } -} -impl TryFrom<&mir::Context> for ModuleMap { - type Error = (); - - fn try_from(value: &mir::Context) -> Result { - let mut map = HashMap::new(); - for module in &value.modules { - if let Some(_) = map.insert(module.module_id, module.name.clone()) { - return Err(()); - } + pub fn set_tokens(&mut self, id: mir::SourceModuleId, tokens: Vec) { + if let Some(module) = self.module_map.get_mut(&id) { + module.tokens = Some(tokens); } - let module_counter = value.modules.iter().map(|m| m.module_id).max().ok_or(())?; - Ok(ModuleMap { - module_map: map, - module_counter, - }) + } + + pub fn get_module(&self, id: &mir::SourceModuleId) -> Option<&ErrModule> { + self.module_map.get(id) } } +// impl TryFrom<&mir::Context> for ModuleMap { +// type Error = (); + +// fn try_from(value: &mir::Context) -> Result { +// let mut map = HashMap::new(); +// for module in &value.modules { +// if let Some(_) = map.insert( +// module.module_id, +// ErrModule { +// name: module.name.clone(), +// tokens: Some(module.clone()), +// }, +// ) { +// return Err(()); +// } +// } +// let module_counter = value.modules.iter().map(|m| m.module_id).max().ok_or(())?; +// Ok(ModuleMap { +// module_map: map, +// module_counter, +// }) +// } +// } + #[derive(Debug, Clone, PartialEq, Eq)] pub struct ReidError { map: ModuleMap, @@ -121,7 +150,11 @@ impl std::fmt::Display for ReidError { "Errors in module {}:", color_err(format!( "{}", - self.map.module_map.get(&meta.source_module_id).unwrap() + self.map + .module_map + .get(&meta.source_module_id) + .unwrap() + .name ))? )?; } diff --git a/reid/src/lexer.rs b/reid/src/lexer.rs index ba72a08..f0cbb43 100644 --- a/reid/src/lexer.rs +++ b/reid/src/lexer.rs @@ -100,7 +100,7 @@ impl From for String { } /// A token with a position -#[derive(Clone)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct FullToken { pub token: Token, pub position: Position, diff --git a/reid/src/lib.rs b/reid/src/lib.rs index 12ff029..018f845 100644 --- a/reid/src/lib.rs +++ b/reid/src/lib.rs @@ -44,6 +44,7 @@ use std::{convert::Infallible, path::PathBuf}; use error_raporting::{ErrorKind as ErrorRapKind, ModuleMap, ReidError}; +use lexer::FullToken; use mir::{ linker::LinkerPass, typecheck::TypeCheck, typeinference::TypeInference, typerefs::TypeRefs, SourceModuleId, @@ -61,42 +62,58 @@ mod pad_adapter; mod token_stream; mod util; -pub fn compile_module<'map>( +pub fn parse_module<'map, T: Into>( source: &str, - name: String, + name: T, + map: &'map mut ModuleMap, +) -> Result<(mir::SourceModuleId, Vec), ReidError> { + let id = map.add_module(name.into()).unwrap(); + + let tokens = ReidError::from_lexer(lexer::tokenize(source), map.clone(), id)?; + + map.set_tokens(id, tokens.clone()); + + #[cfg(debug_assertions)] + dbg!(&tokens); + + Ok((id, tokens)) +} + +pub fn compile_module<'map>( + module_id: mir::SourceModuleId, + tokens: &Vec, map: &'map mut ModuleMap, path: Option, is_main: bool, ) -> Result { - let id = map.add_module(name.clone()).unwrap(); - let tokens = ReidError::from_lexer(lexer::tokenize(source), map.clone(), id)?; - - #[cfg(debug_assertions)] - dbg!(&tokens); + let module = map.get_module(&module_id).cloned().unwrap(); let mut token_stream = TokenStream::from(&tokens); let mut statements = Vec::new(); while !matches!(token_stream.peek().unwrap_or(Token::Eof), Token::Eof) { - let statement = - ReidError::from_parser(token_stream.parse::(), map.clone(), id)?; + let statement = ReidError::from_parser( + token_stream.parse::(), + map.clone(), + module_id, + )?; statements.push(statement); } let ast_module = ast::Module { - name, + name: module.name, top_level_statements: statements, path, is_main, }; - Ok(ast_module.process(id)) + Ok(ast_module.process(module_id)) } pub fn perform_all_passes<'map>( context: &mut mir::Context, - map: &'map mut ModuleMap, + module_map: &'map mut ModuleMap, ) -> Result<(), ReidError> { #[cfg(debug_assertions)] dbg!(&context); @@ -104,11 +121,7 @@ pub fn perform_all_passes<'map>( #[cfg(debug_assertions)] println!("{}", &context); - let mut module_map = (&*context).try_into().unwrap(); - - let state = context.pass(&mut LinkerPass { - module_map: &mut module_map, - }); + let state = context.pass(&mut LinkerPass { module_map }); #[cfg(debug_assertions)] println!("{}", &context); @@ -118,7 +131,7 @@ pub fn perform_all_passes<'map>( if !state.errors.is_empty() { return Err(ReidError::from_kind::<()>( state.errors.iter().map(|e| e.clone().into()).collect(), - map.clone(), + module_map.clone(), )); } @@ -159,7 +172,7 @@ pub fn perform_all_passes<'map>( ); if !errors.is_empty() { - return Err(ReidError::from_kind::<()>(errors, map.clone())); + return Err(ReidError::from_kind::<()>(errors, module_map.clone())); } Ok(()) @@ -174,14 +187,10 @@ pub fn compile_and_pass<'map>( module_map: &'map mut ModuleMap, ) -> Result { let path = path.canonicalize().unwrap(); + let name = path.file_name().unwrap().to_str().unwrap().to_owned(); - let module = compile_module( - source, - path.file_name().unwrap().to_str().unwrap().to_owned(), - module_map, - Some(path.clone()), - true, - )?; + let (id, tokens) = parse_module(source, name, module_map).unwrap(); + 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()); diff --git a/reid/src/mir/linker.rs b/reid/src/mir/linker.rs index b5c7e27..1a04ffc 100644 --- a/reid/src/mir/linker.rs +++ b/reid/src/mir/linker.rs @@ -7,7 +7,7 @@ use std::{ rc::Rc, }; -use crate::{compile_module, error_raporting::ModuleMap}; +use crate::{compile_module, error_raporting::ModuleMap, lexer::FullToken, parse_module}; use super::{ pass::{Pass, PassState}, @@ -41,20 +41,14 @@ pub enum ErrorKind { FunctionIsPrivate(String, String), } -pub fn compile_std(module_map: &mut ModuleMap) -> super::Module { - let module = compile_module( - STD_SOURCE, - "standard_library".to_owned(), - module_map, - None, - false, - ) - .unwrap(); +pub fn compile_std(module_map: &mut ModuleMap) -> (super::Module, Vec) { + let (id, tokens) = parse_module(STD_SOURCE, "standard_library", module_map).unwrap(); + let module = compile_module(id, &tokens, module_map, None, false).unwrap(); let mut mir_context = super::Context::from(vec![module], Default::default()); let std_compiled = mir_context.modules.remove(0); - std_compiled + (std_compiled, tokens) } /// Struct used to implement a type-checking pass that can be performed on the @@ -88,10 +82,17 @@ impl<'map> Pass for LinkerPass<'map> { return; }; - let mut modules = HashMap::>>::new(); + let mut modules = HashMap::>>::new(); for module in context.modules.drain(..) { - modules.insert(module.name.clone(), Rc::new(RefCell::new(module))); + let tokens = self + .module_map + .get_module(&module.module_id) + .unwrap() + .tokens + .clone() + .unwrap(); + modules.insert(module.name.clone(), Rc::new(RefCell::new((module, tokens)))); } modules.insert( @@ -99,12 +100,13 @@ impl<'map> Pass for LinkerPass<'map> { Rc::new(RefCell::new(compile_std(&mut self.module_map))), ); - 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.imports.clone() { + for import in importer_module.0.imports.clone() { let Import(path, _) = &import; if path.len() != 2 { state.ok::<_, Infallible>( @@ -129,13 +131,23 @@ impl<'map> Pass for LinkerPass<'map> { continue; }; - match compile_module( - &source, - module_name.clone(), - &mut self.module_map, - Some(file_path), - false, - ) { + let (id, tokens) = + match parse_module(&source, module_name.clone(), &mut self.module_map) { + Ok(val) => val, + Err(err) => { + state.ok::<_, Infallible>( + Err(ErrorKind::ModuleCompilationError( + module_name.clone(), + format!("{}", err), + )), + import.1, + ); + continue; + } + }; + + match compile_module(id, &tokens, &mut self.module_map, Some(file_path), false) + { Ok(imported_module) => { if imported_module.is_main { state.ok::<_, Infallible>( @@ -147,7 +159,7 @@ impl<'map> Pass for LinkerPass<'map> { let module_name = imported_module.name.clone(); modules.insert( module_name.clone(), - Rc::new(RefCell::new(imported_module)), + Rc::new(RefCell::new((imported_module, tokens))), ); let imported = modules.get_mut(&module_name).unwrap(); modules_to_process.push(imported.clone()); @@ -169,7 +181,11 @@ impl<'map> Pass for LinkerPass<'map> { let func_name = unsafe { path.get_unchecked(1) }; - let Some(func) = imported.functions.iter_mut().find(|f| f.name == *func_name) + let Some(func) = imported + .0 + .functions + .iter_mut() + .find(|f| f.name == *func_name) else { state.ok::<_, Infallible>( Err(ErrorKind::NoSuchFunctionInModule( @@ -195,6 +211,7 @@ 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) @@ -211,7 +228,7 @@ impl<'map> Pass for LinkerPass<'map> { } } - importer_module.functions.push(FunctionDefinition { + importer_module.0.functions.push(FunctionDefinition { name: func.name.clone(), is_pub: false, is_imported: false, @@ -224,7 +241,7 @@ impl<'map> Pass for LinkerPass<'map> { context.modules = modules .into_values() - .map(|v| Rc::into_inner(v).unwrap().into_inner()) + .map(|v| Rc::into_inner(v).unwrap().into_inner().0) .collect(); } } diff --git a/reid/src/mir/mod.rs b/reid/src/mir/mod.rs index 7294a1b..49a73e1 100644 --- a/reid/src/mir/mod.rs +++ b/reid/src/mir/mod.rs @@ -4,7 +4,10 @@ use std::{collections::HashMap, path::PathBuf}; -use crate::{lexer::Position, token_stream::TokenRange}; +use crate::{ + lexer::{FullToken, Position}, + token_stream::TokenRange, +}; mod display; pub mod r#impl; diff --git a/reid/tests/e2e.rs b/reid/tests/e2e.rs index d9475f3..465a6d7 100644 --- a/reid/tests/e2e.rs +++ b/reid/tests/e2e.rs @@ -1,7 +1,7 @@ use reid::{ compile_module, mir::{self}, - perform_all_passes, + parse_module, perform_all_passes, }; use util::assert_err; @@ -9,13 +9,8 @@ mod util; fn test(source: &str, name: &str) { let mut map = Default::default(); - let module = assert_err(compile_module( - source, - name.to_owned(), - &mut map, - None, - true, - )); + let (id, tokens) = assert_err(parse_module(source, name, &mut map)); + let module = assert_err(compile_module(id, &tokens, &mut map, None, true)); assert_err(perform_all_passes( &mut mir::Context { diff --git a/reid/tests/stdlib.rs b/reid/tests/stdlib.rs index 97cf431..dfbf54e 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 mut std = compile_std(&mut map); + let (mut std, _) = compile_std(&mut map); // Needed to pass linker-pass std.is_main = true;