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 | 52 | 
4 files changed, 75 insertions, 37 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)]; +                    let table = L.stack[ra]; +                    let key = this.RKB(base, k, i); +                    let v = this.RKC(base, k, i); -                    if (!t.ttistable() || !t.value.__index(t, k)) { -                        // __index -                    } else { -                        t.value.__newindex(t, k, v); -                    } +                    // if (!table.ttistable() || !table.metatable.__index(table, key)) { +                    //     // __index +                    // } else { +                        table.metatable.__newindex(table, key, v); +                    // }                      break;                  } | 
