summaryrefslogtreecommitdiff
path: root/src/lvm.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/lvm.js')
-rw-r--r--src/lvm.js91
1 files changed, 82 insertions, 9 deletions
diff --git a/src/lvm.js b/src/lvm.js
index 2574a97..1673db7 100644
--- a/src/lvm.js
+++ b/src/lvm.js
@@ -53,7 +53,7 @@ class LuaVM {
return new TValue(CT.LUA_TNUMFLT, v.value);
if (v.type === CT.LUA_TSHRSTR || v.type === CT.LUA_TLNGSTR)
- return new TValue(CT.LUA_TNUMFLT, parseFloat(v.value)); // TODO 0x or other exotic form
+ return new TValue(CT.LUA_TNUMFLT, parseFloat(v.value)); // TODO: 0x or other exotic form
return false;
}
@@ -347,9 +347,19 @@ class LuaVM {
break;
}
case "OP_EQ": {
+ if (LuaVM.luaV_equalobj(this.RKB(base, k, i), this.RKC(base, k, i)) !== i.A)
+ ci.pcOff++;
+ else
+ this.donextjump(ci);
+ base = ci.u.l.base;
break;
}
case "OP_LT": {
+ if (LuaVM.luaV_lessthan(this.RKB(base, k, i), this.RKC(base, k, i)) !== i.A)
+ ci.pcOff++;
+ else
+ this.donextjump(ci);
+ base = ci.u.l.base;
break;
}
case "OP_LE": {
@@ -397,7 +407,7 @@ class LuaVM {
let ofunc = oci.func;
let ofuncOff = oci.funcOff;
let lim = nci.u.l.base + nfunc.p.numparams;
- // TODO close upvalues ?
+ // TODO: close upvalues ?
for (let aux = 0; nfuncOff + aux < lim; aux++)
L.stack[ofuncOff + aux] = L.stack[nfuncOff + aux];
@@ -631,7 +641,7 @@ class LuaVM {
dojump(ci, i, e) {
let a = i.A;
- // TODO if (a != 0) luaF_close(L, ci.u.l.base + a - 1);
+ // TODO: if (a != 0) luaF_close(L, ci.u.l.base + a - 1);
ci.pcOff += i.sBx + e;
}
@@ -644,19 +654,82 @@ class LuaVM {
return LuaVM.LEnum(l, r);
else if (l.ttisstring() && r.ttisstring())
return LuaVM.l_strcmp(l, r) <= 0;
- // TODO metatable
- // else if (l.metatable.__le || r.metatable.__le)
- // return l.metatable.__le ? l.metatable.__le(l, r) : r.metatable.__le(l, r);
- // else {
+ // TODO: metatable
+ // else if (l.metatable.__le || r.metatable.__le) {
+ // let res = l.metatable.__le ? l.metatable.__le(l, r) : r.metatable.__le(l, r);
+ // if (res >= 0)
+ // return res;
+ // } else {
// L.ci.callstatus |= lstate.CIST_LEQ;
// let res = l.metatable.__lt ? l.metatable.__lt(r, l) : r.metatable.__lt(r, l);
// L.ci.callstatus ^= lstate.CIST_LEQ;
// if (res < 0)
- // throw new Error("attempt to compare two string values");
+ // throw new Error("attempt to compare ...");
// return !res;
// }
}
+ static luaV_lessthan(l, r) {
+ if (l.ttisnumber() && r.ttisnumber())
+ return LuaVM.LTnum(l, r);
+ else if (l.ttisstring() && r.ttisstring())
+ return LuaVM.l_strcmp(l, r) < 0;
+ // TODO: metatable
+ // else if (l.metatable.__lt || r.metatable.__lt) {
+ // let res = l.metatable.__lt ? l.metatable.__lt(l, r) : r.metatable.__lt(l, r);
+ // if (res < 0)
+ // throw new Error("attempt to compare ...")
+ // return res;
+ // }
+ }
+
+ static luaV_equalobj(t1, t2) {
+ if (t1.ttype() !== t2.ttype()) { /* not the same variant? */
+ if (t1.ttnov() !== t2.ttnov() || t1.ttnov() !== CT.LUA_NUMBER)
+ return 0; /* only numbers can be equal with different variants */
+ else { /* two numbers with different variants */
+ /* compare them as integers */
+ return Math.floor(t1.value) === Math.floor(t2.value) // TODO: tointeger
+ }
+ }
+
+ /* values have same type and same variant */
+ switch(t1.ttype()) {
+ case CT.LUA_TNIL:
+ return 1;
+ case CT.LUA_TNUMINT:
+ case CT.LUA_TNUMFLT:
+ case CT.LUA_TBOOLEAN:
+ case CT.LUA_TLIGHTUSERDATA:
+ case CT.LUA_TLCF:
+ case CT.LUA_TSHRSTR:
+ case CT.LUA_TLNGSTR:
+ return t1.value === t2.value ? 1 : 0;
+ case CT.LUA_TUSERDATA:
+ case CT.LUA_TTABLE:
+ if (t1 === t2) return 1;
+ // TODO: __eq
+ default:
+ return t1.value === t2.value ? 1 : 0;
+ }
+ }
+
+ static LTnum(l, r) {
+ if (l.ttisinteger()) {
+ if (r.ttisinteger())
+ return l.value < r.value ? 1 : 0;
+ else
+ return LuaVM.LTintfloat(r.value, l.value);
+ } else {
+ if (r.ttisfloat())
+ return l.value < r.value ? 1 : 0;
+ else if (isNan(l.value))
+ return 0;
+ else
+ return !LuaVM.LEintfloat(r.value, l.value);
+ }
+ }
+
static LEnum(l, r) {
if (l.ttisinteger()) {
if (r.ttisinteger())
@@ -684,7 +757,7 @@ class LuaVM {
}
static l_strcmp(ls, rs) {
- // TODO lvm.c:248 static int l_strcmp (const TString *ls, const TString *rs)
+ // TODO: lvm.c:248 static int l_strcmp (const TString *ls, const TString *rs)
return ls.value === rs.value ? 0 : (ls.value < rs.value ? -1 : 1);
}