From c3121a176c366807bbfd24af149707ee6b4ad641 Mon Sep 17 00:00:00 2001 From: Alek Ratzloff Date: Wed, 7 Oct 2020 18:41:45 -0700 Subject: [PATCH] Add self_referring_obj macro for self-referential objects. Signed-off-by: Alek Ratzloff --- src/obj/fun.rs | 51 ++++++++++++++++++----------------------------- src/obj/macros.rs | 16 +++++++++++++++ 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/src/obj/fun.rs b/src/obj/fun.rs index 6c88e6b..b717537 100644 --- a/src/obj/fun.rs +++ b/src/obj/fun.rs @@ -31,24 +31,18 @@ pub struct UserFun { impl UserFun { pub fn new_obj(code: Vec, locals: FunLocals) -> UserFunRef { - let obj_ref = ObjRef::new(UserFun { - vtable: Default::default(), // this is a placeholder for the real vtable - attrs: Default::default(), - code: Arc::new(code), - locals, - }); - - // XXX replace the vtable before returning, since __call__ member points to the object - // itself - { - write_obj!(let obj = obj_ref); - obj.vtable = vtable! { + self_referring_obj! ( + Self { + vtable: Default::default(), // this is a placeholder for the real vtable + attrs: Default::default(), + code: Arc::new(code), + locals, + }, + vtable: |obj_ref: ObjRef| vtable! { TY_MEMBER_NAME.sym => USER_FUN_TY.clone(), CALL_MEMBER_NAME.sym => obj_ref.clone(), - }; - } - - obj_ref + } + ) } pub fn code(&self) -> &Vec { @@ -209,24 +203,17 @@ pub struct NativeFun { impl NativeFun { pub fn new_obj(fun: NativeFunPtr) -> ObjRef { - let obj_ref = ObjRef::new(Self { - vtable: Default::default(), - attrs: Default::default(), - fun: GcSafeWrapper::new(fun), - }); - - - // XXX replace the vtable before returning, since __call__ member points to the object - // itself - { - write_obj!(let obj = obj_ref); - obj.vtable = vtable! { + self_referring_obj! ( + Self { + vtable: Default::default(), + attrs: Default::default(), + fun: GcSafeWrapper::new(fun), + }, + vtable: |obj_ref: ObjRef| vtable! { TY_MEMBER_NAME.sym => NATIVE_FUN_TY.clone(), CALL_MEMBER_NAME.sym => obj_ref.clone(), - }; - } - - obj_ref + } + ) } /// Gets the native function that can be invoked. diff --git a/src/obj/macros.rs b/src/obj/macros.rs index b3ccc1e..91fbbc2 100644 --- a/src/obj/macros.rs +++ b/src/obj/macros.rs @@ -122,3 +122,19 @@ macro_rules! handle_type { impl shredder::EmptyScan for $name {} }; } + +#[macro_export] +macro_rules! self_referring_obj { + ($init:expr $(, $name:ident : $value:expr)* $(,)?) => {{ + let obj_ref = $crate::obj::ObjRef::new($init); + + { + write_obj!(let obj = obj_ref); + $( + obj.$name = ($value)(obj_ref.clone()); + )* + } + + obj_ref + }}; +}