---
source: src/main.rs
expression: compiled
input_file: test-data/lua5.2-tests/closure.lua
---
print("testing closures");
local A, B = 0, {
g = 10
}
global fn f(x) {
local a = {}
for i = 1, 1000 {
local y = 0
{
a[(i)] = fn () {
B.g = B.g + 1
y = y + x
return y + A
}
}
}
local dummy = fn () {
return a[(A)]
}
collectgarbage();
A = 1
assert(dummy() == a[(1)]);
A = 0
assert(a[(1)]() == x);
assert(a[(3)]() == x);
collectgarbage();
assert(B.g == 12);
return a
}
local a = f(10)
local x = {
1 = {}
}
setmetatable(x, {
__mode = 'kv'
});
while x[(1)] {
local a = A .. A .. A .. A
A = A + 1
}
assert(a[(1)]() == 20 + A);
assert(a[(1)]() == 30 + A);
assert(a[(2)]() == 10 + A);
collectgarbage();
assert(a[(2)]() == 20 + A);
assert(a[(2)]() == 30 + A);
assert(a[(3)]() == 20 + A);
assert(a[(8)]() == 10 + A);
assert(getmetatable(x).__mode == 'kv');
assert(B.g == 19);
a = {}
for i = 1, 5 {
a[(i)] = fn (x) {
return x + a + _ENV
}
}
assert(a[(3)] == a[(4)] && a[(4)] == a[(5)]);
for i = 1, 5 {
a[(i)] = fn (x) {
return i + a + _ENV
}
}
assert(a[(3)] != a[(4)] && a[(4)] != a[(5)]);
local fn f() {
return fn (x) {
return math.sin(_ENV[(x)])
}
}
assert(f() == f());
a = {}
for i = 1, 10 {
a[(i)] = {
set = fn (x) {
i = x
},
get = fn () {
return i
}
}
if i == 3 {
break
}
}
assert(a[(4)] == nil);
a[(1)].set(10);
assert(a[(2)].get() == 2);
a[(2)].set('a');
assert(a[(3)].get() == 3);
assert(a[(2)].get() == 'a');
a = {}
local t = {
"a",
"b"
}
for i = 1, #t {
local k = t[(i)]
a[(i)] = {
set = fn (x, y) {
i = x
k = y
},
get = fn () {
return i, k
}
}
if i == 2 {
break
}
}
a[(1)].set(10, 20);
local r, s = a[(2)].get()
assert(r == 2 && s == 'b');
r, s = a[(1)].get()
assert(r == 10 && s == 20);
a[(2)].set('a', 'b');
r, s = a[(2)].get()
assert(r == "a" && s == "b");
for i = 1, 3 {
f = fn () {
return i
}
break
}
assert(f() == 1);
for k = 1, #t {
local v = t[(k)]
f = fn () {
return k, v
}
break
}
assert(({
f()
})[(1)] == 1);
assert(({
f()
})[(2)] == "a");
local b
global fn f(x) {
local first = 1
while 1 {
if x == 3 && !first {
return
}
local a = 'xuxu'
b = fn (op, y) {
if op == 'set' {
a = x + y
} else {
return a
}
}
if x == 1 {
{
break
}
} elseif if x == 2 {
return
} else {
if x != 3 {
error();
}
}
first = nil
}
}
for i = 1, 3 {
f(i);
assert(b('get') == 'xuxu');
b('set', 10);
assert(b('get') == 10 + i);
b = nil
}
pcall(f, 4);
assert(b('get') == 'xuxu');
b('set', 10);
assert(b('get') == 14);
local w
global fn f(x) {
return fn (y) {
return fn (z) {
return w + x + y + z
}
}
}
y = f(10)
w = 1.345
assert(y(20)(30) == 60 + w);
local a = {}
local i = 1
loop {
local x = i
a[(i)] = fn () {
i = x + 1
return x
}
} until i > 10 || a[(i)]() != x
assert(i == 11 && a[(1)]() == 1 && a[(3)]() == 3 && i == 4);
a = {}
for i = 1, 10 {
if i % 3 == 0 {
local y = 0
a[(i)] = fn (x) {
local t = y
y = x
return t
}
} elseif if i % 3 == 1 {
error('not here');
local y = 1
a[(i)] = fn (x) {
local t = y
y = x
return t
}
} elseif if i % 3 == 2 {
local t
a[(i)] = t
error("should never be here!");
local y = 2
t = fn (x) {
local t = y
y = x
return t
}
error("should never be here!");
}
}
for i = 1, 10 {
assert(a[(i)](i * 10) == i % 3 && a[(i)]() == i * 10);
}
print('+');
local fn t() {
local fn c(a, b) {
assert(a == "test" && b == "OK");
}
local fn v(f, ...) {
c("test", f() != 1 && "FAILED" || "OK");
}
local x = 1
return v(fn () {
return x
})
}
t();
local debug = require('debug')
{
local a, b, c = 3, 5, 7
foo1 = fn () {
return a + b
}
foo2 = fn () {
return b + a
}
{
local a = 10
foo3 = fn () {
return a + b
}
}
}
assert(debug.upvalueid(foo1, 1));
assert(debug.upvalueid(foo1, 2));
assert(!pcall(debug.upvalueid, foo1, 3));
assert(debug.upvalueid(foo1, 1) == debug.upvalueid(foo2, 2));
assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo2, 1));
assert(debug.upvalueid(foo3, 1));
assert(debug.upvalueid(foo1, 1) != debug.upvalueid(foo3, 1));
assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo3, 2));
assert(debug.upvalueid(string.gmatch("x", "x"), 1) != nil);
assert(foo1() == 3 + 5 && foo2() == 5 + 3);
debug.upvaluejoin(foo1, 2, foo2, 2);
assert(foo1() == 3 + 3 && foo2() == 5 + 3);
assert(foo3() == 10 + 5);
debug.upvaluejoin(foo3, 2, foo2, 1);
assert(foo3() == 10 + 5);
debug.upvaluejoin(foo3, 2, foo2, 2);
assert(foo3() == 10 + 3);
assert(!pcall(debug.upvaluejoin, foo1, 3, foo2, 1));
assert(!pcall(debug.upvaluejoin, foo1, 1, foo2, 3));
assert(!pcall(debug.upvaluejoin, foo1, 0, foo2, 1));
assert(!pcall(debug.upvaluejoin, print, 1, foo2, 1));
assert(!pcall(debug.upvaluejoin, {}, 1, foo2, 1));
assert(!pcall(debug.upvaluejoin, foo1, 1, print, 1));
print('OK');