Refactor errors and clean up read_line

This commit is contained in:
Jeff 2024-08-09 00:49:17 -04:00
parent 9766777a47
commit c1b71ffccc
5 changed files with 81 additions and 23 deletions

View File

@ -92,7 +92,7 @@ impl BuiltInFunction {
stdin().read_line(&mut input)?;
Ok(Some(Value::string(input)))
Ok(Some(Value::string(input.trim_end_matches('\n'))))
} else {
Err(BuiltInFunctionError::WrongNumberOfValueArguments)
}

View File

@ -35,7 +35,7 @@ impl<'src> DustError<'src> {
AnalyzerError::ExpectedIntegerFloatOrString { position, .. } => position,
AnalyzerError::UnexpectedIdentifier { position, .. } => position,
},
VmError::ParseError(_) => todo!(),
VmError::ParseError(parse_error) => &parse_error.position(),
VmError::ValueError { position, .. } => position,
VmError::BuiltInFunctionCallError(_) => todo!(),
VmError::ExpectedIdentifier { position } => position,
@ -44,6 +44,7 @@ impl<'src> DustError<'src> {
VmError::ExpectedFunction { position, .. } => position,
VmError::ExpectedList { position } => position,
VmError::ExpectedValue { position } => position,
VmError::UndefinedIdentifier { position, .. } => position,
};
let label = self.vm_error.to_string();
let message = Level::Error.title(title).snippet(

View File

@ -128,7 +128,13 @@ impl<'src> Parser<'src> {
}
fn next_token(&mut self) -> Result<(), ParseError> {
self.current = self.lexer.next_token(self.source)?;
self.current =
self.lexer
.next_token(self.source)
.map_err(|lex_error| ParseError::LexError {
error: lex_error,
position: self.current.1,
})?;
Ok(())
}
@ -341,7 +347,10 @@ impl<'src> Parser<'src> {
left_span,
))
}
_ => Err(ParseError::UnexpectedToken(self.current.0.to_owned())),
_ => Err(ParseError::UnexpectedToken {
actual: self.current.0.to_owned(),
position: self.current.1,
}),
}
}
@ -359,18 +368,30 @@ impl<'src> Parser<'src> {
#[derive(Debug, PartialEq, Clone)]
pub enum ParseError {
LexError(LexError),
LexError { error: LexError, position: Span },
ExpectedClosingParenthesis { actual: TokenOwned, position: Span },
ExpectedClosingSquareBrace { actual: TokenOwned, position: Span },
ExpectedOpeningParenthesis { actual: TokenOwned, position: Span },
UnexpectedToken(TokenOwned),
UnexpectedToken { actual: TokenOwned, position: Span },
}
impl ParseError {
pub fn position(&self) -> Span {
match self {
Self::LexError { position, .. } => *position,
Self::ExpectedClosingParenthesis { position, .. } => *position,
Self::ExpectedClosingSquareBrace { position, .. } => *position,
Self::ExpectedOpeningParenthesis { position, .. } => *position,
Self::UnexpectedToken { position, .. } => *position,
}
}
}
impl Error for ParseError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::LexError(error) => Some(error),
Self::LexError { error, .. } => Some(error),
_ => None,
}
}
@ -379,7 +400,7 @@ impl Error for ParseError {
impl Display for ParseError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Self::LexError(error) => write!(f, "{}", error),
Self::LexError { error, .. } => write!(f, "{}", error),
Self::ExpectedClosingParenthesis { actual, .. } => {
write!(f, "Expected closing parenthesis, found {actual}",)
}
@ -389,17 +410,11 @@ impl Display for ParseError {
Self::ExpectedOpeningParenthesis { actual, .. } => {
write!(f, "Expected opening parenthesis, found {actual}",)
}
Self::UnexpectedToken(actual) => write!(f, "Unexpected token {actual}"),
Self::UnexpectedToken { actual, .. } => write!(f, "Unexpected token {actual}"),
}
}
}
impl From<LexError> for ParseError {
fn from(v: LexError) -> Self {
Self::LexError(v)
}
}
#[cfg(test)]
mod tests {
use crate::Identifier;

View File

@ -131,6 +131,9 @@ impl Value {
(ValueInner::Integer(left), ValueInner::Integer(right)) => {
Ok(Value::integer(left.saturating_add(*right)))
}
(ValueInner::String(left), ValueInner::String(right)) => {
Ok(Value::string(left.to_string() + right))
}
_ => Err(ValueError::CannotAdd(self.clone(), other.clone())),
}
}

View File

@ -171,7 +171,16 @@ impl Vm {
Ok(function.clone().call(None, value_parameters, variables)?)
}
Statement::Identifier(_) => Ok(None),
Statement::Identifier(identifier) => {
if let Some(value) = variables.get(&identifier) {
Ok(Some(value.clone()))
} else {
Err(VmError::UndefinedIdentifier {
identifier,
position: node.position,
})
}
}
Statement::List(nodes) => {
let values = nodes
.into_iter()
@ -303,17 +312,37 @@ impl Vm {
pub enum VmError {
AnaylyzerError(AnalyzerError),
ParseError(ParseError),
ValueError { error: ValueError, position: Span },
ValueError {
error: ValueError,
position: Span,
},
// Anaylsis Failures
// These should be prevented by running the analyzer before the VM
BuiltInFunctionCallError(BuiltInFunctionError),
ExpectedIdentifier { position: Span },
ExpectedIdentifierOrInteger { position: Span },
ExpectedInteger { position: Span },
ExpectedFunction { actual: Value, position: Span },
ExpectedList { position: Span },
ExpectedValue { position: Span },
ExpectedIdentifier {
position: Span,
},
ExpectedIdentifierOrInteger {
position: Span,
},
ExpectedInteger {
position: Span,
},
ExpectedFunction {
actual: Value,
position: Span,
},
ExpectedList {
position: Span,
},
ExpectedValue {
position: Span,
},
UndefinedIdentifier {
identifier: Identifier,
position: Span,
},
}
impl From<BuiltInFunctionError> for VmError {
@ -383,6 +412,16 @@ impl Display for VmError {
Self::ExpectedValue { position } => {
write!(f, "Expected a value at position: {:?}", position)
}
Self::UndefinedIdentifier {
identifier,
position,
} => {
write!(
f,
"Undefined identifier: {} at position: {:?}",
identifier, position
)
}
}
}
}