if T == nil then
(Message or print)('\a\n >>> testC not active: skipping opcode tests <<<\n\a')
return
end
print "testing code generation and optimizations"
do
local function f(a)
for k, v, w in a do end
end
end
function check(f, ...)
local arg = { ... }
local c = T.listcode(f)
for i = 1, #arg do
assert(string.find(c[i], '- ' .. arg[i] .. ' *%d'))
end
assert(c[#arg + 2] == nil)
end
function checkequal(a, b)
a = T.listcode(a)
b = T.listcode(b)
for i = 1, #a do
a[i] = string.gsub(a[i], '%b()', '') b[i] = string.gsub(b[i], '%b()', '') assert(a[i] == b[i])
end
end
check(function()
(function() end) { f() }
end, 'CLOSURE', 'NEWTABLE', 'GETTABUP', 'CALL', 'SETLIST', 'CALL', 'RETURN')
check(function()
local a, b, c
local d; local e;
local f, g, h;
d = nil; d = nil; b = nil; a = nil; c = nil;
end, 'LOADNIL', 'RETURN')
check(function()
local a, b, c, d = 1, 1, 1, 1
d = nil; c = nil; b = nil; a = nil
end, 'LOADK', 'LOADK', 'LOADK', 'LOADK', 'LOADNIL', 'RETURN')
do
local a, b, c, d = 1, 1, 1, 1
d = nil; c = nil; b = nil; a = nil
assert(a == nil and b == nil and c == nil and d == nil)
end
check(function(a, b, c) return a end, 'RETURN')
check(function() while true do local a = -1 end end,
'LOADK', 'JMP', 'RETURN')
check(function() while 1 do local a = -1 end end,
'LOADK', 'JMP', 'RETURN')
check(function() repeat local x = 1 until true end,
'LOADK', 'RETURN')
check(function(a, b, c, d) return a .. b .. c .. d end,
'MOVE', 'MOVE', 'MOVE', 'MOVE', 'CONCAT', 'RETURN')
check(function() return not not nil end, 'LOADBOOL', 'RETURN')
check(function() return not not false end, 'LOADBOOL', 'RETURN')
check(function() return not not true end, 'LOADBOOL', 'RETURN')
check(function() return not not 1 end, 'LOADBOOL', 'RETURN')
check(function()
local a, b, c, d
a = b * 2
c[4], a[b] = -((a + d / -20.5 - a[b]) ^ a.x), b
end,
'LOADNIL',
'MUL',
'DIV', 'ADD', 'GETTABLE', 'SUB', 'GETTABLE', 'POW',
'UNM', 'SETTABLE', 'SETTABLE', 'RETURN')
check(function()
local a, b
a.x = 0
a.x = b
a[b] = 'y'
a = 1 - a
b = 1 / a
b = 5 + 4
a[true] = false
end,
'LOADNIL',
'SETTABLE', 'SETTABLE', 'SETTABLE', 'SUB', 'DIV', 'LOADK',
'SETTABLE', 'RETURN')
local function f() return -((2 ^ 8 + -(-1)) % 8) / 2 * 4 - 3 end
check(f, 'LOADK', 'RETURN')
assert(f() == -5)
check(function() return -nil end,
'LOADNIL', 'UNM', 'RETURN')
check(function()
local a, b, c
b[c], a = c, b
b[a], a = c, b
a, b = c, a
a = a
end,
'LOADNIL',
'MOVE', 'MOVE', 'SETTABLE',
'MOVE', 'MOVE', 'MOVE', 'SETTABLE',
'MOVE', 'MOVE', 'MOVE',
'RETURN')
checkequal(function()
if (a == nil) then a = 1 end
; if a ~= nil then a = 1 end
end,
function()
if (a == 9) then a = 1 end
; if a ~= 9 then a = 1 end
end)
check(function() if a == nil then a = 1 end end,
'GETTABUP', 'EQ', 'JMP', 'SETTABUP', 'RETURN')
checkequal(function()
local a; if not (a or b) then b = a end
end,
function()
local a; if (not a and not b) then b = a end
end)
checkequal(function(l)
local a; return 0 <= a and a <= l
end,
function(l)
local a; return not (not (a >= 0) or not (a <= l))
end)
check(function(a)
if a == 1 then
elseif a == 2 then
elseif a == 3 then
else
if a == 4 then
else
end
end
end, 'EQ', 'JMP', 'EQ', 'JMP', 'EQ', 'JMP', 'EQ', 'JMP', 'JMP', 'RETURN')
checkequal(
function(a) while a < 10 do a = a + 1 end end,
function(a)
if not (a < 10) then end
; a = a + 1;
end
)
checkequal(
function(a) while a < 10 do a = a + 1 end end,
function(a)
while true do
if not (a < 10) then break end
; a = a + 1;
end
end
)
print 'OK'