use talc_lang::{exception::{throw, Exception, Result}, symbol::SYM_TYPE_ERROR, value::Value, Vm}; use talc_macros::native_func; use crate::{unpack_args, unpack_varargs}; #[native_func(1..)] pub fn throw(_: &mut Vm, args: Vec) -> Result { let ([_, ty], varargs) = unpack_varargs!(args); let Value::Symbol(ty) = ty else { throw!(*SYM_TYPE_ERROR, "exception type must be a symbol") }; Err(match &*varargs { [] | [Value::Nil] => Exception::new(ty), [Value::Nil, data] => Exception::new_with_data(ty, data.clone()), [Value::String(s)] => Exception::new_with_msg(ty, s.clone()), [Value::String(s), data] => Exception::new_with_msg_data(ty, s.clone(), data.clone()), [_] | [_,_] => throw!(*SYM_TYPE_ERROR, "wrong arguments for throw"), [_,_,_,..] => throw!(*SYM_TYPE_ERROR, "too many arguments for throw"), }) } #[native_func(1)] pub fn rethrow(_: &mut Vm, args: Vec) -> Result { let [_, table] = unpack_args!(args); if let Value::Table(table) = table { if let Some(e) = Exception::from_table(&table) { return Err(e) } } 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()); }