87 lines
2.4 KiB
Rust
87 lines
2.4 KiB
Rust
use crate::{
|
|
parsing::{Location, ParseError},
|
|
schala::{SourceReference, Stage},
|
|
symbol_table::SymbolError,
|
|
type_inference::TypeError,
|
|
};
|
|
|
|
pub struct SchalaError {
|
|
errors: Vec<Error>,
|
|
//TODO unify these sometime
|
|
formatted_parse_error: Option<String>,
|
|
}
|
|
|
|
impl SchalaError {
|
|
pub(crate) fn display(&self) -> String {
|
|
if let Some(ref err) = self.formatted_parse_error {
|
|
err.clone()
|
|
} else {
|
|
self.errors[0].text.as_ref().cloned().unwrap_or_default()
|
|
}
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub(crate) fn from_type_error(err: TypeError) -> Self {
|
|
Self {
|
|
formatted_parse_error: None,
|
|
errors: vec![Error { location: None, text: Some(err.msg), stage: Stage::Typechecking }],
|
|
}
|
|
}
|
|
|
|
pub(crate) fn from_symbol_table(symbol_errs: Vec<SymbolError>) -> Self {
|
|
//TODO this could be better
|
|
let errors = symbol_errs
|
|
.into_iter()
|
|
.map(|_symbol_err| Error {
|
|
location: None,
|
|
text: Some("symbol table error".to_string()),
|
|
stage: Stage::Symbols,
|
|
})
|
|
.collect();
|
|
Self { errors, formatted_parse_error: None }
|
|
}
|
|
|
|
pub(crate) fn from_string(text: String, stage: Stage) -> Self {
|
|
Self { formatted_parse_error: None, errors: vec![Error { location: None, text: Some(text), stage }] }
|
|
}
|
|
|
|
pub(crate) fn from_parse_error(parse_error: ParseError, source_reference: &SourceReference) -> Self {
|
|
Self {
|
|
formatted_parse_error: Some(format_parse_error(parse_error, source_reference)),
|
|
errors: vec![],
|
|
}
|
|
}
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
struct Error {
|
|
location: Option<Location>,
|
|
text: Option<String>,
|
|
stage: Stage,
|
|
}
|
|
|
|
fn format_parse_error(error: ParseError, source_reference: &SourceReference) -> String {
|
|
let offset = error.location.offset;
|
|
let (line_start, line_num, line_from_program) = source_reference.get_line(offset);
|
|
let ch = offset - line_start;
|
|
|
|
let location_pointer = format!("{}^", " ".repeat(ch));
|
|
|
|
let line_num_digits = format!("{}", line_num).chars().count();
|
|
let space_padding = " ".repeat(line_num_digits);
|
|
|
|
format!(
|
|
r#"
|
|
{error_msg}
|
|
{space_padding} |
|
|
{line_num} | {}
|
|
{space_padding} | {}
|
|
"#,
|
|
line_from_program,
|
|
location_pointer,
|
|
error_msg = error.msg,
|
|
space_padding = space_padding,
|
|
line_num = line_num,
|
|
)
|
|
}
|