Add Obj.__init__ and Obj.__call__, fix how __call__ works on Ty
* Obj.__call__ should generically call Obj.__init__, passing along the arguments given to __call__ * Ty::call function (in Rust) sets up the stack frame correctly now. Before, the only arguments visible to a `Ty.__call__` function would have been the values passed to it. However, the Ty.__call__ also needs *itself* passed to the __call__ function so we can retrieve the __init__ function and eventually end up calling that. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -77,21 +77,37 @@ impl Object for Ty {
|
||||
// If you do e.g. `Int.__call__`, Int is an object, so it should be doing `__call__` as a
|
||||
// vtable value.
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
let index = vm.stack().len() - 1 - argc as usize;
|
||||
let this = vm.stack()[index].clone();
|
||||
assert!(
|
||||
std::ptr::addr_eq(&*this.borrow(), self),
|
||||
"calling {}.__call__ on type that is not ourselves",
|
||||
self.ty_name()
|
||||
);
|
||||
}
|
||||
let index = vm.stack().len() - 1 - argc as usize;
|
||||
let this = vm.stack()[index].clone();
|
||||
|
||||
assert!(
|
||||
std::ptr::addr_eq(&*this.borrow(), self),
|
||||
"calling {}.__call__ on type that is not ourselves",
|
||||
self.ty_name()
|
||||
);
|
||||
|
||||
// Additionally, we want to duplicate the type argument on the stack.
|
||||
//
|
||||
// When you call a new constructor, e.g. `MyType(arg1, arg2, arg3)`, the stack will look like this:
|
||||
//
|
||||
// -- stack top
|
||||
// arg3
|
||||
// arg2
|
||||
// arg1
|
||||
// <Ty MyType> <---- NOTE - this is what we are actually calling, and is being treated as a function
|
||||
// ...
|
||||
// -- stack bottom
|
||||
//
|
||||
// With a custom type, we want to be getting the __init__ function off of the type. Since
|
||||
// we don't have access to the function in the call stack (in this case, it's our type),
|
||||
// we duplicate the type to be the first argument.
|
||||
vm.stack_mut().insert(index, this);
|
||||
|
||||
let function = self
|
||||
.vtable
|
||||
.get("__call__")
|
||||
.expect("Why does a type not have a __call__ member?");
|
||||
function.borrow().call(vm, argc);
|
||||
function.borrow().call(vm, argc + 1);
|
||||
}
|
||||
|
||||
fn arity(&self) -> Option<Argc> {
|
||||
@@ -185,7 +201,9 @@ pub fn init_types() {
|
||||
len => BuiltinFunction::create("len", BaseObj::not_implemented_un, 1),
|
||||
},
|
||||
Obj {
|
||||
//__call__ => BuiltinFunction::create("__call__",
|
||||
// Constructor
|
||||
__call__ => BuiltinFunction::create("__call__", Obj::do_call, 1),
|
||||
__init__ => BuiltinFunction::create("__init__", Obj::init, 1),
|
||||
// Methods
|
||||
},
|
||||
List {
|
||||
|
||||
Reference in New Issue
Block a user