--- source: src/main.rs expression: compiled input_file: test-data/lua5.4-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 i + a + _ENV } } assert(a[(3)] != a[(4)] && a[(4)] != a[(5)]); { local a = fn (x) { return math.sin(_ENV[(x)]) } local fn f() { return a } 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)] == undef); 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 X, Y local a = math.sin(0) while a { local b = 10 X = fn () { return b } if a { break } } { local b = 20 Y = fn () { return b } } assert(X() == 10 && Y() == 20); } 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(!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');