---
source: src/main.rs
expression: compiled
input_file: test-data/lua5.3-tests/nextvar.lua
---
print('testing tables, next, and for');
local fn checkerror(msg, f, ...) {
local s, err = pcall(f, ...)
assert(!s && string.find(err, msg));
}
local a = {}
for i = 1, 100 {
a[(i .. "+")] = true
}
for i = 1, 100 {
a[(i .. "+")] = nil
}
for i = 1, 100 {
a[(i)] = true
assert(#a == i);
}
local x = 0
for k, v with ipairs({
10,
20,
30,
x = 12
}) {
x = x + 1
assert(k == x && v == x * 10);
}
for _ with ipairs({
x = 12,
y = 24
}) {
assert(nil);
}
x = false
local i = 0
for k, v with ipairs({
true,
false,
true,
false
}) {
i = i + 1
x = !x
assert(x == v);
}
assert(i == 4);
assert(type(ipairs({})) == 'function' && ipairs({}) == ipairs({}));
if !T {
(Message || print)('\n >>> testC not active: skipping tests for table sizes <<<\n');
} else {
local fn log2(x) {
return math.log(x, 2)
}
local fn mp2(n) {
local mp = 2 ^ math.ceil(log2(n))
assert(n == 0 || (mp / 2 < n && n <= mp));
return mp
}
local fn fb(n) {
local r, nn = T.int2fb(n)
assert(r < 256);
return nn
}
for a = 1, 10000 {
local n = fb(a)
assert(a <= n && n <= a * 1.125);
}
local a = 1024
local lim = 2 ^ 30
while a < lim {
local n = fb(a)
assert(a <= n && n <= a * 1.125);
a = math.ceil(a * 1.3)
}
local fn check(t, na, nh) {
local a, h = T.querytab(t)
if a != na || h != nh {
print(na, nh, a, h);
assert(nil);
}
}
{
local s = 0
for _ with pairs(math) {
s = s + 1
}
check(math, 0, mp2(s));
}
local lim = 40
local s = 'return {'
for i = 1, lim {
s = s .. i .. ','
local s = s
for k = 0, lim {
local t = load(s .. '}', '')()
assert(#t == i);
check(t, fb(i), mp2(k));
s = string.format('%sa%d=%d,', s, k, k)
}
}
local a = {}
for i = 1, lim {
a[(i)] = i
}
for k = 0, lim {
local a = {
table.unpack(a, 1, k)
}
assert(#a == k);
check(a, k, 0);
a = {
1,
2,
3,
table.unpack(a, 1, k)
}
check(a, k + 3, 0);
assert(#a == k + 3);
}
local lim = 130
local a = {}
a[(2)] = 1
check(a, 0, 1);
a = {}
a[(0)] = 1
check(a, 0, 1);
a[(2)] = 1
check(a, 0, 2);
a = {}
a[(0)] = 1
a[(1)] = 1
check(a, 1, 1);
a = {}
for i = 1, lim {
a[(i)] = 1
assert(#a == i);
check(a, mp2(i), 0);
}
a = {}
for i = 1, lim {
a[('a' .. i)] = 1
assert(#a == 0);
check(a, 0, mp2(i));
}
a = {}
for i = 1, 16 {
a[(i)] = i
}
check(a, 16, 0);
{
for i = 1, 11 {
a[(i)] = nil
}
for i = 30, 50 {
a[(i)] = nil
}
check(a, 0, 8);
a[(10)] = 1
for i = 30, 50 {
a[(i)] = nil
}
check(a, 0, 8);
for i = 1, 14 {
a[(i)] = nil
}
for i = 18, 50 {
a[(i)] = nil
}
check(a, 0, 4);
}
for i = 1, lim {
local a = {}
for i = i, 1, -1 {
a[(i)] = i
}
check(a, mp2(i), 0);
}
lim = 35
global fn foo(n, ...) {
local arg = {
...
}
check(arg, n, 0);
assert(select('#', ...) == n);
arg[(n + 1)] = true
check(arg, mp2(n + 1), 0);
arg.x = true
check(arg, mp2(n + 1), 1);
}
local a = {}
for i = 1, lim {
a[(i)] = true
foo(i, table.unpack(a));
}
}
assert(#{} == 0);
assert(#{
nil
} == 0);
assert(#{
nil,
nil
} == 0);
assert(#{
nil,
nil,
nil
} == 0);
assert(#{
nil,
nil,
nil,
nil
} == 0);
print('+');
local nofind = {}
a, b, c = 1, 2, 3
a, b, c = nil
assert(next({}) == next({}));
local fn find(name) {
local n, v
while 1 {
n, v = next(_G, n)
if !n {
return nofind
}
assert(v != nil);
if n == name {
return v
}
}
}
local fn find1(name) {
for n, v with pairs(_G) {
if n == name {
return v
}
}
return nil
}
assert(print == find("print") && print == find1("print"));
assert(_G[("print")] == find("print"));
assert(assert == find1("assert"));
assert(nofind == find("return"));
assert(!find1("return"));
_G[("ret" .. "urn")] = nil
assert(nofind == find("return"));
_G[("xxx")] = 1
assert(xxx == find("xxx"));
checkerror("invalid key", next, {
10,
20
}, 3);
checkerror("bad argument", pairs);
checkerror("bad argument", ipairs);
print('+');
a = {}
for i = 0, 10000 {
if math.fmod(i, 10) != 0 {
a[('x' .. i)] = i
}
}
n = {
n = 0
}
for i, v with pairs(a) {
n.n = n.n + 1
assert(i && v && a[(i)] == v);
}
assert(n.n == 9000);
a = nil
{
local a = {}
for n, v with pairs(_G) {
a[(n)] = v
}
for n, v with pairs(a) {
if !package.loaded[(n)] && type(v) != "function" && !string.find(n, "^[%u_]") {
_G[(n)] = nil
}
collectgarbage();
}
}
local fn checknext(a) {
local b = {}
{
local k, v = next(a)
while k {
b[(k)] = v
k, v = next(a, k)
}
}
for k, v with pairs(b) {
assert(a[(k)] == v);
}
for k, v with pairs(a) {
assert(b[(k)] == v);
}
}
checknext({
1,
x = 1,
y = 2,
z = 3
});
checknext({
1,
2,
x = 1,
y = 2,
z = 3
});
checknext({
1,
2,
3,
x = 1,
y = 2,
z = 3
});
checknext({
1,
2,
3,
4,
x = 1,
y = 2,
z = 3
});
checknext({
1,
2,
3,
4,
5,
x = 1,
y = 2,
z = 3
});
assert(#{} == 0);
assert(#{
-1 = 2
} == 0);
assert(#{
1,
2,
3,
nil,
nil
} == 3);
for i = 0, 40 {
local a = {}
for j = 1, i {
a[(j)] = j
}
assert(#a == i);
}
method table.maxn(t) {
local max = 0
for k with pairs(t) {
max = (type(k) == 'number') && math.max(max, k) || max
}
return max
}
assert(table.maxn({}) == 0);
assert(table.maxn({
"1000" = true
}) == 0);
assert(table.maxn({
"1000" = true,
24.5 = 3
}) == 24.5);
assert(table.maxn({
1000 = true
}) == 1000);
assert(table.maxn({
10 = true,
100 * math.pi = print
}) == 100 * math.pi);
table.maxn = nil
a = {}
for i = 0, 50 {
a[(2 ^ i)] = true
}
assert(a[(#a)]);
print('+');
local t = {
{
1
} = 1,
{
2
} = 2,
string.rep("x ", 4) = 3,
100.3 = 4,
4 = 5
}
local n = 0
for k, v with pairs(t) {
n = n + 1
assert(t[(k)] == v);
t[(k)] = nil
collectgarbage();
assert(t[(k)] == nil);
}
assert(n == 5);
local fn test(a) {
assert(!pcall(table.insert, a, 2, 20));
table.insert(a, 10);
table.insert(a, 2, 20);
table.insert(a, 1, -1);
table.insert(a, 40);
table.insert(a, #a + 1, 50);
table.insert(a, 2, -2);
assert(!pcall(table.insert, a, 0, 20));
assert(!pcall(table.insert, a, #a + 2, 20));
assert(table.remove(a, 1) == -1);
assert(table.remove(a, 1) == -2);
assert(table.remove(a, 1) == 10);
assert(table.remove(a, 1) == 20);
assert(table.remove(a, 1) == 40);
assert(table.remove(a, 1) == 50);
assert(table.remove(a, 1) == nil);
assert(table.remove(a) == nil);
assert(table.remove(a, #a) == nil);
}
a = {
n = 0,
-7 = "ban"
}
test(a);
assert(a.n == 0 && a[(-7)] == "ban");
a = {
-7 = "ban"
}
test(a);
assert(a.n == nil && #a == 0 && a[(-7)] == "ban");
a = {
-1 = "ban"
}
test(a);
assert(#a == 0 && table.remove(a) == nil && a[(-1)] == "ban");
a = {
0 = "ban"
}
assert(#a == 0 && table.remove(a) == "ban" && a[(0)] == nil);
table.insert(a, 1, 10);
table.insert(a, 1, 20);
table.insert(a, 1, -1);
assert(table.remove(a) == 10);
assert(table.remove(a) == 20);
assert(table.remove(a) == -1);
assert(table.remove(a) == nil);
a = {
'c',
'd'
}
table.insert(a, 3, 'a');
table.insert(a, 'b');
assert(table.remove(a, 1) == 'c');
assert(table.remove(a, 1) == 'd');
assert(table.remove(a, 1) == 'a');
assert(table.remove(a, 1) == 'b');
assert(table.remove(a, 1) == nil);
assert(#a == 0 && a.n == nil);
a = {
10,
20,
30,
40
}
assert(table.remove(a, #a + 1) == nil);
assert(!pcall(table.remove, a, 0));
assert(a[(#a)] == 40);
assert(table.remove(a, #a) == 40);
assert(a[(#a)] == 30);
assert(table.remove(a, 2) == 20);
assert(a[(#a)] == 30 && #a == 2);
{
local fn test(proxy, t) {
for i = 1, 10 {
table.insert(proxy, 1, i);
}
assert(#proxy == 10 && #t == 10);
for i = 1, 10 {
assert(t[(i)] == 11 - i);
}
table.sort(proxy);
for i = 1, 10 {
assert(t[(i)] == i && proxy[(i)] == i);
}
assert(table.concat(proxy, ",") == "1,2,3,4,5,6,7,8,9,10");
for i = 1, 8 {
assert(table.remove(proxy, 1) == i);
}
assert(#proxy == 2 && #t == 2);
local a, b, c = table.unpack(proxy)
assert(a == 9 && b == 10 && c == nil);
}
local t = {}
local proxy = setmetatable({}, {
__len = fn () {
return #t
},
__index = t,
__newindex = t
})
test(proxy, t);
local count = 0
t = setmetatable({}, {
__newindex = fn (t, k, v) {
count = count + 1
rawset(t, k, v);
}
})
test(t, t);
assert(count == 10);
t = setmetatable({}, {
__index = fn (_, k) {
return k + 1
},
__len = fn (_) {
return 5
}
})
assert(table.concat(t, ";") == "2;3;4;5;6");
}
if !T {
(Message || print)('\n >>> testC not active: skipping tests for table library on non-tables <<<\n');
} else {
local debug = require('debug')
local tab = {
10,
20,
30
}
local mt = {}
local u = T.newuserdata(0)
checkerror("table expected", table.insert, u, 40);
checkerror("table expected", table.remove, u);
debug.setmetatable(u, mt);
checkerror("table expected", table.insert, u, 40);
checkerror("table expected", table.remove, u);
mt.__index = tab
checkerror("table expected", table.insert, u, 40);
checkerror("table expected", table.remove, u);
mt.__newindex = tab
checkerror("table expected", table.insert, u, 40);
checkerror("table expected", table.remove, u);
mt.__len = fn () {
return #tab
}
table.insert(u, 40);
assert(#u == 4 && #tab == 4 && u[(4)] == 40 && tab[(4)] == 40);
assert(table.remove(u) == 40);
table.insert(u, 1, 50);
assert(#u == 4 && #tab == 4 && u[(4)] == 30 && tab[(1)] == 50);
mt.__newindex = nil
mt.__len = nil
local tab2 = {}
local u2 = T.newuserdata(0)
debug.setmetatable(u2, {
__newindex = fn (_, k, v) {
tab2[(k)] = v
}
});
table.move(u, 1, 4, 1, u2);
assert(#tab2 == 4 && tab2[(1)] == tab[(1)] && tab2[(4)] == tab[(4)]);
}
print('+');
a = {}
for i = 1, 1000 {
a[(i)] = i
a[(i - 1)] = nil
}
assert(next(a, nil) == 1000 && next(a, 1000) == nil);
assert(next({}) == nil);
assert(next({}, nil) == nil);
for a, b with pairs({}) {
error("not here");
}
for i = 1, 0 {
error('not here');
}
for i = 0, 1, -1 {
error('not here');
}
a = nil
for i = 1, 1 {
assert(!a);
a = 1
}
assert(a);
a = nil
for i = 1, 1, -1 {
assert(!a);
a = 1
}
assert(a);
{
print("testing floats in numeric for");
local a
a = 0
for i = 1, 1, 1 {
a = a + 1
}
assert(a == 1);
a = 0
for i = 10000, 1e4, -1 {
a = a + 1
}
assert(a == 1);
a = 0
for i = 1, 0.99999, 1 {
a = a + 1
}
assert(a == 0);
a = 0
for i = 9999, 1e4, -1 {
a = a + 1
}
assert(a == 0);
a = 0
for i = 1, 0.99999, -1 {
a = a + 1
}
assert(a == 1);
a = 0
for i = 0, 0.999999999, 0.1 {
a = a + 1
}
assert(a == 10);
a = 0
for i = 1.0, 1, 1 {
a = a + 1
}
assert(a == 1);
a = 0
for i = -1.5, -1.5, 1 {
a = a + 1
}
assert(a == 1);
a = 0
for i = 1e6, 1e6, -1 {
a = a + 1
}
assert(a == 1);
a = 0
for i = 1.0, 0.99999, 1 {
a = a + 1
}
assert(a == 0);
a = 0
for i = 99999, 1e5, -1.0 {
a = a + 1
}
assert(a == 0);
a = 0
for i = 1.0, 0.99999, -1 {
a = a + 1
}
assert(a == 1);
}
a = 0
for i = "10", "1", "-2" {
a = a + 1
}
assert(a == 5);
{
local c
local fn checkfloat(i) {
assert(math.type(i) == "float");
c = c + 1
}
c = 0
for i = 1.0, 10 {
checkfloat(i);
}
assert(c == 10);
c = 0
for i = -1, -10, -1.0 {
checkfloat(i);
}
assert(c == 10);
local fn checkint(i) {
assert(math.type(i) == "integer");
c = c + 1
}
local m = math.maxinteger
c = 0
for i = m, m - 10, -1 {
checkint(i);
}
assert(c == 11);
c = 0
for i = 1, 10.9 {
checkint(i);
}
assert(c == 10);
c = 0
for i = 10, 0.001, -1 {
checkint(i);
}
assert(c == 10);
c = 0
for i = 1, "10.8" {
checkint(i);
}
assert(c == 10);
c = 0
for i = 9, "3.4", -1 {
checkint(i);
}
assert(c == 6);
c = 0
for i = 0, " -3.4 ", -1 {
checkint(i);
}
assert(c == 4);
c = 0
for i = 100, "96.3", -2 {
checkint(i);
}
assert(c == 2);
c = 0
for i = 1, math.huge {
if i > 10 {
break
}
checkint(i);
}
assert(c == 10);
c = 0
for i = -1, -math.huge, -1 {
if i < -10 {
break
}
checkint(i);
}
assert(c == 10);
for i = math.mininteger, -10e100 {
assert(false);
}
for i = math.maxinteger, 10e100, -1 {
assert(false);
}
}
collectgarbage();
local fn f(n, p) {
local t = {}
for i = 1, p {
t[(i)] = i * 10
}
return fn (_, n) {
if n > 0 {
n = n - 1
return n, table.unpack(t)
}
}, nil, n
}
local x = 0
for n, a, b, c, d with f(5, 3) {
x = x + 1
assert(a == 10 && b == 20 && c == 30 && d == nil);
}
assert(x == 5);
a = {}
{
local x, y, z = pairs(a)
assert(type(x) == 'function' && y == a && z == nil);
}
local fn foo(e, i) {
assert(e == a);
if i <= 10 {
return i + 1, i + 2
}
}
local fn foo1(e, i) {
i = i + 1
assert(e == a);
if i <= e.n {
return i, a[(i)]
}
}
setmetatable(a, {
__pairs = fn (x) {
return foo, x, 0
}
});
local i = 0
for k, v with pairs(a) {
i = i + 1
assert(k == i && v == k + 1);
}
a.n = 5
a[(3)] = 30
a = {
n = 10
}
setmetatable(a, {
__index = fn (t, k) {
if k <= t.n {
return k * 10
}
}
});
i = 0
for k, v with ipairs(a) {
i = i + 1
assert(k == i && v == i * 10);
}
assert(i == a.n);
print("OK");