use std::fmt;
#[derive(Clone, Debug, PartialEq)]
pub enum Fault {
DivideByZero,
RegisterOutOfRange { reg: u8, frame_size: u8 },
BadConstant { index: u32, pool_size: u32 },
BadFunction { index: u32, table_size: u32 },
BadOpcodeByte(u8),
CallStackOverflow { depth: usize },
TypeMismatch { expected: &'static str, got: &'static str },
BadNative { index: u32, table_size: u32 },
NativeError(String),
Explicit(i32),
Invariant(&'static str),
}
impl fmt::Display for Fault {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Fault::DivideByZero => write!(f, "division by zero"),
Fault::RegisterOutOfRange { reg, frame_size } => {
write!(f, "register r{reg} out of range (frame has {frame_size} registers)")
}
Fault::BadConstant { index, pool_size } => {
write!(f, "constant index {index} out of range (pool size {pool_size})")
}
Fault::BadFunction { index, table_size } => {
write!(f, "function index {index} out of range (table size {table_size})")
}
Fault::BadOpcodeByte(b) => write!(f, "unknown opcode byte 0x{b:02X}"),
Fault::CallStackOverflow { depth } => write!(f, "call stack overflow at depth {depth}"),
Fault::TypeMismatch { expected, got } => {
write!(f, "type mismatch: expected {expected}, got {got}")
}
Fault::BadNative { index, table_size } => {
write!(f, "native function index {index} out of range (table size {table_size})")
}
Fault::NativeError(msg) => write!(f, "native function error: {msg}"),
Fault::Explicit(code) => write!(f, "explicit trap (code {code})"),
Fault::Invariant(msg) => write!(f, "vm invariant broken: {msg}"),
}
}
}
impl std::error::Error for Fault {}