diff options
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | src/lvm.js | 21 | ||||
-rw-r--r-- | tests/lvm.js | 108 |
3 files changed, 128 insertions, 5 deletions
@@ -39,8 +39,8 @@ - [x] OP_EQ - [x] OP_LT - [x] OP_LE - - [ ] OP_TEST - - [ ] OP_TESTSET + - [x] OP_TEST + - [x] OP_TESTSET - [x] OP_CALL - [x] OP_TAILCALL - [x] OP_RETURN @@ -333,7 +333,7 @@ class LuaVM { } case "OP_NOT": { let op = L.stack[this.RB(base, i)]; - L.stack[ra] = new TValue(CT.LUA_TBOOLEAN, !!((op.type === CT.LUA_TBOOLEAN && !op.value) || op.type === CT.LUA_TNIL)); + L.stack[ra] = new TValue(CT.LUA_TBOOLEAN, LuaVM.l_isfalse(op)); break; } case "OP_LEN": { @@ -371,9 +371,20 @@ class LuaVM { break; } case "OP_TEST": { + if (i.C ? LuaVM.l_isfalse(L.stack[ra]) : !LuaVM.l_isfalse(L.stack[ra])) + ci.pcOff++; + else + this.donextjump(ci); break; } case "OP_TESTSET": { + let rb = L.stack[this.RB(base, i)]; + if (i.C ? LuaVM.l_isfalse(rb) : !LuaVM.l_isfalse(rb)) + ci.pcOff++; + else { + L.stack[ra] = rb; + this.donextjump(ci); + } break; } case "OP_CALL": { @@ -747,12 +758,12 @@ class LuaVM { } static LEintfloat(l, r) { - // TODO + // TODO: LEintfloat return l <= r ? 1 : 0; } static LTintfloat(l, r) { - // TODO + // TODO: LTintfloat return l < r ? 1 : 0; } @@ -761,6 +772,10 @@ class LuaVM { return ls.value === rs.value ? 0 : (ls.value < rs.value ? -1 : 1); } + static l_isfalse(o) { + return o.ttisnil() || (o.ttisboolean() && o.value === false) + } + } module.exports = { diff --git a/tests/lvm.js b/tests/lvm.js index e2454eb..5f19455 100644 --- a/tests/lvm.js +++ b/tests/lvm.js @@ -342,4 +342,112 @@ test('EQ', function (t) { true, "Program output is correct" ); +}); + + +test('TESTSET (and)', function (t) { + let luaCode = ` + local a = true + local b = "hello" + + return a and b + `, vm; + + t.plan(2); + + t.comment("Running following code: \n" + luaCode); + + t.doesNotThrow(function () { + vm = getVM(luaCode); + vm.execute(); + }, "Program executed without errors"); + + t.strictEqual( + vm.L.stack[vm.L.top - 1].value, + "hello", + "Program output is correct" + ); +}); + + +test('TESTSET (or)', function (t) { + let luaCode = ` + local a = false + local b = "hello" + + return a or b + `, vm; + + t.plan(2); + + t.comment("Running following code: \n" + luaCode); + + t.doesNotThrow(function () { + vm = getVM(luaCode); + vm.execute(); + }, "Program executed without errors"); + + t.strictEqual( + vm.L.stack[vm.L.top - 1].value, + "hello", + "Program output is correct" + ); +}); + + +test('TEST (true)', function (t) { + let luaCode = ` + local a = true + local b = "hello" + + if a then + return b + end + + return "goodbye" + `, vm; + + t.plan(2); + + t.comment("Running following code: \n" + luaCode); + + t.doesNotThrow(function () { + vm = getVM(luaCode); + vm.execute(); + }, "Program executed without errors"); + + t.strictEqual( + vm.L.stack[vm.L.top - 1].value, + "hello", + "Program output is correct" + ); +}); + + +test('TEST (false)', function (t) { + let luaCode = ` + local a = false + local b = "hello" + + if a then + return b + end + + return "goodbye" + `, vm; + + t.plan(2); + + t.comment("Running following code: \n" + luaCode); + + t.doesNotThrow(function () { + vm = getVM(luaCode); + vm.execute(); + }, "Program executed without errors"); + + t.strictEqual( + vm.L.stack[vm.L.top - 1].value, + "goodbye", + "Program output is correct" + ); });
\ No newline at end of file |