--- source: src/main.rs expression: compiled input_file: test-data/lua5.2-tests/code.lua --- if T == nil { (Message || print)('\a\n >>> testC not active: skipping opcode tests <<<\n\a'); return } print("testing code generation and optimizations"); { local fn f(a) { for k, v, w with a { } } } 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[(4)], a[(b)] = -((a + d / -20.5 - a[(b)]) ^ a.x), b }, 'LOADNIL', 'MUL', 'DIV', 'ADD', 'GETTABLE', 'SUB', 'GETTABLE', 'POW', 'UNM', 'SETTABLE', 'SETTABLE', 'RETURN'); check(fn () { local a, b a.x = 0 a.x = b a[(b)] = 'y' a = 1 - a b = 1 / a b = 5 + 4 a[(true)] = false }, 'LOADNIL', 'SETTABLE', 'SETTABLE', 'SETTABLE', 'SUB', 'DIV', 'LOADK', 'SETTABLE', 'RETURN'); local fn f() { return -((2 ^ 8 + -(-1)) % 8) / 2 * 4 - 3 } check(f, 'LOADK', 'RETURN'); assert(f() == -5); 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 = 1 } }, '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) { if a == 1 { } elseif if a == 2 { } elseif if a == 3 { } else { if a == 4 { } 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');