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 <alekratz@gmail.com>
This commit is contained in:
2023-04-07 00:36:16 -07:00
parent 4cec6f0765
commit fcef6c053d
3 changed files with 7 additions and 7 deletions

View File

@@ -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
}

View File

@@ -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

View File

@@ -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 => {