aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lapi.js23
-rw-r--r--src/lobject.js13
-rw-r--r--src/lstate.js4
-rw-r--r--src/ltable.js69
4 files changed, 72 insertions, 37 deletions
diff --git a/src/lapi.js b/src/lapi.js
index 625608b..e9f15c2 100644
--- a/src/lapi.js
+++ b/src/lapi.js
@@ -293,7 +293,7 @@ const auxsetstr = function(L, t, k) {
};
const lua_setglobal = function(L, name) {
- auxsetstr(L, L.l_G.l_registry.value.array[lua.LUA_RIDX_GLOBALS - 1], name);
+ auxsetstr(L, L.l_G.l_registry.value.get(lua.LUA_RIDX_GLOBALS - 1), name);
};
const lua_setmetatable = function(L, objindex) {
@@ -390,9 +390,6 @@ const lua_createtable = function(L, narray, nrec) {
L.stack[L.top++] = t;
assert(L.top <= L.ci.top, "stack overflow");
-
- if (narray > 0)
- t.value.array = new Array(narray);
};
const lua_newtable = function(L) {
@@ -447,7 +444,7 @@ const lua_geti = function(L, idx, n) {
};
const lua_getglobal = function(L, name) {
- return auxgetstr(L, L.l_G.l_registry.value.array[lua.LUA_RIDX_GLOBALS - 1], name);
+ return auxgetstr(L, L.l_G.l_registry.value.get(lua.LUA_RIDX_GLOBALS - 1), name);
};
/*
@@ -558,7 +555,7 @@ const lua_load = function(L, data, chunckname) {
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.array[lua.LUA_RIDX_GLOBALS - 1];
+ let gt = reg.value.get(lua.LUA_RIDX_GLOBALS - 1);
/* set global table as 1st upvalue of 'f' (may be LUA_ENV) */
f.upvals[0].u.value = gt;
}
@@ -654,7 +651,16 @@ const lua_error = function(L) {
};
const lua_next = function(L, idx) {
-
+ let t = index2addr(L, idx);
+ assert(t.ttistable(), "table expected");
+ let more = t.luaH_next(L, L.top - 1);
+ if (more) {
+ L.top++;
+ assert(L.top <= L.ci.top, "stack overflow");
+ } else
+ L.top--;
+
+ return more;
};
const lua_concat = function(L, n) {
@@ -740,4 +746,5 @@ module.exports.lua_gc = lua_gc;
module.exports.lua_getallocf = lua_getallocf;
module.exports.lua_getextraspace = lua_getextraspace;
module.exports.lua_stringtonumber = lua_stringtonumber;
-module.exports.lua_copy = lua_copy; \ No newline at end of file
+module.exports.lua_copy = lua_copy;
+module.exports.lua_next = lua_next; \ No newline at end of file
diff --git a/src/lobject.js b/src/lobject.js
index 0a0b615..2ba45ad 100644
--- a/src/lobject.js
+++ b/src/lobject.js
@@ -113,10 +113,7 @@ const nil = new TValue(CT.LUA_TNIL, null);
class Table extends TValue {
constructor(array, hash) {
- super(CT.LUA_TTABLE, {
- array: array !== undefined ? array : [],
- hash: new Map(hash)
- });
+ super(CT.LUA_TTABLE, new Map(hash));
this.metatable = null;
}
@@ -124,11 +121,9 @@ class Table extends TValue {
static keyValue(key) {
// Those lua values are used by value, others by reference
if (key instanceof TValue
- && [CT.LUA_TNUMBER,
- CT.LUA_TSTRING,
+ && [CT.LUA_TSTRING,
CT.LUA_TSHRSTR,
CT.LUA_TLNGSTR,
- CT.LUA_TNUMFLT,
CT.LUA_TNUMINT].indexOf(key.type) > -1) {
key = key.value;
}
@@ -140,7 +135,7 @@ class Table extends TValue {
key = Table.keyValue(key);
if (typeof key === 'number' && key > 0) {
- table.value.array[key - 1] = value; // Lua array starts at 1
+ table.value.hash.set(key - 1, value); // Lua array starts at 1
} else {
table.value.hash.set(key, value);
}
@@ -151,7 +146,7 @@ class Table extends TValue {
let v = nil;
if (typeof key === 'number' && key > 0) {
- v = table.value.array[key - 1]; // Lua array starts at 1
+ v = table.value.hash.get(key - 1); // Lua array starts at 1
} else {
v = table.value.hash.get(key);
}
diff --git a/src/lstate.js b/src/lstate.js
index 30e4b15..eec9fae 100644
--- a/src/lstate.js
+++ b/src/lstate.js
@@ -96,8 +96,8 @@ const stack_init = function(L1, L) {
const init_registry = function(L, g) {
let registry = new Table();
g.l_registry = registry;
- registry.value.array[lua.LUA_RIDX_MAINTHREAD - 1] = L;
- registry.value.array[lua.LUA_RIDX_GLOBALS - 1] = new Table();
+ registry.value.set(lua.LUA_RIDX_MAINTHREAD - 1, L);
+ registry.value.set(lua.LUA_RIDX_GLOBALS - 1, new Table());
};
/*
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