diff options
Diffstat (limited to 'src/lapi.js')
-rw-r--r-- | src/lapi.js | 465 |
1 files changed, 240 insertions, 225 deletions
diff --git a/src/lapi.js b/src/lapi.js index b42ad92..6196812 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -1,32 +1,76 @@ "use strict"; -const assert = require('assert'); - -const defs = require('./defs.js'); +const { + LUA_MULTRET, + LUA_OPBNOT, + LUA_OPEQ, + LUA_OPLE, + LUA_OPLT, + LUA_OPUNM, + LUA_REGISTRYINDEX, + LUA_RIDX_GLOBALS, + LUA_VERSION_NUM, + constant_types: { + LUA_NUMTAGS, + LUA_TBOOLEAN, + LUA_TCCL, + LUA_TFUNCTION, + LUA_TLCF, + LUA_TLCL, + LUA_TLIGHTUSERDATA, + LUA_TLNGSTR, + LUA_TNIL, + LUA_TNONE, + LUA_TNUMFLT, + LUA_TNUMINT, + LUA_TSHRSTR, + LUA_TTABLE, + LUA_TTHREAD, + LUA_TUSERDATA + }, + thread_status: { LUA_OK }, + from_userstring, + to_luastring, +} = require('./defs.js'); +const { api_check } = require('./llimits.js'); const ldebug = require('./ldebug.js'); const ldo = require('./ldo.js'); -const ldump = require('./ldump.js'); +const { luaU_dump } = require('./ldump.js'); const lfunc = require('./lfunc.js'); const lobject = require('./lobject.js'); const lstate = require('./lstate.js'); -const lstring = require('./lstring.js'); +const { + luaS_bless, + luaS_new, + luaS_newliteral +} = require('./lstring.js'); const ltm = require('./ltm.js'); -const luaconf = require('./luaconf.js'); +const { LUAI_MAXSTACK } = require('./luaconf.js'); const lvm = require('./lvm.js'); const ltable = require('./ltable.js'); -const lzio = require('./lzio.js'); -const MAXUPVAL = lfunc.MAXUPVAL; -const CT = defs.constant_types; -const TS = defs.thread_status; +const { ZIO } = require('./lzio.js'); const TValue = lobject.TValue; const CClosure = lobject.CClosure; +const api_incr_top = function(L) { + L.top++; + api_check(L, L.top <= L.ci.top, "stack overflow"); +}; + +const api_checknelems = function(L, n) { + api_check(L, n < (L.top - L.ci.funcOff), "not enough elements in the stack"); +}; + +const fengari_argcheck = function(c) { + if (!c) throw TypeError("invalid argument"); +}; + const isvalid = function(o) { return o !== lobject.luaO_nilobject; }; const lua_version = function(L) { - if (L === null) return defs.LUA_VERSION_NUM; + if (L === null) return LUA_VERSION_NUM; else return L.l_G.version; }; @@ -47,17 +91,17 @@ const index2addr = function(L, idx) { let ci = L.ci; if (idx > 0) { let o = ci.funcOff + idx; - assert(idx <= ci.top - (ci.funcOff + 1), "unacceptable index"); + api_check(L, idx <= ci.top - (ci.funcOff + 1), "unacceptable index"); if (o >= L.top) return lobject.luaO_nilobject; else return L.stack[o]; - } else if (idx > defs.LUA_REGISTRYINDEX) { - assert(idx !== 0 && -idx <= L.top, "invalid index"); + } else if (idx > LUA_REGISTRYINDEX) { + api_check(L, idx !== 0 && -idx <= L.top, "invalid index"); return L.stack[L.top + idx]; - } else if (idx === defs.LUA_REGISTRYINDEX) { + } else if (idx === LUA_REGISTRYINDEX) { return L.l_G.l_registry; } else { /* upvalues */ - idx = defs.LUA_REGISTRYINDEX - idx; - assert(idx <= MAXUPVAL + 1, "upvalue index too large"); + idx = LUA_REGISTRYINDEX - idx; + api_check(L, idx <= lfunc.MAXUPVAL + 1, "upvalue index too large"); if (ci.func.ttislcf()) /* light C function? */ return lobject.luaO_nilobject; /* it has no upvalues */ else { @@ -71,11 +115,11 @@ const index2addr_ = function(L, idx) { let ci = L.ci; if (idx > 0) { let o = ci.funcOff + idx; - assert(idx <= ci.top - (ci.funcOff + 1), "unacceptable index"); + api_check(L, idx <= ci.top - (ci.funcOff + 1), "unacceptable index"); if (o >= L.top) return null; else return o; - } else if (idx > defs.LUA_REGISTRYINDEX) { - assert(idx !== 0 && -idx <= L.top, "invalid index"); + } else if (idx > LUA_REGISTRYINDEX) { + api_check(L, idx !== 0 && -idx <= L.top, "invalid index"); return L.top + idx; } else { /* registry or upvalue */ throw Error("attempt to use pseudo-index"); @@ -85,12 +129,12 @@ const index2addr_ = function(L, idx) { const lua_checkstack = function(L, n) { let res; let ci = L.ci; - assert(n >= 0, "negative 'n'"); + api_check(L, n >= 0, "negative 'n'"); if (L.stack_last - L.top > n) /* stack large enough? */ res = true; else { /* no; need to grow stack */ let inuse = L.top + lstate.EXTRA_STACK; - if (inuse > luaconf.LUAI_MAXSTACK - n) /* can grow without overflow? */ + if (inuse > LUAI_MAXSTACK - n) /* can grow without overflow? */ res = false; /* no */ else { /* try to grow stack */ ldo.luaD_growstack(L, n); @@ -106,10 +150,9 @@ const lua_checkstack = function(L, n) { const lua_xmove = function(from, to, n) { if (from === to) return; - assert(n < (from.top - from.ci.funcOff), "not enough elements in the stack"); - assert(from.l_G === to.l_G, "moving among independent states"); - assert(to.ci.top - to.top >= n, "stack overflow"); - + api_checknelems(from, n); + api_check(from, from.l_G === to.l_G, "moving among independent states"); + api_check(from, to.ci.top - to.top >= n, "stack overflow"); from.top -= n; for (let i = 0; i < n; i++) { to.stack[to.top] = new lobject.TValue(); @@ -127,7 +170,7 @@ const lua_xmove = function(from, to, n) { ** convert an acceptable stack index into an absolute index */ const lua_absindex = function(L, idx) { - return (idx > 0 || idx <= defs.LUA_REGISTRYINDEX) + return (idx > 0 || idx <= LUA_REGISTRYINDEX) ? idx : (L.top - L.ci.funcOff) + idx; }; @@ -138,17 +181,17 @@ const lua_gettop = function(L) { const lua_pushvalue = function(L, idx) { lobject.pushobj2s(L, index2addr(L, idx)); - assert(L.top <= L.ci.top, "stack overflow"); + api_check(L, L.top <= L.ci.top, "stack overflow"); }; const lua_settop = function(L, idx) { let func = L.ci.funcOff; let newtop; if (idx >= 0) { - assert(idx <= L.stack_last - (func + 1), "new top too large"); + api_check(L, idx <= L.stack_last - (func + 1), "new top too large"); newtop = func + 1 + idx; } else { - assert(-(idx + 1) <= L.top - (func + 1), "invalid new top"); + api_check(L, -(idx + 1) <= L.top - (func + 1), "invalid new top"); newtop = L.top + idx + 1; /* 'subtract' index (index is negative) */ } ldo.adjust_top(L, newtop); @@ -175,12 +218,9 @@ const lua_rotate = function(L, idx, n) { let t = L.top - 1; let pIdx = index2addr_(L, idx); let p = L.stack[pIdx]; - - assert(isvalid(p) && idx > defs.LUA_REGISTRYINDEX, "index not in the stack"); - assert((n >= 0 ? n : -n) <= (t - pIdx + 1), "invalid 'n'"); - + api_check(L, isvalid(p) && idx > LUA_REGISTRYINDEX, "index not in the stack"); + api_check(L, (n >= 0 ? n : -n) <= (t - pIdx + 1), "invalid 'n'"); let m = n >= 0 ? t - n : pIdx - n - 1; /* end of prefix */ - reverse(L, pIdx, m); reverse(L, m + 1, L.top - 1); reverse(L, pIdx, L.top - 1); @@ -210,93 +250,84 @@ const lua_replace = function(L, idx) { */ const lua_pushnil = function(L) { - L.stack[L.top] = new TValue(CT.LUA_TNIL, null); - L.top++; - assert(L.top <= L.ci.top, "stack overflow"); + L.stack[L.top] = new TValue(LUA_TNIL, null); + api_incr_top(L); }; const lua_pushnumber = function(L, n) { - assert(typeof n === "number"); - - L.stack[L.top] = new TValue(CT.LUA_TNUMFLT, n); - L.top++; - assert(L.top <= L.ci.top, "stack overflow"); + fengari_argcheck(typeof n === "number"); + L.stack[L.top] = new TValue(LUA_TNUMFLT, n); + api_incr_top(L); }; const lua_pushinteger = function(L, n) { - assert(typeof n === "number" && (n|0) === n); - L.stack[L.top] = new TValue(CT.LUA_TNUMINT, n); - L.top++; - assert(L.top <= L.ci.top, "stack overflow"); + fengari_argcheck(typeof n === "number" && (n|0) === n); + L.stack[L.top] = new TValue(LUA_TNUMINT, n); + api_incr_top(L); }; const lua_pushlstring = function(L, s, len) { - assert(typeof len === "number"); + fengari_argcheck(typeof len === "number"); let ts; if (len === 0) { - s = defs.to_luastring("", true); + s = to_luastring("", true); + ts = luaS_bless(L, s); } else { - s = defs.from_userstring(s); - assert(s.length >= len, "invalid length to lua_pushlstring"); - s = s.slice(0, len); + s = from_userstring(s); + api_check(L, s.length >= len, "invalid length to lua_pushlstring"); + ts = luaS_new(L, s.subarray(0, len)); } - ts = lstring.luaS_bless(L, s); lobject.pushsvalue2s(L, ts); - assert(L.top <= L.ci.top, "stack overflow"); - + api_check(L, L.top <= L.ci.top, "stack overflow"); return ts.value; }; const lua_pushstring = function (L, s) { if (s === undefined || s === null) { - L.stack[L.top] = new TValue(CT.LUA_TNIL, null); + L.stack[L.top] = new TValue(LUA_TNIL, null); L.top++; } else { - let ts = lstring.luaS_new(L, defs.from_userstring(s)); + let ts = luaS_new(L, from_userstring(s)); lobject.pushsvalue2s(L, ts); s = ts.getstr(); /* internal copy */ } - assert(L.top <= L.ci.top, "stack overflow"); - + api_check(L, L.top <= L.ci.top, "stack overflow"); return s; }; const lua_pushvfstring = function (L, fmt, argp) { - fmt = defs.from_userstring(fmt); + fmt = from_userstring(fmt); return lobject.luaO_pushvfstring(L, fmt, argp); }; const lua_pushfstring = function (L, fmt, ...argp) { - fmt = defs.from_userstring(fmt); + fmt = from_userstring(fmt); return lobject.luaO_pushvfstring(L, fmt, argp); }; /* Similar to lua_pushstring, but takes a JS string */ const lua_pushliteral = function (L, s) { if (s === undefined || s === null) { - L.stack[L.top] = new TValue(CT.LUA_TNIL, null); + L.stack[L.top] = new TValue(LUA_TNIL, null); L.top++; } else { - assert(typeof s === "string", "lua_pushliteral expects a JS string"); - let ts = lstring.luaS_newliteral(L, s); + fengari_argcheck(typeof s === "string", "lua_pushliteral expects a JS string"); + let ts = luaS_newliteral(L, s); lobject.pushsvalue2s(L, ts); s = ts.getstr(); /* internal copy */ } - assert(L.top <= L.ci.top, "stack overflow"); + api_check(L, L.top <= L.ci.top, "stack overflow"); return s; }; const lua_pushcclosure = function(L, fn, n) { - assert(typeof fn === "function"); - assert(typeof n === "number"); - + fengari_argcheck(typeof fn === "function" || typeof n === "number"); if (n === 0) - L.stack[L.top] = new TValue(CT.LUA_TLCF, fn); + L.stack[L.top] = new TValue(LUA_TLCF, fn); else { - assert(n < L.top - L.ci.funcOff, "not enough elements in the stack"); - assert(n <= MAXUPVAL, "upvalue index too large"); - + api_checknelems(L, n); + api_check(L, n <= lfunc.MAXUPVAL, "upvalue index too large"); let cl = new CClosure(L, fn, n); for (let i=0; i<n; i++) cl.upvalue[i].setfrom(L.stack[L.top - n + i]); @@ -306,8 +337,7 @@ const lua_pushcclosure = function(L, fn, n) { --L.top; L.stack[L.top].setclCvalue(cl); } - L.top++; - assert(L.top <= L.ci.top, "stack overflow"); + api_incr_top(L); }; const lua_pushjsclosure = lua_pushcclosure; @@ -319,26 +349,23 @@ const lua_pushcfunction = function(L, fn) { const lua_pushjsfunction = lua_pushcfunction; const lua_pushboolean = function(L, b) { - L.stack[L.top] = new TValue(CT.LUA_TBOOLEAN, b ? true : false); - L.top++; - assert(L.top <= L.ci.top, "stack overflow"); + L.stack[L.top] = new TValue(LUA_TBOOLEAN, b ? true : false); + api_incr_top(L); }; const lua_pushlightuserdata = function(L, p) { - L.stack[L.top] = new TValue(CT.LUA_TLIGHTUSERDATA, p); - L.top++; - assert(L.top <= L.ci.top, "stack overflow"); + L.stack[L.top] = new TValue(LUA_TLIGHTUSERDATA, p); + api_incr_top(L); }; const lua_pushthread = function(L) { - L.stack[L.top] = new TValue(CT.LUA_TTHREAD, L); - L.top++; - assert(L.top <= L.ci.top, "stack overflow"); + L.stack[L.top] = new TValue(LUA_TTHREAD, L); + api_incr_top(L); return L.l_G.mainthread === L; }; const lua_pushglobaltable = function(L) { - lua_rawgeti(L, defs.LUA_REGISTRYINDEX, defs.LUA_RIDX_GLOBALS); + lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS); }; /* @@ -349,10 +376,10 @@ const lua_pushglobaltable = function(L) { ** t[k] = value at the top of the stack (where 'k' is a string) */ const auxsetstr = function(L, t, k) { - let str = lstring.luaS_new(L, defs.from_userstring(k)); - assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack"); + let str = luaS_new(L, from_userstring(k)); + api_checknelems(L, 1); lobject.pushsvalue2s(L, str); /* push 'str' (to make it a TValue) */ - assert(L.top <= L.ci.top, "stack overflow"); + api_check(L, 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 */ delete L.stack[--L.top]; @@ -360,23 +387,23 @@ const auxsetstr = function(L, t, k) { }; const lua_setglobal = function(L, name) { - auxsetstr(L, ltable.luaH_getint(L.l_G.l_registry.value, defs.LUA_RIDX_GLOBALS), name); + auxsetstr(L, ltable.luaH_getint(L.l_G.l_registry.value, LUA_RIDX_GLOBALS), name); }; const lua_setmetatable = function(L, objindex) { - assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack"); + api_checknelems(L, 1); let mt; let obj = index2addr(L, objindex); if (L.stack[L.top - 1].ttisnil()) mt = null; else { - assert(L.stack[L.top - 1].ttistable(), "table expected"); + api_check(L, L.stack[L.top - 1].ttistable(), "table expected"); mt = L.stack[L.top - 1].value; } switch (obj.ttnov()) { - case CT.LUA_TUSERDATA: - case CT.LUA_TTABLE: { + case LUA_TUSERDATA: + case LUA_TTABLE: { obj.value.metatable = mt; break; } @@ -391,8 +418,7 @@ const lua_setmetatable = function(L, objindex) { }; const lua_settable = function(L, idx) { - assert(2 < L.top - L.ci.funcOff, "not enough elements in the stack"); - + api_checknelems(L, 2); let t = index2addr(L, idx); lvm.settable(L, t, L.stack[L.top - 2], L.stack[L.top - 1]); delete L.stack[--L.top]; @@ -404,12 +430,11 @@ const lua_setfield = function(L, idx, k) { }; const lua_seti = function(L, idx, n) { - assert(typeof n === "number" && (n|0) === n); - assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack"); + fengari_argcheck(typeof n === "number" && (n|0) === n); + api_checknelems(L, 1); let t = index2addr(L, idx); - L.stack[L.top] = new TValue(CT.LUA_TNUMINT, n); - L.top++; - assert(L.top <= L.ci.top, "stack overflow"); + L.stack[L.top] = new TValue(LUA_TNUMINT, n); + api_incr_top(L); lvm.settable(L, t, L.stack[L.top - 1], L.stack[L.top - 2]); /* pop value and key */ delete L.stack[--L.top]; @@ -417,9 +442,9 @@ const lua_seti = function(L, idx, n) { }; const lua_rawset = function(L, idx) { - assert(2 < L.top - L.ci.funcOff, "not enough elements in the stack"); + api_checknelems(L, 2); let o = index2addr(L, idx); - assert(o.ttistable(), "table expected"); + api_check(L, o.ttistable(), "table expected"); let k = L.stack[L.top - 2]; let v = L.stack[L.top - 1]; if (v.ttisnil()) { @@ -434,18 +459,18 @@ const lua_rawset = function(L, idx) { }; const lua_rawseti = function(L, idx, n) { - assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack"); + api_checknelems(L, 1); let o = index2addr(L, idx); - assert(o.ttistable(), "table expected"); + api_check(L, o.ttistable(), "table expected"); ltable.luaH_setint(o.value, n, L.stack[L.top - 1]); delete L.stack[--L.top]; }; const lua_rawsetp = function(L, idx, p) { - assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack"); + api_checknelems(L, 1); let o = index2addr(L, idx); - assert(L, o.ttistable(), "table expected"); - let k = new TValue(CT.LUA_TLIGHTUSERDATA, p); + api_check(L, o.ttistable(), "table expected"); + let k = new TValue(LUA_TLIGHTUSERDATA, p); let v = L.stack[L.top - 1]; if (v.ttisnil()) { ltable.luaH_delete(L, o.value, k); @@ -461,43 +486,42 @@ const lua_rawsetp = function(L, idx, p) { */ const auxgetstr = function(L, t, k) { - let str = lstring.luaS_new(L, defs.from_userstring(k)); + let str = luaS_new(L, from_userstring(k)); lobject.pushsvalue2s(L, str); - assert(L.top <= L.ci.top, "stack overflow"); + api_check(L, L.top <= L.ci.top, "stack overflow"); lvm.luaV_gettable(L, t, L.stack[L.top - 1], L.top - 1); return L.stack[L.top - 1].ttnov(); }; const lua_rawgeti = function(L, idx, n) { let t = index2addr(L, idx); - assert(t.ttistable(), "table expected"); + api_check(L, t.ttistable(), "table expected"); lobject.pushobj2s(L, ltable.luaH_getint(t.value, n)); - assert(L.top <= L.ci.top, "stack overflow"); + api_check(L, L.top <= L.ci.top, "stack overflow"); return L.stack[L.top - 1].ttnov(); }; const lua_rawgetp = function(L, idx, p) { let t = index2addr(L, idx); - assert(t.ttistable(), "table expected"); - let k = new TValue(CT.LUA_TLIGHTUSERDATA, p); + api_check(L, t.ttistable(), "table expected"); + let k = new TValue(LUA_TLIGHTUSERDATA, p); lobject.pushobj2s(L, ltable.luaH_get(L, t.value, k)); - assert(L.top <= L.ci.top, "stack overflow"); + api_check(L, L.top <= L.ci.top, "stack overflow"); return L.stack[L.top - 1].ttnov(); }; const lua_rawget = function(L, idx) { let t = index2addr(L, idx); - assert(t.ttistable(t), "table expected"); + api_check(L, t.ttistable(t), "table expected"); lobject.setobj2s(L, L.top - 1, ltable.luaH_get(L, t.value, 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.TValue(CT.LUA_TTABLE, ltable.luaH_new(L)); + let t = new lobject.TValue(LUA_TTABLE, ltable.luaH_new(L)); L.stack[L.top] = t; - L.top++; - assert(L.top <= L.ci.top, "stack overflow"); + api_incr_top(L); }; const luaS_newudata = function(L, size) { @@ -506,30 +530,29 @@ const luaS_newudata = function(L, size) { const lua_newuserdata = function(L, size) { let u = luaS_newudata(L, size); - L.stack[L.top] = new lobject.TValue(CT.LUA_TUSERDATA, u); - L.top++; - assert(L.top <= L.ci.top, "stack overflow"); + L.stack[L.top] = new lobject.TValue(LUA_TUSERDATA, u); + api_incr_top(L); return u.data; }; const aux_upvalue = function(L, fi, n) { switch(fi.ttype()) { - case CT.LUA_TCCL: { /* C closure */ + case LUA_TCCL: { /* C closure */ let f = fi.value; if (!(1 <= n && n <= f.nupvalues)) return null; return { - name: defs.to_luastring("", true), + name: to_luastring("", true), val: f.upvalue[n-1] }; } - case CT.LUA_TLCL: { /* Lua closure */ + case LUA_TLCL: { /* Lua closure */ let f = fi.value; let p = f.p; if (!(1 <= n && n <= p.upvalues.length)) return null; let name = p.upvalues[n-1].name; return { - name: name ? name.getstr() : defs.to_luastring("(*no name)", true), - val: f.upvals[n-1].v + name: name ? name.getstr() : to_luastring("(*no name)", true), + val: f.upvals[n-1] }; } default: return null; /* not a closure */ @@ -542,7 +565,7 @@ const lua_getupvalue = function(L, funcindex, n) { let name = up.name; let val = up.val; lobject.pushobj2s(L, val); - assert(L.top <= L.ci.top, "stack overflow"); + api_check(L, L.top <= L.ci.top, "stack overflow"); return name; } return null; @@ -550,7 +573,7 @@ const lua_getupvalue = function(L, funcindex, n) { const lua_setupvalue = function(L, funcindex, n) { let fi = index2addr(L, funcindex); - assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack"); + api_checknelems(L, 1); let aux = aux_upvalue(L, fi, n); if (aux) { let name = aux.name; @@ -576,8 +599,8 @@ const lua_getmetatable = function(L, objindex) { let mt; let res = false; switch (obj.ttnov()) { - case CT.LUA_TTABLE: - case CT.LUA_TUSERDATA: + case LUA_TTABLE: + case LUA_TUSERDATA: mt = obj.value.metatable; break; default: @@ -586,9 +609,8 @@ const lua_getmetatable = function(L, objindex) { } if (mt !== null && mt !== undefined) { - L.stack[L.top] = new TValue(CT.LUA_TTABLE, mt); - L.top++; - assert(L.top <= L.ci.top, "stack overflow"); + L.stack[L.top] = new TValue(LUA_TTABLE, mt); + api_incr_top(L); res = true; } @@ -597,11 +619,10 @@ const lua_getmetatable = function(L, objindex) { const lua_getuservalue = function(L, idx) { let o = index2addr(L, idx); - assert(L, o.ttisfulluserdata(), "full userdata expected"); + api_check(L, o.ttisfulluserdata(), "full userdata expected"); let uv = o.value.uservalue; L.stack[L.top] = new TValue(uv.type, uv.value); - L.top++; - assert(L.top <= L.ci.top, "stack overflow"); + api_incr_top(L); return L.stack[L.top - 1].ttnov(); }; @@ -616,17 +637,16 @@ const lua_getfield = function(L, idx, k) { }; const lua_geti = function(L, idx, n) { - assert(typeof n === "number" && (n|0) === n); + fengari_argcheck(typeof n === "number" && (n|0) === n); let t = index2addr(L, idx); - L.stack[L.top] = new TValue(CT.LUA_TNUMINT, n); - L.top++; - assert(L.top <= L.ci.top, "stack overflow"); + L.stack[L.top] = new TValue(LUA_TNUMINT, n); + api_incr_top(L); lvm.luaV_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, ltable.luaH_getint(L.l_G.l_registry.value, defs.LUA_RIDX_GLOBALS), name); + return auxgetstr(L, ltable.luaH_getint(L.l_G.l_registry.value, LUA_RIDX_GLOBALS), name); }; /* @@ -674,12 +694,12 @@ const lua_todataview = function(L, idx) { const lua_rawlen = function(L, idx) { let o = index2addr(L, idx); switch (o.ttype()) { - case CT.LUA_TSHRSTR: - case CT.LUA_TLNGSTR: + case LUA_TSHRSTR: + case LUA_TLNGSTR: return o.vslen(); - case CT.LUA_TUSERDATA: + case LUA_TUSERDATA: return o.value.len; - case CT.LUA_TTABLE: + case LUA_TTABLE: return ltable.luaH_getn(o.value); default: return 0; @@ -713,9 +733,9 @@ const lua_tonumberx = function(L, idx) { const lua_touserdata = function(L, idx) { let o = index2addr(L, idx); switch (o.ttnov()) { - case CT.LUA_TUSERDATA: + case LUA_TUSERDATA: return o.value.data; - case CT.LUA_TLIGHTUSERDATA: + case LUA_TLIGHTUSERDATA: return o.value; default: return null; } @@ -729,13 +749,13 @@ const lua_tothread = function(L, idx) { const lua_topointer = function(L, idx) { let o = index2addr(L, idx); switch (o.ttype()) { - case CT.LUA_TTABLE: - case CT.LUA_TLCL: - case CT.LUA_TCCL: - case CT.LUA_TLCF: - case CT.LUA_TTHREAD: - case CT.LUA_TUSERDATA: /* note: this differs in behaviour to reference lua implementation */ - case CT.LUA_TLIGHTUSERDATA: + case LUA_TTABLE: + case LUA_TLCL: + case LUA_TCCL: + case LUA_TLCF: + case LUA_TTHREAD: + case LUA_TUSERDATA: /* note: this differs in behaviour to reference lua implementation */ + case LUA_TLIGHTUSERDATA: return o.value; default: return null; @@ -759,10 +779,9 @@ const lua_isproxy = function(p, L) { /* Use 'create_proxy' helper function so that 'L' is not in scope */ const create_proxy = function(G, type, value) { let proxy = function(L) { - assert(L instanceof lstate.lua_State && G === L.l_G, "must be from same global state"); + api_check(L, L instanceof lstate.lua_State && G === L.l_G, "must be from same global state"); L.stack[L.top] = new TValue(type, value); - L.top++; - assert(L.top <= L.ci.top, "stack overflow"); + api_incr_top(L); }; seen.set(proxy, G); return proxy; @@ -783,10 +802,10 @@ const lua_compare = function(L, index1, index2, op) { if (isvalid(o1) && isvalid(o2)) { switch (op) { - case defs.LUA_OPEQ: i = lvm.luaV_equalobj(L, o1, o2); break; - case defs.LUA_OPLT: i = lvm.luaV_lessthan(L, o1, o2); break; - case defs.LUA_OPLE: i = lvm.luaV_lessequal(L, o1, o2); break; - default: assert(false, "invalid option"); + case LUA_OPEQ: i = lvm.luaV_equalobj(L, o1, o2); break; + case LUA_OPLT: i = lvm.luaV_lessthan(L, o1, o2); break; + case LUA_OPLE: i = lvm.luaV_lessequal(L, o1, o2); break; + default: api_check(L, false, "invalid option"); } } @@ -798,8 +817,7 @@ const lua_stringtonumber = function(L, s) { let sz = lobject.luaO_str2num(s, tv); if (sz !== 0) { L.stack[L.top] = tv; - L.top++; - assert(L.top <= L.ci.top, "stack overflow"); + api_incr_top(L); } return sz; }; @@ -810,11 +828,11 @@ const f_call = function(L, ud) { const lua_type = function(L, idx) { let o = index2addr(L, idx); - return isvalid(o) ? o.ttnov() : CT.LUA_TNONE; + return isvalid(o) ? o.ttnov() : LUA_TNONE; }; const lua_typename = function(L, t) { - assert(CT.LUA_TNONE <= t && t < CT.LUA_NUMTAGS, "invalid tag"); + api_check(L, LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag"); return ltm.ttypename(t); }; @@ -824,15 +842,15 @@ const lua_iscfunction = function(L, idx) { }; const lua_isnil = function(L, n) { - return lua_type(L, n) === CT.LUA_TNIL; + return lua_type(L, n) === LUA_TNIL; }; const lua_isboolean = function(L, n) { - return lua_type(L, n) === CT.LUA_TBOOLEAN; + return lua_type(L, n) === LUA_TBOOLEAN; }; const lua_isnone = function(L, n) { - return lua_type(L, n) === CT.LUA_TNONE; + return lua_type(L, n) === LUA_TNONE; }; const lua_isnoneornil = function(L, n) { @@ -862,15 +880,15 @@ const lua_isuserdata = function(L, idx) { }; const lua_isthread = function(L, idx) { - return lua_type(L, idx) === CT.LUA_TTHREAD; + return lua_type(L, idx) === LUA_TTHREAD; }; const lua_isfunction = function(L, idx) { - return lua_type(L, idx) === CT.LUA_TFUNCTION; + return lua_type(L, idx) === LUA_TFUNCTION; }; const lua_islightuserdata = function(L, idx) { - return lua_type(L, idx) === CT.LUA_TLIGHTUSERDATA; + return lua_type(L, idx) === LUA_TLIGHTUSERDATA; }; const lua_rawequal = function(L, index1, index2) { @@ -880,12 +898,12 @@ const lua_rawequal = function(L, index1, index2) { }; const lua_arith = function(L, op) { - if (op !== defs.LUA_OPUNM && op !== defs.LUA_OPBNOT) - assert(2 < L.top - L.ci.funcOff, "not enough elements in the stack"); /* all other operations expect two operands */ + if (op !== LUA_OPUNM && op !== LUA_OPBNOT) + api_checknelems(L, 2); /* all other operations expect two operands */ else { /* for unary operations, add fake 2nd operand */ - assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack"); + api_checknelems(L, 1); lobject.pushobj2s(L, L.stack[L.top-1]); - assert(L.top <= L.ci.top, "stack overflow"); + api_check(L, L.top <= L.ci.top, "stack overflow"); } /* first operand at top - 2, second at top - 1; result go to top - 2 */ lobject.luaO_arith(L, op, L.stack[L.top - 2], L.stack[L.top - 1], L.stack[L.top - 2]); @@ -896,30 +914,30 @@ const lua_arith = function(L, op) { ** 'load' and 'call' functions (run Lua code) */ -const default_chunkname = defs.to_luastring("?"); +const default_chunkname = to_luastring("?"); const lua_load = function(L, reader, data, chunkname, mode) { if (!chunkname) chunkname = default_chunkname; - else chunkname = defs.from_userstring(chunkname); - if (mode !== null) mode = defs.from_userstring(mode); - let z = new lzio.ZIO(L, reader, data); + else chunkname = from_userstring(chunkname); + if (mode !== null) mode = from_userstring(mode); + let z = new ZIO(L, reader, data); let status = ldo.luaD_protectedparser(L, z, chunkname, mode); - if (status === TS.LUA_OK) { /* no errors? */ + if (status === LUA_OK) { /* no errors? */ 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 gt = ltable.luaH_getint(L.l_G.l_registry.value, defs.LUA_RIDX_GLOBALS); + let gt = ltable.luaH_getint(L.l_G.l_registry.value, LUA_RIDX_GLOBALS); /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ - f.upvals[0].v.setfrom(gt); + f.upvals[0].setfrom(gt); } } return status; }; const lua_dump = function(L, writer, data, strip) { - assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack"); + api_checknelems(L, 1); let o = L.stack[L.top -1]; if (o.ttisLclosure()) - return ldump.luaU_dump(L, o.value.p, writer, data, strip); + return luaU_dump(L, o.value.p, writer, data, strip); return 1; }; @@ -928,19 +946,23 @@ const lua_status = function(L) { }; const lua_setuservalue = function(L, idx) { - assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack"); + api_checknelems(L, 1); let o = index2addr(L, idx); - assert(L, o.ttisfulluserdata(), "full userdata expected"); + api_check(L, o.ttisfulluserdata(), "full userdata expected"); o.value.uservalue.setfrom(L.stack[L.top - 1]); delete L.stack[--L.top]; }; -const lua_callk = function(L, nargs, nresults, ctx, k) { - assert(k === null || !(L.ci.callstatus & lstate.CIST_LUA), "cannot use continuations inside hooks"); - assert(nargs + 1 < L.top - L.ci.funcOff, "not enough elements in the stack"); - assert(L.status === TS.LUA_OK, "cannot do calls on non-normal thread"); - assert(nargs === defs.LUA_MULTRET || (L.ci.top - L.top >= nargs - nresults), "results from function overflow current stack size"); +const checkresults = function(L,na,nr) { + api_check(L, (nr) == LUA_MULTRET || (L.ci.top - L.top >= (nr) - (na)), + "results from function overflow current stack size"); +}; +const lua_callk = function(L, nargs, nresults, ctx, k) { + api_check(L, k === null || !(L.ci.callstatus & lstate.CIST_LUA), "cannot use continuations inside hooks"); + api_checknelems(L, nargs + 1); + api_check(L, L.status === LUA_OK, "cannot do calls on non-normal thread"); + checkresults(L, nargs, nresults); let func = L.top - (nargs + 1); if (k !== null && L.nny === 0) { /* need to prepare continuation? */ L.ci.c_k = k; @@ -950,7 +972,7 @@ const lua_callk = function(L, nargs, nresults, ctx, k) { ldo.luaD_callnoyield(L, func, nresults); } - if (nresults === defs.LUA_MULTRET && L.ci.top < L.top) + if (nresults === LUA_MULTRET && L.ci.top < L.top) L.ci.top = L.top; }; @@ -959,10 +981,10 @@ const lua_call = function(L, n, r) { }; const lua_pcallk = function(L, nargs, nresults, errfunc, ctx, k) { - assert(nargs + 1 < L.top - L.ci.funcOff, "not enough elements in the stack"); - assert(L.status === TS.LUA_OK, "cannot do calls on non-normal thread"); - assert(nargs === defs.LUA_MULTRET || (L.ci.top - L.top >= nargs - nresults), "results from function overflow current stack size"); - + api_check(L, k === null || !(L.ci.callstatus & lstate.CIST_LUA), "cannot use continuations inside hooks"); + api_checknelems(L, nargs + 1); + api_check(L, L.status === LUA_OK, "cannot do calls on non-normal thread"); + checkresults(L, nargs, nresults); let c = { func: null, funcOff: NaN, @@ -998,10 +1020,10 @@ const lua_pcallk = function(L, nargs, nresults, errfunc, ctx, k) { ldo.luaD_call(L, c.funcOff, nresults); /* do the call */ ci.callstatus &= ~lstate.CIST_YPCALL; L.errfunc = ci.c_old_errfunc; - status = TS.LUA_OK; + status = LUA_OK; } - if (nresults === defs.LUA_MULTRET && L.ci.top < L.top) + if (nresults === LUA_MULTRET && L.ci.top < L.top) L.ci.top = L.top; return status; @@ -1016,18 +1038,17 @@ const lua_pcall = function(L, n, r, f) { */ const lua_error = function(L) { - assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack"); + api_checknelems(L, 1); ldebug.luaG_errormsg(L); }; const lua_next = function(L, idx) { let t = index2addr(L, idx); - assert(t.ttistable(), "table expected"); + api_check(L, t.ttistable(), "table expected"); L.stack[L.top] = new TValue(); let more = ltable.luaH_next(L, t.value, L.top - 1); if (more) { - L.top++; - assert(L.top <= L.ci.top, "stack overflow"); + api_incr_top(L); return 1; } else { delete L.stack[L.top]; @@ -1037,12 +1058,12 @@ const lua_next = function(L, idx) { }; const lua_concat = function(L, n) { - assert(n < L.top - L.ci.funcOff, "not enough elements in the stack"); + api_checknelems(L, n); if (n >= 2) lvm.luaV_concat(L, n); else if (n === 0) { - lobject.pushsvalue2s(L, lstring.luaS_bless(L, defs.to_luastring("", true))); - assert(L.top <= L.ci.top, "stack overflow"); + lobject.pushsvalue2s(L, luaS_bless(L, to_luastring("", true))); + api_check(L, L.top <= L.ci.top, "stack overflow"); } }; @@ -1051,35 +1072,34 @@ const lua_len = function(L, idx) { let tv = new TValue(); lvm.luaV_objlen(L, tv, t); L.stack[L.top] = tv; - L.top++; - assert(L.top <= L.ci.top, "stack overflow"); + api_incr_top(L); }; const getupvalref = function(L, fidx, n) { let fi = index2addr(L, fidx); - assert(fi.ttisLclosure(), "Lua function expected"); + api_check(L, fi.ttisLclosure(), "Lua function expected"); let f = fi.value; - assert(1 <= n && n <= f.p.upvalues.length, "invalid upvalue index"); + api_check(L, n|0 === n && 1 <= n && n <= f.p.upvalues.length, "invalid upvalue index"); return { - closure: f, - upval: f.upvals[n - 1], - upvalOff: n - 1 + f: f, + i: n - 1 }; }; const lua_upvalueid = function(L, fidx, n) { let fi = index2addr(L, fidx); switch (fi.ttype()) { - case CT.LUA_TLCL: { /* lua closure */ - return getupvalref(L, fidx, n).upval; + case LUA_TLCL: { /* lua closure */ + let ref = getupvalref(L, fidx, n); + return ref.f.upvals[ref.i]; } - case CT.LUA_TCCL: { /* C closure */ + case LUA_TCCL: { /* C closure */ let f = fi.value; - assert(1 <= n && n <= f.nupvalues, "invalid upvalue index"); + api_check(L, n|0 === n && 1 <= n && n <= f.nupvalues, "invalid upvalue index"); return f.upvalue[n - 1]; } default: { - assert(false, "closure expected"); + api_check(L, false, "closure expected"); return null; } } @@ -1088,13 +1108,8 @@ const lua_upvalueid = function(L, fidx, n) { const lua_upvaluejoin = function(L, fidx1, n1, fidx2, n2) { let ref1 = getupvalref(L, fidx1, n1); let ref2 = getupvalref(L, fidx2, n2); - let up1 = ref1.upval; - let up2 = ref2.upval; - let f1 = ref1.closure; - assert(up1.refcount > 0); - up1.refcount--; - f1.upvals[ref1.upvalOff] = up2; - up2.refcount++; + let up2 = ref2.f.upvals[ref2.i]; + ref1.f.upvals[ref1.i] = up2; }; // This functions are only there for compatibility purposes @@ -1115,8 +1130,8 @@ const lua_getextraspace = function () { return 0; }; -module.exports.index2addr = index2addr; -module.exports.index2addr_ = index2addr_; +module.exports.api_incr_top = api_incr_top; +module.exports.api_checknelems = api_checknelems; module.exports.lua_absindex = lua_absindex; module.exports.lua_arith = lua_arith; module.exports.lua_atpanic = lua_atpanic; |