From d699ad2ff55d9bea0ba643977e3c2424d6bf284a Mon Sep 17 00:00:00 2001 From: Alek Ratzloff Date: Tue, 24 Sep 2024 08:44:05 -0700 Subject: [PATCH] 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 --- src/obj.rs | 10 ++++++++-- src/vm.rs | 26 +++++++++----------------- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/obj.rs b/src/obj.rs index 82324d2..d615577 100644 --- a/src/obj.rs +++ b/src/obj.rs @@ -1079,10 +1079,16 @@ impl Display for MethodInst { impl Obj for MethodInst { fn arity(&self) -> Option { - 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) } diff --git a/src/vm.rs b/src/vm.rs index e0b9e20..ac2c13c 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -131,6 +131,11 @@ impl Vm { &self.stack } + /// Get the stack, mutably. + pub fn stack_mut(&mut self) -> &mut Vec { + &mut self.stack + } + /// Current stack frame. pub fn frame(&self) -> &Frame { self.frames.last().unwrap() @@ -281,12 +286,12 @@ impl Vm { } } Op::Call(argc) => { - let argc = argc as usize; - let index = self.stack.len() - argc - 1; + let argc = argc; + let index = self.stack.len() - (argc as usize) - 1; let fun_ptr = Ptr::clone(&self.stack[index]); let arity = if let Some(arity) = fun_ptr.borrow().arity() { - arity as usize + arity } else { // TODO Vm::run, Op::Call - throw an exception when the value isn't // callable @@ -297,20 +302,7 @@ impl Vm { ); }; - // Methods with bound "self" parameter - // argc may be mutated - let mut argc = argc; - if let Some(method) = fun_ptr.borrow().as_any().downcast_ref::() { - // 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; - + // Check arity if arity != argc { // TODO Vm::run, Op::Call - throw an exception when the number of arguments // does not match the function's arity