diff options
Diffstat (limited to 'src/ltable.js')
-rw-r--r-- | src/ltable.js | 69 |
1 files changed, 51 insertions, 18 deletions
diff --git a/src/ltable.js b/src/ltable.js index c1d5430..14139af 100644 --- a/src/ltable.js +++ b/src/ltable.js @@ -4,35 +4,68 @@ const assert = require('assert'); const lobject = require('./lobject.js'); +const lua = require('./lua.js'); +const CT = lua.constant_types; const nil = require('./ldo.js').nil; const Table = lobject.Table; +Table.prototype.ordered_intindexes = function() { + return [...this.value.keys()] + .filter(e => typeof e === 'number' && e % 1 === 0) // Only integer indexes + .sort(); +}; + +Table.prototype.ordered_indexes = function() { + return [...this.value.keys()] + .sort(function(a, b) { + if (typeof a !== "number") return 1; + if (typeof b !== "number") return -1; + return a > b ? 1 : -1 + }) +}; + /* ** 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). */ Table.prototype.luaH_getn = function() { - let array = this.value.array; - let hash = this.value.hash; - - let j = array.length; - if (j > 0 && array[j - 1].ttisnil()) { - /* there is a boundary in the array part: (binary) search for it */ - let i = 0; - while (j - i > 1) { - let m = (i+j)/2; - if (array[m - 1].ttisnil()) j = m; - else i = m; + // TODO: is this costly ? + let indexes = this.ordered_intindexes(); + let len = indexes.length; + + for (let i = 0; i < len; i++) { + let key = indexes[i]; + + if (!this.value.get(key).ttisnil() // t[i] is non-nil + && (i === len - 1 || this.value.get(indexes[i + 1]).ttisinil())) { // t[i+1] is nil or is the last integer indexed element + return indexes[i]; } - return i; } - /* else must find a boundary in hash part */ - else if (hash.size === 0) - return j; - else return hash.get(j); + + return 0; }; -Table.prototype.luaH_next = function(key) { - +Table.prototype.luaH_next = function(L, keyI) { + let keyO = L.stack[keyI]; + let key = Table.keyValue(keyO); + let indexes = this.ordered_indexes(); + let i = indexes.indexOf(key); + + if (i >= 0 && i < indexes.length - 1) { + let nidx = indexes[i+1]; + let tnidx = typeof nidx; + + if (tnidx === 'number' && nidx % 1 === 0) + L.stack[keyI] = new TValue(CT.LUA_TNUMINT, indexes[i + 1]); + else if (tnidx === 'string') + L.stack[keyI] = new TValue(CT.LUA_TLNGSTR, indexes[i + 1]); + else + L.stack[keyI] = indexes[i + 1]; + + L.stack[keyI + 1] = this.map.get(indexes[i]); + return 1; + } + + return 0; };
\ No newline at end of file |