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:
Roberto Ierusalimschy
2017-11-08 12:50:23 -02:00
parent c3e5946fb2
commit 26679ea35b
8 changed files with 126 additions and 48 deletions

View File

@@ -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}
};