---
source: src/main.rs
expression: compiled
input_file: test-data/lua5.3-tests/calls.lua
---
print("testing functions and calls");
local debug = require("debug")
assert(type(1 < 2) == 'boolean');
assert(type(true) == 'boolean' && type(false) == 'boolean');
assert(type(nil) == 'nil' && type(-3) == 'number' && type('x') == 'string' && type({}) == 'table' && type(type) == 'function');
assert(type(assert) == type(print));
global fn f(x) {
return a::x(x)
}
assert(type(f) == 'function');
assert(!pcall(type));
{
local tostring = _ENV.tostring
_ENV.tostring = nil
local st, msg = pcall(print, 1)
assert(st == false && string.find(msg, "attempt to call a nil value"));
_ENV.tostring = fn () {
return {}
}
local st, msg = pcall(print, 1)
assert(st == false && string.find(msg, "must return a string"));
_ENV.tostring = tostring
}
fact = false
{
local res = 1
local fn fact(n) {
if n == 0 {
return res
} else {
return n * fact(n - 1)
}
}
assert(fact(5) == 120);
}
assert(fact == false);
a = {
i = 10
}
self = 20
method a::x(x) {
return x + self.i
}
method a.y(x) {
return x + self
}
assert(a::x(1) + 10 == a.y(1));
a.t = {
i = -100
}
a[("t")].x = fn (self, a, b) {
return self.i + a + b
}
assert(a.t::x(2, 3) == -95);
{
local a = {
x = 0
}
method a::add(x) {
self.x, a.y = self.x + x, 20
return self
}
assert(a::add(10)::add(20)::add(30).x == 60 && a.y == 20);
}
local a = {
b = {
c = {}
}
}
method a.b.c.f1(x) {
return x + 1
}
method a.b.c::f2(x, y) {
self[(x)] = y
}
assert(a.b.c.f1(4) == 5);
a.b.c::f2('k', 12);
assert(a.b.c.k == 12);
print('+');
t = nil
global fn f(a, b, c) {
local d = 'a'
t = {
a,
b,
c,
d
}
}
f(1, 2);
assert(t[(1)] == 1 && t[(2)] == 2 && t[(3)] == nil && t[(4)] == 'a');
f(1, 2, 3, 4);
assert(t[(1)] == 1 && t[(2)] == 2 && t[(3)] == 3 && t[(4)] == 'a');
global fn fat(x) {
if x <= 1 {
return 1
} else {
return x * load("return fat(" .. x - 1 .. ")", "")()
}
}
assert(load("load 'assert(fat(6)==720)' () "))();
a = load('return fat(5), 3')
a, b = a()
assert(a == 120 && b == 3);
print('+');
global fn err_on_n(n) {
if n == 0 {
error();
exit(1);
} else {
err_on_n(n - 1);
exit(1);
}
}
{
global fn dummy(n) {
if n > 0 {
assert(!pcall(err_on_n, n));
dummy(n - 1);
}
}
}
dummy(10);
global fn deep(n) {
if n > 0 {
deep(n - 1);
}
}
deep(10);
deep(200);
global fn deep(n) {
if n > 0 {
return deep(n - 1)
} else {
return 101
}
}
assert(deep(30000) == 101);
a = {}
method a::deep(n) {
if n > 0 {
return self::deep(n - 1)
} else {
return 101
}
}
assert(a::deep(30000) == 101);
print('+');
a = nil(fn (x) {
a = x
})(23)
assert(a == 23 && (fn (x) {
return x * 2
})(20) == 40);
Z = fn (le) {
local fn a(f) {
return le(fn (x) {
return f(f)(x)
})
}
return a(a)
}
F = fn (f) {
return fn (n) {
if n == 0 {
return 1
} else {
return n * f(n - 1)
}
}
}
fat = Z(F)
assert(fat(0) == 1 && fat(4) == 24 && Z(F)(5) == 5 * Z(F)(4));
local fn g(z) {
local fn f(a, b, c, d) {
return fn (x, y) {
return a + b + c + d + a + x + y + z
}
}
return f(z, z + 1, z + 2, z + 3)
}
f = g(10)
assert(f(9, 16) == 10 + 11 + 12 + 13 + 10 + 9 + 16 + 10);
Z, F, f = nil
print('+');
global fn unlpack(t, i) {
i = i || 1
if (i <= #t) {
return t[(i)], unlpack(t, i + 1)
}
}
global fn equaltab(t1, t2) {
assert(#t1 == #t2);
for i = 1, #t1 {
assert(t1[(i)] == t2[(i)]);
}
}
local pack = fn (...) {
return (table.pack(...))
}
global fn f() {
return 1, 2, 30, 4
}
global fn ret2(a, b) {
return a, b
}
local a, b, c, d = unlpack({
1,
2,
3
})
assert(a == 1 && b == 2 && c == 3 && d == nil);
a = {
1,
2,
3,
4,
false,
10,
'alo',
false,
assert
}
equaltab(pack(unlpack(a)), a);
equaltab(pack(unlpack(a), -1), {
1,
-1
});
a, b, c, d = ret2(f()), ret2(f())
assert(a == 1 && b == 1 && c == 2 && d == nil);
a, b, c, d = unlpack(pack(ret2(f()), ret2(f())))
assert(a == 1 && b == 1 && c == 2 && d == nil);
a, b, c, d = unlpack(pack(ret2(f()), (ret2(f()))))
assert(a == 1 && b == 1 && c == nil && d == nil);
a = ret2({
unlpack({
1,
2,
3
}),
unlpack({
3,
2,
1
}),
unlpack({
"a",
"b"
})
})
assert(a[(1)] == 1 && a[(2)] == 3 && a[(3)] == "a" && a[(4)] == "b");
rawget({}, "x", 1);
rawset({}, "x", 1, 2);
assert(math.sin(1, 2) == math.sin(1));
table.sort({
10,
9,
8,
4,
19,
23,
0,
0
}, fn (a, b) {
return a < b
}, "extra arg");
local x = "-- a comment\0\0\0\n x = 10 + \n23; \
local a = function () x = 'hi' end; \
return '\0'"
global fn read1(x) {
local i = 0
return fn () {
collectgarbage();
i = i + 1
return string.sub(x, i, i)
}
}
global fn cannotload(msg, a, b) {
assert(!a && string.find(b, msg));
}
a = assert(load(read1(x), "modname", "t", _G))
assert(a() == "\0" && _G.x == 33);
assert(debug.getinfo(a).source == "modname");
cannotload("attempt to load a text chunk", load(read1(x), "modname", "b", {}));
cannotload("attempt to load a text chunk", load(x, "modname", "b"));
a = assert(load(fn () {
return nil
}))
a();
assert(!load(fn () {
return true
}));
local t = {
nil,
"return ",
"3"
}
f, msg = load(fn () {
return table.remove(t, 1)
})
assert(f() == nil);
f = load(string.dump(fn () {
return 1
}), nil, "b", {})
assert(type(f) == "function" && f() == 1);
x = string.dump(load("x = 1; return x"))
a = assert(load(read1(x), nil, "b"))
assert(a() == 1 && _G.x == 1);
cannotload("attempt to load a binary chunk", load(read1(x), nil, "t"));
cannotload("attempt to load a binary chunk", load(x, nil, "t"));
assert(!pcall(string.dump, print));
cannotload("unexpected symbol", load(read1("*a = 123")));
cannotload("unexpected symbol", load("*a = 123"));
cannotload("hhi", load(fn () {
error("hhi");
}));
assert(load("return _ENV", nil, nil, 123)() == 123);
local x
XX = 123
local fn h() {
local y = x
return XX
}
local d = string.dump(h)
x = load(d, "", "b")
assert(debug.getupvalue(x, 2) == '_ENV');
debug.setupvalue(x, 2, _G);
assert(x() == 123);
assert(assert(load("return XX + ...", nil, nil, {
XX = 13
}))(4) == 17);
x = `
return function (x)
return function (y)
return function (z)
return x+y+z
end
end
end
`
a = assert(load(read1(x)))
assert(a()(2)(3)(10) == 15);
local a, b = 20, 30
x = load(string.dump(fn (x) {
if x == "set" {
a = 10 + b
b = b + 1
} else {
return a
}
}), "", "b", nil)
assert(x() == nil);
assert(debug.setupvalue(x, 1, "hi") == "a");
assert(x() == "hi");
assert(debug.setupvalue(x, 2, 13) == "b");
assert(!debug.setupvalue(x, 3, 10));
x("set");
assert(x() == 23);
x("set");
assert(x() == 24);
{
local nup = 200
local prog = {
"local a1"
}
for i = 2, nup {
prog[(#prog + 1)] = ", a" .. i
}
prog[(#prog + 1)] = " = 1"
for i = 2, nup {
prog[(#prog + 1)] = ", " .. i
}
local sum = 1
prog[(#prog + 1)] = "; return function () return a1"
for i = 2, nup {
prog[(#prog + 1)] = " + a" .. i
sum = sum + i
}
prog[(#prog + 1)] = " end"
prog = table.concat(prog)
local f = assert(load(prog))()
assert(f() == sum);
f = load(string.dump(f))
local a = 10
local h = fn () {
return a
}
for i = 1, nup {
debug.upvaluejoin(f, i, h, 1);
}
assert(f() == 10 * nup);
}
{
local t = {
x = 1
}
method t::_012345678901234567890123456789012345678901234567890123456789() {
return self.x
}
assert(t::_012345678901234567890123456789012345678901234567890123456789() == 1);
}
assert((fn () {
return nil
})(4) == nil);
assert((fn () {
local a
return a
})(4) == nil);
assert((fn (a) {
return a
})() == nil);
print("testing binary chunks");
{
local header = string.pack("c4BBc6BBBBBj", "\27Lua", 5 * 16 + 3, 0, "\x19\x93\r\n\x1a\n", string.packsize("i"), string.packsize("T"), 4, string.packsize("j"), string.packsize("n"), 0x5678)
local c = string.dump(fn () {
local a = 1
local b = 3
return a + b * 3
})
assert(string.sub(c, 1, #header) == header);
for i = 1, #header {
local s = string.sub(c, 1, i - 1) .. string.char(string.byte(string.sub(c, i, i)) + 1) .. string.sub(c, i + 1, -1)
assert(#s == #c);
assert(!load(s));
}
for i = 1, #c - 1 {
local st, msg = load(string.sub(c, 1, i))
assert(!st && string.find(msg, "truncated"));
}
assert(assert(load(c))() == 10);
}
print('OK');
return deep