From dfe6b5f2c1bde6900f81f1bb6ddc49724baa0471 Mon Sep 17 00:00:00 2001 From: Benoit Giannangeli Date: Mon, 6 Feb 2017 08:15:05 +0100 Subject: RETURN follow lua's source more accurately --- .gitignore | 1 + luac.out | Bin 334 -> 0 bytes src/lfunc.js | 1 + src/lua.js | 3 ++- src/lvm.js | 58 +++++++++++++++++++++++++++++++++++++++++++++------------- tests/lvm.js | 12 ++++++------ 6 files changed, 55 insertions(+), 20 deletions(-) delete mode 100644 luac.out 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 Binary files a/luac.out and /dev/null 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" ); -- cgit v1.2.3-70-g09d2