feat: implement closures with upvalue support and statement/expression separation

Add closure objects that wrap functions with captured upvalues, enabling
first-class closures that close over local variables from enclosing scopes.
Introduce new bytecode instructions (CODE_CLOSURE, CODE_LOAD_UPVALUE,
CODE_STORE_UPVALUE, CODE_CLOSE_UPVALUE, CODE_RETURN) and a CompilerUpvalue
tracking system with a MAX_UPVALUES limit of 256. Refactor the grammar to
strictly separate statements from expressions, fixing a bug where block
expressions incorrectly popped locals while temporaries remained on the
stack. Rename internal functions (wrenCallFunction, wrenDebugDumpInstruction,
wrenDebugDumpStack) and add Upvalue allocation, closure creation, and
debug dump support for the new instructions.
This commit is contained in:
Bob Nystrom
2013-12-04 15:43:50 +00:00
parent 7e7a508096
commit 5b05c477c6
32 changed files with 1063 additions and 416 deletions
+2 -25
View File
@@ -6,27 +6,12 @@ if (false) io.write("bad")
if (true) io.write("good") else io.write("bad") // expect: good
if (false) io.write("bad") else io.write("good") // expect: good
// Allow statements for then branch.
// Allow blocks for branches.
if (true) { io.write("block") } // expect: block
if (true) if (true) io.write("double") // expect: double
// Allow statements for else branch.
if (false) null else { io.write("block") } // expect: block
if (false) null else if (true) io.write("double") // expect: double
// Return the 'then' expression if the condition is true.
var a = if (true) "good"
io.write(a) // expect: good
// Return null if the condition is false and there is no else.
var b = if (false) "bad"
io.write(b) // expect: null
// Return the 'else' expression if the condition is false.
var c = if (false) "bad" else "good"
io.write(c) // expect: good
// Assignment in if condition.
var a = false
if (a = true) io.write(a) // expect: true
// Newline after "if".
@@ -37,14 +22,6 @@ if
if (false) io.write("bad") else
io.write("good") // expect: good
// Definition in then arm.
if (true) var a = io.write("ok") // expect: ok
if (true) class Foo {} // no error
// Definition in else arm.
if (false) null else var a = io.write("ok") // expect: ok
if (true) null else class Foo {} // no error
// Only false is falsy.
if (0) io.write(0) // expect: 0
if (null) io.write(null) // expect: null