Get closures working!
In the process, I had to change the grammar. There is now a strong separation between statements and expressions. The code was just wrong before when it popped locals at the end of a block scope because there could be temporaries on the stack if the block was in expression position. This fixes that. Still need to implement closing over `this`.
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
var f = null
|
||||
var g = null
|
||||
|
||||
{
|
||||
var local = "local"
|
||||
f = fn {
|
||||
io.write(local)
|
||||
local = "after f"
|
||||
io.write(local)
|
||||
}
|
||||
|
||||
g = fn {
|
||||
io.write(local)
|
||||
local = "after g"
|
||||
io.write(local)
|
||||
}
|
||||
}
|
||||
|
||||
f.call
|
||||
// expect: local
|
||||
// expect: after f
|
||||
|
||||
g.call
|
||||
// expect: after f
|
||||
// expect: after g
|
||||
@@ -0,0 +1,9 @@
|
||||
var f = null
|
||||
|
||||
fn(param) {
|
||||
f = fn {
|
||||
io.write(param)
|
||||
}
|
||||
}.call("param")
|
||||
|
||||
f.call // expect: param
|
||||
@@ -0,0 +1,12 @@
|
||||
var f = null
|
||||
|
||||
class Foo {
|
||||
method(param) {
|
||||
f = fn {
|
||||
io.write(param)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Foo.new.method("param")
|
||||
f.call // expect: param
|
||||
@@ -0,0 +1,10 @@
|
||||
var f = null
|
||||
|
||||
{
|
||||
var local = "local"
|
||||
f = fn {
|
||||
io.write(local)
|
||||
}
|
||||
}
|
||||
|
||||
f.call // expect: local
|
||||
@@ -0,0 +1,14 @@
|
||||
var foo = null
|
||||
|
||||
{
|
||||
var local = "local"
|
||||
class Foo {
|
||||
method {
|
||||
io.write(local)
|
||||
}
|
||||
}
|
||||
|
||||
foo = Foo.new
|
||||
}
|
||||
|
||||
foo.method // expect: local
|
||||
@@ -0,0 +1,21 @@
|
||||
var f = null
|
||||
|
||||
fn {
|
||||
var a = "a"
|
||||
fn {
|
||||
var b = "b"
|
||||
fn {
|
||||
var c = "c"
|
||||
f = fn {
|
||||
io.write(a)
|
||||
io.write(b)
|
||||
io.write(c)
|
||||
}
|
||||
}.call
|
||||
}.call
|
||||
}.call
|
||||
|
||||
f.call
|
||||
// expect: a
|
||||
// expect: b
|
||||
// expect: c
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
var local = "local"
|
||||
fn {
|
||||
io.write(local) // expect: local
|
||||
}.call
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
var local = "local"
|
||||
class Foo {
|
||||
method {
|
||||
io.write(local)
|
||||
}
|
||||
}
|
||||
|
||||
Foo.new.method // expect: local
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
var f = null
|
||||
|
||||
{
|
||||
var a = "a"
|
||||
f = fn {
|
||||
io.write(a)
|
||||
io.write(a)
|
||||
}
|
||||
}
|
||||
|
||||
f.call
|
||||
// expect: a
|
||||
// expect: a
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
var f = null
|
||||
|
||||
{
|
||||
var a = "a"
|
||||
f = fn io.write(a)
|
||||
}
|
||||
|
||||
{
|
||||
// Since a is out of scope, the local slot will be reused by b. Make sure
|
||||
// that f still closes over a.
|
||||
var b = "b"
|
||||
f.call // expect: a
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(bob): Closing over this.
|
||||
// TODO(bob): Close over fn/method parameter.
|
||||
// TODO(bob): Maximum number of closed-over variables (directly and/or indirect).
|
||||
@@ -0,0 +1,6 @@
|
||||
var global = "global"
|
||||
// TODO(bob): Forward reference to global declared after use.
|
||||
|
||||
fn {
|
||||
io.write(global) // expect: global
|
||||
}.call
|
||||
@@ -0,0 +1,15 @@
|
||||
var global = "global"
|
||||
// TODO(bob): Forward reference to global declared after use.
|
||||
|
||||
class Foo {
|
||||
method {
|
||||
io.write(global)
|
||||
}
|
||||
|
||||
static classMethod {
|
||||
io.write(global)
|
||||
}
|
||||
}
|
||||
|
||||
Foo.new.method // expect: global
|
||||
Foo.classMethod // expect: global
|
||||
Reference in New Issue
Block a user