From 8f7e3d1d2cd43d30ccc16799fcf69058ccc5a717 Mon Sep 17 00:00:00 2001 From: Mel Date: Thu, 3 Mar 2022 01:57:25 +0100 Subject: Re-arrange error locations --- src/error.rs | 110 ++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 67 insertions(+), 43 deletions(-) (limited to 'src/error.rs') diff --git a/src/error.rs b/src/error.rs index 227a4b0..ed92355 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,10 +1,14 @@ -use crate::{interpret::walker::WalkerError, lex::token::Location, parse::parser::ParserError}; +use crate::{ + interpret::walker::WalkerError, + lex::token::Location, + parse::parser::{ParserError, ParserErrorLocation}, +}; use colored::Colorize; use std::fmt::Display; -pub struct RHError { - pub at: ErrorLocation, - pub kind: RHErrorKind, +pub enum RHError { + Parse(ParserError), + Run(WalkerError), } impl RHError { @@ -16,16 +20,6 @@ impl RHError { } } -pub enum RHErrorKind { - Parse(ParserError), - Run(WalkerError), -} - -pub enum ErrorLocation { - Specific(Location), - Eof, -} - pub struct RHErrorWithSource<'source> { error: RHError, source: &'source str, @@ -33,45 +27,27 @@ pub struct RHErrorWithSource<'source> { impl Display for RHErrorWithSource<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let (error_title, error_string) = match &self.error.kind { - RHErrorKind::Parse(parser_error) => ( + let (error_title, error_string) = match &self.error { + RHError::Parse(parser_error) => ( "Encountered error during parsing", - format!("{}", parser_error), + format!("{}", parser_error.kind), ), - RHErrorKind::Run(walker_error) => { - ("Encountered runtime error", format!("{}", walker_error)) - } - }; - - let weird_source_error_msg = - "Found error but could not get it's location in source, how does this even happen?"; - - let (line_number, line_column, source_line) = match self.error.at { - ErrorLocation::Specific(location) => ( - location.row, - location.col, - self.source - .lines() - .nth(location.row) - .expect(weird_source_error_msg), + RHError::Run(walker_error) => ( + "Encountered runtime error", + format!("{}", walker_error.kind), ), - ErrorLocation::Eof => { - let lines = self.source.lines(); - let (line_count, _) = lines.size_hint(); - let last_line = lines.last().expect(weird_source_error_msg); - - (line_count, last_line.len(), last_line) - } }; - let arrow_pad_len = line_column + 3 + line_number.to_string().len(); + let at = MappedErrorLocation::new(self); + + let arrow_pad_len = at.line_column + 3 + at.line_number.to_string().len(); writeln!(f, "{} {}:\n", " Error ".on_red(), error_title)?; writeln!( f, "{}{}", - format!("{} | ", line_number).dimmed(), - source_line + format!("{} | ", at.line_number).dimmed(), + at.source_line )?; writeln!(f, "{}{}", " ".repeat(arrow_pad_len), "^".red())?; writeln!(f, "{}", error_string)?; @@ -79,3 +55,51 @@ impl Display for RHErrorWithSource<'_> { Ok(()) } } + +pub struct MappedErrorLocation<'s> { + line_number: usize, + line_column: usize, + source_line: &'s str, +} + +impl<'s> MappedErrorLocation<'s> { + const SOURCE_MISSING_ERROR_LOCATION: &'static str = + "Found error but could not get it's location in source, how does this even happen?"; + + fn new(from: &'s RHErrorWithSource<'s>) -> MappedErrorLocation<'s> { + match &from.error { + RHError::Parse(error) => match &error.at { + ParserErrorLocation::Specific(at) => Self::at_location(from, at), + ParserErrorLocation::Eof => Self::last_line(from), + }, + RHError::Run(error) => Self::at_location(from, &error.at), + } + } + + fn last_line(from: &'s RHErrorWithSource<'s>) -> MappedErrorLocation<'s> { + let lines = from.source.lines(); + let (line_count, _) = lines.size_hint(); + let last_line = lines.last().expect(Self::SOURCE_MISSING_ERROR_LOCATION); + + MappedErrorLocation { + line_number: line_count, + line_column: last_line.len(), + source_line: last_line, + } + } + + fn at_location( + from: &'s RHErrorWithSource<'s>, + location: &'s Location, + ) -> MappedErrorLocation<'s> { + MappedErrorLocation { + line_number: location.row, + line_column: location.col, + source_line: from + .source + .lines() + .nth(location.row) + .expect(Self::SOURCE_MISSING_ERROR_LOCATION), + } + } +} -- cgit 1.4.1