summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md4
-rw-r--r--src/lvm.js21
-rw-r--r--tests/lvm.js108
3 files changed, 128 insertions, 5 deletions
diff --git a/README.md b/README.md
index 6126241..0debf84 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/src/lvm.js b/src/lvm.js
index 1673db7..bf74f24 100644
--- a/src/lvm.js
+++ b/src/lvm.js
@@ -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