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:
@@ -142,10 +142,10 @@ impl Compiler {
|
|||||||
fn emit_expr(&mut self, expr: &SpExpr) -> Thunk {
|
fn emit_expr(&mut self, expr: &SpExpr) -> Thunk {
|
||||||
match expr.inner() {
|
match expr.inner() {
|
||||||
Expr::Call(expr, args) => {
|
Expr::Call(expr, args) => {
|
||||||
let mut thunk = VecDeque::with_capacity(args.len() + 1);
|
let mut thunk_items = VecDeque::with_capacity(args.len() + 1);
|
||||||
thunk.push_back(self.emit_expr(expr));
|
thunk_items.extend(args.iter().map(|arg| self.emit_expr(arg)));
|
||||||
thunk.extend(args.iter().map(|arg| self.emit_expr(arg)));
|
thunk_items.push_back(self.emit_expr(expr));
|
||||||
let mut thunk = Thunk::List(thunk);
|
let mut thunk = Thunk::List(thunk_items);
|
||||||
thunk.push_back(Inst::Call(args.len()));
|
thunk.push_back(Inst::Call(args.len()));
|
||||||
thunk
|
thunk
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ pub enum Inst {
|
|||||||
/// Pops the top item off of the stack, discarding it.
|
/// Pops the top item off of the stack, discarding it.
|
||||||
Pop,
|
Pop,
|
||||||
|
|
||||||
/// Pops the top N function arguments off the stack, and attempt to call the
|
/// Pops the top item off of the stack to call, and then pops off the
|
||||||
/// next stack item.
|
/// following N arguments.
|
||||||
Call(usize),
|
Call(usize),
|
||||||
|
|
||||||
/// Exits the current function stack frame and returns control to the
|
/// Exits the current function stack frame and returns control to the
|
||||||
|
|||||||
@@ -195,6 +195,7 @@ impl Vm {
|
|||||||
Inst::Call(argc) => {
|
Inst::Call(argc) => {
|
||||||
let argc = *argc;
|
let argc = *argc;
|
||||||
let stack = self.stack_mut();
|
let stack = self.stack_mut();
|
||||||
|
let fun = stack.pop().expect("No function pointer in Inst::Call");
|
||||||
let split_at = stack.len() - argc;
|
let split_at = stack.len() - argc;
|
||||||
let args = stack.split_off(split_at);
|
let args = stack.split_off(split_at);
|
||||||
|
|
||||||
@@ -204,7 +205,6 @@ impl Vm {
|
|||||||
"Not enough arguments popped in Inst::Call"
|
"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);
|
next_frame = self.make_frame(fun, args);
|
||||||
}
|
}
|
||||||
Inst::Return => {
|
Inst::Return => {
|
||||||
|
|||||||
Reference in New Issue
Block a user