Add self_referring_obj macro for self-referential objects.

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2020-10-07 18:41:45 -07:00
parent e2c84ba7c2
commit c3121a176c
2 changed files with 35 additions and 32 deletions

View File

@@ -31,24 +31,18 @@ pub struct UserFun {
impl UserFun { impl UserFun {
pub fn new_obj(code: Vec<Inst>, locals: FunLocals) -> UserFunRef { pub fn new_obj(code: Vec<Inst>, locals: FunLocals) -> UserFunRef {
let obj_ref = ObjRef::new(UserFun { self_referring_obj! (
Self {
vtable: Default::default(), // this is a placeholder for the real vtable vtable: Default::default(), // this is a placeholder for the real vtable
attrs: Default::default(), attrs: Default::default(),
code: Arc::new(code), code: Arc::new(code),
locals, locals,
}); },
vtable: |obj_ref: ObjRef| vtable! {
// XXX replace the vtable before returning, since __call__ member points to the object
// itself
{
write_obj!(let obj = obj_ref);
obj.vtable = vtable! {
TY_MEMBER_NAME.sym => USER_FUN_TY.clone(), TY_MEMBER_NAME.sym => USER_FUN_TY.clone(),
CALL_MEMBER_NAME.sym => obj_ref.clone(), CALL_MEMBER_NAME.sym => obj_ref.clone(),
};
} }
)
obj_ref
} }
pub fn code(&self) -> &Vec<Inst> { pub fn code(&self) -> &Vec<Inst> {
@@ -209,24 +203,17 @@ pub struct NativeFun {
impl NativeFun { impl NativeFun {
pub fn new_obj(fun: NativeFunPtr) -> ObjRef<Self> { pub fn new_obj(fun: NativeFunPtr) -> ObjRef<Self> {
let obj_ref = ObjRef::new(Self { self_referring_obj! (
Self {
vtable: Default::default(), vtable: Default::default(),
attrs: Default::default(), attrs: Default::default(),
fun: GcSafeWrapper::new(fun), fun: GcSafeWrapper::new(fun),
}); },
vtable: |obj_ref: ObjRef| vtable! {
// XXX replace the vtable before returning, since __call__ member points to the object
// itself
{
write_obj!(let obj = obj_ref);
obj.vtable = vtable! {
TY_MEMBER_NAME.sym => NATIVE_FUN_TY.clone(), TY_MEMBER_NAME.sym => NATIVE_FUN_TY.clone(),
CALL_MEMBER_NAME.sym => obj_ref.clone(), CALL_MEMBER_NAME.sym => obj_ref.clone(),
};
} }
)
obj_ref
} }
/// Gets the native function that can be invoked. /// Gets the native function that can be invoked.

View File

@@ -122,3 +122,19 @@ macro_rules! handle_type {
impl shredder::EmptyScan for $name {} 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
}};
}