rlox/interpreter/src/error.rs

107 lines
3.4 KiB
Rust
Raw Normal View History

2023-01-28 14:19:12 +01:00
use std::rc::Rc;
use itertools::Itertools;
use rlox2_frontend::lexer::LexerError;
use rlox2_frontend::parser::{BinaryOp, ParserError, UnaryOp};
use thiserror::Error;
use crate::Value;
2023-01-28 14:19:12 +01:00
use crate::{LoxClass, ResolverError};
#[derive(Error, Debug)]
pub enum RuntimeError {
2024-09-01 19:16:30 +02:00
#[error("RuntimeError: Unary operator {op} had invalid argument {arg}")]
UnaryOpInvalidArgument { op: UnaryOp, arg: Value },
2024-09-01 19:16:30 +02:00
#[error("RuntimeError: Binary operator {op} had invalid arguments {left} and {right}")]
BinaryOpInvalidArguments {
left: Value,
op: BinaryOp,
right: Value,
},
#[error("RuntimeError: Division by zero")]
DivisionByZero,
2024-09-01 19:16:30 +02:00
#[error("RuntimeError: Local {name} is not defined")]
NameNotDefined { name: String },
2024-09-01 19:16:30 +02:00
#[error("RuntimeError: Global {name} is not defined")]
GlobalNotDefined { name: String },
2024-09-01 19:16:30 +02:00
#[error("RuntimeError: {callee} is not callable")]
NotCallable { callee: Value },
2024-09-01 19:16:30 +02:00
#[error("RuntimeError: {name}() takes {arity} args, but {given} were given.")]
WrongArity {
name: String,
arity: usize,
given: usize,
},
#[error("RuntimeError: Extern function call to {name} failed: {msg}")]
ExtFunCallFailed { name: String, msg: String },
2024-09-01 19:16:30 +02:00
#[error("RuntimeError: Uncaught break statement")]
Break,
2024-09-01 19:16:30 +02:00
#[error("RuntimeError: Uncaught return statement")]
Return { value: Value },
2024-09-01 19:16:30 +02:00
#[error("RuntimeError: Exit with exit code {exit_code}")]
Exit { exit_code: i32 },
2024-09-01 19:16:30 +02:00
#[error("RuntimeError: Only objects have attributes")]
2023-01-28 14:19:12 +01:00
InvalidGetTarget,
2024-09-01 19:16:30 +02:00
#[error("RuntimeError: Only objects have attributes")]
2023-01-28 14:19:12 +01:00
InvalidSetTarget,
2024-09-01 19:16:30 +02:00
#[error("RuntimeError: Class {0} has no property {name}", class.name())]
UndefinedAttribute { class: Rc<LoxClass>, name: Box<str> },
#[error("RuntimeError: {value} is not a valid superclass")]
2023-01-28 14:19:12 +01:00
InvalidSuperclass { value: Value },
2024-09-01 20:47:42 +02:00
#[error("RuntimeError: stack overflow")]
StackOverflow,
}
#[derive(Error, Debug)]
#[allow(clippy::enum_variant_names)]
pub enum LoxError {
#[error("{0}", format_multiple_errors(inner))]
LexerError { inner: Vec<LexerError> },
#[error("{0}", format_multiple_errors(inner))]
ParserError { inner: Vec<ParserError> },
#[error("{inner}")]
ResolverError { inner: ResolverError },
#[error("{inner}")]
RuntimeError { inner: RuntimeError },
#[error("Called exit() with exit code {exit_code}")]
Exit { exit_code: i32 },
}
2024-09-01 19:16:30 +02:00
fn format_multiple_errors(errs: &[impl std::error::Error]) -> String {
let msg = if errs.len() == 1 {
errs[0].to_string()
} else {
errs.iter().map(|err| err.to_string()).join("\n")
};
msg
}
impl From<Vec<LexerError>> for LoxError {
fn from(lexer_errs: Vec<LexerError>) -> Self {
LoxError::LexerError { inner: lexer_errs }
}
}
impl From<Vec<ParserError>> for LoxError {
fn from(parser_errs: Vec<ParserError>) -> Self {
LoxError::ParserError { inner: parser_errs }
}
}
impl From<ResolverError> for LoxError {
fn from(resolver_err: ResolverError) -> Self {
2024-09-01 19:16:30 +02:00
LoxError::ResolverError {
inner: resolver_err,
}
}
}
impl From<RuntimeError> for LoxError {
fn from(runtime_err: RuntimeError) -> Self {
match runtime_err {
RuntimeError::Exit { exit_code } => LoxError::Exit { exit_code },
_ => LoxError::RuntimeError { inner: runtime_err },
}
}
}