diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lfunc.js | 1 | ||||
-rw-r--r-- | src/lua.js | 3 | ||||
-rw-r--r-- | src/lvm.js | 58 |
3 files changed, 48 insertions, 14 deletions
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 } } @@ -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 @@ -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 |