rlox/vm/src/error.rs

63 lines
1.7 KiB
Rust
Raw Normal View History

use itertools::Itertools;
2023-01-31 22:54:12 +01:00
use rlox2_frontend::lexer::{CodePos, LexerError};
use thiserror::Error;
use crate::{Opcode, Value};
#[derive(Error, Debug)]
2023-01-31 22:54:12 +01:00
pub enum CompilerError {
#[error("Missing closing parenthesis at {code_pos}")]
MissingRightParen { code_pos: CodePos },
#[error("{msg}")]
Todo { msg: String },
}
#[derive(Error, Debug)]
pub enum RuntimeError {
#[error("Opcopde {opcode} had invalid operand {operand}")]
UnaryInvalidOperand { opcode: Opcode, operand: Value },
#[error("Opcopde {opcode} had invalid operands {left} and {right}")]
BinaryInvalidOperand { opcode: Opcode, left: Value, right: Value },
#[error("Division by zero")]
DivisionByZero,
}
#[derive(Error, Debug)]
2023-01-31 22:54:12 +01:00
pub enum LoxError {
#[error("{0}", format_multiple_errors(inner))]
LexerError { inner: Vec<LexerError> },
#[error("{inner}")]
2023-01-31 22:54:12 +01:00
CompileError { inner: CompilerError },
#[error("{inner}")]
RuntimeError { inner: RuntimeError },
#[error("Called exit() with exit code {exit_code}")]
Exit { exit_code: i32 },
}
2023-01-31 22:54:12 +01:00
impl From<Vec<LexerError>> for LoxError {
fn from(lexer_errs: Vec<LexerError>) -> Self {
2023-01-31 22:54:12 +01:00
LoxError::LexerError { inner: lexer_errs }
}
}
2023-01-31 22:54:12 +01:00
impl From<CompilerError> for LoxError {
fn from(compile_err: CompilerError) -> Self {
LoxError::CompileError { inner: compile_err }
}
}
2023-01-31 22:54:12 +01:00
impl From<RuntimeError> for LoxError {
fn from(runtime_err: RuntimeError) -> Self {
2023-01-31 22:54:12 +01:00
LoxError::RuntimeError { inner: runtime_err }
}
}
fn format_multiple_errors(errs: &Vec<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
}