cluna 1.1.0

Tool to convert Lua code into Clue code Made by MarkosTh09
Documentation
---
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');