From 3c2a70803ea95bf8e91900038659db3d7cd2739e Mon Sep 17 00:00:00 2001 From: Jeff Date: Mon, 2 Sep 2024 11:04:08 -0400 Subject: [PATCH] Refactor error reports --- dust-lang/src/context.rs | 16 +++++---- dust-lang/src/dust_error.rs | 70 +++++++++++++++++++++++++++++-------- dust-lang/src/vm.rs | 16 +++++---- 3 files changed, 75 insertions(+), 27 deletions(-) diff --git a/dust-lang/src/context.rs b/dust-lang/src/context.rs index 86cf219..1e3d041 100644 --- a/dust-lang/src/context.rs +++ b/dust-lang/src/context.rs @@ -61,9 +61,13 @@ impl Context { &self, identifier: &Identifier, ) -> Result, ContextError> { - let associations = self.associations.read()?; - - Ok(associations.get(identifier).cloned()) + if let Some((variable_data, position)) = self.associations.read()?.get(identifier) { + Ok(Some((variable_data.clone(), *position))) + } else if let Some(parent) = &self.parent { + parent.get(identifier) + } else { + Ok(None) + } } /// Returns the type associated with the given identifier. @@ -268,11 +272,9 @@ impl Context { let mut associations = self.associations.write()?; if let Some((_, last_position)) = associations.get_mut(identifier) { - if position > *last_position { - log::trace!("Updating {identifier}'s last position to {position:?}"); + log::trace!("Updating {identifier}'s last position to {position:?}"); - *last_position = position; - } + *last_position = position; Ok(true) } else { diff --git a/dust-lang/src/dust_error.rs b/dust-lang/src/dust_error.rs index f34b398..907d08e 100644 --- a/dust-lang/src/dust_error.rs +++ b/dust-lang/src/dust_error.rs @@ -1,8 +1,8 @@ //! Top-level error handling for the Dust language. -use annotate_snippets::{Level, Renderer, Snippet}; +use annotate_snippets::{Level, Message, Renderer, Snippet}; use std::fmt::Display; -use crate::{Span, AnalysisError, ContextError, LexError, ParseError, RuntimeError}; +use crate::{AnalysisError, ContextError, LexError, ParseError, RuntimeError, Span}; /// An error that occurred during the execution of the Dust language and its /// corresponding source code. @@ -79,14 +79,26 @@ impl<'src> DustError<'src> { } } - pub fn error_data(&self) -> Vec<(&'static str, Span, String)> { + fn footer(&self) -> Vec<(&'static str, Span, String)> { match self { DustError::ContextError(_) => vec![], - DustError::Runtime { runtime_error, .. } => vec![( - "Runtime error", - runtime_error.position(), - runtime_error.to_string(), - )], + DustError::Runtime { runtime_error, .. } => { + let mut error_data = vec![( + "Runtime error", + runtime_error.position(), + runtime_error.to_string(), + )]; + + if let RuntimeError::Expression { error, position } = runtime_error { + error_data.push(( + "Error occured at this expression", + *position, + error.to_string(), + )); + } + + error_data + } DustError::Analysis { analysis_errors, .. } => analysis_errors @@ -108,13 +120,43 @@ impl<'src> DustError<'src> { let mut report = String::new(); let renderer = Renderer::styled(); - for (title, span, label) in self.error_data() { - let message = Level::Error.title(title).snippet( - Snippet::source(self.source()) - .annotation(Level::Info.span(span.0..span.1).label(&label)), - ); + match self { + DustError::ContextError(_) => { + let message = Level::Error.title("Context error"); - report.push_str(&format!("{}", renderer.render(message))); + report.push_str(&renderer.render(message).to_string()); + } + DustError::Runtime { + runtime_error, + source, + } => { + let error = runtime_error.root_error(); + let position = error.position(); + let label = error.to_string(); + let message = Level::Error + .title("Runtime error") + .snippet( + Snippet::source(source) + .fold(true) + .annotation(Level::Error.span(position.0..position.1).label(&label)), + ) + .footer( + Level::Error + .title("This error occured during the execution of the Dust program."), + ); + + report.push_str(&renderer.render(message).to_string()); + report.push('\n'); + } + DustError::Analysis { + analysis_errors, + source, + } => todo!(), + DustError::Parse { + parse_error, + source, + } => todo!(), + DustError::Lex { lex_error, source } => todo!(), } report diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index 94b7f60..2d5cebc 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -1236,6 +1236,14 @@ impl RuntimeError { Self::UndefinedField { field_position, .. } => *field_position, } } + + pub fn root_error(&self) -> &Self { + match self { + Self::Expression { error, .. } => error.root_error(), + Self::Statement { error, .. } => error.root_error(), + error => error, + } + } } impl From for RuntimeError { @@ -1264,12 +1272,8 @@ impl Display for RuntimeError { write!(f, "Function call error at {:?}: {}", position, error) } Self::ParseError(parse_error) => write!(f, "{}", parse_error), - Self::Expression { error, position } => { - write!( - f, - "Error while running expression at {:?}: {}", - position, error - ) + Self::Expression { .. } => { + write!(f, "Error while running expression") } Self::Statement { error, position } => { write!(