diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ldo.js | 163 | ||||
-rw-r--r-- | src/llimit.js | 1 | ||||
-rw-r--r-- | src/ltm.js | 10 | ||||
-rw-r--r-- | src/lvm.js | 124 |
4 files changed, 180 insertions, 118 deletions
diff --git a/src/ldo.js b/src/ldo.js new file mode 100644 index 0000000..488bc86 --- /dev/null +++ b/src/ldo.js @@ -0,0 +1,163 @@ +/*jshint esversion: 6 */ +"use strict"; + +const OC = require('./lopcodes.js'); +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; +const LClosure = lobject.LClosure; +const lfunc = require('./lfunc.js'); +const UpVal = lfunc.UpVal; +const lstate = require('./lstate.js'); +const CallInfo = lstate.CallInfo; +const llimit = require('./llimit.js'); + +const nil = new TValue(CT.LUA_TNIL, null); + +const precall = function(L, off, func, nresults) { + let ci; + + switch(func.type) { + case CT.LUA_TCCL: // JS function ? + throw new Error("LUA_TCCL not implemeted yet"); + break; + case CT.LUA_TLCF: // still JS function ? + throw new Error("LUA_TLCF not implemeted yet"); + break; + case CT.LUA_TLCL: { + let p = func.p; + let n = L.top - off - 1; + let fsize = p.maxstacksize; + let base; + + if (p.is_vararg) { + base = adjust_varargs(L, p, n); + } else { + for (; n < p.numparams; n++) + L.stack[L.top++] = nil; // complete missing arguments + base = off + 1; + } + + // next_ci + if (L.ci.next) { + L.ci = L.ci.next; + ci = L.ci; + } else { + ci = new CallInfo(off); + L.ci.next = ci; + ci.previous = L.ci; + ci.next = null; + + L.ci = ci; + L.ciOff++; + } + ci.nresults = nresults; + ci.func = func; + ci.u.l.base = base; + ci.top = base + fsize; + L.top = ci.top; + ci.u.l.savedpc = p.code; + ci.callstatus = lstate.CIST_LUA; + + return false; + break; + } + default: + // __call + return false; + } +} + +const postcall = function(L, ci, firstResult, nres) { + let wanted = ci.nresults; + let res = ci.funcOff; + L.ci = ci.previous; + L.ciOff--; + return moveresults(L, firstResult, res, nres, wanted); +} + +const moveresults = function(L, firstResult, res, nres, wanted) { + switch (wanted) { + case 0: + break; + case 1: { + if (nres == 0) + firstResult = nil; + 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] = nil; + } + break; + } + } + + return true; +} + +const adjust_varargs = function(L, p, actual) { + 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; +} + + +/* +** Check appropriate error for stack overflow ("regular" overflow or +** overflow while handling stack overflow). If 'nCalls' is larger than +** LUAI_MAXCCALLS (which means it is handling a "regular" overflow) but +** smaller than 9/8 of LUAI_MAXCCALLS, does not report an error (to +** allow overflow handling to work) +*/ +const stackerror = function(L) { + if (L.nCcalls === LUAI_MAXCCALLS) + throw new Error("JS stack overflow"); + else if (L.nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) /* error while handing stack error */ + throw new Error("stack overflow") // TODO: luaD_throw(L, LUA_ERRERR); +} + +/* +** Call a function (JS or Lua). The function to be called is at func. +** The arguments are on the stack, right after the function. +** When returns, all the results are on the stack, starting at the original +** function position. +*/ +// const luaD_call = function(L, func, nResults) { +// if (++L->nCcalls >= LUAI_MAXCCALLS) +// stackerror(L); +// if () +// } + +module.exports = { + precall: precall, + postcall: postcall, + moveresults: moveresults, + adjust_varargs: adjust_varargs +}
\ No newline at end of file diff --git a/src/llimit.js b/src/llimit.js index 983871f..2cbfbb6 100644 --- a/src/llimit.js +++ b/src/llimit.js @@ -2,6 +2,7 @@ "use strict"; module.exports = { + LUAI_MAXCCALLS: 200, LUA_MAXINTEGER: 2147483647, LUA_MININTEGER: -2147483647 };
\ No newline at end of file diff --git a/src/ltm.js b/src/ltm.js new file mode 100644 index 0000000..ebc0348 --- /dev/null +++ b/src/ltm.js @@ -0,0 +1,10 @@ +/*jshint esversion: 6 */ +"use strict"; + +const lobject = require('./lobject.js'); +const TValue = lobject.TValue; +const Table = lobject.Table; + + + +module.exports = {}
\ No newline at end of file @@ -17,8 +17,7 @@ const UpVal = lfunc.UpVal; const lstate = require('./lstate.js'); const CallInfo = lstate.CallInfo; const llimit = require('./llimit.js'); - -const nil = new TValue(CT.LUA_TNIL, null); +const ldo = require('./ldo.js'); class LuaVM { @@ -85,7 +84,7 @@ class LuaVM { } case "OP_LOADNIL": { for (let j = 0; j <= i.B; j++) - L.stack[ra + j] = nil; + L.stack[ra + j] = ldo.nil; break; } case "OP_GETUPVAL": { @@ -429,7 +428,7 @@ class LuaVM { if (b !== 0) L.top = ra+b; - if (this.precall(ra, L.stack[ra], nresults)) { + if (ldo.precall(L, ra, L.stack[ra], nresults)) { if (nresults >= 0) L.top = ci.top; base = ci.u.l.base; @@ -442,7 +441,7 @@ class LuaVM { } case "OP_TAILCALL": { if (i.B !== 0) L.top = ra + i.B; - if (this.precall(ra, L.stack[ra], LUA_MULTRET)) { // JS function + if (ldo.precall(L, ra, L.stack[ra], LUA_MULTRET)) { // JS function base = ci.u.l.base; } else { /* tail call: put called frame (n) in place of caller one (o) */ @@ -475,7 +474,7 @@ class LuaVM { } case "OP_RETURN": { if (cl.p.p.length > 0) this.closeupvals(base); - let b = this.postcall(ci, ra, (i.B !== 0 ? i.B - 1 : L.top - ra)); + let b = ldo.postcall(L, ci, ra, (i.B !== 0 ? i.B - 1 : L.top - ra)); if (ci.callstatus & lstate.CIST_FRESH) return; /* external invocation: return */ @@ -617,7 +616,7 @@ class LuaVM { L.stack[ra + j] = L.stack[base - n + j]; for (; j < b; j++) /* complete required results with nil */ - L.stack[ra + j] = nil; + L.stack[ra + j] = ldo.nil; break; } case "OP_EXTRAARG": { @@ -627,98 +626,6 @@ class LuaVM { } } - precall(off, func, nresults) { - let L = this.L; - let ci; - - switch(func.type) { - case CT.LUA_TCCL: // JS function ? - throw new Error("LUA_TCCL not implemeted yet") - break; - case CT.LUA_TLCF: // still JS function ? - throw new Error("LUA_TLCF not implemeted yet") - break; - case CT.LUA_TLCL: { - let p = func.p; - let n = L.top - off - 1; - let fsize = p.maxstacksize; - let base; - - if (p.is_vararg) { - base = this.adjust_varargs(p, n); - } else { - for (; n < p.numparams; n++) - L.stack[L.top++] = nil; // complete missing arguments - base = off + 1; - } - - // next_ci - if (L.ci.next) { - L.ci = L.ci.next; - } else { - ci = new CallInfo(off); - L.ci.next = ci; - ci.previous = L.ci; - ci.next = null; - - L.ci = ci; - L.ciOff++; - } - ci.nresults = nresults; - ci.func = func; - ci.u.l.base = base; - ci.top = base + fsize; - L.top = ci.top; - ci.u.l.savedpc = p.code; - ci.callstatus = lstate.CIST_LUA; - break; - } - default: - // __call - } - } - - postcall(ci, firstResult, nres) { - let wanted = ci.nresults; - let res = ci.funcOff; - 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 = nil; - 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] = nil; - } - break; - } - } - - return true; - } - findupval(level) { let L = this.L; let pp = L.openupval; @@ -759,25 +666,6 @@ class LuaVM { } } - 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; - } - dojump(ci, i, e) { let a = i.A; if (a != 0) closeupvals(ci.u.l.base + a - 1); |