Skip to content

Commit

Permalink
Don't pop when setting an upvalue.
Browse files Browse the repository at this point in the history
Fix munificent#40.

Since assignment is an expression, every assignment instruction
(SET_LOCAL, SET_GLOBAL, SET_UPVALUE, SET_PROPERTY) needs to leave the
RHS on the stack. SET_UPVALUE was accidentally consuming it, which
leaves the stack in the wrong state.
  • Loading branch information
munificent committed Mar 17, 2017
1 parent e27fb8e commit f449809
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 2 deletions.
3 changes: 2 additions & 1 deletion c/compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,8 @@ static ObjFunction* endCompiler() {
disassembleChunk(currentChunk(), "code");
*/
//> Calls and Functions not-yet
disassembleChunk(currentChunk(), function->name->chars);
disassembleChunk(currentChunk(),
function->name != NULL ? function->name->chars : "<top>");
//< Calls and Functions not-yet
}
#endif
Expand Down
2 changes: 1 addition & 1 deletion c/vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ static bool run() {

case OP_SET_UPVALUE: {
uint8_t slot = READ_BYTE();
*frame->closure->upvalues[slot]->value = pop();
*frame->closure->upvalues[slot]->value = peek(0);
break;
}
//< Closures not-yet
Expand Down
22 changes: 22 additions & 0 deletions test/regression/40.lox
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
fun caller(g) {
g();
// g should be a function, not nil.
print g == nil; // expect: false
}

fun callCaller() {
var capturedVar = "before";
var a = "a";

fun f() {
// Commenting the next line out prevents the bug!
capturedVar = "after";

// Returning anything also fixes it, even nil:
//return nil;
}

caller(f);
}

callCaller();

0 comments on commit f449809

Please sign in to comment.