talc/talc-std/src/exception.rs

43 lines
1.6 KiB
Rust

use talc_lang::{exception::{throw, Exception, Result}, symbol::{SYM_TYPE_ERROR, SYM_VALUE_ERROR}, value::Value, 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::Nil, data]
=> Exception::new_with_data(*ty, data.clone()),
[Value::Symbol(ty), Value::String(s)]
=> Exception::new_with_msg(*ty, s.clone()),
[Value::Symbol(ty), Value::String(s), data]
=> Exception::new_with_msg_data(*ty, s.clone(), data.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());
}