diff options
author | daurnimator <quae@daurnimator.com> | 2017-05-02 16:37:50 +1000 |
---|---|---|
committer | daurnimator <quae@daurnimator.com> | 2017-05-03 12:20:43 +1000 |
commit | cb0295e52870f22c5dd1a1726342b8d4b147b1c5 (patch) | |
tree | 3655d4d6f4873ed246c00c0eb6680a06124f3046 /src | |
parent | 50820e54d065bffbb504e6b20b6c27802e102c25 (diff) | |
download | fengari-cb0295e52870f22c5dd1a1726342b8d4b147b1c5.tar.gz fengari-cb0295e52870f22c5dd1a1726342b8d4b147b1c5.tar.bz2 fengari-cb0295e52870f22c5dd1a1726342b8d4b147b1c5.zip |
Refactor table implementation
Diffstat (limited to 'src')
-rw-r--r-- | src/lapi.js | 91 | ||||
-rw-r--r-- | src/lcode.js | 5 | ||||
-rw-r--r-- | src/ldebug.js | 6 | ||||
-rw-r--r-- | src/lobject.js | 39 | ||||
-rw-r--r-- | src/lstate.js | 8 | ||||
-rw-r--r-- | src/ltable.js | 191 | ||||
-rw-r--r-- | src/ltablib.js | 56 | ||||
-rw-r--r-- | src/ltm.js | 9 | ||||
-rw-r--r-- | src/lvm.js | 16 |
9 files changed, 235 insertions, 186 deletions
diff --git a/src/lapi.js b/src/lapi.js index a336220..4de27c2 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -329,18 +329,14 @@ const auxsetstr = function(L, t, k) { assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack"); - if (t.ttistable() && !lobject.table_index(t, k).ttisnil()) { - lobject.table_newindex(t, k, L.stack[L.top - 1]); - L.top--; /* pop value */ - } else { - L.stack[L.top++] = str; - lvm.settable(L, t, L.stack[L.top - 1], L.stack[L.top - 2]); - L.top -= 2; /* pop value and key */ - } + L.stack[L.top++] = str; + lvm.settable(L, t, L.stack[L.top - 1], L.stack[L.top - 2]); + /* pop value and key */ + L.top -= 2; }; const lua_setglobal = function(L, name) { - auxsetstr(L, L.l_G.l_registry.value.get(defs.LUA_RIDX_GLOBALS), name); + auxsetstr(L, ltable.luaH_getint(L.l_G.l_registry.value, defs.LUA_RIDX_GLOBALS), name); }; const lua_setmetatable = function(L, objindex) { @@ -351,13 +347,13 @@ const lua_setmetatable = function(L, objindex) { mt = null; else { assert(L.stack[L.top - 1].ttistable(), "table expected"); - mt = L.stack[L.top - 1]; + mt = L.stack[L.top - 1].value; } switch (obj.ttnov()) { case CT.LUA_TUSERDATA: case CT.LUA_TTABLE: { - obj.metatable = mt; + obj.value.metatable = mt; break; } default: { @@ -366,7 +362,7 @@ const lua_setmetatable = function(L, objindex) { } } - L.top--; + L.stack[--L.top] = void 0; return true; }; @@ -383,17 +379,23 @@ const lua_setfield = function(L, idx, k) { }; const lua_seti = function(L, idx, n) { + assert(typeof n === "number"); assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack"); let t = index2addr(L, idx); - lvm.settable(L, t, n, L.stack[L.top - 1]); - L.top--; /* pop value */ + L.stack[L.top++] = new TValue(CT.LUA_TNUMINT, n); + assert(L.top <= L.ci.top, "stack overflow"); + lvm.settable(L, t, L.stack[L.top - 1], L.stack[L.top - 2]); + /* pop value and key */ + L.stack[--L.top] = void 0; + L.stack[--L.top] = void 0; }; const lua_rawset = function(L, idx) { assert(2 < L.top - L.ci.funcOff, "not enough elements in the stack"); let o = index2addr(L, idx); assert(o.ttistable(), "table expected"); - lobject.table_newindex(o, L.stack[L.top - 2], L.stack[L.top - 1]); + let slot = ltable.luaH_set(o.value, L.stack[L.top - 2]); + slot.setfrom(L.stack[L.top - 1]); L.top -= 2; }; @@ -401,8 +403,9 @@ const lua_rawsetp = function(L, idx, p) { assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack"); let o = index2addr(L, idx); assert(L, o.ttistable(), "table expected"); - let k = p; - lobject.table_newindex(o, k, L.stack[L.top - 1]); + let k = new TValue(CT.LUA_TLIGHTUSERDATA, p); + let slot = ltable.luaH_set(o.value, k); + slot.setfrom(L.stack[L.top - 1]); L.top--; }; @@ -414,15 +417,10 @@ const auxgetstr = function(L, t, k) { assert(Array.isArray(k), "key must be an array of bytes"); let str = L.l_G.intern(k); - let slot = lobject.table_index(t, k); - if (t.ttistable() && !slot.ttisnil()) { - L.stack[L.top++] = slot; - assert(L.top <= L.ci.top, "stack overflow"); - } else { - L.stack[L.top++] = str; - assert(L.top <= L.ci.top, "stack overflow"); - lvm.gettable(L, t, L.stack[L.top - 1], L.top - 1); - } + + L.stack[L.top++] = str; + assert(L.top <= L.ci.top, "stack overflow"); + lvm.gettable(L, t, L.stack[L.top - 1], L.top - 1); return L.stack[L.top - 1].ttnov(); }; @@ -432,8 +430,7 @@ const lua_rawgeti = function(L, idx, n) { assert(t.ttistable(), "table expected"); - L.stack[L.top++] = lobject.table_index(t, n); - + L.stack[L.top++] = ltable.luaH_getint(t.value, n); assert(L.top <= L.ci.top, "stack overflow"); return L.stack[L.top - 1].ttnov(); @@ -442,8 +439,8 @@ const lua_rawgeti = function(L, idx, n) { const lua_rawgetp = function(L, idx, p) { let t = index2addr(L, idx); assert(t.ttistable(), "table expected"); - let k = p; - L.stack[L.top++] = lobject.table_index(t, k); + let k = new TValue(CT.LUA_TLIGHTUSERDATA, p); + L.stack[L.top++] = ltable.luaH_get(t.value, k); assert(L.top <= L.ci.top, "stack overflow"); return L.stack[L.top - 1].ttnov(); }; @@ -453,7 +450,7 @@ const lua_rawget = function(L, idx) { assert(t.ttistable(t), "table expected"); - L.stack[L.top - 1] = lobject.table_index(t, L.stack[L.top - 1]); + L.stack[L.top - 1] = ltable.luaH_get(t.value, L.stack[L.top - 1]); return L.stack[L.top - 1].ttnov(); }; @@ -550,7 +547,7 @@ const lua_getmetatable = function(L, objindex) { switch (obj.ttnov()) { case CT.LUA_TTABLE: case CT.LUA_TUSERDATA: - mt = obj.metatable; + mt = obj.value.metatable; break; default: mt = L.l_G.mt[obj.ttnov]; @@ -558,7 +555,7 @@ const lua_getmetatable = function(L, objindex) { } if (mt !== null && mt !== undefined) { - L.stack[L.top++] = mt; + L.stack[L.top++] = new TValue(CT.LUA_TTABLE, mt); assert(L.top <= L.ci.top, "stack overflow"); res = true; } @@ -587,20 +584,14 @@ const lua_getfield = function(L, idx, k) { const lua_geti = function(L, idx, n) { let t = index2addr(L, idx); - let slot = lobject.table_index(t, n); - if (!slot.ttisnil()) { - L.stack[L.top++] = slot; - assert(L.top <= L.ci.top, "stack overflow"); - } else { - L.stack[L.top++] = new TValue(CT.LUA_TNUMINT, n); - assert(L.top <= L.ci.top, "stack overflow"); - lvm.gettable(L, t, L.stack[L.top - 1], L.top - 1); - } + L.stack[L.top++] = new TValue(CT.LUA_TNUMINT, n); + assert(L.top <= L.ci.top, "stack overflow"); + lvm.gettable(L, t, L.stack[L.top - 1], L.top - 1); return L.stack[L.top - 1].ttnov(); }; const lua_getglobal = function(L, name) { - return auxgetstr(L, L.l_G.l_registry.value.get(defs.LUA_RIDX_GLOBALS), name); + return auxgetstr(L, ltable.luaH_getint(L.l_G.l_registry.value, defs.LUA_RIDX_GLOBALS), name); }; /* @@ -656,7 +647,7 @@ const lua_rawlen = function(L, idx) { case CT.LUA_TUSERDATA: return o.len; case CT.LUA_TTABLE: - return ltable.luaH_getn(o); + return ltable.luaH_getn(o.value); default: return 0; } @@ -819,8 +810,7 @@ const lua_load = function(L, reader, data, chunckname, mode) { let f = L.stack[L.top - 1].value; /* get newly created function */ if (f.nupvalues >= 1) { /* does it have an upvalue? */ /* get global table from registry */ - let reg = L.l_G.l_registry; - let gt = reg.value.get(defs.LUA_RIDX_GLOBALS); + let gt = ltable.luaH_getint(L.l_G.l_registry.value, defs.LUA_RIDX_GLOBALS); /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ f.upvals[0].u.value = new TValue(gt.type, gt.value); } @@ -936,14 +926,15 @@ const lua_error = function(L) { const lua_next = function(L, idx) { let t = index2addr(L, idx); assert(t.ttistable(), "table expected"); - let more = ltable.luaH_next(L, t, L.top - 1); + let more = ltable.luaH_next(L, t.value, L.top - 1); if (more) { L.top++; assert(L.top <= L.ci.top, "stack overflow"); - } else + return 1; + } else { L.top--; - - return more; + return 0; + } }; const lua_concat = function(L, n) { diff --git a/src/lcode.js b/src/lcode.js index 9fb7b06..690d07c 100644 --- a/src/lcode.js +++ b/src/lcode.js @@ -7,6 +7,7 @@ const llex = require('./llex.js'); const lobject = require('./lobject.js'); const lopcode = require('./lopcodes.js'); const lparser = require('./lparser.js'); +const ltable = require('./ltable.js'); require('./lstate.js'); /* XXX: if this isn't here then things break on require("ltm") */ const ltm = require('./ltm.js'); const lvm = require('./lvm.js'); @@ -482,7 +483,7 @@ const freeexps = function(fs, e1, e2) { */ const addk = function(fs, key, v) { let f = fs.f; - let idx = lobject.table_index(fs.ls.h, key); /* index scanner table */ + let idx = ltable.luaH_set(fs.ls.h.value, key); /* index scanner table */ if (idx && !idx.ttisnil()) { /* is there an index there? */ /* correct value? (warning: must distinguish floats from integers!) */ if (idx.value < fs.nk && f.k[idx.value].ttype() === v.ttype() && f.k[idx.value].value === v.value) @@ -490,7 +491,7 @@ const addk = function(fs, key, v) { } /* constant not found; create a new entry */ let k = fs.nk; - lobject.table_newindex(fs.ls.h, key, new TValue(CT.LUA_TNUMINT, k)); + idx.setivalue(k); f.k[k] = v; fs.nk++; return k; diff --git a/src/ldebug.js b/src/ldebug.js index d429457..d565829 100644 --- a/src/ldebug.js +++ b/src/ldebug.js @@ -180,12 +180,12 @@ const collectvalidlines = function(L, f) { assert(L.top <= L.ci.top, "stack overflow"); } else { let lineinfo = f.l.p.lineinfo; - let t = new TValue(CT.LUA_TTABLE, ltable.luaH_new(L)); - L.stack[L.top++] = t; + let t = ltable.luaH_new(L); + L.stack[L.top++] = new TValue(CT.LUA_TTABLE, t); assert(L.top <= L.ci.top, "stack overflow"); let v = new TValue(CT.LUA_TBOOLEAN, true); for (let i = 0; i < f.l.p.length; i++) - lobject.table_newindex(t, lineinfo[i], v); + ltable.luaH_setint(t, lineinfo[i], v); } }; diff --git a/src/lobject.js b/src/lobject.js index 784720b..d38e276 100644 --- a/src/lobject.js +++ b/src/lobject.js @@ -18,7 +18,6 @@ class TValue { this.id = tvalueCount++; this.type = type; this.value = value; - this.metatable = null; } /* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */ @@ -164,41 +163,6 @@ class TValue { const luaO_nilobject = new TValue(CT.LUA_TNIL, null); module.exports.luaO_nilobject = luaO_nilobject; -const table_keyValue = function(key) { - // Those lua values are used by value, others by reference - if (key instanceof TValue) { - if ([CT.LUA_TNIL, - CT.LUA_TBOOLEAN, - CT.LUA_TSTRING, - CT.LUA_TTHREAD, - CT.LUA_TNUMINT].indexOf(key.type) > -1) { - key = key.value; - } else if ([CT.LUA_TSHRSTR, CT.LUA_TLNGSTR].indexOf(key.type) > -1) { - key = key.value.map(e => `${e}|`).join(''); - } - } else if (typeof key === "string") { // To avoid - key = defs.to_luastring(key).map(e => `${e}|`).join(''); - } else if (Array.isArray(key)) { - key = key.map(e => `${e}|`).join(''); - } - - return key; -}; - -const table_newindex = function(table, key, value) { - key = table_keyValue(key); - - table.value.set(key, value); -}; - -const table_index = function(table, key) { - key = table_keyValue(key); - - let v = table.value.get(key); - - return v ? v : luaO_nilobject; -}; - class LClosure { constructor(L, n) { @@ -512,6 +476,3 @@ module.exports.luaO_str2num = luaO_str2num; module.exports.luaO_utf8desc = luaO_utf8desc; module.exports.luaO_utf8esc = luaO_utf8esc; module.exports.numarith = numarith; -module.exports.table_index = table_index; -module.exports.table_keyValue = table_keyValue; -module.exports.table_newindex = table_newindex; diff --git a/src/lstate.js b/src/lstate.js index 4b4aaa5..1b077d2 100644 --- a/src/lstate.js +++ b/src/lstate.js @@ -104,10 +104,10 @@ const stack_init = function(L1, L) { ** Create registry table and its predefined values */ const init_registry = function(L, g) { - let registry = new lobject.TValue(CT.LUA_TTABLE, ltable.luaH_new(L)); - g.l_registry = registry; - registry.value.set(defs.LUA_RIDX_MAINTHREAD, L); - registry.value.set(defs.LUA_RIDX_GLOBALS, new lobject.TValue(CT.LUA_TTABLE, ltable.luaH_new(L))); + let registry = ltable.luaH_new(L); + g.l_registry.sethvalue(registry); + ltable.luaH_setint(registry, defs.LUA_RIDX_MAINTHREAD, new lobject.TValue(CT.LUA_TTHREAD, L)); + ltable.luaH_setint(registry, defs.LUA_RIDX_GLOBALS, new lobject.TValue(CT.LUA_TTABLE, ltable.luaH_new(L))); }; /* diff --git a/src/ltable.js b/src/ltable.js index 432a91d..0d711b4 100644 --- a/src/ltable.js +++ b/src/ltable.js @@ -1,84 +1,167 @@ /*jshint esversion: 6 */ "use strict"; +const assert = require('assert'); + const defs = require('./defs.js'); +const ldebug = require('./ldebug.js'); const lobject = require('./lobject.js'); const CT = defs.constant_types; - -const ordered_intindexes = function(table) { - return [...table.value.keys()] - .filter(e => typeof e === 'number' && e % 1 === 0 && e > 0) // Only integer indexes - .sort(function (a, b) { - return a > b ? 1 : -1; - }); +/* converts strings (arrays) to a consistent map key */ +const hashstr = function(str) { + return str.map(e => `${e}|`).join(''); }; -const ordered_indexes = function(table) { - return [...table.value.keys()] - .sort(function(a, b) { - if (typeof a !== "number" || a <= 0) return 1; - if (typeof b !== "number" || b <= 0) return -1; - return a > b ? 1 : -1; - }); +const table_hash = function(key) { + switch(key.type) { + case CT.LUA_TBOOLEAN: + case CT.LUA_TLIGHTUSERDATA: /* XXX: if user pushes conflicting lightuserdata then the table will do odd things */ + case CT.LUA_TNUMFLT: + case CT.LUA_TNUMINT: + case CT.LUA_TTABLE: + case CT.LUA_TLCL: + case CT.LUA_TLCF: + case CT.LUA_TCCL: + case CT.LUA_TUSERDATA: + case CT.LUA_TTHREAD: + return key.value; + case CT.LUA_TSHRSTR: + case CT.LUA_TLNGSTR: + return hashstr(key.value); + default: + throw new Error("unknown key type: " + key.type); + } }; const luaH_new = function(L) { - let t = new Map(); + let t = { + strong: new Map(), + metatable: null + }; return t; }; -/* -** Try to find a boundary in table 't'. A 'boundary' is an integer index -** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil). -*/ -const luaH_getn = function(table) { - let indexes = ordered_intindexes(table); - let len = indexes.length; +const getgeneric = function(t, hash) { + let v = t.strong.get(hash); + return v ? v.value : lobject.luaO_nilobject; +}; - // If first index != 1, length is 0 - if (indexes[0] !== 1) return 0; +const luaH_getint = function(t, key) { + assert(typeof key == "number"); + return getgeneric(t, key); +}; - for (let i = 0; i < len; i++) { - let key = indexes[i]; +const luaH_getstr = function(t, key) { + assert(Array.isArray(key)); + return getgeneric(t, hashstr(key)); +}; - if (!lobject.table_index(table, key).ttisnil() // t[key] is non-nil - && (indexes[i + 1] - key > 1 || lobject.table_index(table, indexes[i + 1]).ttisnil())) { // gap with next key or next value is nil - return indexes[i]; - } - } +const luaH_get = function(t, key) { + assert(key instanceof lobject.TValue); + if (key.ttisnil()) + return lobject.luaO_nilobject; + return getgeneric(t, table_hash(key)); +}; - return 0; +const setgeneric = function(t, hash, key) { + let v = t.strong.get(hash); + if (v) + return v.value; + + let tv = new lobject.TValue(CT.LUA_TNIL, null); + t.strong.set(hash, { + key: key, + value: tv + }); + return tv; }; -const luaH_next = function(L, table, keyI) { - let keyO = L.stack[keyI]; - let key = lobject.table_keyValue(keyO); - let indexes = ordered_indexes(table); +const luaH_setint = function(t, key, value) { + assert(typeof key == "number" && value instanceof lobject.TValue && key|0 === key); + let hash = key; /* table_hash known result */ + let v = t.strong.get(hash); + if (v) { + let tv = v.value; + tv.setfrom(value); + } else { + t.strong.set(hash, { + key: new lobject.TValue(CT.LUA_TNUMINT, key), + value: new lobject.TValue(value.type, value.value) + }); + } +}; - if (indexes.length === 0) return 0; +const luaH_set = function(t, key) { + assert(key instanceof lobject.TValue); + let hash = table_hash(key); + return setgeneric(t, hash, new lobject.TValue(key.type, key.value)); +}; - let i = indexes.indexOf(key); +const luaH_delete = function(t, key) { + assert(key instanceof lobject.TValue); + let hash = table_hash(key); + t.strong.delete(hash); +}; - if ((i >= 0 || key === null) && i < indexes.length - 1) { - if (key === null) i = -1; - let nidx = indexes[i+1]; - let tnidx = typeof nidx; +/* +** Try to find a boundary in table 't'. A 'boundary' is an integer index +** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil). +*/ +const luaH_getn = function(t) { + let i = 0; + let j = t.strong.size + 1; /* use known size of Map to bound search */ + /* now do a binary search between them */ + while (j - i > 1) { + let m = Math.floor((i+j)/2); + if (luaH_getint(t, m).ttisnil()) j = m; + else i = m; + } + return i; +}; - if (tnidx === 'number' && nidx % 1 === 0) - L.stack[keyI] = new lobject.TValue(CT.LUA_TNUMINT, indexes[i + 1]); - else if (tnidx === 'string') - L.stack[keyI] = new lobject.TValue(CT.LUA_TLNGSTR, indexes[i + 1].split('|').map(e => Number.parseInt(e)).slice(0, -1)); - else - L.stack[keyI] = indexes[i + 1]; +/* +** Javascript tables don't have any next-like primitive. +** For each call of `next` this does a full iteration up to the item +*/ +const luaH_next = function(L, table, keyI) { + let keyO = L.stack[keyI]; - L.stack[keyI + 1] = table.value.get(indexes[i + 1]); - return 1; + let iterresult; + if (keyO.type === CT.LUA_TNIL) { + iterresult = table.strong.keys().next(); + } else { + let hash = table_hash(keyO); + + if (!table.strong.has(hash)) + /* item not in table */ + return ldebug.luaG_runerror(L, "invalid key to 'next'"); + + let indexes = table.strong.keys(); + while (1) { + let e = indexes.next(); + if (e.done) + throw "unreachable"; + else if (e.value == hash) + break; + } + iterresult = indexes.next(); } + if (iterresult.done) + return false; - return 0; + let entry = table.strong.get(iterresult.value); + L.stack[keyI] = new lobject.TValue(entry.key.type, entry.key.value); + L.stack[keyI+1] = new lobject.TValue(entry.value.type, entry.value.value); + return true; }; -module.exports.luaH_new = luaH_new; -module.exports.luaH_next = luaH_next; -module.exports.luaH_getn = luaH_getn; +module.exports.luaH_delete = luaH_delete; +module.exports.luaH_get = luaH_get; +module.exports.luaH_getint = luaH_getint; +module.exports.luaH_getn = luaH_getn; +module.exports.luaH_getstr = luaH_getstr; +module.exports.luaH_set = luaH_set; +module.exports.luaH_setint = luaH_setint; +module.exports.luaH_new = luaH_new; +module.exports.luaH_next = luaH_next; diff --git a/src/ltablib.js b/src/ltablib.js index 78c71e4..929cf4b 100644 --- a/src/ltablib.js +++ b/src/ltablib.js @@ -4,6 +4,7 @@ const lua = require('./lua.js'); const lapi = require('./lapi.js'); const lauxlib = require('./lauxlib.js'); const llimit = require('./llimit.js'); +const ltable = require('./ltable.js'); /* @@ -175,32 +176,43 @@ const unpack = function(L) { // TODO: Maybe do the quicksort after all const auxsort = function(L) { - let t = lapi.index2addr(L, 1); + let a = []; + for (let i=1; ;i++) { + if(lua.lua_geti(L, 1, i) === lua.LUA_TNIL) { + lua.lua_pop(L, 1); + break; + } + let t = lapi.index2addr(L, -1); + a.push({ + oldkey: i, + value: t + }); + lua.lua_pop(L, 1); + } + let sort_function; if (lua.lua_type(L, 2) !== lua.LUA_TFUNCTION) { /* no function? */ - [...t.value.entries()] - .sort(function (a, b) { - if (typeof a[0] !== 'number') return 1; - else if (typeof b[0] !== 'number') return -1; - return lapi.lua_compare_(L, a[1], b[1], lua.LUA_OPLT) === 1 ? -1 : 1; /* a < b */ - }) - .forEach((e, i) => typeof e[0] === 'number' ? t.value.set(i + 1, e[1]) : true); + sort_function = function (a, b) { + return lapi.lua_compare_(L, a.value, b.value, lua.LUA_OPLT) === 1 ? -1 : 1; /* a < b */ + }; } else { - [...t.value.entries()] - .sort(function (a, b) { - if (typeof a[0] !== 'number') return 1; - else if (typeof b[0] !== 'number') return -1; - - lua.lua_pushvalue(L, 2); /* push function */ - lua.lua_pushtvalue(L, a[1]); /* since we use Map.sort, a and b are not on the stack */ - lua.lua_pushtvalue(L, b[1]); - lua.lua_call(L, 2, 1); /* call function */ - let res = lua.lua_toboolean(L, -1); /* get result */ - lua.lua_pop(L, 1); /* pop result */ - return res ? -1 : 1; - }) - .forEach((e, i) => typeof e[0] === 'number' ? t.value.set(i + 1, e[1]) : true); + sort_function = function (a, b) { + lua.lua_pushvalue(L, 2); /* push function */ + lua.lua_pushtvalue(L, a.value); /* since we use Map.sort, a and b are not on the stack */ + lua.lua_pushtvalue(L, b.value); + lua.lua_call(L, 2, 1); /* call function */ + let res = lua.lua_toboolean(L, -1); /* get result */ + lua.lua_pop(L, 1); /* pop result */ + return res ? -1 : 1; + }; } + a.sort(sort_function) + .forEach(function(e, i) { + if (e.oldkey != i+1) { + lua.lua_pushtvalue(L, e.value); + lua.lua_seti(L, 1, i+1); + } + }); }; const sort = function(L) { @@ -7,6 +7,7 @@ const defs = require('./defs.js'); const lobject = require('./lobject.js'); const ldo = require('./ldo.js'); const lstate = require('./lstate.js'); +const ltable = require('./ltable.js'); const ldebug = require('./ldebug.js'); const lvm = require('./lvm.js'); const CT = defs.constant_types; @@ -69,9 +70,9 @@ const luaT_init = function(L) { */ const luaT_objtypename = function(L, o) { let mt; - if ((o.ttistable() && (mt = o.metatable) !== null) || + if ((o.ttistable() && (mt = o.value.metatable) !== null) || (o.ttisfulluserdata() && (mt = o.value.metatable) !== null)) { - let name = lobject.table_index(mt, defs.to_luastring('__name', true)); + let name = ltable.luaH_getstr(mt, defs.to_luastring('__name', true)); if (name.ttisstring()) return name.value; } @@ -142,13 +143,13 @@ const luaT_gettmbyobj = function(L, o, event) { switch(o.ttnov()) { case CT.LUA_TTABLE: case CT.LUA_TUSERDATA: - mt = o.metatable; + mt = o.value.metatable; break; default: mt = L.l_G.mt[o.ttnov()]; } - return mt ? lobject.table_index(mt, event) : lobject.luaO_nilobject; + return mt ? ltable.luaH_getstr(mt, event) : lobject.luaO_nilobject; }; module.exports.TMS = TMS; @@ -651,11 +651,11 @@ const luaV_execute = function(L) { c = ci.u.l.savedpc[ci.pcOff++].Ax; } - let table = L.stack[ra]; + let h = L.stack[ra].value; let last = ((c - 1) * OC.LFIELDS_PER_FLUSH) + n; for (; n > 0; n--) { - lobject.table_newindex(table, last--, L.stack[ra + n]); + ltable.luaH_setint(h, last--, L.stack[ra + n]); } L.top = ci.top; /* correct top (in case of previous open call) */ @@ -973,7 +973,7 @@ const luaV_objlen = function(L, ra, rb) { case CT.LUA_TTABLE: { tm = ltm.luaT_gettmbyobj(L, rb, ltm.TMS.TM_LEN); if (!tm.ttisnil()) break; - L.stack[ra] = new TValue(CT.LUA_TNUMINT, ltable.luaH_getn(rb)); + L.stack[ra] = new TValue(CT.LUA_TNUMINT, ltable.luaH_getn(rb.value)); return; } case CT.LUA_TSHRSTR: @@ -1051,10 +1051,10 @@ const gettable = function(L, table, key, ra, recur) { ldebug.luaG_runerror(L, defs.to_luastring("'__index' chain too long; possible loop", true)); if (table.ttistable()) { - let element = lobject.table_index(table, key); + let element = ltable.luaH_get(table.value, key); if (!element.ttisnil()) { - L.stack[ra] = element; + L.stack[ra] = new TValue(element.type, element.value); } else { luaV_finishget(L, table, key, ra, element, recur); } @@ -1094,10 +1094,10 @@ const settable = function(L, table, key, v, recur) { ldebug.luaG_runerror(L, defs.to_luastring("'__newindex' chain too long; possible loop", true)); if (table.ttistable()) { - let element = lobject.table_index(table, key); + let element = ltable.luaH_set(table.value, key); if (!element.ttisnil()) { - lobject.table_newindex(table, key, v); + element.setfrom(v); } else { luaV_finishset(L, table, key, v, element, recur); } @@ -1112,7 +1112,7 @@ const luaV_finishset = function(L, t, key, val, slot, recur) { assert(slot.ttisnil()); tm = ltm.luaT_gettmbyobj(L, t, ltm.TMS.TM_NEWINDEX); // TODO: fasttm if (tm.ttisnil()) { - lobject.table_newindex(t, key, val); + slot.setfrom(val); return; } } else { /* not a table; check metamethod */ |