mirror of https://github.com/rusefi/lua.git
new function 'luaV_flttointeger' to convert floats to integers (without
string coercions) + string operands to bitwise operations handled by string metamethods
This commit is contained in:
parent
c3e5946fb2
commit
26679ea35b
6
lcode.c
6
lcode.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lcode.c,v 2.130 2017/10/04 21:56:32 roberto Exp roberto $
|
||||
** $Id: lcode.c,v 2.131 2017/11/07 17:20:42 roberto Exp roberto $
|
||||
** Code generator for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -611,7 +611,7 @@ static void luaK_float (FuncState *fs, int reg, lua_Number f) {
|
|||
TValue v;
|
||||
lua_Integer fi;
|
||||
setfltvalue(&v, f);
|
||||
if (luaV_tointeger(&v, &fi, 0) &&
|
||||
if (luaV_flttointeger(&v, &fi, 0) &&
|
||||
l_castS2U(fi) + MAXARG_sBx <= l_castS2U(MAXARG_Bx))
|
||||
luaK_codeAsBx(fs, OP_LOADF, reg, cast_int(fi));
|
||||
else
|
||||
|
@ -1146,7 +1146,7 @@ static int validop (int op, TValue *v1, TValue *v2) {
|
|||
case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR:
|
||||
case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT: { /* conversion errors */
|
||||
lua_Integer i;
|
||||
return (tointeger(v1, &i) && tointeger(v2, &i));
|
||||
return (tointegerns(v1, &i) && tointegerns(v2, &i));
|
||||
}
|
||||
case LUA_OPDIV: case LUA_OPIDIV: case LUA_OPMOD: /* division by 0 */
|
||||
return (nvalue(v2) != 0);
|
||||
|
|
4
ldebug.c
4
ldebug.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: ldebug.c,v 2.140 2017/11/07 13:25:26 roberto Exp roberto $
|
||||
** $Id: ldebug.c,v 2.141 2017/11/07 17:20:42 roberto Exp roberto $
|
||||
** Debug Interface
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -670,7 +670,7 @@ l_noret luaG_opinterror (lua_State *L, const TValue *p1,
|
|||
*/
|
||||
l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) {
|
||||
lua_Integer temp;
|
||||
if (!tointeger(p1, &temp))
|
||||
if (!tointegerns(p1, &temp))
|
||||
p2 = p1;
|
||||
luaG_runerror(L, "number%s has no integer representation", varinfo(L, p2));
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lobject.c,v 2.117 2017/07/07 16:34:32 roberto Exp roberto $
|
||||
** $Id: lobject.c,v 2.118 2017/10/10 20:05:40 roberto Exp roberto $
|
||||
** Some generic functions over Lua objects
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -127,7 +127,7 @@ int luaO_rawarith (lua_State *L, int op, const TValue *p1, const TValue *p2,
|
|||
case LUA_OPSHL: case LUA_OPSHR:
|
||||
case LUA_OPBNOT: { /* operate only on integers */
|
||||
lua_Integer i1; lua_Integer i2;
|
||||
if (tointeger(p1, &i1) && tointeger(p2, &i2)) {
|
||||
if (tointegerns(p1, &i1) && tointegerns(p2, &i2)) {
|
||||
setivalue(res, intarith(L, op, i1, i2));
|
||||
return 1;
|
||||
}
|
||||
|
|
80
lstrlib.c
80
lstrlib.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lstrlib.c,v 1.256 2017/05/19 16:29:40 roberto Exp roberto $
|
||||
** $Id: lstrlib.c,v 1.257 2017/07/07 16:34:32 roberto Exp roberto $
|
||||
** Standard library for string operations and pattern-matching
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -220,17 +220,49 @@ static int tonum (lua_State *L, int arg) {
|
|||
}
|
||||
|
||||
|
||||
static int toint (lua_State *L, int arg) {
|
||||
if (!tonum(L, arg))
|
||||
return 0; /* not coercible to a number */
|
||||
else if (lua_isinteger(L, arg))
|
||||
return 1; /* already an integer */
|
||||
else { /* a float */
|
||||
int ok;
|
||||
lua_Integer n = lua_tointegerx(L, arg, &ok);
|
||||
if (!ok)
|
||||
return 0;
|
||||
else {
|
||||
lua_pop(L, 1); /* remove the float */
|
||||
lua_pushinteger(L, n); /* push an integer */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void trymt (lua_State *L, const char *mtname) {
|
||||
lua_settop(L, 2); /* back to the original arguments */
|
||||
if (lua_type(L, 2) == LUA_TSTRING || !luaL_getmetafield(L, 2, mtname))
|
||||
luaL_error(L, "attempt to %s a '%s' with a '%s'", mtname + 2,
|
||||
luaL_typename(L, -2), luaL_typename(L, -1));
|
||||
lua_insert(L, -3); /* put metamethod before arguments */
|
||||
lua_call(L, 2, 1); /* call metamethod */
|
||||
}
|
||||
|
||||
|
||||
static int arith (lua_State *L, int op, const char *mtname) {
|
||||
if (tonum(L, 1) && tonum(L, 2))
|
||||
lua_arith(L, op); /* result will be on the top */
|
||||
else {
|
||||
lua_settop(L, 2); /* back to the original arguments */
|
||||
if (lua_type(L, 2) == LUA_TSTRING || !luaL_getmetafield(L, 2, mtname))
|
||||
return luaL_error(L, "attempt to %s a '%s' with a '%s'", mtname + 2,
|
||||
luaL_typename(L, -2), luaL_typename(L, -1));
|
||||
lua_insert(L, -3); /* put metamethod before arguments */
|
||||
lua_call(L, 2, 1); /* call metamethod */
|
||||
}
|
||||
else
|
||||
trymt(L, mtname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int bitwise (lua_State *L, int op, const char *mtname) {
|
||||
if (toint(L, 1) && toint(L, 2))
|
||||
lua_arith(L, op); /* result will be on the top */
|
||||
else
|
||||
trymt(L, mtname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -267,6 +299,30 @@ static int arith_unm (lua_State *L) {
|
|||
return arith(L, LUA_OPUNM, "__unm");
|
||||
}
|
||||
|
||||
static int bitwise_band (lua_State *L) {
|
||||
return bitwise(L, LUA_OPBAND, "__band");
|
||||
}
|
||||
|
||||
static int bitwise_bor (lua_State *L) {
|
||||
return bitwise(L, LUA_OPBOR, "__bor");
|
||||
}
|
||||
|
||||
static int bitwise_bxor (lua_State *L) {
|
||||
return bitwise(L, LUA_OPBXOR, "__bxor");
|
||||
}
|
||||
|
||||
static int bitwise_shl (lua_State *L) {
|
||||
return bitwise(L, LUA_OPSHL, "__shl");
|
||||
}
|
||||
|
||||
static int bitwise_shr (lua_State *L) {
|
||||
return bitwise(L, LUA_OPSHR, "__shr");
|
||||
}
|
||||
|
||||
static int bitwise_bnot (lua_State *L) {
|
||||
return bitwise(L, LUA_OPBNOT, "__bnot");
|
||||
}
|
||||
|
||||
|
||||
static const luaL_Reg stringmetamethods[] = {
|
||||
{"__add", arith_add},
|
||||
|
@ -277,6 +333,12 @@ static const luaL_Reg stringmetamethods[] = {
|
|||
{"__div", arith_div},
|
||||
{"__idiv", arith_idiv},
|
||||
{"__unm", arith_unm},
|
||||
{"__band", bitwise_band},
|
||||
{"__bor", bitwise_bor},
|
||||
{"__bxor", bitwise_bxor},
|
||||
{"__shl", bitwise_shl},
|
||||
{"__shr", bitwise_shr},
|
||||
{"__bnot", bitwise_bnot},
|
||||
{"__index", NULL}, /* placeholder */
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
|
6
ltable.c
6
ltable.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: ltable.c,v 2.124 2017/06/12 14:21:44 roberto Exp roberto $
|
||||
** $Id: ltable.c,v 2.125 2017/06/29 15:06:44 roberto Exp roberto $
|
||||
** Lua tables (hash)
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -495,7 +495,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
|
|||
if (ttisnil(key)) luaG_runerror(L, "table index is nil");
|
||||
else if (ttisfloat(key)) {
|
||||
lua_Integer k;
|
||||
if (luaV_tointeger(key, &k, 0)) { /* does index fit in an integer? */
|
||||
if (luaV_flttointeger(key, &k, 0)) { /* does index fit in an integer? */
|
||||
setivalue(&aux, k);
|
||||
key = &aux; /* insert it as an integer */
|
||||
}
|
||||
|
@ -604,7 +604,7 @@ const TValue *luaH_get (Table *t, const TValue *key) {
|
|||
case LUA_TNIL: return luaO_nilobject;
|
||||
case LUA_TNUMFLT: {
|
||||
lua_Integer k;
|
||||
if (luaV_tointeger(key, &k, 0)) /* index is int? */
|
||||
if (luaV_flttointeger(key, &k, 0)) /* index is an integral? */
|
||||
return luaH_getint(t, k); /* use specialized version */
|
||||
/* else... */
|
||||
} /* FALLTHROUGH */
|
||||
|
|
5
ltm.c
5
ltm.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: ltm.c,v 2.45 2017/10/04 15:49:05 roberto Exp $
|
||||
** $Id: ltm.c,v 2.47 2017/11/07 13:25:26 roberto Exp roberto $
|
||||
** Tag methods
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -153,8 +153,7 @@ void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
|
|||
/* call never returns, but to avoid warnings: *//* FALLTHROUGH */
|
||||
case TM_BAND: case TM_BOR: case TM_BXOR:
|
||||
case TM_SHL: case TM_SHR: case TM_BNOT: {
|
||||
lua_Number dummy;
|
||||
if (tonumber(p1, &dummy) && tonumber(p2, &dummy))
|
||||
if (ttisnumber(p1) && ttisnumber(p2))
|
||||
luaG_tointerror(L, p1, p2);
|
||||
else
|
||||
luaG_opinterror(L, p1, p2, "perform bitwise operation on");
|
||||
|
|
60
lvm.c
60
lvm.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lvm.c,v 2.306 2017/11/07 13:25:26 roberto Exp roberto $
|
||||
** $Id: lvm.c,v 2.307 2017/11/07 17:20:42 roberto Exp roberto $
|
||||
** Lua virtual machine
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -74,7 +74,7 @@ int luaV_tonumber_ (const TValue *obj, lua_Number *n) {
|
|||
*n = cast_num(ivalue(obj));
|
||||
return 1;
|
||||
}
|
||||
else if (cvt2num(obj) && /* string convertible to number? */
|
||||
else if (cvt2num(obj) && /* string coercible to number? */
|
||||
luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) {
|
||||
*n = nvalue(&v); /* convert result of 'luaO_str2num' to a float */
|
||||
return 1;
|
||||
|
@ -85,15 +85,15 @@ int luaV_tonumber_ (const TValue *obj, lua_Number *n) {
|
|||
|
||||
|
||||
/*
|
||||
** try to convert a value to an integer, rounding according to 'mode':
|
||||
** try to convert a float to an integer, rounding according to 'mode':
|
||||
** mode == 0: accepts only integral values
|
||||
** mode == 1: takes the floor of the number
|
||||
** mode == 2: takes the ceil of the number
|
||||
*/
|
||||
int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) {
|
||||
TValue v;
|
||||
again:
|
||||
if (ttisfloat(obj)) {
|
||||
int luaV_flttointeger (const TValue *obj, lua_Integer *p, int mode) {
|
||||
if (!ttisfloat(obj))
|
||||
return 0;
|
||||
else {
|
||||
lua_Number n = fltvalue(obj);
|
||||
lua_Number f = l_floor(n);
|
||||
if (n != f) { /* not an integral value? */
|
||||
|
@ -103,16 +103,23 @@ int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) {
|
|||
}
|
||||
return lua_numbertointeger(f, p);
|
||||
}
|
||||
else if (ttisinteger(obj)) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** try to convert a value to an integer. ("Fast track" is handled
|
||||
** by macro 'tointeger'.)
|
||||
*/
|
||||
int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) {
|
||||
TValue v;
|
||||
if (cvt2num(obj) && luaO_str2num(svalue(obj), &v) == vslen(obj) + 1)
|
||||
obj = &v; /* change string to its corresponding number */
|
||||
if (ttisinteger(obj)) {
|
||||
*p = ivalue(obj);
|
||||
return 1;
|
||||
}
|
||||
else if (cvt2num(obj) &&
|
||||
luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) {
|
||||
obj = &v;
|
||||
goto again; /* convert result from 'luaO_str2num' to an integer */
|
||||
}
|
||||
return 0; /* conversion failed */
|
||||
else
|
||||
return luaV_flttointeger(obj, p, mode);
|
||||
}
|
||||
|
||||
|
||||
|
@ -120,9 +127,9 @@ int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) {
|
|||
** Try to convert a 'for' limit to an integer, preserving the semantics
|
||||
** of the loop. (The following explanation assumes a non-negative step;
|
||||
** it is valid for negative steps mutatis mutandis.)
|
||||
** If the limit can be converted to an integer, rounding down, that is
|
||||
** it.
|
||||
** Otherwise, check whether the limit can be converted to a number. If
|
||||
** If the limit is an integer or can be converted to an integer,
|
||||
** rounding down, that is it.
|
||||
** Otherwise, check whether the limit can be converted to a float. If
|
||||
** the number is too large, it is OK to set the limit as LUA_MAXINTEGER,
|
||||
** which means no limit. If the number is too negative, the loop
|
||||
** should not run, because any initial integer value is larger than the
|
||||
|
@ -133,7 +140,10 @@ int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) {
|
|||
static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step,
|
||||
int *stopnow) {
|
||||
*stopnow = 0; /* usually, let loops run */
|
||||
if (!luaV_tointeger(obj, p, (step < 0 ? 2 : 1))) { /* not fit in integer? */
|
||||
if (ttisinteger(obj))
|
||||
*p = ivalue(obj);
|
||||
else if (!luaV_tointeger(obj, p, (step < 0 ? 2 : 1))) {
|
||||
/* not coercible to in integer */
|
||||
lua_Number n; /* try to convert to float */
|
||||
if (!tonumber(obj, &n)) /* cannot convert to float? */
|
||||
return 0; /* not a number */
|
||||
|
@ -411,7 +421,7 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
|
|||
return 0; /* only numbers can be equal with different variants */
|
||||
else { /* two numbers with different variants */
|
||||
lua_Integer i1, i2; /* compare them as integers */
|
||||
return (tointeger(t1, &i1) && tointeger(t2, &i2) && i1 == i2);
|
||||
return (tointegerns(t1, &i1) && tointegerns(t2, &i2) && i1 == i2);
|
||||
}
|
||||
}
|
||||
/* values have same type and same variant */
|
||||
|
@ -1144,7 +1154,7 @@ void luaV_execute (lua_State *L) {
|
|||
TValue *rb = vRB(i);
|
||||
TValue *rc = vRC(i);
|
||||
lua_Integer ib; lua_Integer ic;
|
||||
if (tointeger(rb, &ib) && tointeger(rc, &ic)) {
|
||||
if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) {
|
||||
setivalue(s2v(ra), intop(&, ib, ic));
|
||||
}
|
||||
else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BAND)); }
|
||||
|
@ -1154,7 +1164,7 @@ void luaV_execute (lua_State *L) {
|
|||
TValue *rb = vRB(i);
|
||||
TValue *rc = vRC(i);
|
||||
lua_Integer ib; lua_Integer ic;
|
||||
if (tointeger(rb, &ib) && tointeger(rc, &ic)) {
|
||||
if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) {
|
||||
setivalue(s2v(ra), intop(|, ib, ic));
|
||||
}
|
||||
else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BOR)); }
|
||||
|
@ -1164,7 +1174,7 @@ void luaV_execute (lua_State *L) {
|
|||
TValue *rb = vRB(i);
|
||||
TValue *rc = vRC(i);
|
||||
lua_Integer ib; lua_Integer ic;
|
||||
if (tointeger(rb, &ib) && tointeger(rc, &ic)) {
|
||||
if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) {
|
||||
setivalue(s2v(ra), intop(^, ib, ic));
|
||||
}
|
||||
else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BXOR)); }
|
||||
|
@ -1174,7 +1184,7 @@ void luaV_execute (lua_State *L) {
|
|||
TValue *rb = vRB(i);
|
||||
TValue *rc = vRC(i);
|
||||
lua_Integer ib; lua_Integer ic;
|
||||
if (tointeger(rb, &ib) && tointeger(rc, &ic)) {
|
||||
if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) {
|
||||
setivalue(s2v(ra), luaV_shiftl(ib, ic));
|
||||
}
|
||||
else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHL)); }
|
||||
|
@ -1184,7 +1194,7 @@ void luaV_execute (lua_State *L) {
|
|||
TValue *rb = vRB(i);
|
||||
TValue *rc = vRC(i);
|
||||
lua_Integer ib; lua_Integer ic;
|
||||
if (tointeger(rb, &ib) && tointeger(rc, &ic)) {
|
||||
if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) {
|
||||
setivalue(s2v(ra), luaV_shiftl(ib, -ic));
|
||||
}
|
||||
else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHR)); }
|
||||
|
@ -1248,7 +1258,7 @@ void luaV_execute (lua_State *L) {
|
|||
vmcase(OP_BNOT) {
|
||||
TValue *rb = vRB(i);
|
||||
lua_Integer ib;
|
||||
if (tointeger(rb, &ib)) {
|
||||
if (tointegerns(rb, &ib)) {
|
||||
setivalue(s2v(ra), intop(^, ~l_castS2U(0), ib));
|
||||
}
|
||||
else {
|
||||
|
|
9
lvm.h
9
lvm.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lvm.h,v 2.45 2017/06/29 15:06:44 roberto Exp roberto $
|
||||
** $Id: lvm.h,v 2.46 2017/07/07 16:34:32 roberto Exp roberto $
|
||||
** Lua virtual machine
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -53,6 +53,12 @@
|
|||
(ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger(o,i,LUA_FLOORN2I))
|
||||
|
||||
|
||||
/* convert an object to an integer (without string coercion) */
|
||||
#define tointegerns(o,i) \
|
||||
(ttisinteger(o) ? (*(i) = ivalue(o), 1) \
|
||||
: luaV_flttointeger(o,i,LUA_FLOORN2I))
|
||||
|
||||
|
||||
#define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2))
|
||||
|
||||
#define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2)
|
||||
|
@ -100,6 +106,7 @@ 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 int luaV_tonumber_ (const TValue *obj, lua_Number *n);
|
||||
LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode);
|
||||
LUAI_FUNC int luaV_flttointeger (const TValue *obj, lua_Integer *p, int mode);
|
||||
LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key,
|
||||
StkId val, const TValue *slot);
|
||||
LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
|
||||
|
|
Loading…
Reference in New Issue