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:
10
src/obj.rs
10
src/obj.rs
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
26
src/vm.rs
26
src/vm.rs
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user