From 83018ec5ec44888032947f3f62be36428b91aa3c Mon Sep 17 00:00:00 2001 From: Jeff Date: Fri, 9 Aug 2024 01:43:58 -0400 Subject: [PATCH] Improve error reports --- dust-lang/src/analyzer.rs | 14 +++++++++++ dust-lang/src/dust_error.rs | 24 ++----------------- dust-lang/src/lex.rs | 17 +++++++++++++- dust-lang/src/parse.rs | 22 +++++++++++++----- dust-lang/src/vm.rs | 46 ++++++++++++++++++++++++++++--------- 5 files changed, 83 insertions(+), 40 deletions(-) diff --git a/dust-lang/src/analyzer.rs b/dust-lang/src/analyzer.rs index a6685fb..90f634f 100644 --- a/dust-lang/src/analyzer.rs +++ b/dust-lang/src/analyzer.rs @@ -225,6 +225,20 @@ pub enum AnalyzerError { UnexpectedIdentifier { identifier: Node, position: Span }, } +impl AnalyzerError { + pub fn position(&self) -> Span { + match self { + AnalyzerError::ExpectedBoolean { position, .. } => *position, + AnalyzerError::ExpectedFunction { position, .. } => *position, + AnalyzerError::ExpectedIdentifier { position, .. } => *position, + AnalyzerError::ExpectedIdentifierOrValue { position, .. } => *position, + AnalyzerError::ExpectedIntegerOrFloat { position, .. } => *position, + AnalyzerError::ExpectedIntegerFloatOrString { position, .. } => *position, + AnalyzerError::UnexpectedIdentifier { position, .. } => *position, + } + } +} + impl Error for AnalyzerError {} impl Display for AnalyzerError { diff --git a/dust-lang/src/dust_error.rs b/dust-lang/src/dust_error.rs index 25907d0..1993b4f 100644 --- a/dust-lang/src/dust_error.rs +++ b/dust-lang/src/dust_error.rs @@ -22,30 +22,10 @@ impl<'src> DustError<'src> { VmError::AnaylyzerError(_) => "Analyzer error", VmError::ParseError(_) => "Parse error", VmError::ValueError { .. } => "Value error", - VmError::BuiltInFunctionCallError(_) => "Runtime error", + VmError::BuiltInFunctionError { .. } => "Runtime error", _ => "Analysis Failure", }; - let span = match &self.vm_error { - VmError::AnaylyzerError(analyzer_error) => match analyzer_error { - AnalyzerError::ExpectedBoolean { position, .. } => position, - AnalyzerError::ExpectedFunction { position, .. } => position, - AnalyzerError::ExpectedIdentifier { position, .. } => position, - AnalyzerError::ExpectedIdentifierOrValue { position, .. } => position, - AnalyzerError::ExpectedIntegerOrFloat { position, .. } => position, - AnalyzerError::ExpectedIntegerFloatOrString { position, .. } => position, - AnalyzerError::UnexpectedIdentifier { position, .. } => position, - }, - VmError::ParseError(parse_error) => &parse_error.position(), - VmError::ValueError { position, .. } => position, - VmError::BuiltInFunctionCallError(_) => todo!(), - VmError::ExpectedIdentifier { position } => position, - VmError::ExpectedIdentifierOrInteger { position } => position, - VmError::ExpectedInteger { position } => position, - VmError::ExpectedFunction { position, .. } => position, - VmError::ExpectedList { position } => position, - VmError::ExpectedValue { position } => position, - VmError::UndefinedIdentifier { position, .. } => position, - }; + let span = self.vm_error.position(); let label = self.vm_error.to_string(); let message = Level::Error.title(title).snippet( Snippet::source(self.source).annotation(Level::Info.span(span.0..span.1).label(&label)), diff --git a/dust-lang/src/lex.rs b/dust-lang/src/lex.rs index e42476e..572a3e5 100644 --- a/dust-lang/src/lex.rs +++ b/dust-lang/src/lex.rs @@ -108,12 +108,14 @@ impl Lexer { self.lex_number(source)? } else if "-Infinity" == self.peek_chars(source, 9) { self.position += 9; + ( Token::Float(f64::NEG_INFINITY), (self.position - 9, self.position), ) } else { self.position += 1; + (Token::Minus, (self.position - 1, self.position)) } } @@ -122,41 +124,54 @@ impl Lexer { '\'' => self.lex_string('\'', source)?, '+' => { self.position += 1; + (Token::Plus, (self.position - 1, self.position)) } '*' => { self.position += 1; + (Token::Star, (self.position - 1, self.position)) } '(' => { self.position += 1; + (Token::LeftParenthesis, (self.position - 1, self.position)) } ')' => { self.position += 1; + (Token::RightParenthesis, (self.position - 1, self.position)) } '=' => { self.position += 1; + (Token::Equal, (self.position - 1, self.position)) } '[' => { self.position += 1; + (Token::LeftSquareBrace, (self.position - 1, self.position)) } ']' => { self.position += 1; + (Token::RightSquareBrace, (self.position - 1, self.position)) } ',' => { self.position += 1; + (Token::Comma, (self.position - 1, self.position)) } '.' => { self.position += 1; + (Token::Dot, (self.position - 1, self.position)) } - _ => return Err(LexError::UnexpectedCharacter(c)), + _ => { + self.position += 1; + + return Err(LexError::UnexpectedCharacter(c)); + } } } else { (Token::Eof, (self.position, self.position)) diff --git a/dust-lang/src/parse.rs b/dust-lang/src/parse.rs index cb42e5b..eea2505 100644 --- a/dust-lang/src/parse.rs +++ b/dust-lang/src/parse.rs @@ -128,13 +128,23 @@ impl<'src> Parser<'src> { } fn next_token(&mut self) -> Result<(), ParseError> { - self.current = - self.lexer - .next_token(self.source) - .map_err(|lex_error| ParseError::LexError { + let next = self.lexer.next_token(self.source); + + self.current = match next { + Ok((token, position)) => (token, position), + Err(lex_error) => { + let position = { + self.next_token()?; + + self.current.1 + }; + + return Err(ParseError::LexError { error: lex_error, - position: self.current.1, - })?; + position, + }); + } + }; Ok(()) } diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index e5bb5c5..66ac663 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -122,7 +122,13 @@ impl Vm { } else { None }; - let function_call_return = function.call(None, values)?; + let function_call_return = + function + .call(None, values) + .map_err(|built_in_function_error| VmError::BuiltInFunctionError { + error: built_in_function_error, + position: node.position, + })?; Ok(function_call_return) } @@ -269,7 +275,12 @@ impl Vm { } } - let function_call_return = function.call(None, Some(value_arguments))?; + let function_call_return = function.call(None, Some(value_arguments)).map_err( + |built_in_function_error| VmError::BuiltInFunctionError { + error: built_in_function_error, + position: right_span, + }, + )?; return Ok(function_call_return); } @@ -319,7 +330,10 @@ pub enum VmError { // Anaylsis Failures // These should be prevented by running the analyzer before the VM - BuiltInFunctionCallError(BuiltInFunctionError), + BuiltInFunctionError { + error: BuiltInFunctionError, + position: Span, + }, ExpectedIdentifier { position: Span, }, @@ -345,9 +359,21 @@ pub enum VmError { }, } -impl From for VmError { - fn from(v: BuiltInFunctionError) -> Self { - Self::BuiltInFunctionCallError(v) +impl VmError { + pub fn position(&self) -> Span { + match self { + Self::AnaylyzerError(analyzer_error) => analyzer_error.position(), + Self::ParseError(parse_error) => parse_error.position(), + Self::ValueError { position, .. } => *position, + Self::BuiltInFunctionError { position, .. } => *position, + Self::ExpectedIdentifier { position } => *position, + Self::ExpectedIdentifierOrInteger { position } => *position, + Self::ExpectedInteger { position } => *position, + Self::ExpectedFunction { position, .. } => *position, + Self::ExpectedList { position } => *position, + Self::ExpectedValue { position } => *position, + Self::UndefinedIdentifier { position, .. } => *position, + } } } @@ -369,9 +395,7 @@ impl Error for VmError { Self::AnaylyzerError(analyzer_error) => Some(analyzer_error), Self::ParseError(parse_error) => Some(parse_error), Self::ValueError { error, .. } => Some(error), - Self::BuiltInFunctionCallError(built_in_function_error) => { - Some(built_in_function_error) - } + Self::BuiltInFunctionError { error, .. } => Some(error), _ => None, } } @@ -383,8 +407,8 @@ impl Display for VmError { Self::AnaylyzerError(analyzer_error) => write!(f, "{}", analyzer_error), Self::ParseError(parse_error) => write!(f, "{}", parse_error), Self::ValueError { error, .. } => write!(f, "{}", error), - Self::BuiltInFunctionCallError(built_in_function_error) => { - write!(f, "{}", built_in_function_error) + Self::BuiltInFunctionError { error, .. } => { + write!(f, "{}", error) } Self::ExpectedFunction { actual, position } => { write!(