From a02f4e93b92e7ebb7ef038ad151e51652b0ce84d Mon Sep 17 00:00:00 2001 From: Benoit Giannangeli Date: Tue, 18 Apr 2017 15:20:37 +0200 Subject: No more Table, just TValue with table type and Map value --- src/lapi.js | 20 ++++++++--------- src/lcode.js | 4 ++-- src/ldblib.js | 2 +- src/ldebug.js | 5 ++--- src/ldo.js | 2 +- src/lobject.js | 66 ++++++++++++++++++++++++------------------------------- src/loslib.js | 6 ++--- src/lparser.js | 5 ++--- src/lstate.js | 4 ++-- src/lstrlib.js | 4 ++-- src/ltable.js | 7 +++--- src/ltm.js | 5 ++--- src/lvm.js | 13 +++++------ tests/lexparse.js | 3 +-- tests/lvm.js | 3 +-- 15 files changed, 67 insertions(+), 82 deletions(-) diff --git a/src/lapi.js b/src/lapi.js index 35f8d21..99b0859 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -336,8 +336,8 @@ const auxsetstr = function(L, t, k) { assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack"); - if (t.ttistable() && !t.__index(t, k).ttisnil()) { - t.__newindex(t, k, L.stack[L.top - 1]); + 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; @@ -400,7 +400,7 @@ 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"); - o.__newindex(o, L.stack[L.top - 2], L.stack[L.top - 1]); + lobject.table_newindex(o, L.stack[L.top - 2], L.stack[L.top - 1]); L.top -= 2; }; @@ -409,7 +409,7 @@ const lua_rawsetp = function(L, idx, p) { let o = index2addr(L, idx); assert(L, o.ttistable(), "table expected"); let k = p; - o.__newindex(o, k, L.stack[L.top - 1]); + lobject.table_newindex(o, k, L.stack[L.top - 1]); L.top--; }; @@ -421,7 +421,7 @@ 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 = t.__index(t, 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"); @@ -439,7 +439,7 @@ const lua_rawgeti = function(L, idx, n) { assert(t.ttistable(), "table expected"); - L.stack[L.top++] = t.__index(t, n); + L.stack[L.top++] = lobject.table_index(t, n); assert(L.top <= L.ci.top, "stack overflow"); @@ -450,7 +450,7 @@ const lua_rawgetp = function(L, idx, p) { let t = index2addr(L, idx); assert(t.ttistable(), "table expected"); let k = p; - L.stack[L.top++] = t.__index(t, k); + L.stack[L.top++] = lobject.table_index(t, k); assert(L.top <= L.ci.top, "stack overflow"); return L.stack[L.top - 1].ttnov(); }; @@ -460,14 +460,14 @@ const lua_rawget = function(L, idx) { assert(t.ttistable(t), "table expected"); - L.stack[L.top - 1] = t.__index(t, L.stack[L.top - 1]); + L.stack[L.top - 1] = lobject.table_index(t, L.stack[L.top - 1]); return L.stack[L.top - 1].ttnov(); }; // narray and nrec are mostly useless for this implementation const lua_createtable = function(L, narray, nrec) { - let t = new lobject.Table(); + let t = new lobject.TValue(CT.LUA_TTABLE, new Map()); L.stack[L.top++] = t; assert(L.top <= L.ci.top, "stack overflow"); @@ -577,7 +577,7 @@ const lua_getfield = function(L, idx, k) { const lua_geti = function(L, idx, n) { let t = index2addr(L, idx); - let slot = t.__index(t, n); + let slot = lobject.table_index(t, n); if (!slot.ttisnil()) { L.stack[L.top++] = slot; assert(L.top <= L.ci.top, "stack overflow"); diff --git a/src/lcode.js b/src/lcode.js index ec233c6..2f95baa 100644 --- a/src/lcode.js +++ b/src/lcode.js @@ -483,7 +483,7 @@ const freeexps = function(fs, e1, e2) { */ const addk = function(fs, key, v) { let f = fs.f; - let idx = fs.ls.h.__index(fs.ls.h, key); /* index scanner table */ + let idx = lobject.table_index(fs.ls.h, 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) @@ -491,7 +491,7 @@ const addk = function(fs, key, v) { } /* constant not found; create a new entry */ let k = fs.nk; - fs.ls.h.__newindex(fs.ls.h, key, new TValue(CT.LUA_TNUMINT, k)); + lobject.table_newindex(fs.ls.h, key, new TValue(CT.LUA_TNUMINT, k)); f.k[k] = v; fs.nk++; return k; diff --git a/src/ldblib.js b/src/ldblib.js index c637af2..a4de832 100644 --- a/src/ldblib.js +++ b/src/ldblib.js @@ -15,7 +15,7 @@ const ldebug = require('./ldebug.js'); */ const checkstack = function(L, L1, n) { if (L !== L1 && !lapi.lua_checkstack(L1, n)) - lauxlib.luaL_error(L, "stack overflow"); + lauxlib.luaL_error(L, lua.to_luastring("stack overflow", true)); }; const db_getregistry = function(L) { diff --git a/src/ldebug.js b/src/ldebug.js index 16449e2..4090011 100644 --- a/src/ldebug.js +++ b/src/ldebug.js @@ -14,7 +14,6 @@ const ltm = require('./ltm.js'); const lfunc = require('./lfunc.js'); const lapi = require('./lapi.js'); const TValue = lobject.TValue; -const Table = lobject.Table; const CT = lua.constant_types; const TS = lua.thread_status; @@ -181,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 Table(); + let t = new TValue(CT.LUA_TTABLE, new Map()); L.stack[L.top++] = t; assert(L.top <= L.ci.top, "stack overflow"); let v = new TValue(true, CT.LUA_TBOOLEAN); for (let i = 0; i < f.l.p.length; i++) - t.__newindex(t, lineinfo[i], v); + lobject.table_newindex(t, lineinfo[i], v); } }; diff --git a/src/ldo.js b/src/ldo.js index a3521c8..3bdd5b5 100644 --- a/src/ldo.js +++ b/src/ldo.js @@ -227,7 +227,7 @@ const adjust_varargs = function(L, p, actual) { const tryfuncTM = function(L, off, func) { let tm = ltm.luaT_gettmbyobj(L, func, ltm.TMS.TM_CALL); if (!tm.ttisfunction(tm)) - ldebug.luaG_typeerror(L, func, "call"); + ldebug.luaG_typeerror(L, func, lua.to_luastring("call", true)); /* Open a hole inside the stack at 'func' */ for (let p = L.top; p > off; p--) L.stack[p] = L.stack[p-1]; diff --git a/src/lobject.js b/src/lobject.js index adec0ba..9a79c95 100644 --- a/src/lobject.js +++ b/src/lobject.js @@ -176,49 +176,39 @@ const jsstring = function(value, from, to) { return str; }; -class Table extends TValue { - - constructor(array, hash) { - super(CT.LUA_TTABLE, new Map(hash)); - - this.metatable = null; - } - - static keyValue(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_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 = lua.to_luastring(key).map(e => `${e}|`).join(''); - } else if (Array.isArray(key)) { - key = key.map(e => `${e}|`).join(''); +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_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(''); } - - return key; + } else if (typeof key === "string") { // To avoid + key = lua.to_luastring(key).map(e => `${e}|`).join(''); + } else if (Array.isArray(key)) { + key = key.map(e => `${e}|`).join(''); } - __newindex(table, key, value) { - key = Table.keyValue(key); + return key; +}; - table.value.set(key, value); - } +const table_newindex = function(table, key, value) { + key = table_keyValue(key); - __index(table, key) { - key = Table.keyValue(key); + table.value.set(key, value); +}; - let v = table.value.get(key); +const table_index = function(table, key) { + key = table_keyValue(key); - return v ? v : luaO_nilobject; - } + let v = table.value.get(key); -} + return v ? v : luaO_nilobject; +}; class LClosure extends TValue { @@ -233,7 +223,7 @@ class LClosure extends TValue { _ENV.v = null; _ENV.u.open.next = null; _ENV.u.open.touched = true; - _ENV.u.value = new Table(); + _ENV.u.value = new TValue(CT.LUA_TTABLE, new Map()); this.upvals = [ _ENV @@ -566,7 +556,6 @@ module.exports.CClosure = CClosure; module.exports.LClosure = LClosure; module.exports.LocVar = LocVar; module.exports.TValue = TValue; -module.exports.Table = Table; module.exports.UTF8BUFFSZ = UTF8BUFFSZ; module.exports.frexp = frexp; module.exports.intarith = intarith; @@ -579,3 +568,6 @@ 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/loslib.js b/src/loslib.js index 20675a1..a319b3b 100644 --- a/src/loslib.js +++ b/src/loslib.js @@ -33,14 +33,14 @@ const getfield = function(L, key, d, delta) { let res = lapi.lua_tointegerx(L, -1); if (res !== false) { /* field is not an integer? */ if (t != lua.CT.LUA_TNIL) /* some other value? */ - return lauxlib.luaL_error(L, `field '${key}' is not an integer`); + return lauxlib.luaL_error(L, lua.to_luastring(`field '${key}' is not an integer`), true); else if (d < 0) /* absent field; no default? */ - return lauxlib.luaL_error(L, `field '${key}' missing in date table`); + return lauxlib.luaL_error(L, lua.to_luastring(`field '${key}' missing in date table`), true); res = d; } else { if (!(-L_MAXDATEFIELD <= res && res <= L_MAXDATEFIELD)) - return lauxlib.luaL_error(L, `field '${key}' is out-of-bound`); + return lauxlib.luaL_error(L, lua.to_luastring(`field '${key}' is out-of-bound`), true); res -= delta; } lapi.lua_pop(L, 1); diff --git a/src/lparser.js b/src/lparser.js index cf5f55b..a0d671b 100644 --- a/src/lparser.js +++ b/src/lparser.js @@ -14,7 +14,6 @@ const OpCodesI = lopcode.OpCodesI; const Proto = lfunc.Proto; const R = llex.RESERVED; const TValue = lobject.TValue; -const Table = lobject.Table; const UnOpr = lcode.UnOpr; const UpVal = lfunc.UpVal; const char = lua.char; @@ -1342,7 +1341,7 @@ const test_then_block = function(ls, escapelist) { escapelist = lcode.luaK_concat(fs, escapelist, lcode.luaK_jump(fs)); /* must jump over it */ lcode.luaK_patchtohere(fs, jf); - return escapelist + return escapelist; }; const ifstat = function(ls, line) { @@ -1547,7 +1546,7 @@ const luaY_parser = function(L, z, buff, dyd, name, firstchar) { let funcstate = new FuncState(); let cl = lfunc.luaF_newLclosure(L, 1); /* create main closure */ L.stack[L.top++] = cl; - lexstate.h = new Table(); /* create table for scanner */ + lexstate.h = new TValue(lua.CT.LUA_TTABLE, new Map()); /* create table for scanner */ L.stack[L.top++] = lexstate.h; funcstate.f = cl.p = new Proto(L); funcstate.f.source = new TValue(lua.CT.LUA_TLNGSTR, name); diff --git a/src/lstate.js b/src/lstate.js index e18e7aa..d95889b 100644 --- a/src/lstate.js +++ b/src/lstate.js @@ -107,10 +107,10 @@ const stack_init = function(L1, L) { ** Create registry table and its predefined values */ const init_registry = function(L, g) { - let registry = new lobject.Table(); + let registry = new lobject.TValue(CT.LUA_TTABLE, new Map()); g.l_registry = registry; registry.value.set(lua.LUA_RIDX_MAINTHREAD, L); - registry.value.set(lua.LUA_RIDX_GLOBALS, new lobject.Table()); + registry.value.set(lua.LUA_RIDX_GLOBALS, new lobject.TValue(CT.LUA_TTABLE, new Map())); }; /* diff --git a/src/lstrlib.js b/src/lstrlib.js index c2ee817..f8158a8 100644 --- a/src/lstrlib.js +++ b/src/lstrlib.js @@ -81,7 +81,7 @@ const str_dump = function(L) { lauxlib.luaL_checktype(L, 1, CT.LUA_TFUNCTION); lapi.lua_settop(L, 1); if (lapi.lua_dump(L, writer, b, strip) !== 0) - return lauxlib.luaL_error(L, "unable to dump given function"); + return lauxlib.luaL_error(L, lua.to_luastring("unable to dump given function")); lapi.lua_pushstring(L, b); return 1; }; @@ -1392,7 +1392,7 @@ const createmetatable = function(L) { lapi.lua_setmetatable(L, -2); /* set table as metatable for strings */ lapi.lua_pop(L, 1); /* pop dummy string */ lapi.lua_pushvalue(L, -2); /* get string library */ - lapi.lua_setfield(L, -2, lua.to_luastring("__index", true)); /* metatable.__index = string */ + lapi.lua_setfield(L, -2, lua.to_luastring("__index", true)); /* lobject.table_index = string */ lapi.lua_pop(L, 1); /* pop metatable */ }; diff --git a/src/ltable.js b/src/ltable.js index d3009a5..23ecc11 100644 --- a/src/ltable.js +++ b/src/ltable.js @@ -7,7 +7,6 @@ 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; const TValue = lobject.TValue; @@ -42,8 +41,8 @@ const luaH_getn = function(table) { for (let i = 0; i < len; i++) { let key = indexes[i]; - if (!table.__index(table, key).ttisnil() // t[key] is non-nil - && (indexes[i + 1] - key > 1 || table.__index(table, indexes[i + 1]).ttisnil())) { // gap with next key or next value is nil + 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]; } } @@ -53,7 +52,7 @@ const luaH_getn = function(table) { const luaH_next = function(L, table, keyI) { let keyO = L.stack[keyI]; - let key = Table.keyValue(keyO); + let key = lobject.table_keyValue(keyO); let indexes = ordered_indexes(table); if (indexes.length === 0) return 0; diff --git a/src/ltm.js b/src/ltm.js index 57c2e3f..1a9e454 100644 --- a/src/ltm.js +++ b/src/ltm.js @@ -5,7 +5,6 @@ const assert = require('assert'); const lobject = require('./lobject.js'); const TValue = lobject.TValue; -const Table = lobject.Table; const ldo = require('./ldo.js'); const lstate = require('./lstate.js'); const lua = require('./lua.js'); @@ -71,7 +70,7 @@ const luaT_init = function(L) { */ const luaT_objtypename = function(L, o) { if ((o.ttistable() && o.metatable !== null) || (o.ttisfulluserdata() && o.metatable !== null)) { - let name = o.__index(o, lua.to_luastring('__name', true)); + let name = lobject.table_index(o, lua.to_luastring('__name', true)); if (name.ttisstring()) return name.jsstring(); } @@ -149,7 +148,7 @@ const luaT_gettmbyobj = function(L, o, event) { mt = L.l_G.mt[o.ttnov()]; } - return mt ? mt.__index(mt, event) : lobject.luaO_nilobject; + return mt ? lobject.table_index(mt, event) : lobject.luaO_nilobject; }; module.exports.TMS = TMS; diff --git a/src/lvm.js b/src/lvm.js index 4c43da5..209cd6f 100644 --- a/src/lvm.js +++ b/src/lvm.js @@ -11,7 +11,6 @@ const CT = lua.constant_types; const LUA_MULTRET = lua.LUA_MULTRET; const lobject = require('./lobject.js'); const TValue = lobject.TValue; -const Table = lobject.Table; const LClosure = lobject.LClosure; const lfunc = require('./lfunc.js'); const UpVal = lfunc.UpVal; @@ -212,7 +211,7 @@ const luaV_execute = function(L) { break; } case OCi.OP_NEWTABLE: { - L.stack[ra] = new Table(); + L.stack[ra] = new TValue(CT.LUA_TTABLE, new Map()); break; } case OCi.OP_SELF: { @@ -660,7 +659,7 @@ const luaV_execute = function(L) { let last = ((c - 1) * OC.LFIELDS_PER_FLUSH) + n; for (; n > 0; n--) { - table.__newindex(table, last--, L.stack[ra + n]); + lobject.table_newindex(table, last--, L.stack[ra + n]); } L.top = ci.top; /* correct top (in case of previous open call) */ @@ -1056,7 +1055,7 @@ const gettable = function(L, table, key, ra, recur) { ldebug.luaG_runerror(L, lua.to_luastring("'__index' chain too long; possible loop", true)); if (table.ttistable()) { - let element = table.__index(table, key); + let element = lobject.table_index(table, key); if (!element.ttisnil()) { L.stack[ra] = element; @@ -1099,10 +1098,10 @@ const settable = function(L, table, key, v, recur) { ldebug.luaG_runerror(L, lua.to_luastring("'__newindex' chain too long; possible loop", true)); if (table.ttistable()) { - let element = table.__index(table, key); + let element = lobject.table_index(table, key); if (!element.ttisnil()) { - table.__newindex(table, key, v); + lobject.table_newindex(table, key, v); } else { luaV_finishset(L, table, key, v, element, recur); } @@ -1117,7 +1116,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()) { - t.__newindex(t, key, val); + lobject.table_newindex(t, key, val); return; } } else { /* not a table; check metamethod */ diff --git a/tests/lexparse.js b/tests/lexparse.js index 96c8fca..68b6667 100644 --- a/tests/lexparse.js +++ b/tests/lexparse.js @@ -10,7 +10,6 @@ const lua = require("../src/lua.js"); const lapi = require("../src/lapi.js"); const lauxlib = require("../src/lauxlib.js"); const linit = require('../src/linit.js'); -const Table = require("../src/lobject.js").Table; // Roughly the same tests as test/lvm.js to cover all opcodes @@ -203,7 +202,7 @@ test('NEWTABLE', function (t) { }, "Lua program ran without error"); t.ok( - L.stack[lapi.index2addr_(L, -1)] instanceof Table, + L.stack[lapi.index2addr_(L, -1)].ttistable(), "Program output is correct" ); }); diff --git a/tests/lvm.js b/tests/lvm.js index 0f91d81..fe463eb 100644 --- a/tests/lvm.js +++ b/tests/lvm.js @@ -6,7 +6,6 @@ const beautify = require('js-beautify').js_beautify; const lua_State = require("../src/lstate.js").lua_State; const VM = require("../src/lvm.js"); const lapi = require("../src/lapi.js"); -const Table = require("../src/lobject.js").Table; const getState = require("./tests.js").getState; @@ -120,7 +119,7 @@ test('NEWTABLE', function (t) { }, "Program executed without errors"); t.ok( - L.stack[L.top - 1] instanceof Table, + L.stack[L.top - 1].ttistable(), "Program output is correct" ); }); -- cgit v1.2.3-54-g00ecf