Add FullToken array to error raporting
This commit is contained in:
		
							parent
							
								
									ce7c4bfb52
								
							
						
					
					
						commit
						9d1b18f083
					
				| @ -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<Vec<FullToken>>, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone, PartialEq, Eq, Default)] | ||||
| pub struct ModuleMap { | ||||
|     module_map: HashMap<mir::SourceModuleId, String>, | ||||
|     module_map: HashMap<mir::SourceModuleId, ErrModule>, | ||||
|     module_counter: mir::SourceModuleId, | ||||
| } | ||||
| 
 | ||||
| impl ModuleMap { | ||||
|     pub fn add_module<T: Into<String>>(&mut self, name: T) -> Option<mir::SourceModuleId> { | ||||
|         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<Self, Self::Error> { | ||||
|         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<FullToken>) { | ||||
|         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<Self, Self::Error> {
 | ||||
| //         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 | ||||
|                     ))? | ||||
|                 )?; | ||||
|             } | ||||
|  | ||||
| @ -100,7 +100,7 @@ impl From<Token> for String { | ||||
| } | ||||
| 
 | ||||
| /// A token with a position
 | ||||
| #[derive(Clone)] | ||||
| #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] | ||||
| pub struct FullToken { | ||||
|     pub token: Token, | ||||
|     pub position: Position, | ||||
|  | ||||
| @ -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<String>>( | ||||
|     source: &str, | ||||
|     name: String, | ||||
|     name: T, | ||||
|     map: &'map mut ModuleMap, | ||||
| ) -> Result<(mir::SourceModuleId, Vec<FullToken>), 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<FullToken>, | ||||
|     map: &'map mut ModuleMap, | ||||
|     path: Option<PathBuf>, | ||||
|     is_main: bool, | ||||
| ) -> Result<mir::Module, ReidError> { | ||||
|     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::<TopLevelStatement>(), map.clone(), id)?; | ||||
|         let statement = ReidError::from_parser( | ||||
|             token_stream.parse::<TopLevelStatement>(), | ||||
|             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<CompileOutput, ReidError> { | ||||
|     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()); | ||||
| 
 | ||||
|  | ||||
| @ -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<FullToken>) { | ||||
|     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::<String, Rc<RefCell<Module>>>::new(); | ||||
|         let mut modules = HashMap::<String, Rc<RefCell<_>>>::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<Rc<RefCell<Module>>> = modules.values().cloned().collect(); | ||||
|         let mut modules_to_process: Vec<Rc<RefCell<(Module, Vec<FullToken>)>>> = | ||||
|             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(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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 { | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user