macro_rules! impl_base_obj { ($base_name:ident, $type_name:ident) => { fn instantiate(&mut self) { let ty = $crate::obj::BUILTINS.with_borrow(|builtins| { builtins .get(stringify!($type_name)) .expect(concat!("no ", stringify!($type_name))) .clone() }); self.set_attr("__ty__", ty); self.$base_name.instantiate(); } fn is_instantiated(&self) -> bool { self.$base_name.is_instantiated() } fn attrs(&self) -> &$crate::obj::Attrs { self.$base_name.attrs() } fn attrs_mut(&mut self) -> &mut $crate::obj::Attrs { self.$base_name.attrs_mut() } fn as_any(&self) -> &dyn std::any::Any { self } fn as_any_mut(&mut self) -> &mut dyn std::any::Any { self } }; ($type_name:ident) => { impl_base_obj! { base, $type_name } }; } macro_rules! impl_create { ($($arg:ident : $ty:ty),* $(,)?) => { // TODO - obj::macros::impl_create - remove this #[allow(dead_code)] designator #[allow(dead_code)] pub fn create($($arg : $ty ),*) -> $crate::obj::ObjP { let ptr = $crate::obj::make_ptr(Self::new($($arg),*)); ptr.borrow_mut().instantiate(); ptr } } } macro_rules! impl_do_call { ($name:ident) => { pub(crate) fn do_call( vm: &mut $crate::vm::Vm, state: $crate::obj::function::FunctionState, ) -> $crate::obj::function::FunctionResult { match state { $crate::obj::function::FunctionState::Begin => { // get the top item off the stack and call to_float on it let arg = vm.peek(); let method = if let Some(method) = arg.borrow().get_vtable_attr(arg.clone(), stringify!($name)) { method } else { // TODO builtins::do_call - throw exception when target doesn't have a // to_$name method // BLOCKED-ON: exceptions todo!( concat!("{} does not have a ", stringify!($name), " method"), arg.borrow().ty_name() ); }; vm.push(method.clone()); method.borrow().call(vm, 0); // resume execution $crate::obj::function::FunctionResult::Yield(0) } $crate::obj::function::FunctionState::Resume(0) => { $crate::obj::function::FunctionResult::Return } _ => unreachable!(), } } }; } pub(crate) use impl_base_obj; pub(crate) use impl_create; pub(crate) use impl_do_call;