106 lines
2.4 KiB
Rust
106 lines
2.4 KiB
Rust
use std::{rc::Rc, collections::HashMap, cell::RefCell, fmt::Display};
|
|
use crate::{value::{HashValue, Value}, symbol::{SYM_DATA, SYM_MSG, SYM_TYPE}, symbol::Symbol};
|
|
|
|
pub type Result<T> = std::result::Result<T, Exception>;
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct Exception {
|
|
pub ty: Symbol,
|
|
pub msg: Option<Rc<str>>,
|
|
pub data: Option<Value>,
|
|
}
|
|
|
|
impl Exception {
|
|
pub fn new(ty: Symbol) -> Self {
|
|
Self { ty, msg: None, data: None }
|
|
}
|
|
|
|
pub fn new_with_msg(ty: Symbol, msg: Rc<str>) -> Self {
|
|
Self { ty, msg: Some(msg), data: None }
|
|
}
|
|
|
|
pub fn new_with_data(ty: Symbol, data: Value) -> Self {
|
|
Self { ty, msg: None, data: Some(data) }
|
|
}
|
|
|
|
pub fn new_with_msg_data(ty: Symbol, msg: Rc<str>, data: Value) -> Self {
|
|
Self { ty, msg: Some(msg), data: Some(data) }
|
|
}
|
|
|
|
pub fn from_table(table: &Rc<RefCell<HashMap<HashValue, Value>>>) -> Option<Self> {
|
|
let table = table.borrow();
|
|
let ty = table.get(&(*SYM_TYPE).into())?;
|
|
if let Value::Symbol(ty) = ty {
|
|
let data = table.get(&(*SYM_DATA).into()).cloned();
|
|
let msg = table.get(&(*SYM_MSG).into());
|
|
match msg {
|
|
None => Some(Self {
|
|
ty: *ty,
|
|
data,
|
|
msg: None,
|
|
}),
|
|
Some(Value::String(msg)) => Some(Self {
|
|
ty: *ty,
|
|
data,
|
|
msg: Some(msg.clone()),
|
|
}),
|
|
Some(_) => None,
|
|
}
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
pub fn to_table(self) -> Rc<RefCell<HashMap<HashValue, Value>>> {
|
|
let mut table = HashMap::new();
|
|
table.insert((*SYM_TYPE).into(), self.ty.into());
|
|
if let Some(msg) = self.msg {
|
|
table.insert((*SYM_MSG).into(), Value::String(msg));
|
|
}
|
|
if let Some(data) = self.data {
|
|
table.insert((*SYM_DATA).into(), data);
|
|
}
|
|
Rc::new(RefCell::new(table))
|
|
}
|
|
}
|
|
|
|
impl Display for Exception {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
if let Some(msg) = &self.msg {
|
|
write!(f, "{}: {}", self.ty.name(), msg)
|
|
} else {
|
|
write!(f, "{}", self.ty.name())
|
|
}
|
|
}
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! exception {
|
|
($exc_ty:expr, $fstr:literal, $($arg:expr),*) => {
|
|
$crate::exception::Exception::new_with_msg(
|
|
$exc_ty,
|
|
format!($fstr, $($arg),*).into()
|
|
)
|
|
};
|
|
($exc_ty:expr, $fstr:literal) => {
|
|
$crate::exception::exception!($exc_ty, $fstr,)
|
|
};
|
|
($exc_ty:expr) => {
|
|
$crate::exception::Exception::new($exc_ty)
|
|
};
|
|
}
|
|
|
|
pub use exception;
|
|
|
|
#[macro_export]
|
|
macro_rules! throw {
|
|
($($args:tt)*) => {
|
|
return Err($crate::exception::exception!($($args)*))
|
|
};
|
|
}
|
|
|
|
pub use throw;
|
|
|
|
|
|
|