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/constructs.lua
---
print("testing syntax");
local debug = require("debug")
{
    
}
{
    a = 3
    assert(a == 3);
}
assert(2 ^ 3 ^ 2 == 2 ^ (3 ^ 2));
assert(2 ^ 3 * 4 == (2 ^ 3) * 4);
assert(2 ^ -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(2 * 1 + 3 / 3 == 3 && 1 + 2 .. 3 * 1 == "33");
assert(!(2 + 1 > 3 * 1) && "a" .. "b" > "a");
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);
global fn ID(x) {
    return x
}
global fn f(t, i) {
    local b = t.n
    local res = math.fmod(math.floor(i / c), b) + 1
    c = c * b
    return t[(res)]
}
local arg = {
    " ( 1 < 2 ) ", 
    " ( 1 >= 2 ) ", 
    " F ( ) ", 
    "  nil ", 
    n = 4
}
local op = {
    " and ", 
    " or ", 
    " == ", 
    " ~= ", 
    n = 4
}
local neg = {
    " ", 
    " not ", 
    n = 2
}
local i = 0
loop  {
    c = 1
    local s = f(neg, i) .. 'ID(' .. f(neg, i) .. f(arg, i) .. f(op, i) .. f(neg, i) .. 'ID(' .. f(arg, i) .. f(op, i) .. f(neg, i) .. f(arg, i) .. '))'
    local s1 = string.gsub(s, 'ID', '')
    K, X, NX, WX1, WX2 = nil
    s = string.format(`
      local a = %s
      local b = not %s
      K = b
      local xxx; 
      if %s then X = a  else X = b end
      if %s then NX = b  else NX = a end
      while %s do WX1 = a; break end
      while %s do WX2 = a; break end
      repeat if (%s) then break end; assert(b)  until not(%s)
  `, s1, s, s1, s, s1, s, s1, s, s)
    assert(load(s))();
    assert(X && !NX && !WX1 == K && !WX2 == K);
    if math.fmod(i, 4000) == 0 {
        print('+');
    }
    i = i + 1
} until i == c
print('+');
print('testing short-circuit optimizations');
_ENV.GLOB1 = 1
_ENV.GLOB2 = 2
local basiccases = {
    {
        "nil", 
        nil
    }, 
    {
        "false", 
        false
    }, 
    {
        "true", 
        true
    }, 
    {
        "10", 
        10
    }, 
    {
        "(_ENV.GLOB1 < _ENV.GLOB2)", 
        true
    }, 
    {
        "(_ENV.GLOB2 < _ENV.GLOB1)", 
        false
    }
}
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 mem = {
    basiccases
}
local fn allcases(n) {
    if mem[(n)] {
        return mem[(n)]
    }
    local res = {}
    for _, v with ipairs(allcases(n - 1)) {
        res[(#res + 1)] = v
    }
    for i = 1, n - 1 {
        for _, v1 with ipairs(allcases(i)) {
            for _, v2 with ipairs(allcases(n - i)) {
                for _, op with ipairs(binops) {
                    res[(#res + 1)] = {
                        "(" .. v1[(1)] .. op[(1)] .. v2[(1)] .. ")", 
                        op[(2)](v1[(2)], v2[(2)])
                    }
                }
            }
        }
        print('+');
    }
    mem[(n)] = res
    return res
}
local level = _soft && 3 || 4
for _, v with pairs(allcases(level)) {
    local res = load("return " .. v[(1)])()
    assert(res == v[(2)]);
}
print('OK');