schala/schala-lang/src/error.rs

87 lines
2.4 KiB
Rust
Raw Normal View History

2021-10-30 00:07:05 -07:00
use crate::{
parsing::{Location, ParseError},
2021-10-30 00:07:05 -07:00
schala::{SourceReference, Stage},
symbol_table::SymbolError,
type_inference::TypeError,
};
2021-10-14 04:11:53 -07:00
pub struct SchalaError {
2021-10-14 04:16:20 -07:00
errors: Vec<Error>,
//TODO unify these sometime
formatted_parse_error: Option<String>,
2021-10-14 04:11:53 -07:00
}
impl SchalaError {
2021-10-14 04:16:20 -07:00
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()
}
2021-10-14 04:11:53 -07:00
}
#[allow(dead_code)]
2021-10-14 04:16:20 -07:00
pub(crate) fn from_type_error(err: TypeError) -> Self {
Self {
formatted_parse_error: None,
2021-10-30 00:07:05 -07:00
errors: vec![Error { location: None, text: Some(err.msg), stage: Stage::Typechecking }],
2021-10-14 04:16:20 -07:00
}
2021-10-14 04:11:53 -07:00
}
2021-10-19 19:19:21 -07:00
pub(crate) fn from_symbol_table(symbol_errs: Vec<SymbolError>) -> Self {
2021-10-30 00:07:05 -07:00
//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 }
2021-10-19 19:19:21 -07:00
}
2021-10-14 04:16:20 -07:00
pub(crate) fn from_string(text: String, stage: Stage) -> Self {
2021-10-30 00:07:05 -07:00
Self { formatted_parse_error: None, errors: vec![Error { location: None, text: Some(text), stage }] }
2021-10-14 04:11:53 -07:00
}
2021-10-30 00:07:05 -07:00
pub(crate) fn from_parse_error(parse_error: ParseError, source_reference: &SourceReference) -> Self {
2021-10-14 04:16:20 -07:00
Self {
formatted_parse_error: Some(format_parse_error(parse_error, source_reference)),
errors: vec![],
}
2021-10-14 04:11:53 -07:00
}
}
#[allow(dead_code)]
struct Error {
2021-10-14 04:16:20 -07:00
location: Option<Location>,
text: Option<String>,
stage: Stage,
2021-10-14 04:11:53 -07:00
}
fn format_parse_error(error: ParseError, source_reference: &SourceReference) -> String {
2021-11-14 02:15:08 -08:00
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));
2021-10-14 04:11:53 -07:00
2021-10-14 04:16:20 -07:00
let line_num_digits = format!("{}", line_num).chars().count();
let space_padding = " ".repeat(line_num_digits);
2021-10-14 04:11:53 -07:00
2021-10-14 04:16:20 -07:00
format!(
r#"
2021-11-14 02:15:08 -08:00
{error_msg}
2021-10-14 04:11:53 -07:00
{space_padding} |
{line_num} | {}
{space_padding} | {}
2021-10-14 04:16:20 -07:00
"#,
line_from_program,
location_pointer,
error_msg = error.msg,
space_padding = space_padding,
line_num = line_num,
)
2021-10-14 04:11:53 -07:00
}