Add FullToken array to error raporting
This commit is contained in:
parent
ce7c4bfb52
commit
9d1b18f083
@ -4,7 +4,8 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast, lexer,
|
ast,
|
||||||
|
lexer::{self, FullToken},
|
||||||
mir::{self, pass, Metadata, SourceModuleId},
|
mir::{self, pass, Metadata, SourceModuleId},
|
||||||
token_stream,
|
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)]
|
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
||||||
pub struct ModuleMap {
|
pub struct ModuleMap {
|
||||||
module_map: HashMap<mir::SourceModuleId, String>,
|
module_map: HashMap<mir::SourceModuleId, ErrModule>,
|
||||||
module_counter: mir::SourceModuleId,
|
module_counter: mir::SourceModuleId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModuleMap {
|
impl ModuleMap {
|
||||||
pub fn add_module<T: Into<String>>(&mut self, name: T) -> Option<mir::SourceModuleId> {
|
pub fn add_module<T: Into<String>>(&mut self, name: T) -> Option<mir::SourceModuleId> {
|
||||||
let id = self.module_counter.increment();
|
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)
|
Some(id)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<&mir::Context> for ModuleMap {
|
pub fn set_tokens(&mut self, id: mir::SourceModuleId, tokens: Vec<FullToken>) {
|
||||||
type Error = ();
|
if let Some(module) = self.module_map.get_mut(&id) {
|
||||||
|
module.tokens = Some(tokens);
|
||||||
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,
|
pub fn get_module(&self, id: &mir::SourceModuleId) -> Option<&ErrModule> {
|
||||||
module_counter,
|
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)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct ReidError {
|
pub struct ReidError {
|
||||||
map: ModuleMap,
|
map: ModuleMap,
|
||||||
@ -121,7 +150,11 @@ impl std::fmt::Display for ReidError {
|
|||||||
"Errors in module {}:",
|
"Errors in module {}:",
|
||||||
color_err(format!(
|
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
|
/// A token with a position
|
||||||
#[derive(Clone)]
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct FullToken {
|
pub struct FullToken {
|
||||||
pub token: Token,
|
pub token: Token,
|
||||||
pub position: Position,
|
pub position: Position,
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
use std::{convert::Infallible, path::PathBuf};
|
use std::{convert::Infallible, path::PathBuf};
|
||||||
|
|
||||||
use error_raporting::{ErrorKind as ErrorRapKind, ModuleMap, ReidError};
|
use error_raporting::{ErrorKind as ErrorRapKind, ModuleMap, ReidError};
|
||||||
|
use lexer::FullToken;
|
||||||
use mir::{
|
use mir::{
|
||||||
linker::LinkerPass, typecheck::TypeCheck, typeinference::TypeInference, typerefs::TypeRefs,
|
linker::LinkerPass, typecheck::TypeCheck, typeinference::TypeInference, typerefs::TypeRefs,
|
||||||
SourceModuleId,
|
SourceModuleId,
|
||||||
@ -61,42 +62,58 @@ mod pad_adapter;
|
|||||||
mod token_stream;
|
mod token_stream;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
pub fn compile_module<'map>(
|
pub fn parse_module<'map, T: Into<String>>(
|
||||||
source: &str,
|
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,
|
map: &'map mut ModuleMap,
|
||||||
path: Option<PathBuf>,
|
path: Option<PathBuf>,
|
||||||
is_main: bool,
|
is_main: bool,
|
||||||
) -> Result<mir::Module, ReidError> {
|
) -> Result<mir::Module, ReidError> {
|
||||||
let id = map.add_module(name.clone()).unwrap();
|
let module = map.get_module(&module_id).cloned().unwrap();
|
||||||
let tokens = ReidError::from_lexer(lexer::tokenize(source), map.clone(), id)?;
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
dbg!(&tokens);
|
|
||||||
|
|
||||||
let mut token_stream = TokenStream::from(&tokens);
|
let mut token_stream = TokenStream::from(&tokens);
|
||||||
|
|
||||||
let mut statements = Vec::new();
|
let mut statements = Vec::new();
|
||||||
|
|
||||||
while !matches!(token_stream.peek().unwrap_or(Token::Eof), Token::Eof) {
|
while !matches!(token_stream.peek().unwrap_or(Token::Eof), Token::Eof) {
|
||||||
let statement =
|
let statement = ReidError::from_parser(
|
||||||
ReidError::from_parser(token_stream.parse::<TopLevelStatement>(), map.clone(), id)?;
|
token_stream.parse::<TopLevelStatement>(),
|
||||||
|
map.clone(),
|
||||||
|
module_id,
|
||||||
|
)?;
|
||||||
statements.push(statement);
|
statements.push(statement);
|
||||||
}
|
}
|
||||||
|
|
||||||
let ast_module = ast::Module {
|
let ast_module = ast::Module {
|
||||||
name,
|
name: module.name,
|
||||||
top_level_statements: statements,
|
top_level_statements: statements,
|
||||||
path,
|
path,
|
||||||
is_main,
|
is_main,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(ast_module.process(id))
|
Ok(ast_module.process(module_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn perform_all_passes<'map>(
|
pub fn perform_all_passes<'map>(
|
||||||
context: &mut mir::Context,
|
context: &mut mir::Context,
|
||||||
map: &'map mut ModuleMap,
|
module_map: &'map mut ModuleMap,
|
||||||
) -> Result<(), ReidError> {
|
) -> Result<(), ReidError> {
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
dbg!(&context);
|
dbg!(&context);
|
||||||
@ -104,11 +121,7 @@ pub fn perform_all_passes<'map>(
|
|||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
println!("{}", &context);
|
println!("{}", &context);
|
||||||
|
|
||||||
let mut module_map = (&*context).try_into().unwrap();
|
let state = context.pass(&mut LinkerPass { module_map });
|
||||||
|
|
||||||
let state = context.pass(&mut LinkerPass {
|
|
||||||
module_map: &mut module_map,
|
|
||||||
});
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
println!("{}", &context);
|
println!("{}", &context);
|
||||||
@ -118,7 +131,7 @@ pub fn perform_all_passes<'map>(
|
|||||||
if !state.errors.is_empty() {
|
if !state.errors.is_empty() {
|
||||||
return Err(ReidError::from_kind::<()>(
|
return Err(ReidError::from_kind::<()>(
|
||||||
state.errors.iter().map(|e| e.clone().into()).collect(),
|
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() {
|
if !errors.is_empty() {
|
||||||
return Err(ReidError::from_kind::<()>(errors, map.clone()));
|
return Err(ReidError::from_kind::<()>(errors, module_map.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -174,14 +187,10 @@ pub fn compile_and_pass<'map>(
|
|||||||
module_map: &'map mut ModuleMap,
|
module_map: &'map mut ModuleMap,
|
||||||
) -> Result<CompileOutput, ReidError> {
|
) -> Result<CompileOutput, ReidError> {
|
||||||
let path = path.canonicalize().unwrap();
|
let path = path.canonicalize().unwrap();
|
||||||
|
let name = path.file_name().unwrap().to_str().unwrap().to_owned();
|
||||||
|
|
||||||
let module = compile_module(
|
let (id, tokens) = parse_module(source, name, module_map).unwrap();
|
||||||
source,
|
let module = compile_module(id, &tokens, module_map, Some(path.clone()), true)?;
|
||||||
path.file_name().unwrap().to_str().unwrap().to_owned(),
|
|
||||||
module_map,
|
|
||||||
Some(path.clone()),
|
|
||||||
true,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let mut mir_context = mir::Context::from(vec![module], path.parent().unwrap().to_owned());
|
let mut mir_context = mir::Context::from(vec![module], path.parent().unwrap().to_owned());
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ use std::{
|
|||||||
rc::Rc,
|
rc::Rc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{compile_module, error_raporting::ModuleMap};
|
use crate::{compile_module, error_raporting::ModuleMap, lexer::FullToken, parse_module};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
pass::{Pass, PassState},
|
pass::{Pass, PassState},
|
||||||
@ -41,20 +41,14 @@ pub enum ErrorKind {
|
|||||||
FunctionIsPrivate(String, String),
|
FunctionIsPrivate(String, String),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile_std(module_map: &mut ModuleMap) -> super::Module {
|
pub fn compile_std(module_map: &mut ModuleMap) -> (super::Module, Vec<FullToken>) {
|
||||||
let module = compile_module(
|
let (id, tokens) = parse_module(STD_SOURCE, "standard_library", module_map).unwrap();
|
||||||
STD_SOURCE,
|
let module = compile_module(id, &tokens, module_map, None, false).unwrap();
|
||||||
"standard_library".to_owned(),
|
|
||||||
module_map,
|
|
||||||
None,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut mir_context = super::Context::from(vec![module], Default::default());
|
let mut mir_context = super::Context::from(vec![module], Default::default());
|
||||||
|
|
||||||
let std_compiled = mir_context.modules.remove(0);
|
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
|
/// 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;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut modules = HashMap::<String, Rc<RefCell<Module>>>::new();
|
let mut modules = HashMap::<String, Rc<RefCell<_>>>::new();
|
||||||
|
|
||||||
for module in context.modules.drain(..) {
|
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(
|
modules.insert(
|
||||||
@ -99,12 +100,13 @@ impl<'map> Pass for LinkerPass<'map> {
|
|||||||
Rc::new(RefCell::new(compile_std(&mut self.module_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() {
|
while let Some(module) = modules_to_process.pop() {
|
||||||
let mut importer_module = module.borrow_mut();
|
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;
|
let Import(path, _) = &import;
|
||||||
if path.len() != 2 {
|
if path.len() != 2 {
|
||||||
state.ok::<_, Infallible>(
|
state.ok::<_, Infallible>(
|
||||||
@ -129,13 +131,23 @@ impl<'map> Pass for LinkerPass<'map> {
|
|||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
match compile_module(
|
let (id, tokens) =
|
||||||
&source,
|
match parse_module(&source, module_name.clone(), &mut self.module_map) {
|
||||||
module_name.clone(),
|
Ok(val) => val,
|
||||||
&mut self.module_map,
|
Err(err) => {
|
||||||
Some(file_path),
|
state.ok::<_, Infallible>(
|
||||||
false,
|
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) => {
|
Ok(imported_module) => {
|
||||||
if imported_module.is_main {
|
if imported_module.is_main {
|
||||||
state.ok::<_, Infallible>(
|
state.ok::<_, Infallible>(
|
||||||
@ -147,7 +159,7 @@ impl<'map> Pass for LinkerPass<'map> {
|
|||||||
let module_name = imported_module.name.clone();
|
let module_name = imported_module.name.clone();
|
||||||
modules.insert(
|
modules.insert(
|
||||||
module_name.clone(),
|
module_name.clone(),
|
||||||
Rc::new(RefCell::new(imported_module)),
|
Rc::new(RefCell::new((imported_module, tokens))),
|
||||||
);
|
);
|
||||||
let imported = modules.get_mut(&module_name).unwrap();
|
let imported = modules.get_mut(&module_name).unwrap();
|
||||||
modules_to_process.push(imported.clone());
|
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 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 {
|
else {
|
||||||
state.ok::<_, Infallible>(
|
state.ok::<_, Infallible>(
|
||||||
Err(ErrorKind::NoSuchFunctionInModule(
|
Err(ErrorKind::NoSuchFunctionInModule(
|
||||||
@ -195,6 +211,7 @@ impl<'map> Pass for LinkerPass<'map> {
|
|||||||
func.is_imported = true;
|
func.is_imported = true;
|
||||||
|
|
||||||
if let Some(existing) = importer_module
|
if let Some(existing) = importer_module
|
||||||
|
.0
|
||||||
.functions
|
.functions
|
||||||
.iter()
|
.iter()
|
||||||
.find(|f| f.name == *func_name)
|
.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(),
|
name: func.name.clone(),
|
||||||
is_pub: false,
|
is_pub: false,
|
||||||
is_imported: false,
|
is_imported: false,
|
||||||
@ -224,7 +241,7 @@ impl<'map> Pass for LinkerPass<'map> {
|
|||||||
|
|
||||||
context.modules = modules
|
context.modules = modules
|
||||||
.into_values()
|
.into_values()
|
||||||
.map(|v| Rc::into_inner(v).unwrap().into_inner())
|
.map(|v| Rc::into_inner(v).unwrap().into_inner().0)
|
||||||
.collect();
|
.collect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,10 @@
|
|||||||
|
|
||||||
use std::{collections::HashMap, path::PathBuf};
|
use std::{collections::HashMap, path::PathBuf};
|
||||||
|
|
||||||
use crate::{lexer::Position, token_stream::TokenRange};
|
use crate::{
|
||||||
|
lexer::{FullToken, Position},
|
||||||
|
token_stream::TokenRange,
|
||||||
|
};
|
||||||
|
|
||||||
mod display;
|
mod display;
|
||||||
pub mod r#impl;
|
pub mod r#impl;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use reid::{
|
use reid::{
|
||||||
compile_module,
|
compile_module,
|
||||||
mir::{self},
|
mir::{self},
|
||||||
perform_all_passes,
|
parse_module, perform_all_passes,
|
||||||
};
|
};
|
||||||
use util::assert_err;
|
use util::assert_err;
|
||||||
|
|
||||||
@ -9,13 +9,8 @@ mod util;
|
|||||||
|
|
||||||
fn test(source: &str, name: &str) {
|
fn test(source: &str, name: &str) {
|
||||||
let mut map = Default::default();
|
let mut map = Default::default();
|
||||||
let module = assert_err(compile_module(
|
let (id, tokens) = assert_err(parse_module(source, name, &mut map));
|
||||||
source,
|
let module = assert_err(compile_module(id, &tokens, &mut map, None, true));
|
||||||
name.to_owned(),
|
|
||||||
&mut map,
|
|
||||||
None,
|
|
||||||
true,
|
|
||||||
));
|
|
||||||
|
|
||||||
assert_err(perform_all_passes(
|
assert_err(perform_all_passes(
|
||||||
&mut mir::Context {
|
&mut mir::Context {
|
||||||
|
@ -14,7 +14,7 @@ fn compiles() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn passes_all_passes() {
|
fn passes_all_passes() {
|
||||||
let mut map = Default::default();
|
let mut map = Default::default();
|
||||||
let mut std = compile_std(&mut map);
|
let (mut std, _) = compile_std(&mut map);
|
||||||
|
|
||||||
// Needed to pass linker-pass
|
// Needed to pass linker-pass
|
||||||
std.is_main = true;
|
std.is_main = true;
|
||||||
|
Loading…
Reference in New Issue
Block a user