summaryrefslogtreecommitdiff
path: root/src/lvm.js
diff options
context:
space:
mode:
authorBenoit Giannangeli <giann008@gmail.com>2017-02-04 09:01:25 +0100
committerBenoit Giannangeli <giann008@gmail.com>2017-02-04 22:17:24 +0100
commit18b89ee8e1059a21f8d5e3a52c2e256b7dea79cb (patch)
tree3f215ba709174b057ea76b2a8b0fbb2f6ad850e5 /src/lvm.js
parentb618b835c74a8637e00ba1f4adf6b8884d360d43 (diff)
downloadfengari-18b89ee8e1059a21f8d5e3a52c2e256b7dea79cb.tar.gz
fengari-18b89ee8e1059a21f8d5e3a52c2e256b7dea79cb.tar.bz2
fengari-18b89ee8e1059a21f8d5e3a52c2e256b7dea79cb.zip
CLOSURE, CALL
Diffstat (limited to 'src/lvm.js')
-rw-r--r--src/lvm.js128
1 files changed, 118 insertions, 10 deletions
diff --git a/src/lvm.js b/src/lvm.js
index 9518721..963d545 100644
--- a/src/lvm.js
+++ b/src/lvm.js
@@ -1,11 +1,16 @@
-/*jshint esversion: 6 */
+ /*jshint esversion: 6 */
"use strict";
const BytecodeParser = require("./lundump.js");
const OC = require('./lopcodes.js');
const CT = require('./lua.js').constant_types;
-const TValue = require('./lobject.js').TValue;
-const Table = require('./lobject.js').Table;
+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 CallInfo = require('./lstate.js').CallInfo;
class LuaVM {
@@ -52,11 +57,11 @@ class LuaVM {
newframe:
for (;;) {
- var cl = L.stack[ci.func];
+ var cl = ci.func;
let k = cl.p.k;
let base = ci.base;
- let i = ci.savedpc[ci.pcOff++];
+ let i = ci.u.l.savedpc[ci.pcOff++];
let ra = this.RA(base, i);
switch (OC.OpCodes[i.opcode]) {
@@ -69,8 +74,8 @@ class LuaVM {
break;
}
case "OP_LOADKX": {
- assert(OC.OpCodes[ci.savedpc[ci.pcOff].opcode] === "OP_EXTRAARG");
- L.stack[ra] = k[ci.savedpc[ci.pcOff++].Ax];
+ assert(OC.OpCodes[ci.u.l.savedpc[ci.pcOff].opcode] === "OP_EXTRAARG");
+ L.stack[ra] = k[ci.u.l.savedpc[ci.pcOff++].Ax];
break;
}
case "OP_LOADBOOL": {
@@ -92,15 +97,15 @@ class LuaVM {
case "OP_GETTABUP": {
break;
}
- case "OP_GETTABLE": {
- break;
- }
case "OP_SETTABUP": {
break;
}
case "OP_SETUPVAL": {
break;
}
+ case "OP_GETTABLE": {
+ break;
+ }
case "OP_SETTABLE": {
break;
}
@@ -345,6 +350,16 @@ class LuaVM {
break;
}
case "OP_CALL": {
+ let b = i.B;
+ let nresults = i.C - 1;
+
+ if (b !== 0)
+ L.top = ra+b;
+
+ this.precall(ra, L.stack[ra], nresults);
+ ci = L.ci;
+ continue newframe;
+
break;
}
case "OP_TAILCALL": {
@@ -383,6 +398,20 @@ class LuaVM {
break;
}
case "OP_CLOSURE": {
+ let p = cl.p.p[i.Bx];
+ let nup = p.upvalues.length;
+ let uv = p.upvalues;
+ let ncl = new LClosure(nup);
+ ncl.p = p;
+
+ L.stack[ra] = ncl;
+
+ for (let i = 0; i < nup; i++) { // TODO test
+ if (uv[i].instack)
+ ncl.upvals[i] = this.findupval(base + uv[i].idx);
+ else
+ ncl.upvals[i] = cl.upvals[uv[i].idx];
+ }
break;
}
case "OP_VARARG": {
@@ -395,6 +424,85 @@ 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 = adjust_varargs(L, p, n);
+ } else {
+ for (; n < p.numparams; n++)
+ L.stack[L.top++] = new TValue(CT.LUA_TNIL, null);
+ base = off + 1;
+ }
+
+ // next_ci
+ if (L.ci.next) {
+ L.ci = L.ci.next;
+ } else {
+ ci = new CallInfo();
+ L.ci.next = ci;
+ ci.previous = L.ci;
+ ci.next = null;
+
+ L.ci = ci;
+ }
+ 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;
+ break;
+ }
+ default:
+ // __call
+ }
+ }
+
+ postcall(ci, firstResult, nres) {
+
+ }
+
+ findupval(level) { // TODO test
+ let pp = L.openupval;
+
+ while(pp !== null && pp.v >= level) {
+ let p = pp;
+
+ if (p.v === level)
+ return p;
+
+ pp = p.u.open.next;
+ }
+
+ let uv = new UpVal();
+ uv.refcount = 0;
+ uv.u.open.next = pp;
+ uv.u.open.touched = true;
+
+ pp = uv;
+
+ uv.v = level;
+
+ // Thread with upvalue list business ? lfunc.c:75
+
+ return uv;
+ }
+
}
module.exports = {