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,37 +66,65 @@ 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)
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&mir::Context> for ModuleMap {
|
||||
type Error = ();
|
||||
pub fn get_module(&self, id: &mir::SourceModuleId) -> Option<&ErrModule> {
|
||||
self.module_map.get(id)
|
||||
}
|
||||
}
|
||||
|
||||
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(());
|
||||
}
|
||||
}
|
||||
let module_counter = value.modules.iter().map(|m| m.module_id).max().ok_or(())?;
|
||||
Ok(ModuleMap {
|
||||
module_map: map,
|
||||
module_counter,
|
||||
})
|
||||
}
|
||||
}
|
||||
// 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 {
|
||||
@ -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,
|
||||
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(),
|
||||
&mut self.module_map,
|
||||
Some(file_path),
|
||||
false,
|
||||
) {
|
||||
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