issue #195 number and integer conversions

lua54-misc
Dibyendu Majumdar 4 years ago
parent f884782a60
commit 0e41a51114

@ -33,10 +33,20 @@
** integral values)
*/
#if !defined(LUA_FLOORN2I)
#define LUA_FLOORN2I 0
#define LUA_FLOORN2I F2Ieq
#endif
/*
** Rounding modes for float->integer coercion
*/
typedef enum {
F2Ieq, /* no rounding; accepts only integral values */
F2Ifloor, /* takes the floor of the number */
F2Iceil /* takes the ceil of the number */
} F2Imod;
/* convert an object to a float (including string coercion) */
#define tonumber(o,n) \
(RAVI_LIKELY(ttisfloat(o)) ? (*(n) = fltvalue(o), 1) : luaV_tonumber_(o,n))
@ -55,8 +65,7 @@
/* 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))
(ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointegerns(o,i,LUA_FLOORN2I))
#define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2))
@ -105,9 +114,11 @@ 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 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_tointeger (const TValue *obj, lua_Integer *p, F2Imod mode);
LUAI_FUNC int luaV_tointegerns (const TValue *obj, lua_Integer *p,
F2Imod mode);
LUAI_FUNC int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode);
/** RAVI changes start **/
LUAI_FUNC int luaV_flttointeger (const TValue *obj, lua_Integer *p, int mode);
LUAI_FUNC int luaV_tointeger_(const TValue *obj, lua_Integer *p);
LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key,
StkId val);
@ -122,8 +133,9 @@ LUAI_FUNC void luaV_finishOp (lua_State *L);
/* RAVI change: the int return value is a Ravi extension */
LUAI_FUNC int luaV_execute (lua_State *L);
LUAI_FUNC void luaV_concat (lua_State *L, int total);
LUAI_FUNC lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y);
LUAI_FUNC lua_Integer luaV_idiv (lua_State *L, lua_Integer x, lua_Integer y);
LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y);
LUAI_FUNC lua_Number luaV_modf (lua_State *L, lua_Number x, lua_Number y);
LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y);
LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb);

@ -253,7 +253,7 @@ struct LuaLLVMTypes {
llvm::FunctionType *luaV_tointegerT;
llvm::FunctionType *luaV_modT;
llvm::FunctionType *luaV_objlenT;
llvm::FunctionType *luaV_divT;
llvm::FunctionType *luaV_idivT;
llvm::FunctionType *luaV_executeT;
llvm::FunctionType *luaV_gettableT;
llvm::FunctionType *luaV_settableT;
@ -801,7 +801,7 @@ struct RaviFunctionDef {
llvm::Function *luaV_gettableF;
llvm::Function *luaV_settableF;
llvm::Function *luaV_modF;
llvm::Function *luaV_divF;
llvm::Function *luaV_idivF;
llvm::Function *luaV_objlenF;
llvm::Function *luaC_upvalbarrierF;
llvm::Function *luaH_getstrF;

@ -87,7 +87,7 @@ static lua_Integer intarith (lua_State *L, int op, lua_Integer v1,
case LUA_OPSUB:return intop(-, v1, v2);
case LUA_OPMUL:return intop(*, v1, v2);
case LUA_OPMOD: return luaV_mod(L, v1, v2);
case LUA_OPIDIV: return luaV_div(L, v1, v2);
case LUA_OPIDIV: return luaV_idiv(L, v1, v2);
case LUA_OPBAND: return intop(&, v1, v2);
case LUA_OPBOR: return intop(|, v1, v2);
case LUA_OPBXOR: return intop(^, v1, v2);
@ -110,11 +110,7 @@ static lua_Number numarith (lua_State *L, int op, lua_Number v1,
case LUA_OPPOW: return luai_numpow(L, v1, v2);
case LUA_OPIDIV: return luai_numidiv(L, v1, v2);
case LUA_OPUNM: return luai_numunm(L, v1);
case LUA_OPMOD: {
lua_Number m;
luai_nummod(L, v1, v2, m);
return m;
}
case LUA_OPMOD: return luaV_modf(L, v1, v2);
default: lua_assert(0); return 0;
}
}

@ -40,12 +40,10 @@
#define MAXTAGLOOP 2000
/*
** 'l_intfitsf' checks whether a given integer is in the range that
** can be converted to a float without rounding. Used in comparisons.
*/
#if !defined(l_intfitsf)
/* number of bits in the mantissa of a float */
#define NBM (l_floatatt(MANT_DIG))
@ -72,8 +70,21 @@
#endif
#endif
/*
** Try to convert a value from string to a number value.
** If the value is not a string or is a string not representing
** a valid numeral (or if coercions from strings to numbers
** are disabled via macro 'cvt2num'), do not modify 'result'
** and return 0.
*/
static int l_strton (const TValue *obj, TValue *result) {
lua_assert(obj != result);
if (!cvt2num(obj)) /* is object not a string? */
return 0;
else
return (luaO_str2num(svalue(obj), result) == vslen(obj) + 1);
}
/*
@ -86,8 +97,7 @@ int luaV_tonumber_ (const TValue *obj, lua_Number *n) {
*n = cast_num(ivalue(obj));
return 1;
}
else if (cvt2num(obj) && /* string coercible to number? */
luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) {
else if (l_strton(obj, &v)) { /* string coercible to number? */
*n = nvalue(&v); /* convert result of 'luaO_str2num' to a float */
return 1;
}
@ -97,46 +107,49 @@ int luaV_tonumber_ (const TValue *obj, lua_Number *n) {
/*
** 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
** try to convert a float to an integer, rounding according to 'mode'.
*/
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? */
if (mode == 0) return 0; /* fails if mode demands integral value */
else if (mode > 1) /* needs ceil? */
f += 1; /* convert floor to ceil (remember: n != f) */
}
return lua_numbertointeger(f, p);
int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode) {
lua_Number f = l_floor(n);
if (n != f) { /* not an integral value? */
if (mode == F2Ieq) return 0; /* fails if mode demands integral value */
else if (mode == F2Iceil) /* needs ceil? */
f += 1; /* convert floor to ceil (remember: n != f) */
}
return lua_numbertointeger(f, p);
}
/*
** try to convert a value to an integer. ("Fast track" is handled
** by macro 'tointeger'.)
** try to convert a value to an integer, rounding according to 'mode',
** without string coercion.
** ("Fast track" handled by macro 'tointegerns'.)
*/
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)) {
int luaV_tointegerns (const TValue *obj, lua_Integer *p, F2Imod mode) {
if (ttisfloat(obj))
return luaV_flttointeger(fltvalue(obj), p, mode);
else if (ttisinteger(obj)) {
*p = ivalue(obj);
return 1;
}
else
return luaV_flttointeger(obj, p, mode);
return 0;
}
/*
** try to convert a value to an integer.
*/
int luaV_tointeger (const TValue *obj, lua_Integer *p, F2Imod mode) {
TValue v;
if (l_strton(obj, &v)) /* does 'obj' point to a numerical string? */
obj = &v; /* change it to point to its corresponding number */
return luaV_tointegerns(obj, p, mode);
}
/*
** try to convert a value to an integer
** try to convert a value to an integer.
*/
int luaV_tointeger_ (const TValue *obj, lua_Integer *p) {
return luaV_tointeger(obj, p, LUA_FLOORN2I);
@ -163,7 +176,7 @@ int luaV_forlimit (const TValue *obj, lua_Integer *p, lua_Integer step,
*stopnow = 0; /* usually, let loops run */
if (ttisinteger(obj))
*p = ivalue(obj);
else if (!luaV_tointeger(obj, p, (step < 0 ? 2 : 1))) {
else if (!luaV_tointeger(obj, p, (step < 0 ? F2Iceil : F2Ifloor))) {
/* not coercible to in integer */
lua_Number n; /* try to convert to float */
if (!tonumber(obj, &n)) /* cannot convert to float? */
@ -837,8 +850,8 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
** 'floor(q) == trunc(q)' when 'q >= 0' or when 'q' is integer,
** otherwise 'floor(q) == trunc(q) - 1'.
*/
lua_Integer luaV_div (lua_State *L, lua_Integer m, lua_Integer n) {
if (l_castS2U(n) + 1u <= 1u) { /* special cases: -1 or 0 */
lua_Integer luaV_idiv (lua_State *L, lua_Integer m, lua_Integer n) {
if (unlikely(l_castS2U(n) + 1u <= 1u)) { /* special cases: -1 or 0 */
if (n == 0)
luaG_runerror(L, "attempt to divide by zero");
return intop(-, 0, m); /* n==-1; avoid overflow with 0x80000...//-1 */
@ -855,23 +868,33 @@ lua_Integer luaV_div (lua_State *L, lua_Integer m, lua_Integer n) {
/*
** Integer modulus; return 'm % n'. (Assume that C '%' with
** negative operands follows C99 behavior. See previous comment
** about luaV_div.)
** about luaV_idiv.)
*/
lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) {
if (l_castS2U(n) + 1u <= 1u) { /* special cases: -1 or 0 */
if (unlikely(l_castS2U(n) + 1u <= 1u)) { /* special cases: -1 or 0 */
if (n == 0)
luaG_runerror(L, "attempt to perform 'n%%0'");
return 0; /* m % -1 == 0; avoid overflow with 0x80000...%-1 */
}
else {
lua_Integer r = m % n;
if (r != 0 && (m ^ n) < 0) /* 'm/n' would be non-integer negative? */
if (r != 0 && (r ^ n) < 0) /* 'm/n' would be non-integer negative? */
r += n; /* correct result for different rounding */
return r;
}
}
/*
** Float modulus
*/
lua_Number luaV_modf (lua_State *L, lua_Number m, lua_Number n) {
lua_Number r;
luai_nummod(L, m, n, r);
return r;
}
/* number of bits in an integer */
#define NBITS cast_int(sizeof(lua_Integer) * CHAR_BIT)
@ -1547,7 +1570,7 @@ int luaV_execute (lua_State *L) {
lua_Number nb; lua_Number nc;
if (ttisinteger(rb) && ttisinteger(rc)) {
lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
setivalue(ra, luaV_div(L, ib, ic));
setivalue(ra, luaV_idiv(L, ib, ic));
}
else if (tonumberns(rb, nb) && tonumberns(rc, nc)) {
setfltvalue(ra, luai_numidiv(L, nb, nc));

@ -739,7 +739,7 @@ void RaviCodeGenerator::emit_IDIV(RaviFunctionDef *def, int A, int B, int C,
// lua_Number nb; lua_Number nc;
// if (ttisinteger(rb) && ttisinteger(rc)) {
// lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
// setivalue(ra, luaV_div(L, ib, ic));
// setivalue(ra, luaV_idiv(L, ib, ic));
//}
// else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
// setfltvalue(ra, luai_numidiv(L, nb, nc));
@ -786,7 +786,7 @@ void RaviCodeGenerator::emit_IDIV(RaviFunctionDef *def, int A, int B, int C,
llvm::Instruction *rhs = emit_load_reg_i(def, rc);
llvm::Value *result =
CreateCall3(def->builder, def->luaV_divF, def->L, lhs, rhs);
CreateCall3(def->builder, def->luaV_idivF, def->L, lhs, rhs);
emit_store_reg_i_withtype(def, result, ra);
def->builder->CreateBr(done_block);

@ -1135,8 +1135,8 @@ void RaviCodeGenerator::emit_extern_declarations(RaviFunctionDef *def) {
reinterpret_cast<void *>(&raviV_op_setlist), "raviV_op_setlist");
def->luaV_modF = def->raviF->addExternFunction(
def->types->luaV_modT, reinterpret_cast<void *>(&luaV_mod), "luaV_mod");
def->luaV_divF = def->raviF->addExternFunction(
def->types->luaV_divT, reinterpret_cast<void *>(&luaV_div), "luaV_div");
def->luaV_idivF = def->raviF->addExternFunction(
def->types->luaV_idivT, reinterpret_cast<void *>(&luaV_idiv), "luaV_idiv");
def->luaV_objlenF = def->raviF->addExternFunction(
def->types->luaV_objlenT, reinterpret_cast<void *>(&luaV_objlen),
"luaV_objlen");

@ -151,7 +151,7 @@ static struct {
{"luaV_forlimit", reinterpret_cast<void *>(luaV_forlimit)},
{"luaV_finishget", reinterpret_cast<void *>(luaV_finishget)},
{"luaV_mod", reinterpret_cast<void *>(luaV_mod)},
{"luaV_div", reinterpret_cast<void *>(luaV_div)},
{"luaV_idiv", reinterpret_cast<void *>(luaV_idiv)},
{"raviV_op_newtable", reinterpret_cast<void *>(raviV_op_newtable)},
{"raviV_op_newarrayint", reinterpret_cast<void *>(raviV_op_newarrayint)},
{"raviV_op_newarrayfloat", reinterpret_cast<void *>(raviV_op_newarrayfloat)},

@ -899,14 +899,14 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) {
raviV_op_setlistT =
llvm::FunctionType::get(llvm::Type::getVoidTy(context), elements, false);
// lua_Integer luaV_div (lua_State *L, lua_Integer m, lua_Integer n)
// lua_Integer luaV_idiv (lua_State *L, lua_Integer m, lua_Integer n)
// lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n)
elements.clear();
elements.push_back(plua_StateT);
elements.push_back(lua_IntegerT);
elements.push_back(lua_IntegerT);
luaV_modT = llvm::FunctionType::get(lua_IntegerT, elements, false);
luaV_divT = llvm::FunctionType::get(lua_IntegerT, elements, false);
luaV_idivT = llvm::FunctionType::get(lua_IntegerT, elements, false);
// void raviV_op_concat(lua_State *L, CallInfo *ci, int a, int b, int c)
elements.clear();

Loading…
Cancel
Save