106 lines
3.6 KiB
Rust
106 lines
3.6 KiB
Rust
use std::fmt;
|
|
|
|
/// Shared object/bytecode/execution errors. The established VmError name is
|
|
/// retained for embedders; defining it here avoids a dependency on the VM.
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub enum VmError {
|
|
ForeignHandle,
|
|
InvalidHandle,
|
|
IdentityExhausted,
|
|
RefCountOverflow,
|
|
NoOwnedReference,
|
|
AttributeNotFound(String),
|
|
UnsupportedOperation(&'static str),
|
|
InvalidArgument(&'static str),
|
|
ObjectKindMismatch(&'static str),
|
|
TraitViolation {
|
|
capability: String,
|
|
method: String,
|
|
reason: &'static str,
|
|
},
|
|
OverrideViolation {
|
|
definition: String,
|
|
method: String,
|
|
reason: &'static str,
|
|
},
|
|
UnknownAnnotation(String),
|
|
TypeMismatch {
|
|
function: String,
|
|
position: String,
|
|
expected: String,
|
|
actual: String,
|
|
},
|
|
EmptyCell,
|
|
InvalidBytecode {
|
|
offset: usize,
|
|
reason: &'static str,
|
|
},
|
|
UnboundLocal(String),
|
|
NameNotFound(String),
|
|
ArgumentCount {
|
|
name: String,
|
|
required: usize,
|
|
maximum: usize,
|
|
provided: usize,
|
|
},
|
|
ExecutionLimit(&'static str),
|
|
}
|
|
|
|
impl fmt::Display for VmError {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
Self::ForeignHandle => f.write_str("handle belongs to another VM"),
|
|
Self::InvalidHandle => f.write_str("handle does not identify a live object"),
|
|
Self::IdentityExhausted => f.write_str("process-local VM identities exhausted"),
|
|
Self::RefCountOverflow => f.write_str("object reference count exhausted"),
|
|
Self::NoOwnedReference => f.write_str("no external strong reference to release"),
|
|
Self::AttributeNotFound(name) => write!(f, "attribute not found: {name}"),
|
|
Self::UnsupportedOperation(operation) => {
|
|
write!(f, "object does not support {operation}")
|
|
}
|
|
Self::InvalidArgument(message) => f.write_str(message),
|
|
Self::ObjectKindMismatch(expected) => write!(f, "expected {expected} object"),
|
|
Self::TraitViolation {
|
|
capability,
|
|
method,
|
|
reason,
|
|
} => write!(f, "trait {capability} method {method}: {reason}"),
|
|
Self::UnknownAnnotation(name) => {
|
|
write!(f, "unknown or invalid type annotation: {name}")
|
|
}
|
|
Self::OverrideViolation {
|
|
definition,
|
|
method,
|
|
reason,
|
|
} => write!(f, "override {definition}.{method}: {reason}"),
|
|
Self::TypeMismatch {
|
|
function,
|
|
position,
|
|
expected,
|
|
actual,
|
|
} => write!(
|
|
f,
|
|
"{function} {position} expects {expected}, received {actual}"
|
|
),
|
|
Self::EmptyCell => f.write_str("cell is empty"),
|
|
Self::InvalidBytecode { offset, reason } => {
|
|
write!(f, "invalid bytecode at code unit {offset}: {reason}")
|
|
}
|
|
Self::UnboundLocal(name) => write!(f, "local variable is unbound: {name}"),
|
|
Self::NameNotFound(name) => write!(f, "name not found: {name}"),
|
|
Self::ArgumentCount {
|
|
name,
|
|
required,
|
|
maximum,
|
|
provided,
|
|
} => write!(
|
|
f,
|
|
"{name} expects {required}..={maximum} positional arguments, received {provided}"
|
|
),
|
|
Self::ExecutionLimit(limit) => write!(f, "execution limit reached: {limit}"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::error::Error for VmError {}
|