schala/schala-lang/src/error.rs

80 lines
2.3 KiB
Rust

use crate::{
parsing::{Location, ParseError},
schala::{SourceReference, Stage},
symbol_table::SymbolError,
type_inference::TypeError,
};
pub struct SchalaError {
errors: Vec<Error>,
}
impl SchalaError {
pub(crate) fn display(&self) -> String {
match self.errors[0] {
Error::Parse(ref parse_err) => parse_err.to_string(),
Error::Standard { ref text, .. } => text.as_ref().cloned().unwrap_or_default(),
}
}
#[allow(dead_code)]
pub(crate) fn from_type_error(err: TypeError) -> Self {
Self {
errors: vec![Error::Standard { 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::Standard {
location: None,
text: Some("symbol table error".to_string()),
stage: Stage::Symbols,
})
.collect();
Self { errors }
}
pub(crate) fn from_string(text: String, stage: Stage) -> Self {
Self { errors: vec![Error::Standard { location: None, text: Some(text), stage }] }
}
pub(crate) fn from_parse_error(parse_error: ParseError, source_reference: &SourceReference) -> Self {
let formatted_parse_error = format_parse_error(parse_error, source_reference);
Self { errors: vec![Error::Parse(formatted_parse_error)] }
}
}
#[allow(dead_code)]
enum Error {
Standard { location: Option<Location>, text: Option<String>, stage: Stage },
Parse(String),
}
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,
)
}