diff --git a/lobject.h b/lobject.h index 773a167b..40977e99 100644 --- a/lobject.h +++ b/lobject.h @@ -1,5 +1,5 @@ /* -** $Id: lobject.h,v 2.71 2012/09/11 18:21:44 roberto Exp roberto $ +** $Id: lobject.h,v 2.70 2012/05/11 14:10:50 roberto Exp $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -57,6 +57,11 @@ #define LUA_TLNGSTR (LUA_TSTRING | (1 << 4)) /* long strings */ +/* Variant tags for numbers */ +#define LUA_TNUMFLT (LUA_TNUMBER | (0 << 4)) /* float numbers */ +#define LUA_TNUMINT (LUA_TNUMBER | (1 << 4)) /* integer numbers */ + + /* Bit mark for collectable types */ #define BIT_ISCOLLECTABLE (1 << 6) @@ -92,8 +97,6 @@ typedef struct GCheader { typedef union Value Value; -#define numfield lua_Number n; /* numbers */ - /* @@ -111,7 +114,6 @@ typedef struct lua_TValue TValue; #define val_(o) ((o)->value_) -#define num_(o) (val_(o).n) /* raw type tag of a TValue */ @@ -130,7 +132,9 @@ typedef struct lua_TValue TValue; /* Macros to test type */ #define checktag(o,t) (rttype(o) == (t)) #define checktype(o,t) (ttnov(o) == (t)) -#define ttisnumber(o) checktag((o), LUA_TNUMBER) +#define ttisnumber(o) checktype((o), LUA_TNUMBER) +#define ttisfloat(o) checktag((o), LUA_TNUMFLT) +#define ttisinteger(o) checktag((o), LUA_TNUMINT) #define ttisnil(o) checktag((o), LUA_TNIL) #define ttisboolean(o) checktag((o), LUA_TBOOLEAN) #define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA) @@ -147,10 +151,13 @@ typedef struct lua_TValue TValue; #define ttisthread(o) checktag((o), ctb(LUA_TTHREAD)) #define ttisdeadkey(o) checktag((o), LUA_TDEADKEY) -#define ttisequal(o1,o2) (rttype(o1) == rttype(o2)) /* Macros to access values */ -#define nvalue(o) check_exp(ttisnumber(o), num_(o)) +#define nvalue(o) \ + check_exp(ttisnumber(o), (ttisfloat(o) ? val_(o).n : cast_num(val_(o).i))) + +#define ivalue(o) check_exp(ttisinteger(o), val_(o).i) +#define fltvalue(o) check_exp(ttisfloat(o), val_(o).n) #define gcvalue(o) check_exp(iscollectable(o), val_(o).gc) #define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p) #define rawtsvalue(o) check_exp(ttisstring(o), &val_(o).gc->ts) @@ -185,7 +192,10 @@ typedef struct lua_TValue TValue; #define settt_(o,t) ((o)->tt_=(t)) #define setnvalue(obj,x) \ - { TValue *io=(obj); num_(io)=(x); settt_(io, LUA_TNUMBER); } + { TValue *io=(obj); val_(io).n=(x); settt_(io, LUA_TNUMFLT); } + +#define setivalue(obj,x) \ + { TValue *io=(obj); val_(io).i=(x); settt_(io, LUA_TNUMINT); } #define setnilvalue(obj) settt_(obj, LUA_TNIL) @@ -267,115 +277,6 @@ typedef struct lua_TValue TValue; #define luai_checknum(L,o,c) { /* empty */ } -/* -** {====================================================== -** NaN Trick -** ======================================================= -*/ -#if defined(LUA_NANTRICK) - -/* -** numbers are represented in the 'd_' field. All other values have the -** value (NNMARK | tag) in 'tt__'. A number with such pattern would be -** a "signaled NaN", which is never generated by regular operations by -** the CPU (nor by 'strtod') -*/ - -/* allows for external implementation for part of the trick */ -#if !defined(NNMARK) /* { */ - - -#if !defined(LUA_IEEEENDIAN) -#error option 'LUA_NANTRICK' needs 'LUA_IEEEENDIAN' -#endif - - -#define NNMARK 0x7FF7A500 -#define NNMASK 0x7FFFFF00 - -#undef TValuefields -#undef NILCONSTANT - -#if (LUA_IEEEENDIAN == 0) /* { */ - -/* little endian */ -#define TValuefields \ - union { struct { Value v__; int tt__; } i; double d__; } u -#define NILCONSTANT {{{NULL}, tag2tt(LUA_TNIL)}} -/* field-access macros */ -#define v_(o) ((o)->u.i.v__) -#define d_(o) ((o)->u.d__) -#define tt_(o) ((o)->u.i.tt__) - -#else /* }{ */ - -/* big endian */ -#define TValuefields \ - union { struct { int tt__; Value v__; } i; double d__; } u -#define NILCONSTANT {{tag2tt(LUA_TNIL), {NULL}}} -/* field-access macros */ -#define v_(o) ((o)->u.i.v__) -#define d_(o) ((o)->u.d__) -#define tt_(o) ((o)->u.i.tt__) - -#endif /* } */ - -#endif /* } */ - - -/* correspondence with standard representation */ -#undef val_ -#define val_(o) v_(o) -#undef num_ -#define num_(o) d_(o) - - -#undef numfield -#define numfield /* no such field; numbers are the entire struct */ - -/* basic check to distinguish numbers from non-numbers */ -#undef ttisnumber -#define ttisnumber(o) ((tt_(o) & NNMASK) != NNMARK) - -#define tag2tt(t) (NNMARK | (t)) - -#undef rttype -#define rttype(o) (ttisnumber(o) ? LUA_TNUMBER : tt_(o) & 0xff) - -#undef settt_ -#define settt_(o,t) (tt_(o) = tag2tt(t)) - -#undef setnvalue -#define setnvalue(obj,x) \ - { TValue *io_=(obj); num_(io_)=(x); lua_assert(ttisnumber(io_)); } - -#undef setobj -#define setobj(L,obj1,obj2) \ - { const TValue *o2_=(obj2); TValue *o1_=(obj1); \ - o1_->u = o2_->u; \ - checkliveness(G(L),o1_); } - - -/* -** these redefinitions are not mandatory, but these forms are more efficient -*/ - -#undef checktag -#undef checktype -#define checktag(o,t) (tt_(o) == tag2tt(t)) -#define checktype(o,t) (ctb(tt_(o) | VARBITS) == ctb(tag2tt(t) | VARBITS)) - -#undef ttisequal -#define ttisequal(o1,o2) \ - (ttisnumber(o1) ? ttisnumber(o2) : (tt_(o1) == tt_(o2))) - - -#undef luai_checknum -#define luai_checknum(L,o,c) { if (!ttisnumber(o)) c; } - -#endif -/* }====================================================== */ - /* @@ -390,7 +291,8 @@ union Value { void *p; /* light userdata */ int b; /* booleans */ lua_CFunction f; /* light C functions */ - numfield /* numbers */ + lua_Integer i; /* integer numbers */ + lua_Number n; /* float numbers */ }; diff --git a/ltable.c b/ltable.c index 8c971b27..7147f6fe 100644 --- a/ltable.c +++ b/ltable.c @@ -1,5 +1,5 @@ /* -** $Id: ltable.c,v 2.71 2012/05/23 15:37:09 roberto Exp roberto $ +** $Id: ltable.c,v 2.71 2012/05/23 15:37:09 roberto Exp $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -52,6 +52,7 @@ #define hashstr(t,str) hashpow2(t, (str)->tsv.hash) #define hashboolean(t,p) hashpow2(t, p) +#define hashint(t,i) hashpow2(t, i) /* @@ -96,8 +97,12 @@ static Node *hashnum (const Table *t, lua_Number n) { */ static Node *mainposition (const Table *t, const TValue *key) { switch (ttype(key)) { - case LUA_TNUMBER: - return hashnum(t, nvalue(key)); + case LUA_TNUMINT: + return hashint(t, ivalue(key)); + case LUA_TNUMFLT: + return hashnum(t, fltvalue(key)); + case LUA_TSHRSTR: + return hashstr(t, rawtsvalue(key)); case LUA_TLNGSTR: { TString *s = rawtsvalue(key); if (s->tsv.extra == 0) { /* no hash? */ @@ -106,8 +111,6 @@ static Node *mainposition (const Table *t, const TValue *key) { } return hashstr(t, rawtsvalue(key)); } - case LUA_TSHRSTR: - return hashstr(t, rawtsvalue(key)); case LUA_TBOOLEAN: return hashboolean(t, bvalue(key)); case LUA_TLIGHTUSERDATA: @@ -120,19 +123,24 @@ static Node *mainposition (const Table *t, const TValue *key) { } +static int numisint (lua_Number n, int *p) { + int k; + lua_number2int(k, n); + if (luai_numeq(cast_num(k), n)) { /* 'k' is int? */ + *p = k; + return 1; + } + return 0; +} + + /* ** returns the index for `key' if `key' is an appropriate key to live in ** the array part of the table, -1 otherwise. */ static int arrayindex (const TValue *key) { - if (ttisnumber(key)) { - lua_Number n = nvalue(key); - int k; - lua_number2int(k, n); - if (luai_numeq(cast_num(k), n)) - return k; - } - return -1; /* `key' did not match some condition */ + if (ttisinteger(key)) return ivalue(key); + else return -1; /* `key' did not match some condition */ } @@ -170,7 +178,7 @@ int luaH_next (lua_State *L, Table *t, StkId key) { int i = findindex(L, t, key); /* find original element */ for (i++; i < t->sizearray; i++) { /* try first array part */ if (!ttisnil(&t->array[i])) { /* a non-nil value? */ - setnvalue(key, cast_num(i+1)); + setivalue(key, i + 1); setobj2s(L, key+1, &t->array[i]); return 1; } @@ -404,9 +412,18 @@ static Node *getfreepos (Table *t) { */ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { Node *mp; + TValue aux; if (ttisnil(key)) luaG_runerror(L, "table index is nil"); - else if (ttisnumber(key) && luai_numisnan(L, nvalue(key))) - luaG_runerror(L, "table index is NaN"); + else if (ttisfloat(key)) { + lua_Number n = fltvalue(key); + int k; + if (luai_numisnan(L, n)) + luaG_runerror(L, "table index is NaN"); + if (numisint(n, &k)) { /* index is int? */ + setivalue(&aux, k); + key = &aux; /* insert it as an integer */ + } + } mp = mainposition(t, key); if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */ Node *othern; @@ -448,10 +465,9 @@ const TValue *luaH_getint (Table *t, int key) { if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) return &t->array[key-1]; else { - lua_Number nk = cast_num(key); - Node *n = hashnum(t, nk); + Node *n = hashint(t, key); do { /* check whether `key' is somewhere in the chain */ - if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) + if (ttisinteger(gkey(n)) && ivalue(gkey(n)) == key) return gval(n); /* that's it */ else n = gnext(n); } while (n); @@ -481,12 +497,11 @@ const TValue *luaH_getstr (Table *t, TString *key) { const TValue *luaH_get (Table *t, const TValue *key) { switch (ttype(key)) { case LUA_TSHRSTR: return luaH_getstr(t, rawtsvalue(key)); + case LUA_TNUMINT: return luaH_getint(t, ivalue(key)); case LUA_TNIL: return luaO_nilobject; - case LUA_TNUMBER: { + case LUA_TNUMFLT: { int k; - lua_Number n = nvalue(key); - lua_number2int(k, n); - if (luai_numeq(cast_num(k), n)) /* index is int? */ + if (numisint(fltvalue(key), &k)) /* index is int? */ return luaH_getint(t, k); /* use specialized version */ /* else go through */ } @@ -522,7 +537,7 @@ void luaH_setint (lua_State *L, Table *t, int key, TValue *value) { cell = cast(TValue *, p); else { TValue k; - setnvalue(&k, cast_num(key)); + setivalue(&k, key); cell = luaH_newkey(L, t, &k); } setobj2t(L, cell, value); diff --git a/lvm.c b/lvm.c index c502d303..be8ba326 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.155 2013/03/16 21:10:18 roberto Exp roberto $ +** $Id: lvm.c,v 2.154 2012/08/16 17:34:28 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -34,7 +34,11 @@ const TValue *luaV_tonumber (const TValue *obj, TValue *n) { lua_Number num; - if (ttisnumber(obj)) return obj; + if (ttisfloat(obj)) return obj; + if (ttisinteger(obj)) { + setnvalue(n, cast_num(ivalue(obj))); + return n; + } if (ttisstring(obj) && luaO_str2d(svalue(obj), tsvalue(obj)->len, &num)) { setnvalue(n, num); return n; @@ -257,12 +261,19 @@ int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { /* ** equality of Lua values. L == NULL means raw equality (no metamethods) */ -int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2) { +int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { const TValue *tm; - lua_assert(ttisequal(t1, t2)); + if (ttype(t1) != ttype(t2)) { + if (ttnov(t1) != ttnov(t2) || ttnov(t1) != LUA_TNUMBER) + return 0; /* only numbers can be equal with different variants */ + else /* two numbers with different variants */ + return luai_numeq(nvalue(t1), nvalue(t2)); + } + /* values have same type and same variant */ switch (ttype(t1)) { case LUA_TNIL: return 1; - case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); + case LUA_TNUMINT: return (ivalue(t1) == ivalue(t2)); + case LUA_TNUMFLT: return luai_numeq(fltvalue(t1), fltvalue(t2)); case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); case LUA_TLCF: return fvalue(t1) == fvalue(t2); @@ -281,7 +292,6 @@ int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2) { break; /* will try TM */ } default: - lua_assert(iscollectable(t1)); return gcvalue(t1) == gcvalue(t2); } if (tm == NULL) return 0; /* no TM? */ @@ -615,7 +625,13 @@ void luaV_execute (lua_State *L) { Protect(luaV_gettable(L, rb, RKC(i), ra)); ) vmcase(OP_ADD, - arith_op(luai_numadd, TM_ADD); + TValue *rb1 = RKB(i); + TValue *rc1 = RKC(i); + if (ttisinteger(rb1) && ttisinteger(rc1)) { + lua_Integer ib = ivalue(rb1); lua_Integer ic = ivalue(rc1); + setivalue(ra, ib + ic); + } + else arith_op(luai_numadd, TM_ADD); ) vmcase(OP_SUB, arith_op(luai_numsub, TM_SUB); @@ -669,7 +685,7 @@ void luaV_execute (lua_State *L) { TValue *rb = RKB(i); TValue *rc = RKC(i); Protect( - if (cast_int(equalobj(L, rb, rc)) != GETARG_A(i)) + if (cast_int(luaV_equalobj(L, rb, rc)) != GETARG_A(i)) ci->u.l.savedpc++; else donextjump(ci); diff --git a/lvm.h b/lvm.h index 911f0e97..365e4a48 100644 --- a/lvm.h +++ b/lvm.h @@ -1,5 +1,5 @@ /* -** $Id: lvm.h,v 2.17 2011/05/31 18:27:56 roberto Exp roberto $ +** $Id: lvm.h,v 2.17 2011/05/31 18:27:56 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -15,17 +15,13 @@ #define tostring(L,o) (ttisstring(o) || (luaV_tostring(L, o))) -#define tonumber(o,n) (ttisnumber(o) || (((o) = luaV_tonumber(o,n)) != NULL)) - -#define equalobj(L,o1,o2) (ttisequal(o1, o2) && luaV_equalobj_(L, o1, o2)) - -#define luaV_rawequalobj(o1,o2) equalobj(NULL,o1,o2) +#define tonumber(o,n) (ttisfloat(o) || (((o) = luaV_tonumber(o,n)) != NULL)) -/* not to called directly */ -LUAI_FUNC int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2); +#define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2) +LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n);