diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lfunc.js | 19 | ||||
-rw-r--r-- | src/lobject.js | 37 | ||||
-rw-r--r-- | src/lstate.js | 4 | ||||
-rw-r--r-- | src/lvm.js | 54 |
4 files changed, 76 insertions, 38 deletions
diff --git a/src/lfunc.js b/src/lfunc.js index 929dae8..2c33a7d 100644 --- a/src/lfunc.js +++ b/src/lfunc.js @@ -24,16 +24,25 @@ class Proto { class UpVal { constructor() { - this.v = null; + this.v = null; /* if null, upval is closed, value is in u.value */ this.u = { - open: { - next: null, - touched: false + open: { /* (when open) */ + next: null, /* linked list */ + touched: false /* mark to avoid cycles with dead threads */ }, - value: null + value: null /* the value (when closed) */ }; } + val(L) { + return this.v !== null ? L.stack[this.v] : this.u.value; + } + + setval(L, ra) { + if (this.v !== null) this.v = ra; + else this.u.value = L.stack[ra]; + } + } module.exports = { diff --git a/src/lobject.js b/src/lobject.js index 3781623..a1ed6ca 100644 --- a/src/lobject.js +++ b/src/lobject.js @@ -1,8 +1,8 @@ /*jshint esversion: 6 */ "use strict"; -const CT = require('./lua.js').constant_types; - +const CT = require('./lua.js').constant_types; +const UpVal = require('./lfunc.js').UpVal; class TValue { @@ -59,15 +59,15 @@ class TValue { } ttisshrstring() { - return this.checktag(ctb(CT.LUA_TSHRSTR)); + return this.checktag(CT.LUA_TSHRSTR); } ttislngstring() { - return this.checktag(ctb(CT.LUA_TLNGSTR)); + return this.checktag(CT.LUA_TLNGSTR); } ttistable() { - return this.checktag(ctb(CT.LUA_TTABLE)); + return this.checktag(CT.LUA_TTABLE); } ttisfunction() { @@ -79,11 +79,11 @@ class TValue { } ttisCclosure() { - return this.checktag(ctb(CT.LUA_TCCL)); + return this.checktag(CT.LUA_TCCL); } ttisLclosure() { - return this.checktag(ctb(CT.LUA_TLCL)); + return this.checktag(CT.LUA_TLCL); } ttislcf() { @@ -91,11 +91,11 @@ class TValue { } ttisfulluserdata() { - return this.checktag(ctb(CT.LUA_TUSERDATA)); + return this.checktag(CT.LUA_TUSERDATA); } ttisthread() { - return this.checktag(ctb(CT.LUA_TTHREAD)); + return this.checktag(CT.LUA_TTHREAD); } ttisdeadkey() { @@ -112,7 +112,16 @@ class LClosure extends TValue { this.p = null; this.nupvalues = n; - this.upvals = []; + + let _ENV = new UpVal(); + _ENV.refcount = 0; + _ENV.v = 0; // _ENV is on the stack at index 0 + _ENV.u.open.next = null; + _ENV.u.open.touched = true; + + this.upvals = [ + _ENV + ]; this.value = this; } @@ -139,10 +148,10 @@ class Table extends TValue { this.usermetatable = null; this.metatable = { - __newindex: function (table, key) { + __newindex: function (table, key, value) { if (key instanceof TValue) { // Those lua values are used by value, tables and functions by reference - if ([CT.TNUMBER, CT.TSTRING, CT.TSHRSTR, CT.TLNGSTR, CT.TNUMFLT, CT.TNUMINT].indexOf(key.type) > -1) { + if ([CT.LUA_TNUMBER, CT.LUA_TSTRING, CT.LUA_TSHRSTR, CT.LUA_TLNGSTR, CT.LUA_TNUMFLT, CT.LUA_TNUMINT].indexOf(key.type) > -1) { key = key.value; } } @@ -154,10 +163,10 @@ class Table extends TValue { } }, - __index: function (table, key, value) { + __index: function (table, key) { if (key instanceof TValue) { // Those lua values are used by value, tables and functions by reference - if ([CT.TNUMBER, CT.TSTRING, CT.TSHRSTR, CT.TLNGSTR, CT.TNUMFLT, CT.TNUMINT].indexOf(key.type) > -1) { + if ([CT.LUA_TNUMBER, CT.LUA_TSTRING, CT.LUA_TSHRSTR, CT.LUA_TLNGSTR, CT.LUA_TNUMFLT, CT.LUA_TNUMINT].indexOf(key.type) > -1) { key = key.value; } } diff --git a/src/lstate.js b/src/lstate.js index 37f2d6b..2c322c3 100644 --- a/src/lstate.js +++ b/src/lstate.js @@ -2,6 +2,7 @@ "use strict"; const LUA_MULTRET = require('./lua.js').LUA_MULTRET; +const Table = require('./lobject.js').Table; class CallInfo { @@ -27,12 +28,13 @@ class CallInfo { class lua_State { constructor(cl) { - this.top = 1; + this.top = 2; this.ci = new CallInfo(0, cl, 1, 1, null, null); this.ci.u.l.savedpc = cl.p.code; this.ci.nresults = LUA_MULTRET; this.ciOff = 0; this.stack = [ + new Table(), // _ENV cl ]; this.openupval = []; @@ -89,40 +89,58 @@ class LuaVM { break; } case "OP_GETUPVAL": { - L.stack[ra] = L.stack[cl.upvals[i.B].v]; + L.stack[ra] = cl.upvals[i.B].val(L); break; } case "OP_SETUPVAL": { - L.stack[cl.upvals[i.B].v] = L.stack[ra]; + cl.upvals[i.B].setval(L, ra); break; } case "OP_GETTABUP": { + let table = cl.upvals[i.B].val(L); + let key = this.RKC(base, k, i); + + // if (!table.ttistable() || !table.metatable.__index(table, key)) { + // // __index + // } else { + L.stack[ra] = table.metatable.__index(table, key); + // } break; } case "OP_SETTABUP": { + let table = cl.upvals[i.A].val(L); + let key = this.RKB(base, k, i); + let v = this.RKC(base, k, i); + + // if (!table.ttistable() || !table.metatable.__index(table, key)) { + // // __index + // } else { + table.metatable.__newindex(table, key, v); + // } + break; } case "OP_GETTABLE": { - let t = L.stack[this.RKB(base, i)]; - let k = L.stack[this.RKC(base, i)]; + let table = this.RKB(base, k, i); + let key = this.RKC(base, k, i); - if (!t.ttistable() || !t.value.__index(t, k)) { - // __index - } else { - L.stack[ra] = t.value.__index(t, k); - } + // if (!table.ttistable() || !table.metatable.__index(table, key)) { + // // __index + // } else { + L.stack[ra] = table.metatable.__index(table, key); + // } break; } case "OP_SETTABLE": { - let t = L.stack[ra]; - let k = L.stack[this.RKB(base, i)]; - let v = L.stack[this.RKC(base, i)]; - - if (!t.ttistable() || !t.value.__index(t, k)) { - // __index - } else { - t.value.__newindex(t, k, v); - } + let table = L.stack[ra]; + let key = this.RKB(base, k, i); + let v = this.RKC(base, k, i); + + // if (!table.ttistable() || !table.metatable.__index(table, key)) { + // // __index + // } else { + table.metatable.__newindex(table, key, v); + // } break; } |