Improve error reports
This commit is contained in:
parent
c1b71ffccc
commit
83018ec5ec
@ -225,6 +225,20 @@ pub enum AnalyzerError {
|
|||||||
UnexpectedIdentifier { identifier: Node, position: Span },
|
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 Error for AnalyzerError {}
|
||||||
|
|
||||||
impl Display for AnalyzerError {
|
impl Display for AnalyzerError {
|
||||||
|
@ -22,30 +22,10 @@ impl<'src> DustError<'src> {
|
|||||||
VmError::AnaylyzerError(_) => "Analyzer error",
|
VmError::AnaylyzerError(_) => "Analyzer error",
|
||||||
VmError::ParseError(_) => "Parse error",
|
VmError::ParseError(_) => "Parse error",
|
||||||
VmError::ValueError { .. } => "Value error",
|
VmError::ValueError { .. } => "Value error",
|
||||||
VmError::BuiltInFunctionCallError(_) => "Runtime error",
|
VmError::BuiltInFunctionError { .. } => "Runtime error",
|
||||||
_ => "Analysis Failure",
|
_ => "Analysis Failure",
|
||||||
};
|
};
|
||||||
let span = match &self.vm_error {
|
let span = self.vm_error.position();
|
||||||
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 label = self.vm_error.to_string();
|
let label = self.vm_error.to_string();
|
||||||
let message = Level::Error.title(title).snippet(
|
let message = Level::Error.title(title).snippet(
|
||||||
Snippet::source(self.source).annotation(Level::Info.span(span.0..span.1).label(&label)),
|
Snippet::source(self.source).annotation(Level::Info.span(span.0..span.1).label(&label)),
|
||||||
|
@ -108,12 +108,14 @@ impl Lexer {
|
|||||||
self.lex_number(source)?
|
self.lex_number(source)?
|
||||||
} else if "-Infinity" == self.peek_chars(source, 9) {
|
} else if "-Infinity" == self.peek_chars(source, 9) {
|
||||||
self.position += 9;
|
self.position += 9;
|
||||||
|
|
||||||
(
|
(
|
||||||
Token::Float(f64::NEG_INFINITY),
|
Token::Float(f64::NEG_INFINITY),
|
||||||
(self.position - 9, self.position),
|
(self.position - 9, self.position),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
self.position += 1;
|
self.position += 1;
|
||||||
|
|
||||||
(Token::Minus, (self.position - 1, self.position))
|
(Token::Minus, (self.position - 1, self.position))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,41 +124,54 @@ impl Lexer {
|
|||||||
'\'' => self.lex_string('\'', source)?,
|
'\'' => self.lex_string('\'', source)?,
|
||||||
'+' => {
|
'+' => {
|
||||||
self.position += 1;
|
self.position += 1;
|
||||||
|
|
||||||
(Token::Plus, (self.position - 1, self.position))
|
(Token::Plus, (self.position - 1, self.position))
|
||||||
}
|
}
|
||||||
'*' => {
|
'*' => {
|
||||||
self.position += 1;
|
self.position += 1;
|
||||||
|
|
||||||
(Token::Star, (self.position - 1, self.position))
|
(Token::Star, (self.position - 1, self.position))
|
||||||
}
|
}
|
||||||
'(' => {
|
'(' => {
|
||||||
self.position += 1;
|
self.position += 1;
|
||||||
|
|
||||||
(Token::LeftParenthesis, (self.position - 1, self.position))
|
(Token::LeftParenthesis, (self.position - 1, self.position))
|
||||||
}
|
}
|
||||||
')' => {
|
')' => {
|
||||||
self.position += 1;
|
self.position += 1;
|
||||||
|
|
||||||
(Token::RightParenthesis, (self.position - 1, self.position))
|
(Token::RightParenthesis, (self.position - 1, self.position))
|
||||||
}
|
}
|
||||||
'=' => {
|
'=' => {
|
||||||
self.position += 1;
|
self.position += 1;
|
||||||
|
|
||||||
(Token::Equal, (self.position - 1, self.position))
|
(Token::Equal, (self.position - 1, self.position))
|
||||||
}
|
}
|
||||||
'[' => {
|
'[' => {
|
||||||
self.position += 1;
|
self.position += 1;
|
||||||
|
|
||||||
(Token::LeftSquareBrace, (self.position - 1, self.position))
|
(Token::LeftSquareBrace, (self.position - 1, self.position))
|
||||||
}
|
}
|
||||||
']' => {
|
']' => {
|
||||||
self.position += 1;
|
self.position += 1;
|
||||||
|
|
||||||
(Token::RightSquareBrace, (self.position - 1, self.position))
|
(Token::RightSquareBrace, (self.position - 1, self.position))
|
||||||
}
|
}
|
||||||
',' => {
|
',' => {
|
||||||
self.position += 1;
|
self.position += 1;
|
||||||
|
|
||||||
(Token::Comma, (self.position - 1, self.position))
|
(Token::Comma, (self.position - 1, self.position))
|
||||||
}
|
}
|
||||||
'.' => {
|
'.' => {
|
||||||
self.position += 1;
|
self.position += 1;
|
||||||
|
|
||||||
(Token::Dot, (self.position - 1, self.position))
|
(Token::Dot, (self.position - 1, self.position))
|
||||||
}
|
}
|
||||||
_ => return Err(LexError::UnexpectedCharacter(c)),
|
_ => {
|
||||||
|
self.position += 1;
|
||||||
|
|
||||||
|
return Err(LexError::UnexpectedCharacter(c));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
(Token::Eof, (self.position, self.position))
|
(Token::Eof, (self.position, self.position))
|
||||||
|
@ -128,13 +128,23 @@ impl<'src> Parser<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn next_token(&mut self) -> Result<(), ParseError> {
|
fn next_token(&mut self) -> Result<(), ParseError> {
|
||||||
self.current =
|
let next = self.lexer.next_token(self.source);
|
||||||
self.lexer
|
|
||||||
.next_token(self.source)
|
self.current = match next {
|
||||||
.map_err(|lex_error| ParseError::LexError {
|
Ok((token, position)) => (token, position),
|
||||||
|
Err(lex_error) => {
|
||||||
|
let position = {
|
||||||
|
self.next_token()?;
|
||||||
|
|
||||||
|
self.current.1
|
||||||
|
};
|
||||||
|
|
||||||
|
return Err(ParseError::LexError {
|
||||||
error: lex_error,
|
error: lex_error,
|
||||||
position: self.current.1,
|
position,
|
||||||
})?;
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,13 @@ impl Vm {
|
|||||||
} else {
|
} else {
|
||||||
None
|
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)
|
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);
|
return Ok(function_call_return);
|
||||||
}
|
}
|
||||||
@ -319,7 +330,10 @@ pub enum VmError {
|
|||||||
|
|
||||||
// Anaylsis Failures
|
// Anaylsis Failures
|
||||||
// These should be prevented by running the analyzer before the VM
|
// These should be prevented by running the analyzer before the VM
|
||||||
BuiltInFunctionCallError(BuiltInFunctionError),
|
BuiltInFunctionError {
|
||||||
|
error: BuiltInFunctionError,
|
||||||
|
position: Span,
|
||||||
|
},
|
||||||
ExpectedIdentifier {
|
ExpectedIdentifier {
|
||||||
position: Span,
|
position: Span,
|
||||||
},
|
},
|
||||||
@ -345,9 +359,21 @@ pub enum VmError {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<BuiltInFunctionError> for VmError {
|
impl VmError {
|
||||||
fn from(v: BuiltInFunctionError) -> Self {
|
pub fn position(&self) -> Span {
|
||||||
Self::BuiltInFunctionCallError(v)
|
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::AnaylyzerError(analyzer_error) => Some(analyzer_error),
|
||||||
Self::ParseError(parse_error) => Some(parse_error),
|
Self::ParseError(parse_error) => Some(parse_error),
|
||||||
Self::ValueError { error, .. } => Some(error),
|
Self::ValueError { error, .. } => Some(error),
|
||||||
Self::BuiltInFunctionCallError(built_in_function_error) => {
|
Self::BuiltInFunctionError { error, .. } => Some(error),
|
||||||
Some(built_in_function_error)
|
|
||||||
}
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -383,8 +407,8 @@ impl Display for VmError {
|
|||||||
Self::AnaylyzerError(analyzer_error) => write!(f, "{}", analyzer_error),
|
Self::AnaylyzerError(analyzer_error) => write!(f, "{}", analyzer_error),
|
||||||
Self::ParseError(parse_error) => write!(f, "{}", parse_error),
|
Self::ParseError(parse_error) => write!(f, "{}", parse_error),
|
||||||
Self::ValueError { error, .. } => write!(f, "{}", error),
|
Self::ValueError { error, .. } => write!(f, "{}", error),
|
||||||
Self::BuiltInFunctionCallError(built_in_function_error) => {
|
Self::BuiltInFunctionError { error, .. } => {
|
||||||
write!(f, "{}", built_in_function_error)
|
write!(f, "{}", error)
|
||||||
}
|
}
|
||||||
Self::ExpectedFunction { actual, position } => {
|
Self::ExpectedFunction { actual, position } => {
|
||||||
write!(
|
write!(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user