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 --- src/lfunc.js | 1 + src/lua.js | 3 ++- src/lvm.js | 58 +++++++++++++++++++++++++++++++++++++++++++++------------- 3 files changed, 48 insertions(+), 14 deletions(-) (limited to 'src') 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 -- cgit v1.2.3-54-g00ecf