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) -> Result { 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) -> 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_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()); }