aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--luac.outbin0 -> 203 bytes
-rw-r--r--sandbox/helloworld.lua1
-rw-r--r--src/lstate.js11
-rw-r--r--src/lvm.js27
-rw-r--r--tests/lvm.js66
5 files changed, 96 insertions, 9 deletions
diff --git a/luac.out b/luac.out
new file mode 100644
index 0000000..1c971ab
--- /dev/null
+++ b/luac.out
Binary files differ
diff --git a/sandbox/helloworld.lua b/sandbox/helloworld.lua
new file mode 100644
index 0000000..7785fb9
--- /dev/null
+++ b/sandbox/helloworld.lua
@@ -0,0 +1 @@
+local a = "hello world"
diff --git a/src/lstate.js b/src/lstate.js
index 9c7eec3..15dedcb 100644
--- a/src/lstate.js
+++ b/src/lstate.js
@@ -21,14 +21,19 @@ class lua_State {
constructor(cl) {
this.top = 1;
this.ci = [
- new CallInfo(0, 1, 1, null, null);
+ new CallInfo(0, 1, 1, null, null)
];
this.ci[0].savedpc = cl.p.code;
this.ciOff = 0;
this.stack = [
- closure
+ cl
];
this.openupval = [];
}
-} \ No newline at end of file
+}
+
+module.exports = {
+ lua_State: lua_State,
+ CallInfo: CallInfo
+}; \ No newline at end of file
diff --git a/src/lvm.js b/src/lvm.js
index 349cccf..7a65d74 100644
--- a/src/lvm.js
+++ b/src/lvm.js
@@ -14,7 +14,7 @@ class LuaVM {
return base + a;
}
- RB(base, opcode, base, b) {
+ RB(base, opcode, b) {
return base + b;
}
@@ -35,18 +35,21 @@ class LuaVM {
let ci = L.ci[this.L.ciOff];
newframe:
- let cl = ci.func;
- let k = cl.p.k;
- let base = ci.base;
-
for (;;) {
+ var cl = L.stack[ci.func];
+ let k = cl.p.k;
+ let base = ci.base;
+
let i = ci.savedpc[ci.pcOff++];
- let ra = this.RA(base, i.a);
+ let ra = this.RA(base, i.A);
+ console.log(OC.OpCodes[i.opcode]);
switch (OC.OpCodes[i.opcode]) {
case "OP_MOVE":
+ L.stack[ra] = RB(base, i.opcode, i.B);
break;
case "OP_LOADK":
+ L.stack[ra] = k[i.Bx];
break;
case "OP_LOADKX":
break;
@@ -121,6 +124,18 @@ class LuaVM {
case "OP_TAILCALL":
break;
case "OP_RETURN":
+ if (i.B >= 2) {
+ for (let j = 0; j <= i.B-2; j++) {
+ L.stack[L.ciOff + j] = L.stack[ra + j];
+ }
+ }
+ L.ci = ci.previous;
+
+ if (L.ci === null) return;
+
+ if (i.B !== 0) L.top = ci.top;
+
+ continue newframe;
break;
case "OP_FORLOOP":
break;
diff --git a/tests/lvm.js b/tests/lvm.js
new file mode 100644
index 0000000..6ee348d
--- /dev/null
+++ b/tests/lvm.js
@@ -0,0 +1,66 @@
+"use strict";
+
+const test = require('tape');
+const fs = require('fs');
+const child_process = require('child_process');
+const beautify = require('js-beautify').js_beautify;
+const tmp = require('tmp');
+const DataView = require('buffer-dataview');
+
+const BytecodeParser = require("../src/lundump.js");
+const lua_State = require("../src/lstate.js").lua_State;
+const LuaVM = require("../src/lvm.js").LuaVM;
+
+const toByteCode = function (luaCode) {
+ var luaFile = tmp.fileSync(),
+ bclist;
+
+ fs.writeSync(luaFile.fd, luaCode);
+
+ child_process.execSync(`luac-5.3 -o ${luaFile.name}.bc ${luaFile.name}`);
+ child_process.execSync(`luac-5.3 -l ${luaFile.name} > ${luaFile.name}.bc.txt`);
+
+ bclist = fs.readFileSync(`${luaFile.name}.bc.txt`, 'utf8');
+
+ console.log(bclist);
+
+ return {
+ dataView: new DataView(fs.readFileSync(`${luaFile.name}.bc`)),
+ bclist: bclist
+ };
+};
+
+const getVM = function (luaCode) {
+ var bc = toByteCode(luaCode),
+ dv = bc.dataView,
+ bcl = bc.bclist;
+
+ let p = new BytecodeParser(dv);
+ let cl = p.luaU_undump();
+
+ let L = new lua_State(cl);
+
+ return new LuaVM(L);
+};
+
+test('LOADK, RETURN', function (t) {
+ let luaCode = `
+ local a = "hello world"
+ return a
+ `, 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[0].value,
+ "hello world",
+ "Program output is correct"
+ );
+}); \ No newline at end of file