diff options
-rw-r--r-- | src/lvm.js | 40 | ||||
-rw-r--r-- | tests/lvm.js | 12 |
2 files changed, 37 insertions, 15 deletions
@@ -16,6 +16,8 @@ const lfunc = require('./lfunc.js'); const UpVal = lfunc.UpVal; const CallInfo = require('./lstate.js').CallInfo; +const nil = new TValue(CT.LUA_TNIL, null); + class LuaVM { constructor(L) { @@ -92,7 +94,7 @@ class LuaVM { } case "OP_LOADNIL": { for (let j = 0; j <= i.B; j++) - L.stack[ra + j] = new TValue(CT.LUA_TNIL, null); + L.stack[ra + j] = nil; break; } case "OP_GETUPVAL": { @@ -451,7 +453,7 @@ class LuaVM { case "OP_VARARG": { let b = i.B - 1; let n = base - ci.funcOff - cl.p.numparams - 1; - let j + let j; if (n < 0) /* less arguments than parameters? */ n = 0; /* no vararg arguments */ @@ -459,15 +461,16 @@ class LuaVM { if (b < 0) { b = n; /* get all var. arguments */ base = ci.u.l.base; - ra = this.RA(i); /* previous call may change the stack */ + ra = this.RA(base, i); /* previous call may change the stack */ + L.top = ra + n; } for (j = 0; j < b && j < n; j++) - L.stack[ra + j] = L.stack[base - n - j]; + L.stack[ra + j] = L.stack[base - n + j]; for (; j < b; j++) /* complete required results with nil */ - L.stack[ra + j] = new TValue(CT.LUA_TNIL, null); + L.stack[ra + j] = nil; break; } case "OP_EXTRAARG": { @@ -495,10 +498,10 @@ class LuaVM { let base; if (p.is_vararg) { - // base = adjust_varargs(L, p, n); + base = this.adjust_varargs(p, n); } else { for (; n < p.numparams; n++) - L.stack[L.top++] = new TValue(CT.LUA_TNIL, null); // complete missing arguments + L.stack[L.top++] = nil; // complete missing arguments base = off + 1; } @@ -543,7 +546,7 @@ class LuaVM { break; case 1: { if (nres == 0) - firstResult = new TValue(CT.LUA_TNIL, null); + firstResult = nil; L.stack[res] = L.stack[firstResult]; break; } @@ -559,7 +562,7 @@ class LuaVM { 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); + L.stack[res + i] = nil; } break; } @@ -594,6 +597,25 @@ class LuaVM { return uv; } + adjust_varargs (p, actual) { + let L = this.L; + let nfixargs = p.numparams; + /* move fixed parameters to final position */ + let fixed = L.top - actual; /* first fixed argument */ + let base = L.top; /* final position of first argument */ + + let i; + for (i = 0; i < nfixargs && i < actual; i++) { + L.stack[L.top++] = L.stack[fixed + i]; + L.stack[fixed + i] = nil; + } + + for (; i < nfixargs; i++) + L.stack[L.top++] = nil; + + return base; + } + } module.exports = { diff --git a/tests/lvm.js b/tests/lvm.js index 62f9fff..e10ddb2 100644 --- a/tests/lvm.js +++ b/tests/lvm.js @@ -249,11 +249,11 @@ test('TAILCALL', function (t) { test('VARARG', function (t) { let luaCode = ` - local f = function (a, b) - return a + b + local f = function (...) + return ... end - return f(1,2) + return f(1,2,3) `, vm; t.plan(2); @@ -265,9 +265,9 @@ test('VARARG', function (t) { vm.execute(); }, "Program executed without errors"); - t.strictEqual( - vm.L.stack[vm.L.top - 1].value, - 3, + t.deepEqual( + vm.L.stack.slice(vm.L.stack.length - 3).map(function (e) { return e.value; }), + [1, 2, 3], "Program output is correct" ); });
\ No newline at end of file |