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.4-tests/main.lua
---
if _port {
    return
}
print("testing stand-alone interpreter");
assert(os.execute());
local arg = arg || ARG
local prog = os.tmpname()
local otherprog = os.tmpname()
local out = os.tmpname()
local progname
{
    local i = 0
    while arg[(i)] {
        i = i - 1
    }
    progname = arg[(i + 1)]
}
print("progname: " .. progname);
local prepfile = fn (s, p) {
    p = p || prog
    io.output(p);
    io.write(s);
    assert(io.close());
}
local fn getoutput() {
    io.input(out);
    local t = io.read("a")
    io.input()::close();
    assert(os.remove(out));
    return t
}
local fn checkprogout(s) {
    assert(string.sub(s, -1) == "\n");
    local t = getoutput()
    for line with string.gmatch(s, ".-\n") {
        assert(string.find(t, line, 1, true));
    }
}
local fn checkout(s) {
    local t = getoutput()
    if s != t {
        print(string.format("'%s' - '%s'\n", s, t));
    }
    assert(s == t);
    return t
}
local fn RUN(p, ...) {
    p = string.gsub(p, "lua", '"' .. progname .. '"', 1)
    local s = string.format(p, ...)
    assert(os.execute(s));
}
local fn NoRun(msg, p, ...) {
    p = string.gsub(p, "lua", '"' .. progname .. '"', 1)
    local s = string.format(p, ...)
    s = string.format("%s 2> %s", s, out)
    assert(!os.execute(s));
    assert(string.find(getoutput(), msg, 1, true));
}
RUN('lua -v');
print(string.format("(temporary program file used in these tests: %s)", prog));
prepfile("");
RUN('lua - < %s > %s', prog, out);
checkout("");
prepfile([[
  print(
1, a
)
]]);
RUN('lua - < %s > %s', prog, out);
checkout("1\tnil\n");
RUN('echo "print(10)\nprint(2)\n" | lua > %s', out);
checkout("10\n2\n");
RUN('echo "print(arg[1])" | lua - -h > %s', out);
checkout("-h\n");
prepfile("print(package.path)");
RUN('env LUA_INIT= LUA_PATH=x lua %s > %s', prog, out);
checkout("x\n");
RUN('env LUA_INIT= LUA_PATH_5_4=y LUA_PATH=x lua %s > %s', prog, out);
checkout("y\n");
prepfile("print(package.cpath)");
RUN('env LUA_INIT= LUA_CPATH=xuxu lua %s > %s', prog, out);
checkout("xuxu\n");
RUN('env LUA_INIT= LUA_CPATH_5_4=yacc LUA_CPATH=x lua %s > %s', prog, out);
checkout("yacc\n");
prepfile("print(X)");
RUN('env LUA_INIT="X=tonumber(arg[1])" lua %s 3.2 > %s', prog, out);
checkout("3.2\n");
prepfile("print(X)");
RUN('env LUA_INIT_5_4="X=10" LUA_INIT="X=3" lua %s > %s', prog, out);
checkout("10\n");
prepfile("x = x or 10; print(x); x = x + 1");
RUN('env LUA_INIT="@%s" lua %s > %s', prog, prog, out);
checkout("10\n11\n");
NoRun('LUA_INIT:1: msg', 'env LUA_INIT="error(\'msg\')" lua');
local defaultpath, defaultCpath
{
    prepfile("print(package.path, package.cpath)");
    RUN('env LUA_INIT="error(10)" LUA_PATH=xxx LUA_CPATH=xxx lua -E %s > %s', prog, out);
    local output = getoutput()
    defaultpath = string.match(output, "^(.-)\t")
    defaultCpath = string.match(output, "\t(.-)$")
    RUN('env -i lua %s > %s', prog, out);
    local out = getoutput()
    assert(defaultpath == string.match(output, "^(.-)\t"));
    assert(defaultCpath == string.match(output, "\t(.-)$"));
}
assert(!string.find(defaultpath, "xxx") && string.find(defaultpath, "lua") && !string.find(defaultCpath, "xxx") && string.find(defaultCpath, "lua"));
local fn convert(p) {
    prepfile("print(package.path)");
    RUN('env LUA_PATH="%s" lua %s > %s', p, prog, out);
    local expected = getoutput()
    expected = string.sub(expected, 1, -2)
    if string.find(p, ";;") {
        p = string.gsub(p, ";;", ";" .. defaultpath .. ";")
        p = string.gsub(p, "^;", "")
        p = string.gsub(p, ";$", "")
    }
    assert(p == expected);
}
convert(";");
convert(";;");
convert("a;;b");
convert(";;b");
convert("a;;");
convert("a;b;;c");
prepfile("print(1); a=2; return {x=15}");
prepfile(("print(a); print(_G['%s'].x)")::format(prog), otherprog);
RUN('env LUA_PATH="?;;" lua -l %s -l%s -lstring -l io %s > %s', prog, otherprog, otherprog, out);
checkout("1\n2\n15\n2\n15\n");
prepfile("print(str.upper'alo alo', m.max(10, 20))");
RUN("lua -l 'str=string' '-lm=math' -e 'print(m.sin(0))' %s > %s", prog, out);
checkout("0.0\nALO ALO\t20\n");
local a = `
  assert(#arg == 3 and arg[1] == 'a' and
         arg[2] == 'b' and arg[3] == 'c')
  assert(arg[-1] == '--' and arg[-2] == "-e " and arg[-3] == '%s')
  assert(arg[4] == undef and arg[-4] == undef)
  local a, b, c = ...
  assert(... == 'a' and a == 'a' and b == 'b' and c == 'c')
`
a = string.format(a, progname)
prepfile(a);
RUN('lua "-e " -- %s a b c', prog);
prepfile("assert(arg)");
prepfile("assert(arg)", otherprog);
RUN('env LUA_PATH="?;;" lua -l%s - < %s', prog, otherprog);
RUN('echo "print(...)" | lua -e "arg[1] = 100" - > %s', out);
checkout("100\n");
NoRun("'arg' is not a table", 'echo "" | lua -e "arg = 1" -');
RUN('echo 10 | lua -e "print=nil" -i > /dev/null 2> %s', out);
assert(string.find(getoutput(), "error calling 'print'"));
RUN('echo "io.stderr:write(1000)\ncont" | lua -e "require\'debug\'.debug()" 2> %s', out);
checkout("lua_debug> 1000lua_debug> ");
print("testing warnings");
RUN('echo "io.stderr:write(1); warn[[XXX]]" | lua 2> %s', out);
checkout("1");
prepfile([[
warn("@allow")               -- unknown control, ignored
warn("@off", "XXX", "@off")  -- these are not control messages
warn("@off")                 -- this one is
warn("@on", "YYY", "@on")    -- not control, but warn is off
warn("@off")                 -- keep it off
warn("@on")                  -- restart warnings
warn("", "@on")              -- again, no control, real warning
warn("@on")                  -- keep it "started"
warn("Z", "Z", "Z")          -- common warning
]]);
RUN('lua -W %s 2> %s', prog, out);
checkout([[
Lua warning: @offXXX@off
Lua warning: @on
Lua warning: ZZZ
]]);
prepfile([[
warn("@allow")
-- create two objects to be finalized when closing state
-- the errors in the finalizers must generate warnings
u1 = setmetatable({}, {__gc = function () error("XYZ") end})
u2 = setmetatable({}, {__gc = function () error("ZYX") end})
]]);
RUN('lua -W %s 2> %s', prog, out);
checkprogout("ZYX)\nXYZ)\n");
prepfile([[
-- should be called last
print("creating 1")
setmetatable({}, {__gc = function () print(1) end})

print("creating 2")
setmetatable({}, {__gc = function ()
  print("2")
  print("creating 3")
  -- this finalizer should not be called, as object will be
  -- created after 'lua_close' has been called
  setmetatable({}, {__gc = function () print(3) end})
  print(collectgarbage())    -- cannot call collector here
  os.exit(0, true)
end})
]]);
RUN('lua -W %s > %s', prog, out);
checkout([[
creating 1
creating 2
2
creating 3
nil
1
]]);
prepfile([[print(({...})[30])]]);
RUN('lua %s %s > %s', prog, string.rep(" a", 30), out);
checkout("a\n");
RUN(`lua "-eprint(1)" -ea=3 -e "print(a)" > %s`, out);
checkout("1\n3\n");
prepfile([[
(6*2-6) -- ===
a =
10
print(a)
a]]);
RUN(`lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s`, prog, out);
checkprogout("6\n10\n10\n\n");
prepfile("a = [[b\nc\nd\ne]]\n=a");
RUN(`lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s`, prog, out);
checkprogout("b\nc\nd\ne\n\n");
prompt = "alo"
prepfile([[ --
a = 2
]]);
RUN(`lua "-e_PROMPT='%s'" -i < %s > %s`, prompt, prog, out);
local t = getoutput()
assert(string.find(t, prompt .. ".*" .. prompt .. ".*" .. prompt));
prepfile([[ --
a = 2
]]);
RUN(`lua -i < %s > %s`, prog, out);
local t = getoutput()
prompt = "> "
assert(string.find(t, prompt .. ".*" .. prompt .. ".*" .. prompt));
prompt = "local C = 0;\z
   _PROMPT=setmetatable({},{__tostring = function () \z
     C = C + 1; return C end})"
prepfile([[ --
a = 2
]]);
RUN(`lua -e "%s" -i < %s > %s`, prompt, prog, out);
local t = getoutput()
assert(string.find(t, `
1 --
2a = 2
3
`, 1, true));
prepfile([[
debug = require "debug"
m = {x=0}
setmetatable(m, {__tostring = function(x)
  return tostring(debug.getinfo(4).currentline + x.x)
end})
error(m)
]]);
NoRun(progname .. ": 6\n", `lua %s`, prog);
prepfile("error{}");
NoRun("error object is a table value", `lua %s`, prog);
s = ` --
function f ( x )
  local a = [[
xuxu
]]
  local b = "\
xuxu\n"
  if x == 11 then return 1 + 12 , 2 + 20 end  --[[ test multiple returns ]]
  return x + 1
  --\\
end
return( f( 100 ) )
assert( a == b )
do return f( 11 ) end  `
s = string.gsub(s, ' ', '\n\n')
prepfile(s);
RUN(`lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s`, prog, out);
checkprogout("101\n13\t22\n\n");
prepfile([[#comment in 1st line without \n at the end]]);
RUN('lua %s', prog);
prepfile([[#test line number when file starts with comment line
debug = require"debug"
print(debug.getinfo(1).currentline)
]]);
RUN('lua %s > %s', prog, out);
checkprogout('3\n');
prepfile(string.format(`io.output(%q); io.write('alo')`, out));
RUN('lua %s', prog);
checkout('alo');
RUN(`lua -v  -e"print'hello'" > %s`, out);
t = getoutput()
assert(string.find(t, "PUC%-Rio\nhello"));
prepfile("os.exit(nil, true)");
RUN('lua %s', prog);
prepfile("os.exit(0, true)");
RUN('lua %s', prog);
prepfile("os.exit(true, true)");
RUN('lua %s', prog);
prepfile("os.exit(1, true)");
NoRun("", "lua %s", prog);
prepfile("os.exit(false, true)");
NoRun("", "lua %s", prog);
prepfile([[
  local x <close> = setmetatable({},
        {__close = function (self, err)
                     assert(err == nil)
                     print("Ok")
                   end})
  local e1 <close> = setmetatable({}, {__close = function () print(120) end})
  os.exit(true, true)
]]);
RUN('lua %s > %s', prog, out);
checkprogout("120\nOk\n");
assert(os.remove(prog));
assert(os.remove(otherprog));
assert(!os.remove(out));
NoRun("unrecognized option '-h'", "lua -h");
NoRun("unrecognized option '---'", "lua ---");
NoRun("unrecognized option '-Ex'", "lua -Ex");
NoRun("unrecognized option '-vv'", "lua -vv");
NoRun("unrecognized option '-iv'", "lua -iv");
NoRun("'-e' needs argument", "lua -e");
NoRun("syntax error", "lua -e a");
NoRun("'-l' needs argument", "lua -l");
if T {
    print("testing 'not enough memory' to create a state");
    NoRun("not enough memory", "env MEMLIMIT=100 lua");
    warn("@store");
    warn("@123", "456", "789");
    assert(_WARN == "@123456789");
    _WARN = false
    warn("zip", "", " ", "zap");
    assert(_WARN == "zip zap");
    _WARN = false
    warn("ZIP", "", " ", "ZAP");
    assert(_WARN == "ZIP ZAP");
    _WARN = false
    warn("@normal");
}
{
    local st, msg = pcall(warn)
    assert(string.find(msg, "string expected"));
    st, msg = pcall(warn, "SHOULD NOT APPEAR", {})
    assert(string.find(msg, "string expected"));
}
print('+');
print('testing Ctrl C');
{
    local fn kill(pid) {
        return os.execute(string.format('kill -INT %s 2> /dev/null', pid))
    }
    local fn runback(luaprg) {
        local shellprg = string.format('%s -e "%s" & echo $!', progname, luaprg)
        local f = io.popen(shellprg, "r")
        local pid = f::read()
        print("(if test fails now, it may leave a Lua script running in \z
            background, pid " .. pid .. ")");
        return f, pid
    }
    local f, pid = runback([[
    pcall(function () print(12); while true do end end); print(42)]])
    assert(f::read() == "12");
    kill(pid);
    assert(f::read() == "42");
    assert(f::close());
    print("done");
    local f, pid = runback([[
    print(15); string.find(string.rep('a', 100000), '.*b')]])
    assert(f::read() == "15");
    assert(os.execute("sleep 1"));
    local n = 100
    for i = 0, 100 {
        if !kill(pid) {
            n = i
            break
        }
    }
    assert(f::close());
    assert(n >= 2);
    print(string.format("done (with %d kills)", n));
}
print("OK");