---
source: src/main.rs
expression: compiled
input_file: test-data/lua5.1-tests/events.lua
---
print('testing metatables');
X = 20
B = 30
setfenv(1, setmetatable({}, {
__index = _G
}));
collectgarbage();
X = X + 10
assert(X == 30 && _G.X == 20);
B = false
assert(B == false);
B = nil
assert(B == 30);
assert(getmetatable({}) == nil);
assert(getmetatable(4) == nil);
assert(getmetatable(nil) == nil);
a = {}
setmetatable(a, {
__metatable = "xuxu",
__tostring = fn (x) {
return x.name
}
});
assert(getmetatable(a) == "xuxu");
assert(tostring(a) == nil);
assert(pcall(setmetatable, a, {}) == false);
a.name = "gororoba"
assert(tostring(a) == "gororoba");
local a, t = {
10,
20,
30,
x = "10",
y = "20"
}, {}
assert(setmetatable(a, t) == a);
assert(getmetatable(a) == t);
assert(setmetatable(a, nil) == a);
assert(getmetatable(a) == nil);
assert(setmetatable(a, t) == a);
global fn f(t, i, e) {
assert(!e);
local p = rawget(t, "parent")
return (p && p[(i)] + 3), "dummy return"
}
t.__index = f
a.parent = {
z = 25,
x = 12,
4 = 24
}
assert(a[(1)] == 10 && a.z == 28 && a[(4)] == 27 && a.x == "10");
collectgarbage();
a = setmetatable({}, t)
global fn f(t, i, v) {
rawset(t, i, v - 3);
}
t.__newindex = f
a[(1)] = 30
a.x = "101"
a[(5)] = 200
assert(a[(1)] == 27 && a.x == 98 && a[(5)] == 197);
local c = {}
a = setmetatable({}, t)
t.__newindex = c
a[(1)] = 10
a[(2)] = 20
a[(3)] = 90
assert(c[(1)] == 10 && c[(2)] == 20 && c[(3)] == 90);
{
local a
a = setmetatable({}, {
__index = setmetatable({}, {
__index = setmetatable({}, {
__index = fn (_, n) {
return a[(n - 3)] + 4, "lixo"
}
})
})
})
a[(0)] = 20
for i = 0, 10 {
assert(a[(i * 3)] == 20 + i * 4);
}
}
{
local foi
local a = {}
for i = 1, 10 {
a[(i)] = 0
a[('a' .. i)] = 0
}
setmetatable(a, {
__newindex = fn (t, k, v) {
foi = true
rawset(t, k, v);
}
});
foi = false
a[(1)] = 0
assert(!foi);
foi = false
a[('a1')] = 0
assert(!foi);
foi = false
a[('a11')] = 0
assert(foi);
foi = false
a[(11)] = 0
assert(foi);
foi = false
a[(1)] = nil
assert(!foi);
foi = false
a[(1)] = nil
assert(foi);
}
global fn f(t, ...) {
return t, {
...
}
}
t.__call = f
{
local x, y = a(unpack({
'a',
1
}))
assert(x == a && y[(1)] == 'a' && y[(2)] == 1 && y[(3)] == nil);
x, y = a()
assert(x == a && y[(1)] == nil);
}
local b = setmetatable({}, t)
setmetatable(b, t);
global fn f(op) {
return fn (...) {
cap = {
0 = op,
...
}
return (...)
}
}
t.__add = f("add")
t.__sub = f("sub")
t.__mul = f("mul")
t.__div = f("div")
t.__mod = f("mod")
t.__unm = f("unm")
t.__pow = f("pow")
assert(b + 5 == b);
assert(cap[(0)] == "add" && cap[(1)] == b && cap[(2)] == 5 && cap[(3)] == nil);
assert(b + '5' == b);
assert(cap[(0)] == "add" && cap[(1)] == b && cap[(2)] == '5' && cap[(3)] == nil);
assert(5 + b == 5);
assert(cap[(0)] == "add" && cap[(1)] == 5 && cap[(2)] == b && cap[(3)] == nil);
assert('5' + b == '5');
assert(cap[(0)] == "add" && cap[(1)] == '5' && cap[(2)] == b && cap[(3)] == nil);
b = b - 3
assert(getmetatable(b) == t);
assert(5 - a == 5);
assert(cap[(0)] == "sub" && cap[(1)] == 5 && cap[(2)] == a && cap[(3)] == nil);
assert('5' - a == '5');
assert(cap[(0)] == "sub" && cap[(1)] == '5' && cap[(2)] == a && cap[(3)] == nil);
assert(a * a == a);
assert(cap[(0)] == "mul" && cap[(1)] == a && cap[(2)] == a && cap[(3)] == nil);
assert(a / 0 == a);
assert(cap[(0)] == "div" && cap[(1)] == a && cap[(2)] == 0 && cap[(3)] == nil);
assert(a % 2 == a);
assert(cap[(0)] == "mod" && cap[(1)] == a && cap[(2)] == 2 && cap[(3)] == nil);
assert(-a == a);
assert(cap[(0)] == "unm" && cap[(1)] == a);
assert(a ^ 4 == a);
assert(cap[(0)] == "pow" && cap[(1)] == a && cap[(2)] == 4 && cap[(3)] == nil);
assert(a ^ '4' == a);
assert(cap[(0)] == "pow" && cap[(1)] == a && cap[(2)] == '4' && cap[(3)] == nil);
assert(4 ^ a == 4);
assert(cap[(0)] == "pow" && cap[(1)] == 4 && cap[(2)] == a && cap[(3)] == nil);
assert('4' ^ a == '4');
assert(cap[(0)] == "pow" && cap[(1)] == '4' && cap[(2)] == a && cap[(3)] == nil);
t = {}
t.__lt = fn (a, b, c) {
collectgarbage();
assert(c == nil);
if type(a) == 'table' {
a = a.x
}
if type(b) == 'table' {
b = b.x
}
return a < b, "dummy"
}
global fn Op(x) {
return setmetatable({
x = x
}, t)
}
local fn test() {
assert(!(Op(1) < Op(1)) && (Op(1) < Op(2)) && !(Op(2) < Op(1)));
assert(!(Op('a') < Op('a')) && (Op('a') < Op('b')) && !(Op('b') < Op('a')));
assert((Op(1) <= Op(1)) && (Op(1) <= Op(2)) && !(Op(2) <= Op(1)));
assert((Op('a') <= Op('a')) && (Op('a') <= Op('b')) && !(Op('b') <= Op('a')));
assert(!(Op(1) > Op(1)) && !(Op(1) > Op(2)) && (Op(2) > Op(1)));
assert(!(Op('a') > Op('a')) && !(Op('a') > Op('b')) && (Op('b') > Op('a')));
assert((Op(1) >= Op(1)) && !(Op(1) >= Op(2)) && (Op(2) >= Op(1)));
assert((Op('a') >= Op('a')) && !(Op('a') >= Op('b')) && (Op('b') >= Op('a')));
}
test();
t.__le = fn (a, b, c) {
assert(c == nil);
if type(a) == 'table' {
a = a.x
}
if type(b) == 'table' {
b = b.x
}
return a <= b, "dummy"
}
test();
local fn Set(x) {
local y = {}
for _, k with pairs(x) {
y[(k)] = 1
}
return setmetatable(y, t)
}
t.__lt = fn (a, b) {
for k with pairs(a) {
if !b[(k)] {
return false
}
b[(k)] = nil
}
return next(b) != nil
}
t.__le = nil
assert(Set({
1,
2,
3
}) < Set({
1,
2,
3,
4
}));
assert(!(Set({
1,
2,
3,
4
}) < Set({
1,
2,
3,
4
})));
assert((Set({
1,
2,
3,
4
}) <= Set({
1,
2,
3,
4
})));
assert((Set({
1,
2,
3,
4
}) >= Set({
1,
2,
3,
4
})));
assert((Set({
1,
3
}) <= Set({
3,
5
})));
t.__le = fn (a, b) {
for k with pairs(a) {
if !b[(k)] {
return false
}
}
return true
}
assert(!(Set({
1,
3
}) <= Set({
3,
5
})));
assert(!(Set({
1,
3
}) <= Set({
3,
5
})));
assert(!(Set({
1,
3
}) >= Set({
3,
5
})));
t.__eq = fn (a, b) {
for k with pairs(a) {
if !b[(k)] {
return false
}
b[(k)] = nil
}
return next(b) == nil
}
local s = Set({
1,
3,
5
})
assert(s == Set({
3,
5,
1
}));
assert(!rawequal(s, Set({
3,
5,
1
})));
assert(rawequal(s, s));
assert(Set({
1,
3,
5,
1
}) == Set({
3,
5,
1
}));
assert(Set({
1,
3,
5
}) != Set({
3,
5,
1,
6
}));
t[(Set({
1,
3,
5
}))] = 1
assert(t[(Set({
1,
3,
5
}))] == nil);
t.__concat = fn (a, b, c) {
assert(c == nil);
if type(a) == 'table' {
a = a.val
}
if type(b) == 'table' {
b = b.val
}
if A {
return a .. b
} else {
return setmetatable({
val = a .. b
}, t)
}
}
c = {
val = "c"
}
setmetatable(c, t);
d = {
val = "d"
}
setmetatable(d, t);
A = true
assert(c .. d == 'cd');
assert(0 .. "a" .. "b" .. c .. d .. "e" .. "f" .. (5 + 3) .. "g" == "0abcdef8g");
A = false
x = c .. d
assert(getmetatable(x) == t && x.val == 'cd');
x = 0 .. "a" .. "b" .. c .. d .. "e" .. "f" .. "g"
assert(x.val == "0abcdefg");
local t1, t2, c, d
t1 = {}
c = {}
setmetatable(c, t1);
d = {}
t1.__eq = fn () {
return true
}
t1.__lt = fn () {
return true
}
assert(c != d && !pcall(fn () {
return c < d
}));
setmetatable(d, t1);
assert(c == d && c < d && !(d <= c));
t2 = {}
t2.__eq = t1.__eq
t2.__lt = t1.__lt
setmetatable(d, t2);
assert(c == d && c < d && !(d <= c));
local i
local tt = {
__call = fn (t, ...) {
i = i + 1
if t.f {
return t.f(...)
} else {
return {
...
}
}
}
}
local a = setmetatable({}, tt)
local b = setmetatable({
f = a
}, tt)
local c = setmetatable({
f = b
}, tt)
i = 0
x = c(3, 4, 5)
assert(i == 3 && x[(1)] == 3 && x[(3)] == 5);
assert(_G.X == 20);
assert(_G == getfenv(0));
print('+');
local _g = _G
setfenv(1, setmetatable({}, {
__index = fn (_, k) {
return _g[(k)]
}
}));
assert(getmetatable(newproxy()) == nil);
assert(getmetatable(newproxy(false)) == nil);
local u = newproxy(true)
getmetatable(u).__newindex = fn (u, k, v) {
getmetatable(u)[(k)] = v
}
getmetatable(u).__index = fn (u, k) {
return getmetatable(u)[(k)]
}
for i = 1, 10 {
u[(i)] = i
}
for i = 1, 10 {
assert(u[(i)] == i);
}
local k = newproxy(u)
assert(getmetatable(k) == getmetatable(u));
a = {}
rawset(a, "x", 1, 2, 3);
assert(a.x == 1 && rawget(a, "x", 3) == 1);
print('+');
mt = {}
debug.setmetatable(10, mt);
assert(getmetatable(-2) == mt);
mt.__index = fn (a, b) {
return a + b
}
assert((10)[(3)] == 13);
assert((10)[("3")] == 13);
debug.setmetatable(23, nil);
assert(getmetatable(-2) == nil);
debug.setmetatable(true, mt);
assert(getmetatable(false) == mt);
mt.__index = fn (a, b) {
return a || b
}
assert((true)[(false)] == true);
assert((false)[(false)] == false);
debug.setmetatable(false, nil);
assert(getmetatable(true) == nil);
debug.setmetatable(nil, mt);
assert(getmetatable(nil) == mt);
mt.__add = fn (a, b) {
return (a || 0) + (b || 0)
}
assert(10 + nil == 10);
assert(nil + 23 == 23);
assert(nil + nil == 0);
debug.setmetatable(nil, nil);
assert(getmetatable(nil) == nil);
debug.setmetatable(nil, {});
print('OK');
return 12