Improve error reports
This commit is contained in:
parent
c1b71ffccc
commit
83018ec5ec
@ -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 {
|
||||
|
@ -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)),
|
||||
|
@ -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))
|
||||
|
@ -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(())
|
||||
}
|
||||
|
@ -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<BuiltInFunctionError> 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!(
|
||||
|
Loading…
Reference in New Issue
Block a user