Add self_referring_obj macro for self-referential objects.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -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.
|
||||||
|
|||||||
@@ -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
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user