---
source: src/main.rs
expression: compiled
input_file: test-data/lua5.1-tests/db.lua
---
local fn dostring(s) {
return assert(loadstring(s))()
}
print("testing debug library and debug information");
{
local a = 1
}
global fn test(s, l, p) {
collectgarbage();
local fn f(event, line) {
assert(event == 'line');
local l = table.remove(l, 1)
if p {
print(l, line);
}
assert(l == line, "wrong trace!!");
}
debug.sethook(f, "l");
loadstring(s)();
debug.sethook();
assert(table.getn(l) == 0);
}
{
local a = debug.getinfo(print)
assert(a.what == "C" && a.short_src == "[C]");
local b = debug.getinfo(test, "SfL")
assert(b.name == nil && b.what == "Lua" && b.linedefined == 11 && b.lastlinedefined == b.linedefined + 10 && b.func == test && !string.find(b.short_src, "%["));
assert(b.activelines[(b.linedefined + 1)] && b.activelines[(b.lastlinedefined)]);
assert(!b.activelines[(b.linedefined)] && !b.activelines[(b.lastlinedefined + 1)]);
}
a = "function f () end"
local fn dostring(s, x) {
return loadstring(s, x)()
}
dostring(a);
assert(debug.getinfo(f).short_src == string.format('[string "%s"]', a));
dostring(a .. string.format("; %s\n=1", string.rep('p', 400)));
assert(string.find(debug.getinfo(f).short_src, '^%[string [^\n]*%.%.%."%]$'));
dostring("\n" .. a);
assert(debug.getinfo(f).short_src == '[string "..."]');
dostring(a, "");
assert(debug.getinfo(f).short_src == '[string ""]');
dostring(a, "@xuxu");
assert(debug.getinfo(f).short_src == "xuxu");
dostring(a, "@" .. string.rep('p', 1000) .. 't');
assert(string.find(debug.getinfo(f).short_src, "^%.%.%.p*t$"));
dostring(a, "=xuxu");
assert(debug.getinfo(f).short_src == "xuxu");
dostring(a, string.format("=%s", string.rep('x', 500)));
assert(string.find(debug.getinfo(f).short_src, "^x*"));
dostring(a, "=");
assert(debug.getinfo(f).short_src == "");
a = nil
f = nil
loop {
local g = {
x = fn () {
local a = debug.getinfo(2)
assert(a.name == 'f' && a.namewhat == 'local');
a = debug.getinfo(1)
assert(a.name == 'x' && a.namewhat == 'field');
return 'xixi'
}
}
local f = fn () {
return 1 + 1 && (!1 || g.x())
}
assert(f() == 'xixi');
g = debug.getinfo(f)
assert(g.what == "Lua" && g.func == f && g.namewhat == "" && !g.name);
global fn f(x, name) {
name = name || 'f'
local a = debug.getinfo(1)
assert(a.name == name && a.namewhat == 'local');
return x
}
if 3 > 4 {
break
}
f();
if 3 < 4 {
a = 1
} else {
break
}
f();
while 1 {
local x = 10
break
}
f();
local b = 1
if 3 > 4 {
return math.sin(1)
}
f();
a = 3 < 4
f();
a = 3 < 4 || 1
f();
loop {
local x = 20
if 4 > 3 {
f();
} else {
break
}
f();
} until 1
g = {}
f(g).x = f(2) && f(10) + f(9)
assert(g.x == f(19));
global fn g(x) {
if !x {
return 3
}
return (x('a', 'x'))
}
assert(g(f) == 'a');
} until 1
test(`if
math.sin(1)
then
a=1
else
a=2
end
`, {
2,
4,
7
});
test(`--
if nil then
a=1
else
a=2
end
`, {
2,
5,
6
});
test(`a=1
repeat
a=a+1
until a==3
`, {
1,
3,
4,
3,
4
});
test(` do
return
end
`, {
2
});
test(`local a
a=1
while a<=3 do
a=a+1
end
`, {
2,
3,
4,
3,
4,
3,
4,
3,
5
});
test(`while math.sin(1) do
if math.sin(1)
then
break
end
end
a=1`, {
1,
2,
4,
7
});
test(`for i=1,3 do
a=i
end
`, {
1,
2,
1,
2,
1,
2,
1,
3
});
test(`for i,v in pairs{'a','b'} do
a=i..v
end
`, {
1,
2,
1,
2,
1,
3
});
test(`for i=1,4 do a=1 end`, {
1,
1,
1,
1,
1
});
print('+');
a = {}
L = nil
local glob = 1
local oldglob = glob
debug.sethook(fn (e, l) {
collectgarbage();
local f, m, c = debug.gethook()
assert(m == 'crl' && c == 0);
if e == "line" {
if glob != oldglob {
L = l - 1
oldglob = glob
}
} elseif if e == "call" {
local f = debug.getinfo(2, "f").func
a[(f)] = 1
} else {
assert(e == "return");
}
}, "crl");
global fn f(a, b) {
collectgarbage();
local _, x = debug.getlocal(1, 1)
local _, y = debug.getlocal(1, 2)
assert(x == a && y == b);
assert(debug.setlocal(2, 3, "pera") == "AA" .. "AA");
assert(debug.setlocal(2, 4, "ma��") == "B");
x = debug.getinfo(2)
assert(x.func == g && x.what == "Lua" && x.name == 'g' && x.nups == 0 && string.find(x.source, "^@.*db%.lua"));
glob = glob + 1
assert(debug.getinfo(1, "l").currentline == L + 1);
assert(debug.getinfo(1, "l").currentline == L + 2);
}
global fn foo() {
glob = glob + 1
assert(debug.getinfo(1, "l").currentline == L + 1);
}
foo();
_ = 'alo\
alo' .. `
`
assert(debug.getinfo(1, "l").currentline == L + 11);
global fn g(...) {
{
local a, b, c
a = math.sin(40)
}
local feijao
local AAAA, B = "xuxu", "mam�o"
f(AAAA, B);
assert(AAAA == "pera" && B == "ma��");
{
local B = 13
local x, y = debug.getlocal(1, 5)
assert(x == 'B' && y == 13);
}
}
g();
assert(a[(f)] && a[(g)] && a[(assert)] && a[(debug.getlocal)] && !a[(print)]);
local n, v = debug.getlocal(0, 1)
assert(v == 0 && n == "(*temporary)");
local n, v = debug.getlocal(0, 2)
assert(v == 2 && n == "(*temporary)");
assert(!debug.getlocal(0, 3));
assert(!debug.getlocal(0, 0));
global fn f() {
assert(select(2, debug.getlocal(2, 3)) == 1);
assert(!debug.getlocal(2, 4));
debug.setlocal(2, 3, 10);
return 20
}
global fn g(a, b) {
return (a + 1) + f()
}
assert(g(0, 0) == 30);
debug.sethook(nil);
assert(debug.gethook() == nil);
X = nil
a = {}
method a::f(a, b, ...) {
local c = 13
}
debug.sethook(fn (e) {
assert(e == "call");
dostring("XX = 12");
assert(!pcall(loadstring("a='joao'+1")));
debug.sethook(fn (e, l) {
assert(debug.getinfo(2, "l").currentline == l);
local f, m, c = debug.gethook()
assert(e == "line");
assert(m == 'l' && c == 0);
debug.sethook(nil);
assert(!X);
X = {}
local i = 1
local x, y
while 1 {
x, y = debug.getlocal(2, i)
if x == nil {
break
}
X[(x)] = y
i = i + 1
}
}, "l");
}, "c");
a::f(1, 2, 3, 4, 5);
assert(X.self == a && X.a == 1 && X.b == 2 && X.arg.n == 3 && X.c == nil);
assert(XX == 12);
assert(debug.gethook() == nil);
local fn getupvalues(f) {
local t = {}
local i = 1
while true {
local name, value = debug.getupvalue(f, i)
if !name {
break
}
assert(!t[(name)]);
t[(name)] = value
i = i + 1
}
return t
}
local a, b, c = 1, 2, 3
local fn foo1(a) {
b = a
return c
}
local fn foo2(x) {
a = x
return c + b
}
assert(debug.getupvalue(foo1, 3) == nil);
assert(debug.getupvalue(foo1, 0) == nil);
assert(debug.setupvalue(foo1, 3, "xuxu") == nil);
local t = getupvalues(foo1)
assert(t.a == nil && t.b == 2 && t.c == 3);
t = getupvalues(foo2)
assert(t.a == 1 && t.b == 2 && t.c == 3);
assert(debug.setupvalue(foo1, 1, "xuxu") == "b");
assert(({
debug.getupvalue(foo2, 3)
})[(2)] == "xuxu");
assert(debug.getupvalue(io.read, 1) == nil);
assert(debug.setupvalue(io.read, 1, 10) == nil);
local a = 0
debug.sethook(fn (e) {
a = a + 1
}, "", 1);
a = 0
for i = 1, 1000 {
}
assert(1000 < a && a < 1012);
debug.sethook(fn (e) {
a = a + 1
}, "", 4);
a = 0
for i = 1, 1000 {
}
assert(250 < a && a < 255);
local f, m, c = debug.gethook()
assert(m == "" && c == 4);
debug.sethook(fn (e) {
a = a + 1
}, "", 4000);
a = 0
for i = 1, 1000 {
}
assert(a == 0);
debug.sethook(print, "", 2 ^ 24 - 1);
local f, m, c = debug.gethook()
assert(({
debug.gethook()
})[(3)] == 2 ^ 24 - 1);
debug.sethook();
local fn f(x) {
if x {
assert(debug.getinfo(1, "S").what == "Lua");
local tail = debug.getinfo(2)
assert(!pcall(getfenv, 3));
assert(tail.what == "tail" && tail.short_src == "(tail call)" && tail.linedefined == -1 && tail.func == nil);
assert(debug.getinfo(3, "f").func == g1);
assert(getfenv(3));
assert(debug.getinfo(4, "S").what == "tail");
assert(!pcall(getfenv, 5));
assert(debug.getinfo(5, "S").what == "main");
assert(getfenv(5));
print("+");
}
}
global fn g(x) {
return f(x)
}
global fn g1(x) {
g(x);
}
local fn h(x) {
local f = g1
return f(x)
}
h(true);
local b = {}
debug.sethook(fn (e) {
table.insert(b, e);
}, "cr");
h(false);
debug.sethook();
local res = {
"return",
"call",
"call",
"call",
"call",
"return",
"tail return",
"return",
"tail return",
"call"
}
for _, k with ipairs(res) {
assert(k == table.remove(b, 1));
}
lim = 30000
local fn foo(x) {
if x == 0 {
assert(debug.getinfo(lim + 2).what == "main");
for i = 2, lim {
assert(debug.getinfo(i, "S").what == "tail");
}
} else {
return foo(x - 1)
}
}
foo(lim);
print("+");
assert(debug.traceback(print) == print);
assert(debug.traceback(print, 4) == print);
assert(string.find(debug.traceback("hi", 4), "^hi\n"));
assert(string.find(debug.traceback("hi"), "^hi\n"));
assert(!string.find(debug.traceback("hi"), "'traceback'"));
assert(string.find(debug.traceback("hi", 0), "'traceback'"));
assert(string.find(debug.traceback(), "^stack traceback:\n"));
local fn checktraceback(co, p) {
local tb = debug.traceback(co)
local i = 0
for l with string.gmatch(tb, "[^\n]+\n?") {
assert(i == 0 || string.find(l, p[(i)]));
i = i + 1
}
assert(p[(i)] == nil);
}
local fn f(n) {
if n > 0 {
return f(n - 1)
} else {
coroutine.yield();
}
}
local co = coroutine.create(f)
coroutine.resume(co, 3);
checktraceback(co, {
"yield",
"db.lua",
"tail",
"tail",
"tail"
});
co = coroutine.create(fn (x) {
local a = 1
coroutine.yield(debug.getinfo(1, "l"));
coroutine.yield(debug.getinfo(1, "l").currentline);
return a
})
local tr = {}
local foo = fn (e, l) {
table.insert(tr, l);
}
debug.sethook(co, foo, "l");
local _, l = coroutine.resume(co, 10)
local x = debug.getinfo(co, 1, "lfLS")
assert(x.currentline == l.currentline && x.activelines[(x.currentline)]);
assert(type(x.func) == "function");
for i = x.linedefined + 1, x.lastlinedefined {
assert(x.activelines[(i)]);
x.activelines[(i)] = nil
}
assert(next(x.activelines) == nil);
assert(debug.getinfo(co, 2) == nil);
local a, b = debug.getlocal(co, 1, 1)
assert(a == "x" && b == 10);
a, b = debug.getlocal(co, 1, 2)
assert(a == "a" && b == 1);
debug.setlocal(co, 1, 2, "hi");
assert(debug.gethook(co) == foo);
assert(table.getn(tr) == 2 && tr[(1)] == l.currentline - 1 && tr[(2)] == l.currentline);
a, b, c = pcall(coroutine.resume, co)
assert(a && b && c == l.currentline + 1);
checktraceback(co, {
"yield",
"in function <"
});
a, b = coroutine.resume(co)
assert(a && b == "hi");
assert(table.getn(tr) == 4 && tr[(4)] == l.currentline + 2);
assert(debug.gethook(co) == foo);
assert(debug.gethook() == nil);
checktraceback(co, {});
global fn f(i) {
if i == 0 {
error(i);
} else {
coroutine.yield();
f(i - 1);
}
}
co = coroutine.create(fn (x) {
f(x);
})
a, b = coroutine.resume(co, 3)
t = {
"'yield'",
"'f'",
"in function <"
}
while coroutine.status(co) == "suspended" {
checktraceback(co, t);
a, b = coroutine.resume(co)
table.insert(t, 2, "'f'");
}
t[(1)] = "'error'"
checktraceback(co, t);
local fn g(x) {
coroutine.yield(x);
}
local fn f(i) {
debug.sethook(fn () {
}, "l");
for j = 1, 1000 {
g(i + j);
}
}
local co = coroutine.wrap(f)
co(10);
pcall(co);
pcall(co);
assert(type(debug.getregistry()) == "table");
print("OK");