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.3-tests/constructs.lua
---
print("testing syntax");
local debug = require("debug")
local fn checkload(s, msg) {
    assert(string.find(select(2, load(s)), msg));
}
{
    
}
{
    a = 3
    assert(a == 3);
}
if false {
    a = 3 /_ 0
    a = 0 % 0
}
assert(2 ^ 3 ^ 2 == 2 ^ (3 ^ 2));
assert(2 ^ 3 * 4 == (2 ^ 3) * 4);
assert(2.0 ^ -2 == 1 / 4 && -2 ^ - - 2 == - - -4);
assert(!nil && 2 && !(2 > 3 || 3 < 2));
assert(-3 - 1 - 5 == 0 + 0 - 9);
assert(-2 ^ 2 == -4 && (-2) ^ 2 == 4 && 2 * 2 - 3 - 1 == 0);
assert(-3 % 5 == 2 && -3 + 5 == 2);
assert(2 * 1 + 3 / 3 == 3 && 1 + 2 .. 3 * 1 == "33");
assert(!(2 + 1 > 3 * 1) && "a" .. "b" > "a");
assert("7" .. 3 << 1 == 146);
assert(10 >> 1 .. "9" == 0);
assert(10 | 1 .. "9" == 27);
assert(0xF0 | 0xCC ~ 0xAA & 0xFD == 0xF4);
assert(0xFD & 0xAA ~ 0xCC | 0xF0 == 0xF4);
assert(0xF0 & 0x0F + 1 == 0x10);
assert(3 ^ 4 /_ 2 ^ 3 /_ 5 == 2);
assert(-3 + 4 * 5 /_ 2 ^ 3 ^ 2 /_ 9 + 4 % 10 / 3 == (-3) + (((4 * 5) /_ (2 ^ (3 ^ 2))) /_ 9) + ((4 % 10) / 3));
assert(!((true || false) && nil));
assert(true || false && nil);
assert((((1 || false) && true) || false) == true);
assert((((nil && true) || false) && true) == false);
local a, b = 1, nil
assert(-(1 || 2) == -1 && (1 && 2) + (-1.25 || -4) == 0.75);
x = ((b || a) + 1 == 2 && (10 || a) + 1 == 11)
assert(x);
x = (((2 < 3) || 1) == true && (2 < 3 && 4) == 4)
assert(x);
x, y = 1, 2
assert((x > y) && x || y == 2);
x, y = 2, 1
assert((x > y) && x || y == 2);
assert(1234567890 == tonumber('1234567890') && 1234567890 + 1 == 1234567891);
loop  {
    
} until 1
loop  {
    
} until true
while false {
    
}
while nil {
    
}
{
    local a
    global fn f(x) {
        x = {
            a = 1
        }
        x = {
            x = 1
        }
        x = {
            G = 1
        }
    }
}
global fn f(i) {
    if type(i) != 'number' {
        return i, 'jojo'
    }
    if i > 0 {
        return i, f(i - 1)
    }
}
x = {
    f(3), 
    f(5), 
    f(10)
}
assert(x[(1)] == 3 && x[(2)] == 5 && x[(3)] == 10 && x[(4)] == 9 && x[(12)] == 1);
assert(x[(nil)] == nil);
x = {
    f('alo'), 
    f('xixi'), 
    nil
}
assert(x[(1)] == 'alo' && x[(2)] == 'xixi' && x[(3)] == nil);
x = {
    f('alo') .. 'xixi'
}
assert(x[(1)] == 'aloxixi');
x = {
    f({})
}
assert(x[(2)] == 'jojo' && type(x[(1)]) == 'table');
local f = fn (i) {
    if i < 10 {
        return 'a'
    } elseif if i < 20 {
        return 'b'
    } elseif if i < 30 {
        return 'c'
    }
}
assert(f(3) == 'a' && f(12) == 'b' && f(26) == 'c' && f(100) == nil);
for i = 1, 1000 {
    break
}
n = 100
i = 3
t = {}
a = nil
while !a {
    a = 0
    for i = 1, n {
        for i = i, 1, -1 {
            a = a + 1
            t[(i)] = 1
        }
    }
}
assert(a == n * (n + 1) / 2 && i == 3);
assert(t[(1)] && t[(n)] && !t[(0)] && !t[(n + 1)]);
global fn f(b) {
    local x = 1
    loop  {
        local a
        if b == 1 {
            local b = 1
            x = 10
            break
        } elseif if b == 2 {
            x = 20
            break
        } elseif if b == 3 {
            x = 30
        } else {
            local a, b, c, d = math.sin(1)
            x = x + 1
        }
    } until x >= 12
    return x
}
assert(f(1) == 10 && f(2) == 20 && f(3) == 30 && f(4) == 12);
local f = fn (i) {
    if i < 10 {
        return 'a'
    } elseif if i < 20 {
        return 'b'
    } elseif if i < 30 {
        return 'c'
    } else {
        return 8
    }
}
assert(f(3) == 'a' && f(12) == 'b' && f(26) == 'c' && f(100) == 8);
local a, b = nil, 23
x = {
    f(100) * 2 + 3 || a, 
    a || b + 2
}
assert(x[(1)] == 19 && x[(2)] == 25);
x = {
    f = 2 + 3 || a, 
    a = b + 2
}
assert(x.f == 5 && x.a == 25);
a = {
    y = 1
}
x = {
    a.y
}
assert(x[(1)] == 1);
global fn f(i) {
    while 1 {
        if i > 0 {
            i = i - 1
        } else {
            return
        }
    }
}
global fn g(i) {
    while 1 {
        if i > 0 {
            i = i - 1
        } else {
            return
        }
    }
}
f(10);
g(10);
{
    global fn f() {
        return 1, 2, 3
    }
    local a, b, c = f()
    assert(a == 1 && b == 2 && c == 3);
    a, b, c = (f())
    assert(a == 1 && b == nil && c == nil);
}
local a, b = 3 && f()
assert(a == 1 && b == nil);
global fn g() {
    f();
    return
}
assert(g() == nil);
global fn g() {
    return nil || f()
}
a, b = g()
assert(a == 1 && b == nil);
print('+');
f = `
return function ( a , b , c , d , e )
  local x = a >= b or c or ( d and e ) or nil
  return x
end , { a = 1 , b = 2 >= 1 , } or { 1 };
`
f = string.gsub(f, "%s+", "\n")
f, a = load(f)()
assert(a.a == 1 && a.b);
global fn g(a, b, c, d, e) {
    if !(a >= b || c || d && e || nil) {
        return 0
    } else {
        return 1
    }
}
global fn h(a, b, c, d, e) {
    while (a >= b || c || (d && e) || nil) {
        return 1
    }
    return 0
}
assert(f(2, 1) == true && g(2, 1) == 1 && h(2, 1) == 1);
assert(f(1, 2, 'a') == 'a' && g(1, 2, 'a') == 1 && h(1, 2, 'a') == 1);
assert(f(1, 2, 'a') != nil, "");
assert(f(1, 2, 'a') == 'a' && g(1, 2, 'a') == 1 && h(1, 2, 'a') == 1);
assert(f(1, 2, nil, 1, 'x') == 'x' && g(1, 2, nil, 1, 'x') == 1 && h(1, 2, nil, 1, 'x') == 1);
assert(f(1, 2, nil, nil, 'x') == nil && g(1, 2, nil, nil, 'x') == 0 && h(1, 2, nil, nil, 'x') == 0);
assert(f(1, 2, nil, 1, nil) == nil && g(1, 2, nil, 1, nil) == 0 && h(1, 2, nil, 1, nil) == 0);
assert(1 && 2 < 3 == true && 2 < 3 && 'a' < 'b' == true);
x = 2 < 3 && !3
assert(x == false);
x = 2 < 1 || (2 > 1 && 'a')
assert(x == 'a');
{
    local a
    if nil {
        a = 1
    } else {
        a = 2
    }
    assert(a == 2);
}
global fn F(a) {
    assert(debug.getinfo(1, "n").name == 'F');
    return a, 2, 3
}
a, b = F(1) != nil
assert(a == true && b == nil);
a, b = F(nil) == nil
assert(a == true && b == nil);
_ENV.GLOB1 = math.floor(os.time()) % 2
local basiccases = {
    {
        "nil", 
        nil
    }, 
    {
        "false", 
        false
    }, 
    {
        "true", 
        true
    }, 
    {
        "10", 
        10
    }, 
    {
        "(0==_ENV.GLOB1)", 
        0 == _ENV.GLOB1
    }
}
print('testing short-circuit optimizations (' .. _ENV.GLOB1 .. ')');
local binops = {
    {
        " and ", 
        fn (a, b) {
            if !a {
                return a
            } else {
                return b
            }
        }
    }, 
    {
        " or ", 
        fn (a, b) {
            if a {
                return a
            } else {
                return b
            }
        }
    }
}
local cases = {}
local fn createcases(n) {
    local res = {}
    for i = 1, n - 1 {
        for _, v1 with ipairs(cases[(i)]) {
            for _, v2 with ipairs(cases[(n - i)]) {
                for _, op with ipairs(binops) {
                    local t = {
                        "(" .. v1[(1)] .. op[(1)] .. v2[(1)] .. ")", 
                        op[(2)](v1[(2)], v2[(2)])
                    }
                    res[(#res + 1)] = t
                    res[(#res + 1)] = {
                        "not" .. t[(1)], 
                        !t[(2)]
                    }
                }
            }
        }
    }
    return res
}
local level = _soft && 3 || 4
cases[(1)] = basiccases
for i = 2, level {
    cases[(i)] = createcases(i)
}
print("+");
local prog = `if %s then IX = true end; return %s`
local i = 0
for n = 1, level {
    for _, v with pairs(cases[(n)]) {
        local s = v[(1)]
        local p = load(string.format(prog, s, s), "")
        IX = false
        assert(p() == v[(2)] && IX == !!v[(2)]);
        i = i + 1
        if i % 60000 == 0 {
            print('+');
        }
    }
}
checkload("for x do", "expected");
checkload("x:call", "expected");
if !_soft {
    local s = string.rep("a = a + 1\n", 2 ^ 18)
    s = "while true do " .. s .. "end"
    checkload(s, "too long");
}
print('OK');