summaryrefslogtreecommitdiff
path: root/src/lapi.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/lapi.js')
-rw-r--r--src/lapi.js201
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");
};