aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--luac.outbin334 -> 0 bytes
-rw-r--r--src/lfunc.js1
-rw-r--r--src/lua.js3
-rw-r--r--src/lvm.js58
-rw-r--r--tests/lvm.js12
6 files changed, 55 insertions, 20 deletions
diff --git a/.gitignore b/.gitignore
index 16699e3..9b97118 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,3 +39,4 @@ jspm_packages
# JSDoc
help
+luac.out \ No newline at end of file
diff --git a/luac.out b/luac.out
deleted file mode 100644
index 7cb0869..0000000
--- a/luac.out
+++ /dev/null
Binary files differ
diff --git a/src/lfunc.js b/src/lfunc.js
index 929dae8..abc87e8 100644
--- a/src/lfunc.js
+++ b/src/lfunc.js
@@ -17,6 +17,7 @@ class Proto {
this.linedefined = 0; // debug information
this.lastlinedefined = 0; // debug information
this.source = null; // used for debug information
+ this.nresults = 0; // expected number of results from this function
}
}
diff --git a/src/lua.js b/src/lua.js
index c496c33..1989133 100644
--- a/src/lua.js
+++ b/src/lua.js
@@ -37,5 +37,6 @@ constant_types.LUA_TCCL = constant_types.LUA_TFUNCTION | (2 << 4); /* C closure
module.exports = {
constant_types: constant_types,
- thread_status: thread_status
+ thread_status: thread_status,
+ LUA_MULTRET: -1
}; \ No newline at end of file
diff --git a/src/lvm.js b/src/lvm.js
index 0fa1de5..155e057 100644
--- a/src/lvm.js
+++ b/src/lvm.js
@@ -3,7 +3,9 @@
const BytecodeParser = require("./lundump.js");
const OC = require('./lopcodes.js');
-const CT = require('./lua.js').constant_types;
+const lua = require('./lua.js');
+const CT = lua.constant_types;
+const LUA_MULTRET = lua.LUA_MULTRET;
const lobject = require('./lobject.js');
const TValue = lobject.TValue;
const Table = lobject.Table;
@@ -366,21 +368,14 @@ class LuaVM {
break;
}
case "OP_RETURN": {
- if (i.B >= 2) {
- // TODO moveresults, ldo.c:334
- for (let j = 0; j <= i.B-2; j++) {
- L.stack[L.ciOff + j] = L.stack[ra + j];
- L.top++;
- }
- }
- L.ciOff--;
- L.ci = ci.previous;
+ let b = this.postcall(ci, ra, (i.B !== 0 ? i.B - 1 : L.top - ra));
+ // TODO call status check
+ ci = L.ci;
// TODO what to return when end of program ?
if (L.ci === null) return;
- if (i.B !== 0) L.top = ci.top;
-
+ if (b) L.top = ci.top;
continue newframe;
break;
}
@@ -477,7 +472,44 @@ class LuaVM {
}
postcall(ci, firstResult, nres) {
-
+ let wanted = ci.nresults;
+ let res = ci.func;
+ this.L.ci = ci.previous;
+ this.L.ciOff--;
+ return this.moveresults(firstResult, res, nres, wanted);
+ }
+
+ moveresults(firstResult, res, nres, wanted) {
+ let L = this.L;
+
+ switch (wanted) {
+ case 0:
+ break;
+ case 1: {
+ if (nres == 0)
+ firstResult = new TValue(CT.LUA_TNIL, null);
+ L.stack[res] = L.stack[firstResult];
+ break;
+ }
+ case LUA_MULTRET: {
+ for (let i = 0; i < nres; i++)
+ L.stack[res + i] = L.stack[firstResult + i];
+ L.top = res + nres;
+ return false;
+ }
+ default: {
+ let i;
+ if (wanted <= nres) {
+ for (i = 0; i < wanted; i++)
+ L.stack[res + i] = L.stack[firstResult + i];
+ for (; i < wanted; i++)
+ L.stack[res + i] = new TValue(CT.LUA_TNIL, null);
+ }
+ break;
+ }
+ }
+
+ return true;
}
findupval(level) { // TODO test
diff --git a/tests/lvm.js b/tests/lvm.js
index 54c40ae..d328b6b 100644
--- a/tests/lvm.js
+++ b/tests/lvm.js
@@ -61,7 +61,7 @@ test('LOADK, RETURN', function (t) {
}, "Program executed without errors");
t.strictEqual(
- vm.L.stack[vm.L.top - 1].value,
+ vm.L.stack[vm.L.top].value,
"hello world",
"Program output is correct"
);
@@ -85,7 +85,7 @@ test('MOV', function (t) {
}, "Program executed without errors");
t.strictEqual(
- vm.L.stack[vm.L.top - 1].value,
+ vm.L.stack[vm.L.top].value,
"hello world",
"Program output is correct"
);
@@ -108,7 +108,7 @@ test('Binary op', function (t) {
}, "Program executed without errors");
t.deepEqual(
- vm.L.stack.slice(vm.L.top - 12 - 1, vm.L.top - 1).map(function (e) { return e.value; }),
+ vm.L.stack.slice(vm.L.top, vm.L.top + 12).map(function (e) { return e.value; }),
[15, -5, 50, 0.5, 5, 9765625.0, 0, 0, 15, 15, 5120, 0],
"Program output is correct"
);
@@ -132,7 +132,7 @@ test('Unary op, LOADBOOL', function (t) {
}, "Program executed without errors");
t.deepEqual(
- vm.L.stack.slice(vm.L.top - 3 - 1, vm.L.top - 1).map(function (e) { return e.value; }),
+ vm.L.stack.slice(vm.L.top - 3, vm.L.top).map(function (e) { return e.value; }),
[-5, true, -6],
"Program output is correct"
);
@@ -155,7 +155,7 @@ test('NEWTABLE', function (t) {
}, "Program executed without errors");
t.ok(
- vm.L.stack[vm.L.top - 1] instanceof Table,
+ vm.L.stack[vm.L.top] instanceof Table,
"Program output is correct"
);
});
@@ -182,7 +182,7 @@ test('CALL', function (t) {
}, "Program executed without errors");
t.strictEqual(
- vm.L.stack[vm.L.top - 1].value,
+ vm.L.stack[vm.L.top].value,
3,
"Program output is correct"
);