diff options
Diffstat (limited to 'src/lapi.js')
-rw-r--r-- | src/lapi.js | 201 |
1 files changed, 106 insertions, 95 deletions
diff --git a/src/lapi.js b/src/lapi.js index 9b40b36..1dfd112 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -112,7 +112,9 @@ const lua_xmove = function(from, to, n) { from.top -= n; for (let i = 0; i < n; i++) { - to.stack[to.top] = from.stack[from.top + i]; + to.stack[to.top] = new lobject.TValue(); + lobject.setobj2s(to, to.top, from.stack[from.top + i]); + delete from.stack[from.top + i]; to.top++; } }; @@ -135,22 +137,24 @@ const lua_gettop = function(L) { }; const lua_pushvalue = function(L, idx) { - L.stack[L.top] = index2addr(L, idx); - - L.top++; + lobject.pushobj2s(L, index2addr(L, idx)); assert(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"); - while (L.top < func + 1 + idx) - L.stack[L.top++] = new TValue(CT.LUA_TNIL, null); - L.top = func + 1 + idx; + newtop = func + 1 + idx; } else { assert(-(idx + 1) <= L.top - (func + 1), "invalid new top"); - let newtop = L.top + idx + 1; /* 'subtract' index (index is negative) */ + newtop = L.top + idx + 1; /* 'subtract' index (index is negative) */ + } + if (L.top < newtop) { + while (L.top < newtop) + L.stack[L.top++] = new TValue(CT.LUA_TNIL, null); + } else { while (L.top > newtop) delete L.stack[--L.top]; } @@ -162,9 +166,10 @@ const lua_pop = function(L, n) { const reverse = function(L, from, to) { for (; from < to; from++, to--) { - let temp = L.stack[from]; - L.stack[from] = L.stack[to]; - L.stack[to] = temp; + let fromtv = L.stack[from]; + let temp = new TValue(fromtv.type, fromtv.value); + lobject.setobjs2s(L, from, to); + lobject.setobj2s(L, to, temp); } }; @@ -189,7 +194,7 @@ const lua_rotate = function(L, idx, n) { const lua_copy = function(L, fromidx, toidx) { let from = index2addr(L, fromidx); - L.stack[index2addr_(L, toidx)] = new TValue(from.type, from.value); + L.stack[index2addr_(L, toidx)].setfrom(from); }; const lua_remove = function(L, idx) { @@ -211,34 +216,36 @@ const lua_replace = function(L, idx) { */ const lua_pushnil = function(L) { - L.stack[L.top++] = new TValue(CT.LUA_TNIL, null); - + L.stack[L.top] = new TValue(CT.LUA_TNIL, null); + L.top++; assert(L.top <= L.ci.top, "stack overflow"); }; const lua_pushnumber = function(L, n) { assert(typeof n === "number"); - L.stack[L.top++] = new TValue(CT.LUA_TNUMFLT, n); - + L.stack[L.top] = new TValue(CT.LUA_TNUMFLT, n); + L.top++; assert(L.top <= L.ci.top, "stack overflow"); }; const lua_pushinteger = function(L, n) { assert(typeof n === "number" && (n|0) === n); - - L.stack[L.top++] = new TValue(CT.LUA_TNUMINT, n); - + L.stack[L.top] = new TValue(CT.LUA_TNUMINT, n); + L.top++; assert(L.top <= L.ci.top, "stack overflow"); }; const lua_pushlstring = function(L, s, len) { - assert(Array.isArray(s), "lua_pushlstring expects array of byte"); assert(typeof len === "number"); - - let ts = new TValue(CT.LUA_TLNGSTR, lstring.luaS_bless(L, s.slice(0, len))); - L.stack[L.top++] = ts; - + let ts; + if (len === 0) { + ts = lstring.luaS_bless(L, []); + } else { + assert(Array.isArray(s), "lua_pushlstring expects array of byte"); + ts = lstring.luaS_bless(L, s.slice(0, len)); + } + lobject.pushsvalue2s(L, ts); assert(L.top <= L.ci.top, "stack overflow"); return ts.value; @@ -247,13 +254,14 @@ const lua_pushlstring = function(L, s, len) { const lua_pushstring = function (L, s) { assert(Array.isArray(s) || s === undefined || s === null, "lua_pushstring expects array of byte"); - if (s === undefined || s === null) - L.stack[L.top] = new TValue(CT.LUA_TNIL, null); - else { - L.stack[L.top] = new TValue(CT.LUA_TLNGSTR, lstring.luaS_new(L, s)); + if (s === undefined || s === null) { + L.stack[L.top] = new TValue(CT.LUA_TNIL, null) + L.top++; + } else { + let ts = lstring.luaS_new(L, s); + lobject.pushsvalue2s(L, ts); + s = ts.getstr(); /* internal copy */ } - - L.top++; assert(L.top <= L.ci.top, "stack overflow"); return s; @@ -269,17 +277,18 @@ const lua_pushfstring = function (L, fmt, ...argp) { return lobject.luaO_pushvfstring(L, fmt, argp); }; +/* Similar to lua_pushstring, but takes a JS string */ const lua_pushliteral = function (L, s) { assert(typeof s === "string" || s === undefined || s === null, "lua_pushliteral expects a JS string"); - if (s === undefined || s === null) + if (s === undefined || s === null) { L.stack[L.top] = new TValue(CT.LUA_TNIL, null); - else { - let ts = new TValue(CT.LUA_TLNGSTR, lstring.luaS_newliteral(L, s)); - L.stack[L.top] = ts; + L.top++; + } else { + let ts = lstring.luaS_newliteral(L, s); + lobject.pushsvalue2s(L, ts); + s = ts.getstr(); /* internal copy */ } - - L.top++; assert(L.top <= L.ci.top, "stack overflow"); return s; @@ -296,16 +305,14 @@ const lua_pushcclosure = function(L, fn, n) { assert(n <= MAXUPVAL, "upvalue index too large"); let cl = new CClosure(L, fn, n); - - L.top -= n; - while (n--) { - cl.upvalue[n].setfrom(L.stack[L.top + n]) - delete L.stack[L.top + n]; - } - - L.stack[L.top] = new TValue(CT.LUA_TCCL, cl); + for (let i=0; i<n; i++) + cl.upvalue[i].setfrom(L.stack[L.top - n + i]); + for (let i=1; i<n; i++) + delete L.stack[--L.top]; + if (n>0) + --L.top; + L.stack[L.top].setclCvalue(cl); } - L.top++; assert(L.top <= L.ci.top, "stack overflow"); }; @@ -319,21 +326,21 @@ 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.stack[L.top] = new TValue(CT.LUA_TBOOLEAN, b ? true : false); + L.top++; assert(L.top <= L.ci.top, "stack overflow"); }; const lua_pushlightuserdata = function(L, p) { - L.stack[L.top++] = new TValue(CT.LUA_TLIGHTUSERDATA, p); - + L.stack[L.top] = new TValue(CT.LUA_TLIGHTUSERDATA, p); + L.top++; assert(L.top <= L.ci.top, "stack overflow"); }; const lua_pushthread = function(L) { - L.stack[L.top++] = new TValue(CT.LUA_TTHREAD, L); + L.stack[L.top] = new TValue(CT.LUA_TTHREAD, L); + L.top++; assert(L.top <= L.ci.top, "stack overflow"); - return L.l_G.mainthread === L; }; @@ -351,11 +358,10 @@ const lua_pushglobaltable = function(L) { const auxsetstr = function(L, t, k) { assert(Array.isArray(k), "key must be an array of bytes"); - let str = new TValue(CT.LUA_TLNGSTR, lstring.luaS_new(L, k)); - + let str = lstring.luaS_new(L, k); assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack"); - - L.stack[L.top++] = str; + lobject.pushsvalue2s(L, str); /* push 'str' (to make it a TValue) */ + 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 */ delete L.stack[--L.top]; @@ -409,7 +415,8 @@ 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"); let t = index2addr(L, idx); - L.stack[L.top++] = new TValue(CT.LUA_TNUMINT, n); + L.stack[L.top] = new TValue(CT.LUA_TNUMINT, n); + L.top++; 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 */ @@ -430,7 +437,8 @@ const lua_rawset = function(L, idx) { slot.setfrom(v); } ltable.invalidateTMcache(o.value); - L.top -= 2; + delete L.stack[--L.top]; + delete L.stack[--L.top]; }; const lua_rawseti = function(L, idx, n) { @@ -453,7 +461,7 @@ const lua_rawsetp = function(L, idx, p) { let slot = ltable.luaH_set(L, o.value, k); slot.setfrom(v); } - L.top--; + delete L.stack[--L.top]; }; /* @@ -462,24 +470,18 @@ const lua_rawsetp = function(L, idx, p) { const auxgetstr = function(L, t, k) { assert(Array.isArray(k), "key must be an array of bytes"); - - let str = new TValue(CT.LUA_TLNGSTR, lstring.luaS_new(L, k)); - - L.stack[L.top++] = str; + let str = lstring.luaS_new(L, k); + lobject.pushsvalue2s(L, 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(); }; const lua_rawgeti = function(L, idx, n) { let t = index2addr(L, idx); - assert(t.ttistable(), "table expected"); - - L.stack[L.top++] = ltable.luaH_getint(t.value, n); + lobject.pushobj2s(L, ltable.luaH_getint(t.value, n)); assert(L.top <= L.ci.top, "stack overflow"); - return L.stack[L.top - 1].ttnov(); }; @@ -487,26 +489,23 @@ 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); - L.stack[L.top++] = ltable.luaH_get(L, t.value, k); + lobject.pushobj2s(L, ltable.luaH_get(L, t.value, k)); assert(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"); - - L.stack[L.top - 1] = ltable.luaH_get(L, t.value, L.stack[L.top - 1]); - + 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)); - L.stack[L.top++] = t; - + L.stack[L.top] = t; + L.top++; assert(L.top <= L.ci.top, "stack overflow"); }; @@ -516,10 +515,9 @@ 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.stack[L.top] = new lobject.TValue(CT.LUA_TUSERDATA, u); + L.top++; assert(L.top <= L.ci.top, "stack overflow"); - return u.data; }; @@ -552,9 +550,8 @@ const lua_getupvalue = function(L, funcindex, n) { if (up) { let name = up.name; let val = up.val; - - L.stack[L.top++] = new TValue(val.type, val.value); - + lobject.pushobj2s(L, val); + assert(L.top <= L.ci.top, "stack overflow"); return name; } return null; @@ -567,8 +564,8 @@ const lua_setupvalue = function(L, funcindex, n) { if (aux) { let name = aux.name; let val = aux.val; - L.top--; - val.setfrom(L.stack[L.top]); + val.setfrom(L.stack[L.top-1]); + delete L.stack[--L.top]; return name; } return null; @@ -598,7 +595,8 @@ const lua_getmetatable = function(L, objindex) { } if (mt !== null && mt !== undefined) { - L.stack[L.top++] = new TValue(CT.LUA_TTABLE, mt); + L.stack[L.top] = new TValue(CT.LUA_TTABLE, mt); + L.top++; assert(L.top <= L.ci.top, "stack overflow"); res = true; } @@ -610,7 +608,8 @@ const lua_getuservalue = function(L, idx) { let o = index2addr(L, idx); assert(L, o.ttisfulluserdata(), "full userdata expected"); let uv = o.value.uservalue; - L.stack[L.top++] = new TValue(uv.type, uv.value); + L.stack[L.top] = new TValue(uv.type, uv.value); + L.top++; assert(L.top <= L.ci.top, "stack overflow"); return L.stack[L.top - 1].ttnov(); }; @@ -628,7 +627,8 @@ const lua_getfield = function(L, idx, k) { const lua_geti = function(L, idx, n) { assert(typeof n === "number" && (n|0) === n); let t = index2addr(L, idx); - L.stack[L.top++] = new TValue(CT.LUA_TNUMINT, n); + L.stack[L.top] = new TValue(CT.LUA_TNUMINT, n); + L.top++; 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(); @@ -654,7 +654,8 @@ const lua_tolstring = function(L, idx) { if (!lvm.cvt2str(o)) { /* not convertible? */ return null; } - o = lobject.luaO_tostring(L, o); + /* TODO: this should modify number on the stack */ + return lobject.luaO_tostring(L, o).getstr(); } return o.svalue(); }; @@ -668,7 +669,8 @@ const lua_toljsstring = function(L, idx) { if (!lvm.cvt2str(o)) { /* not convertible? */ return null; } - o = lobject.luaO_tostring(L, o); + /* TODO: this should modify number on the stack */ + return defs.to_jsstring(lobject.luaO_tostring(L, o).getstr()); } return o.jsstring(); }; @@ -768,7 +770,9 @@ const lua_isproxy = function(p, L) { 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"); - L.stack[L.top++] = new TValue(type, value); + L.stack[L.top] = new TValue(type, value); + L.top++; + assert(L.top <= L.ci.top, "stack overflow"); }; seen.set(proxy, G); return proxy; @@ -802,7 +806,8 @@ const lua_compare = function(L, index1, index2, op) { const lua_stringtonumber = function(L, s) { let tv = lobject.luaO_str2num(s); if (tv) { - L.stack[L.top++] = tv; + L.stack[L.top] = tv; + L.top++; assert(L.top <= L.ci.top, "stack overflow"); return s.length+1; } @@ -893,11 +898,12 @@ const lua_arith = function(L, op) { assert(2 < L.top - L.ci.funcOff, "not enough elements in the stack"); /* 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"); - L.stack[L.top++] = L.stack[L.top - 1]; + lobject.pushobj2s(L, L.stack[L.top-1]); + assert(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.top - 2); - L.top--; /* remove second operand */ + lobject.luaO_arith(L, op, L.stack[L.top - 2], L.stack[L.top - 1], L.stack[L.top - 2]); + delete L.stack[--L.top]; /* remove second operand */ }; /* @@ -1030,13 +1036,15 @@ const lua_error = function(L) { const lua_next = function(L, idx) { let t = index2addr(L, idx); assert(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"); return 1; } else { - L.top--; + delete L.stack[L.top]; + delete L.stack[--L.top]; return 0; } }; @@ -1046,14 +1054,17 @@ const lua_concat = function(L, n) { if (n >= 2) lvm.luaV_concat(L, n); else if (n === 0) { - L.stack[L.top++] = new TValue(CT.LUA_TLNGSTR, lstring.luaS_newliteral(L, "")); + lobject.pushsvalue2s(L, lstring.luaS_bless(L, [])); assert(L.top <= L.ci.top, "stack overflow"); } }; const lua_len = function(L, idx) { let t = index2addr(L, idx); - lvm.luaV_objlen(L, L.top++, t); + 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"); }; |