diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-11-08 12:50:23 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-11-08 12:50:23 -0200 |
| commit | 26679ea35bf261f2b5edc2fb2f5cc4df483fd50d (patch) | |
| tree | 94c99ed74251cdf3e10a7e52560c3a7a78053ad1 /lstrlib.c | |
| parent | c3e5946fb2b7b5781d9bca9d303967abe6263482 (diff) | |
| download | lua-26679ea35bf261f2b5edc2fb2f5cc4df483fd50d.tar.gz lua-26679ea35bf261f2b5edc2fb2f5cc4df483fd50d.tar.bz2 lua-26679ea35bf261f2b5edc2fb2f5cc4df483fd50d.zip | |
new function 'luaV_flttointeger' to convert floats to integers (without
string coercions) + string operands to bitwise operations handled
by string metamethods
Diffstat (limited to 'lstrlib.c')
| -rw-r--r-- | lstrlib.c | 80 |
1 files changed, 71 insertions, 9 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstrlib.c,v 1.256 2017/05/19 16:29:40 roberto Exp roberto $ | 2 | ** $Id: lstrlib.c,v 1.257 2017/07/07 16:34:32 roberto Exp roberto $ |
| 3 | ** Standard library for string operations and pattern-matching | 3 | ** Standard library for string operations and pattern-matching |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -220,17 +220,49 @@ static int tonum (lua_State *L, int arg) { | |||
| 220 | } | 220 | } |
| 221 | 221 | ||
| 222 | 222 | ||
| 223 | static int toint (lua_State *L, int arg) { | ||
| 224 | if (!tonum(L, arg)) | ||
| 225 | return 0; /* not coercible to a number */ | ||
| 226 | else if (lua_isinteger(L, arg)) | ||
| 227 | return 1; /* already an integer */ | ||
| 228 | else { /* a float */ | ||
| 229 | int ok; | ||
| 230 | lua_Integer n = lua_tointegerx(L, arg, &ok); | ||
| 231 | if (!ok) | ||
| 232 | return 0; | ||
| 233 | else { | ||
| 234 | lua_pop(L, 1); /* remove the float */ | ||
| 235 | lua_pushinteger(L, n); /* push an integer */ | ||
| 236 | return 1; | ||
| 237 | } | ||
| 238 | } | ||
| 239 | } | ||
| 240 | |||
| 241 | |||
| 242 | static void trymt (lua_State *L, const char *mtname) { | ||
| 243 | lua_settop(L, 2); /* back to the original arguments */ | ||
| 244 | if (lua_type(L, 2) == LUA_TSTRING || !luaL_getmetafield(L, 2, mtname)) | ||
| 245 | luaL_error(L, "attempt to %s a '%s' with a '%s'", mtname + 2, | ||
| 246 | luaL_typename(L, -2), luaL_typename(L, -1)); | ||
| 247 | lua_insert(L, -3); /* put metamethod before arguments */ | ||
| 248 | lua_call(L, 2, 1); /* call metamethod */ | ||
| 249 | } | ||
| 250 | |||
| 251 | |||
| 223 | static int arith (lua_State *L, int op, const char *mtname) { | 252 | static int arith (lua_State *L, int op, const char *mtname) { |
| 224 | if (tonum(L, 1) && tonum(L, 2)) | 253 | if (tonum(L, 1) && tonum(L, 2)) |
| 225 | lua_arith(L, op); /* result will be on the top */ | 254 | lua_arith(L, op); /* result will be on the top */ |
| 226 | else { | 255 | else |
| 227 | lua_settop(L, 2); /* back to the original arguments */ | 256 | trymt(L, mtname); |
| 228 | if (lua_type(L, 2) == LUA_TSTRING || !luaL_getmetafield(L, 2, mtname)) | 257 | return 1; |
| 229 | return luaL_error(L, "attempt to %s a '%s' with a '%s'", mtname + 2, | 258 | } |
| 230 | luaL_typename(L, -2), luaL_typename(L, -1)); | 259 | |
| 231 | lua_insert(L, -3); /* put metamethod before arguments */ | 260 | |
| 232 | lua_call(L, 2, 1); /* call metamethod */ | 261 | static int bitwise (lua_State *L, int op, const char *mtname) { |
| 233 | } | 262 | if (toint(L, 1) && toint(L, 2)) |
| 263 | lua_arith(L, op); /* result will be on the top */ | ||
| 264 | else | ||
| 265 | trymt(L, mtname); | ||
| 234 | return 1; | 266 | return 1; |
| 235 | } | 267 | } |
| 236 | 268 | ||
| @@ -267,6 +299,30 @@ static int arith_unm (lua_State *L) { | |||
| 267 | return arith(L, LUA_OPUNM, "__unm"); | 299 | return arith(L, LUA_OPUNM, "__unm"); |
| 268 | } | 300 | } |
| 269 | 301 | ||
| 302 | static int bitwise_band (lua_State *L) { | ||
| 303 | return bitwise(L, LUA_OPBAND, "__band"); | ||
| 304 | } | ||
| 305 | |||
| 306 | static int bitwise_bor (lua_State *L) { | ||
| 307 | return bitwise(L, LUA_OPBOR, "__bor"); | ||
| 308 | } | ||
| 309 | |||
| 310 | static int bitwise_bxor (lua_State *L) { | ||
| 311 | return bitwise(L, LUA_OPBXOR, "__bxor"); | ||
| 312 | } | ||
| 313 | |||
| 314 | static int bitwise_shl (lua_State *L) { | ||
| 315 | return bitwise(L, LUA_OPSHL, "__shl"); | ||
| 316 | } | ||
| 317 | |||
| 318 | static int bitwise_shr (lua_State *L) { | ||
| 319 | return bitwise(L, LUA_OPSHR, "__shr"); | ||
| 320 | } | ||
| 321 | |||
| 322 | static int bitwise_bnot (lua_State *L) { | ||
| 323 | return bitwise(L, LUA_OPBNOT, "__bnot"); | ||
| 324 | } | ||
| 325 | |||
| 270 | 326 | ||
| 271 | static const luaL_Reg stringmetamethods[] = { | 327 | static const luaL_Reg stringmetamethods[] = { |
| 272 | {"__add", arith_add}, | 328 | {"__add", arith_add}, |
| @@ -277,6 +333,12 @@ static const luaL_Reg stringmetamethods[] = { | |||
| 277 | {"__div", arith_div}, | 333 | {"__div", arith_div}, |
| 278 | {"__idiv", arith_idiv}, | 334 | {"__idiv", arith_idiv}, |
| 279 | {"__unm", arith_unm}, | 335 | {"__unm", arith_unm}, |
| 336 | {"__band", bitwise_band}, | ||
| 337 | {"__bor", bitwise_bor}, | ||
| 338 | {"__bxor", bitwise_bxor}, | ||
| 339 | {"__shl", bitwise_shl}, | ||
| 340 | {"__shr", bitwise_shr}, | ||
| 341 | {"__bnot", bitwise_bnot}, | ||
| 280 | {"__index", NULL}, /* placeholder */ | 342 | {"__index", NULL}, /* placeholder */ |
| 281 | {NULL, NULL} | 343 | {NULL, NULL} |
| 282 | }; | 344 | }; |
