Add Method type for objects

* Methods are wrappers created with an owner and a function, which
  passes the owner as the first argument when the function is called.
* Fix a small bug in the VM where the pc was being set at the wrong
  time

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2020-10-08 16:10:10 -07:00
parent c3121a176c
commit c738c52455
4 changed files with 90 additions and 15 deletions

View File

@@ -11,6 +11,61 @@ pub trait Fun {
fn create_frame(&self, callee: ObjRef, vm: &Vm, _args: Vec<ObjRef>) -> Frame;
}
pub type MethodRef = ObjRef<Method>;
#[derive(Scan, Debug)]
pub struct Method {
vtable: Vtable,
attrs: Attrs,
}
impl Method {
pub fn new_obj(owner: ObjRef, function: ObjRef) -> MethodRef {
self_referring_obj! {
Self {
vtable: Default::default(),
attrs: attrs! {
SELF_MEMBER_NAME.sym => owner,
FUNC_MEMBER_NAME.sym => function,
}
},
vtable: |obj_ref: ObjRef| vtable! {
CALL_MEMBER_NAME.sym => obj_ref.clone(),
}
}
}
}
impl Obj for Method {
fn vtable(&self) -> &Vtable {
&self.vtable
}
fn attrs(&self) -> &Attrs {
&self.attrs
}
fn attrs_mut(&mut self) -> Option<&mut Attrs> {
Some(&mut self.attrs)
}
fn as_any(&self) -> &dyn std::any::Any { self }
fn as_fun(&self) -> Option<&dyn Fun> { Some(self) }
}
impl Fun for Method {
fn create_frame(&self, _callee: ObjRef, vm: &Vm, mut args: Vec<ObjRef>) -> Frame {
// insert self argument
args.insert(0, self.get_attr(SELF_MEMBER_NAME.sym).unwrap());
// get function and use its create_frame method with the updated args
let fun_ref = self.get_attr(FUNC_MEMBER_NAME.sym).unwrap();
read_obj!(let fun_obj = fun_ref);
let fun = fun_obj.as_fun().unwrap();
fun.create_frame(fun_ref.clone(), vm, args)
}
}
//
// struct UserFun
//