aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ldo.js163
-rw-r--r--src/llimit.js1
-rw-r--r--src/ltm.js10
-rw-r--r--src/lvm.js124
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
diff --git a/src/lvm.js b/src/lvm.js
index bd3e2c4..479dcfe 100644
--- a/src/lvm.js
+++ b/src/lvm.js
@@ -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);