diff options
Diffstat (limited to 'test/lexparse.test.js')
-rw-r--r-- | test/lexparse.test.js | 761 |
1 files changed, 761 insertions, 0 deletions
diff --git a/test/lexparse.test.js b/test/lexparse.test.js new file mode 100644 index 0000000..a9407ed --- /dev/null +++ b/test/lexparse.test.js @@ -0,0 +1,761 @@ +"use strict"; + +const lua = require('../src/lua.js'); +const lauxlib = require('../src/lauxlib.js'); +const lualib = require('../src/lualib.js'); +const lstring = require("../src/lstring.js"); +const {to_luastring} = require("../src/fengaricore.js"); + +// Roughly the same tests as test/lvm.js to cover all opcodes +test('LOADK, RETURN', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + local a = "hello world" + return a + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect(lua.lua_tojsstring(L, -1)).toBe("hello world"); +}); + + +test('MOVE', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + local a = "hello world" + local b = a + return b + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect(lua.lua_tojsstring(L, -1)).toBe("hello world"); +}); + + +test('Binary op', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + local a = 5 + local b = 10 + return a + b, a - b, a * b, a / b, a % b, a^b, a // b, a & b, a | b, a ~ b, a << b, a >> b + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect(L.stack.slice(L.top - 12, L.top).map(e => e.value)) + .toEqual([15, -5, 50, 0.5, 5, 9765625.0, 0, 0, 15, 15, 5120, 0]); +}); + + +test('Unary op, LOADBOOL', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + local a = 5 + local b = false + return -a, not b, ~a + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect(L.stack.slice(L.top - 3, L.top).map(e => e.value)) + .toEqual([-5, true, -6]); +}); + + +test('NEWTABLE', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + local a = {} + return a + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect(lua.lua_type(L, -1)).toBe(lua.LUA_TTABLE); +}); + + +test('CALL', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + local f = function (a, b) + return a + b + end + + local c = f(1, 2) + + return c + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect(lua.lua_tointeger(L, -1)).toBe(3); +}); + +test('Multiple return', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + local f = function (a, b) + return a + b, a - b, a * b + end + + local c + local d + local e + + c, d, e = f(1,2) + + return c, d, e + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect(L.stack.slice(L.top - 3, L.top).map(e => e.value)) + .toEqual([3, -1, 2]); +}); + + +test('TAILCALL', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + local f = function (a, b) + return a + b + end + + return f(1,2) + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect(lua.lua_tointeger(L, -1)).toBe(3); +}); + + +test('VARARG', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + local f = function (...) + return ... + end + + return f(1,2,3) + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect(L.stack.slice(L.top - 3, L.top).map(e => e.value)) + .toEqual([1, 2, 3]); +}); + + +test('LE, JMP', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + local a, b = 1, 1 + + return a >= b + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect(lua.lua_toboolean(L, -1)).toBe(true); +}); + + +test('LT', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + local a, b = 1, 1 + + return a > b + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect(lua.lua_toboolean(L, -1)).toBe(false); +}); + + +test('EQ', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + local a, b = 1, 1 + + return a == b + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect(lua.lua_toboolean(L, -1)).toBe(true); +}); + + +test('TESTSET (and)', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + local a = true + local b = "hello" + + return a and b + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect(lua.lua_tojsstring(L, -1)).toBe("hello"); +}); + + +test('TESTSET (or)', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + local a = false + local b = "hello" + + return a or b + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect(lua.lua_tojsstring(L, -1)).toBe("hello"); +}); + + +test('TEST (false)', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + local a = false + local b = "hello" + + if a then + return b + end + + return "goodbye" + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect(lua.lua_tojsstring(L, -1)).toBe("goodbye"); +}); + + +test('FORPREP, FORLOOP (int)', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + local total = 0 + + for i = 0, 10 do + total = total + i + end + + return total + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect(lua.lua_tointeger(L, -1)).toBe(55); +}); + + +test('FORPREP, FORLOOP (float)', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + local total = 0 + + for i = 0.5, 10.5 do + total = total + i + end + + return total + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect(lua.lua_tonumber(L, -1)).toBe(60.5); +}); + + +test('SETTABLE, GETTABLE', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + local t = {} + + t[1] = "hello" + t["two"] = "world" + + return t + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect(lua.lua_topointer(L, -1).strong.get(1).value.jsstring()) + .toBe("hello"); + expect(lua.lua_topointer(L, -1).strong.get(lstring.luaS_hash(to_luastring("two"))).value.jsstring()) + .toBe("world"); +}); + + +test('SETUPVAL, GETUPVAL', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + local up = "hello" + + local f = function () + upup = "yo" + up = "world" + return up; + end + + return f() + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect(lua.lua_tojsstring(L, -1)).toBe("world"); +}); + + +test('SETTABUP, GETTABUP', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + t = {} + + t[1] = "hello" + t["two"] = "world" + + return t + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect(lua.lua_topointer(L, -1).strong.get(1).value.jsstring()) + .toBe("hello"); + expect(lua.lua_topointer(L, -1).strong.get(lstring.luaS_hash(to_luastring("two"))).value.jsstring()) + .toBe("world"); +}); + + +test('SELF', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + local t = {} + + t.value = "hello" + t.get = function (self) + return self.value + end + + return t:get() + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect(lua.lua_tojsstring(L, -1)).toBe("hello"); +}); + + +test('SETLIST', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + local t = {1, 2, 3, 4, 5, 6, 7, 8, 9} + + return t + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect([...lua.lua_topointer(L, -1).strong.entries()].map(e => e[1].value.value).sort()) + .toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9]); +}); + + +test('Variable SETLIST', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + local a = function () + return 6, 7, 8, 9 + end + + local t = {1, 2, 3, 4, 5, a()} + + return t + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect([...lua.lua_topointer(L, -1).strong.entries()].map(e => e[1].value.value).sort()) + .toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9]); +}); + +test('Long SETLIST', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + local t = {1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5} + + return t + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect([...lua.lua_topointer(L, -1).strong.entries()].map(e => e[1].value.value).reverse()) + .toEqual([1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]); +}); + + +test('TFORCALL, TFORLOOP', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + local iterator = function (t, i) + i = i + 1 + local v = t[i] + if v then + return i, v + end + end + + local iprs = function(t) + return iterator, t, 0 + end + + local t = {1, 2, 3} + local r = 0 + for k,v in iprs(t) do + r = r + v + end + + return r + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect(lua.lua_tonumber(L, -1)).toBe(6); +}); + + +test('LEN', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + local t = {[10000] = "foo"} + local t2 = {1, 2, 3} + local s = "hello" + + return #t, #t2, #s + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect(lua.lua_tonumber(L, -1)).toBe(5); + expect(lua.lua_tonumber(L, -2)).toBe(3); + expect(lua.lua_tonumber(L, -3)).toBe(0); +}); + + +test('CONCAT', () => { + let L = lauxlib.luaL_newstate(); + if (!L) throw Error("failed to create lua state"); + + let luaCode = ` + return "hello " .. 2 .. " you" + `; + { + lualib.luaL_openlibs(L); + let reader = function(L, data) { + let code = luaCode ? luaCode.trim() : null; + luaCode = null; + return code ? to_luastring(code) : null; + }; + lua.lua_load(L, reader, luaCode, to_luastring("test"), to_luastring("text")); + + lua.lua_call(L, 0, -1); + } + + expect(lua.lua_tojsstring(L, -1)).toBe("hello 2 you"); +}); |