use crate::eval::Fuel;
use crate::heap::{Address, Heap};
use crate::syntax::{Position, VarName};
use crate::value::Value;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ThrownPayload {
value: Value,
heap: Heap,
fuel: Fuel,
}
impl ThrownPayload {
#[must_use]
pub fn new(value: Value, heap: Heap, fuel: Fuel) -> Self {
Self { value, heap, fuel }
}
#[must_use]
pub fn value(&self) -> &Value {
&self.value
}
#[must_use]
pub fn into_parts(self) -> (Value, Heap, Fuel) {
(self.value, self.heap, self.fuel)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Error {
UnexpectedChar {
at: Position,
ch: char,
},
UnexpectedEnd {
expected: &'static str,
},
UnexpectedToken {
at: Position,
expected: &'static str,
found: String,
},
UnboundVariable {
name: VarName,
},
FuelExhausted {
limit: u64,
},
DanglingReference {
address: Address,
},
NotAReference {
found: String,
},
NotAFunction {
found: String,
},
NotAnObject {
found: String,
},
PropertyNotFound {
name: VarName,
},
Thrown(Box<ThrownPayload>),
UncaughtException {
value: Value,
},
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::UnexpectedChar { at, ch } => {
write!(f, "unexpected character {ch:?} at byte {}", at.value())
}
Self::UnexpectedEnd { expected } => {
write!(f, "unexpected end of input; expected {expected}")
}
Self::UnexpectedToken {
at,
expected,
found,
} => {
write!(
f,
"unexpected token {found:?} at byte {}; expected {expected}",
at.value()
)
}
Self::UnboundVariable { name } => {
write!(f, "unbound variable {:?}", name.as_str())
}
Self::FuelExhausted { limit } => {
write!(f, "evaluation exceeded step limit of {limit}")
}
Self::DanglingReference { address } => {
write!(f, "dangling reference to address {address}")
}
Self::NotAReference { found } => {
write!(f, "expected a reference, found {found}")
}
Self::NotAFunction { found } => {
write!(f, "expected a function, found {found}")
}
Self::NotAnObject { found } => {
write!(f, "expected an object, found {found}")
}
Self::PropertyNotFound { name } => {
write!(
f,
"property {:?} not found on object or its prototype chain",
name.as_str()
)
}
Self::Thrown(payload) => {
write!(f, "propagating throw of {}", payload.value())
}
Self::UncaughtException { value } => {
write!(f, "uncaught exception: {value}")
}
}
}
}
impl std::error::Error for Error {}