talc/talc-std/src/exception.rs
2024-11-14 14:16:33 -05:00

49 lines
1.3 KiB
Rust

use talc_lang::{
exception::{throw, Exception, Result},
symbol::{SYM_TYPE_ERROR, SYM_VALUE_ERROR},
value::Value,
vm::Vm,
};
use talc_macros::native_func;
use crate::unpack_args;
#[native_func(1)]
pub fn throw(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
let [_, arg] = unpack_args!(args);
let exc = match arg {
Value::Symbol(ty) => Exception::new(ty),
Value::List(l) => match l.borrow().as_slice() {
[Value::Symbol(ty)] | [Value::Symbol(ty), Value::Nil] => Exception::new(*ty),
[Value::Symbol(ty), Value::String(s)] => {
Exception::new_with_msg(*ty, s.clone())
}
[] | [_] | [_, _] => {
throw!(*SYM_TYPE_ERROR, "wrong argument for throw")
}
[_, _, _, ..] => throw!(
*SYM_VALUE_ERROR,
"too many elements in list argument for throw"
),
},
_ => throw!(*SYM_TYPE_ERROR, "throw expected symbol or list"),
};
Err(exc)
}
#[native_func(1)]
pub fn rethrow(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
let [_, table] = unpack_args!(args);
if let Value::Table(table) = table {
if let Some(e) = Exception::from_table(&table) {
return Err(e)
}
throw!(*SYM_VALUE_ERROR, "argument not a valid exception")
}
throw!(*SYM_TYPE_ERROR, "argument not a valid exception")
}
pub fn load(vm: &mut Vm) {
vm.set_global_name("throw", throw().into());
vm.set_global_name("rethrow", rethrow().into());
}