Move MethodInst stack mangling to MethodInst::call

When a MethodInst is called as a function in the VM, it needs to push
its `self_binding` member to the stack. Previously, we were downcasting
(if possible) to MethodInst in the VM, but really, we are calling
`MethodInst::call` anyway, so it makes more sense to do
MethodInst-specific stuff in the MethodInst-specific function.

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2024-09-24 08:44:05 -07:00
parent 3545488ef8
commit d699ad2ff5
2 changed files with 17 additions and 19 deletions

View File

@@ -1079,10 +1079,16 @@ impl Display for MethodInst {
impl Obj for MethodInst { impl Obj for MethodInst {
fn arity(&self) -> Option<Argc> { fn arity(&self) -> Option<Argc> {
self.function.borrow().arity() // Subtract one from the arity - this is because the VM uses arity() to check against the
// number of arguments passed.
self.function.borrow().arity().map(|arity| arity - 1)
} }
fn call(&self, vm: &mut Vm, argc: Argc) { fn call(&self, vm: &mut Vm, mut argc: Argc) {
let self_pos = vm.stack().len() - (argc as usize);
vm.stack_mut().insert(self_pos, self.self_binding.clone());
argc += 1;
self.function.borrow().call(vm, argc) self.function.borrow().call(vm, argc)
} }

View File

@@ -131,6 +131,11 @@ impl Vm {
&self.stack &self.stack
} }
/// Get the stack, mutably.
pub fn stack_mut(&mut self) -> &mut Vec<ObjP> {
&mut self.stack
}
/// Current stack frame. /// Current stack frame.
pub fn frame(&self) -> &Frame { pub fn frame(&self) -> &Frame {
self.frames.last().unwrap() self.frames.last().unwrap()
@@ -281,12 +286,12 @@ impl Vm {
} }
} }
Op::Call(argc) => { Op::Call(argc) => {
let argc = argc as usize; let argc = argc;
let index = self.stack.len() - argc - 1; let index = self.stack.len() - (argc as usize) - 1;
let fun_ptr = Ptr::clone(&self.stack[index]); let fun_ptr = Ptr::clone(&self.stack[index]);
let arity = if let Some(arity) = fun_ptr.borrow().arity() { let arity = if let Some(arity) = fun_ptr.borrow().arity() {
arity as usize arity
} else { } else {
// TODO Vm::run, Op::Call - throw an exception when the value isn't // TODO Vm::run, Op::Call - throw an exception when the value isn't
// callable // callable
@@ -297,20 +302,7 @@ impl Vm {
); );
}; };
// Methods with bound "self" parameter // Check arity
// argc may be mutated
let mut argc = argc;
if let Some(method) = fun_ptr.borrow().as_any().downcast_ref::<MethodInst>() {
// shift all of the arguments over by one
// (duplicate the last item on the stack and then shift everyone else over)
self.stack
.insert(self.stack.len() - argc, Ptr::clone(method.self_binding()));
// also increment argc since we're specifying another arg
argc += 1;
}
// remove mutability
let argc = argc;
if arity != argc { if arity != argc {
// TODO Vm::run, Op::Call - throw an exception when the number of arguments // TODO Vm::run, Op::Call - throw an exception when the number of arguments
// does not match the function's arity // does not match the function's arity