From fcef6c053d5f6fb507bb30cf10325c4c13cd9360 Mon Sep 17 00:00:00 2001 From: Alek Ratzloff Date: Fri, 7 Apr 2023 00:36:16 -0700 Subject: [PATCH] Update calling convention Previously, the stack would look like this when calling a function: TOP | arg2 | | arg1 | | function | BOTTOM This order is now reversed, with the function coming first and then the args: TOP | function | | arg2 | | arg1 | BOTTOM This is a little more friendly to the stack-based machine. It is slightly less intuitive as far as order of operations goes, but having a function's arguments depend on the state of the function itself is a little suspect and easy to work around if you truly need that. Signed-off-by: Alek Ratzloff --- src/compile/compiler.rs | 8 ++++---- src/vm/inst.rs | 4 ++-- src/vm/mod.rs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/compile/compiler.rs b/src/compile/compiler.rs index 987bfc6..af05aa4 100644 --- a/src/compile/compiler.rs +++ b/src/compile/compiler.rs @@ -142,10 +142,10 @@ impl Compiler { fn emit_expr(&mut self, expr: &SpExpr) -> Thunk { match expr.inner() { Expr::Call(expr, args) => { - let mut thunk = VecDeque::with_capacity(args.len() + 1); - thunk.push_back(self.emit_expr(expr)); - thunk.extend(args.iter().map(|arg| self.emit_expr(arg))); - let mut thunk = Thunk::List(thunk); + let mut thunk_items = VecDeque::with_capacity(args.len() + 1); + thunk_items.extend(args.iter().map(|arg| self.emit_expr(arg))); + thunk_items.push_back(self.emit_expr(expr)); + let mut thunk = Thunk::List(thunk_items); thunk.push_back(Inst::Call(args.len())); thunk } diff --git a/src/vm/inst.rs b/src/vm/inst.rs index f11548f..b1075d5 100644 --- a/src/vm/inst.rs +++ b/src/vm/inst.rs @@ -25,8 +25,8 @@ pub enum Inst { /// Pops the top item off of the stack, discarding it. Pop, - /// Pops the top N function arguments off the stack, and attempt to call the - /// next stack item. + /// Pops the top item off of the stack to call, and then pops off the + /// following N arguments. Call(usize), /// Exits the current function stack frame and returns control to the diff --git a/src/vm/mod.rs b/src/vm/mod.rs index bd16af8..a37daeb 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -195,6 +195,7 @@ impl Vm { Inst::Call(argc) => { let argc = *argc; let stack = self.stack_mut(); + let fun = stack.pop().expect("No function pointer in Inst::Call"); let split_at = stack.len() - argc; let args = stack.split_off(split_at); @@ -204,7 +205,6 @@ impl Vm { "Not enough arguments popped in Inst::Call" ); - let fun = stack.pop().expect("No function pointer in Inst::Call"); next_frame = self.make_frame(fun, args); } Inst::Return => {