---
source: src/main.rs
assertion_line: 136
expression: compiled
input_file: test-data/lua5.3-tests/code.lua
---
if T == nil {
(Message || print)('\n >>> testC not active: skipping opcode tests <<<\n');
return
}
print("testing code generation and optimizations");
{
local fn f(a) {
for k, v, w with a {
}
}
}
local fn checkKlist(func, list) {
local k = T.listk(func)
assert(#k == #list);
for i = 1, #k {
assert(k[(i)] == list[(i)] && math.type(k[(i)]) == math.type(list[(i)]));
}
}
local fn foo() {
local a
a = 3
a = 0
a = 0.0
a = -7 + 7
a = 3.78 / 4
a = 3.78 / 4
a = -3.78 / 4
a = 3.78 / 4
a = -3.78 / 4
a = -3.79 / 4
a = 0.0
a = -0
a = 3
a = 3.0
a = 3
a = 3.0
}
checkKlist(foo, {
3,
0,
0.0,
3.78 / 4,
-3.78 / 4,
-3.79 / 4,
3.0
});
global fn check(f, ...) {
local arg = {
...
}
local c = T.listcode(f)
for i = 1, #arg {
assert(string.find(c[(i)], '- ' .. arg[(i)] .. ' *%d'));
}
assert(c[(#arg + 2)] == nil);
}
global fn checkequal(a, b) {
a = T.listcode(a)
b = T.listcode(b)
for i = 1, #a {
a[(i)] = string.gsub(a[(i)], '%b()', '')
b[(i)] = string.gsub(b[(i)], '%b()', '')
assert(a[(i)] == b[(i)]);
}
}
check(fn () {
(fn () {
})({
f()
});
}, 'CLOSURE', 'NEWTABLE', 'GETTABUP', 'CALL', 'SETLIST', 'CALL', 'RETURN');
check(fn () {
local a, b, c
local d
local e
local f, g, h
d = nil
d = nil
b = nil
a = nil
c = nil
}, 'LOADNIL', 'RETURN');
check(fn () {
local a, b, c, d = 1, 1, 1, 1
d = nil
c = nil
b = nil
a = nil
}, 'LOADK', 'LOADK', 'LOADK', 'LOADK', 'LOADNIL', 'RETURN');
{
local a, b, c, d = 1, 1, 1, 1
d = nil
c = nil
b = nil
a = nil
assert(a == nil && b == nil && c == nil && d == nil);
}
check(fn (a, b, c) {
return a
}, 'RETURN');
check(fn () {
while true {
local a = -1
}
}, 'LOADK', 'JMP', 'RETURN');
check(fn () {
while 1 {
local a = -1
}
}, 'LOADK', 'JMP', 'RETURN');
check(fn () {
loop {
local x = 1
} until true
}, 'LOADK', 'RETURN');
check(fn (a, b, c, d) {
return a .. b .. c .. d
}, 'MOVE', 'MOVE', 'MOVE', 'MOVE', 'CONCAT', 'RETURN');
check(fn () {
return !!nil
}, 'LOADBOOL', 'RETURN');
check(fn () {
return !!false
}, 'LOADBOOL', 'RETURN');
check(fn () {
return !!true
}, 'LOADBOOL', 'RETURN');
check(fn () {
return !!1
}, 'LOADBOOL', 'RETURN');
check(fn () {
local a, b, c, d
a = b * 2
c[(2)], a[(b)] = -((a + d / 2 - a[(b)]) ^ a.x), b
}, 'LOADNIL', 'MUL', 'DIV', 'ADD', 'GETTABLE', 'SUB', 'GETTABLE', 'POW', 'UNM', 'SETTABLE', 'SETTABLE', 'RETURN');
check(fn () {
local a, b
a.x = 3.2
a.x = b
a[(b)] = 'x'
}, 'LOADNIL', 'SETTABLE', 'SETTABLE', 'SETTABLE', 'RETURN');
check(fn () {
local a, b
a = 1 - a
b = 1 / a
b = 5 - 4
}, 'LOADNIL', 'SUB', 'DIV', 'LOADK', 'RETURN');
check(fn () {
local a, b
a[(true)] = false
}, 'LOADNIL', 'SETTABLE', 'RETURN');
local fn checkK(func, val) {
check(func, 'LOADK', 'RETURN');
local k = T.listk(func)
assert(#k == 1 && k[(1)] == val && math.type(k[(1)]) == math.type(val));
assert(func() == val);
}
checkK(fn () {
return 0.0
}, 0.0);
checkK(fn () {
return 0
}, 0);
checkK(fn () {
return -0 /_ 1
}, 0);
checkK(fn () {
return 3 ^ -1
}, 1 / 3);
checkK(fn () {
return (1 + 1) ^ (50 + 50)
}, 2 ^ 100);
checkK(fn () {
return (-2) ^ (31 - 2)
}, -0x20000000 + 0.0);
checkK(fn () {
return (-3 ^ 0 + 5) /_ 3.0
}, 1.0);
checkK(fn () {
return -3 % 5
}, 2);
checkK(fn () {
return -((2.0 ^ 8 + -(-1)) % 8) / 2 * 4 - 3
}, -5.0);
checkK(fn () {
return -((2 ^ 8 + -(-1)) % 8) /_ 2 * 4 - 3
}, -7.0);
checkK(fn () {
return 240 | 204 ^^ 0xAA & 0xFD
}, 0xF4);
checkK(fn () {
return ~(~0xFF0 | 0xFF0)
}, 0);
checkK(fn () {
return ~ ^^ -100024.0
}, -100024);
checkK(fn () {
return ((100 << 6) << -4) >> 2
}, 100);
check(fn () {
return -0.0
}, 'LOADK', 'UNM', 'RETURN');
check(fn () {
return 3 / 0
}, 'DIV', 'RETURN');
check(fn () {
return 0 % 0
}, 'MOD', 'RETURN');
check(fn () {
return -4 /_ 0
}, 'IDIV', 'RETURN');
check(fn () {
return -nil
}, 'LOADNIL', 'UNM', 'RETURN');
check(fn () {
local a, b, c
b[(c)], a = c, b
b[(a)], a = c, b
a, b = c, a
a = a
}, 'LOADNIL', 'MOVE', 'MOVE', 'SETTABLE', 'MOVE', 'MOVE', 'MOVE', 'SETTABLE', 'MOVE', 'MOVE', 'MOVE', 'RETURN');
checkequal(fn () {
if (a == nil) {
a = 1
}
if a != nil {
a = 1
}
}, fn () {
if (a == 9) {
a = 1
}
if a != 9 {
a = 1
}
});
check(fn () {
if a == nil {
a = 'a'
}
}, 'GETTABUP', 'EQ', 'JMP', 'SETTABUP', 'RETURN');
checkequal(fn () {
local a
if !(a || b) {
b = a
}
}, fn () {
local a
if (!a && !b) {
b = a
}
});
checkequal(fn (l) {
local a
return 0 <= a && a <= l
}, fn (l) {
local a
return !(!(a >= 0) || !(a <= l))
});
check(fn (a, b, c, d, e) {
if a == b {
} elseif if a == c {
} elseif if a == d {
} else {
if a == e {
} else {
}
}
}, 'EQ', 'JMP', 'EQ', 'JMP', 'EQ', 'JMP', 'EQ', 'JMP', 'JMP', 'RETURN');
checkequal(fn (a) {
while a < 10 {
a = a + 1
}
}, fn (a) {
if !(a < 10) {
}
a = a + 1
});
checkequal(fn (a) {
while a < 10 {
a = a + 1
}
}, fn (a) {
while true {
if !(a < 10) {
break
}
a = a + 1
}
});
print('OK');