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