diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-07-07 13:34:32 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-07-07 13:34:32 -0300 |
| commit | 4dff277255e3785b76b6b52fe2a98592e6cbc834 (patch) | |
| tree | e3607d2aab29b6e0dbd46ac1acc81e9c6bf08dd7 /lstrlib.c | |
| parent | 07db10813cb044252c18973688f63b5eac6a90a6 (diff) | |
| download | lua-4dff277255e3785b76b6b52fe2a98592e6cbc834.tar.gz lua-4dff277255e3785b76b6b52fe2a98592e6cbc834.tar.bz2 lua-4dff277255e3785b76b6b52fe2a98592e6cbc834.zip | |
coercion string->number in arithmetic operations moved to string
library
Diffstat (limited to 'lstrlib.c')
| -rw-r--r-- | lstrlib.c | 88 |
1 files changed, 86 insertions, 2 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstrlib.c,v 1.255 2017/03/14 12:40:44 roberto Exp roberto $ | 2 | ** $Id: lstrlib.c,v 1.256 2017/05/19 16:29:40 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 | */ |
| @@ -203,6 +203,88 @@ static int str_dump (lua_State *L) { | |||
| 203 | 203 | ||
| 204 | /* | 204 | /* |
| 205 | ** {====================================================== | 205 | ** {====================================================== |
| 206 | ** METAMETHODS | ||
| 207 | ** ======================================================= | ||
| 208 | */ | ||
| 209 | |||
| 210 | static int tonum (lua_State *L, int arg) { | ||
| 211 | if (lua_type(L, arg) == LUA_TNUMBER) { /* already a number? */ | ||
| 212 | lua_pushvalue(L, arg); | ||
| 213 | return 1; | ||
| 214 | } | ||
| 215 | else { /* check whether it is a numerical string */ | ||
| 216 | size_t len; | ||
| 217 | const char *s = lua_tolstring(L, arg, &len); | ||
| 218 | return (s != NULL && lua_stringtonumber(L, s) == len + 1); | ||
| 219 | } | ||
| 220 | } | ||
| 221 | |||
| 222 | |||
| 223 | static int arith (lua_State *L, int op, const char *mtname) { | ||
| 224 | if (tonum(L, 1) && tonum(L, 2)) | ||
| 225 | lua_arith(L, op); /* result will be on the top */ | ||
| 226 | else { | ||
| 227 | lua_settop(L, 2); /* back to the original arguments */ | ||
| 228 | if (lua_type(L, 2) == LUA_TSTRING || !luaL_getmetafield(L, 2, mtname)) | ||
| 229 | return luaL_error(L, "attempt to %s a '%s' with a '%s'", mtname + 2, | ||
| 230 | luaL_typename(L, -2), luaL_typename(L, -1)); | ||
| 231 | lua_insert(L, -3); /* put metamethod before arguments */ | ||
| 232 | lua_call(L, 2, 1); /* call metamethod */ | ||
| 233 | } | ||
| 234 | return 1; | ||
| 235 | } | ||
| 236 | |||
| 237 | |||
| 238 | static int arith_add (lua_State *L) { | ||
| 239 | return arith(L, LUA_OPADD, "__add"); | ||
| 240 | } | ||
| 241 | |||
| 242 | static int arith_sub (lua_State *L) { | ||
| 243 | return arith(L, LUA_OPSUB, "__sub"); | ||
| 244 | } | ||
| 245 | |||
| 246 | static int arith_mul (lua_State *L) { | ||
| 247 | return arith(L, LUA_OPMUL, "__mul"); | ||
| 248 | } | ||
| 249 | |||
| 250 | static int arith_mod (lua_State *L) { | ||
| 251 | return arith(L, LUA_OPMOD, "__mod"); | ||
| 252 | } | ||
| 253 | |||
| 254 | static int arith_pow (lua_State *L) { | ||
| 255 | return arith(L, LUA_OPPOW, "__pow"); | ||
| 256 | } | ||
| 257 | |||
| 258 | static int arith_div (lua_State *L) { | ||
| 259 | return arith(L, LUA_OPDIV, "__div"); | ||
| 260 | } | ||
| 261 | |||
| 262 | static int arith_idiv (lua_State *L) { | ||
| 263 | return arith(L, LUA_OPIDIV, "__idiv"); | ||
| 264 | } | ||
| 265 | |||
| 266 | static int arith_unm (lua_State *L) { | ||
| 267 | return arith(L, LUA_OPUNM, "__unm"); | ||
| 268 | } | ||
| 269 | |||
| 270 | |||
| 271 | static const luaL_Reg stringmetamethods[] = { | ||
| 272 | {"__add", arith_add}, | ||
| 273 | {"__sub", arith_sub}, | ||
| 274 | {"__mul", arith_mul}, | ||
| 275 | {"__mod", arith_mod}, | ||
| 276 | {"__pow", arith_pow}, | ||
| 277 | {"__div", arith_div}, | ||
| 278 | {"__idiv", arith_idiv}, | ||
| 279 | {"__unm", arith_unm}, | ||
| 280 | {"__index", NULL}, /* placeholder */ | ||
| 281 | {NULL, NULL} | ||
| 282 | }; | ||
| 283 | |||
| 284 | /* }====================================================== */ | ||
| 285 | |||
| 286 | /* | ||
| 287 | ** {====================================================== | ||
| 206 | ** PATTERN MATCHING | 288 | ** PATTERN MATCHING |
| 207 | ** ======================================================= | 289 | ** ======================================================= |
| 208 | */ | 290 | */ |
| @@ -1576,7 +1658,9 @@ static const luaL_Reg strlib[] = { | |||
| 1576 | 1658 | ||
| 1577 | 1659 | ||
| 1578 | static void createmetatable (lua_State *L) { | 1660 | static void createmetatable (lua_State *L) { |
| 1579 | lua_createtable(L, 0, 1); /* table to be metatable for strings */ | 1661 | /* table to be metatable for strings */ |
| 1662 | luaL_newlibtable(L, stringmetamethods); | ||
| 1663 | luaL_setfuncs(L, stringmetamethods, 0); | ||
| 1580 | lua_pushliteral(L, ""); /* dummy string */ | 1664 | lua_pushliteral(L, ""); /* dummy string */ |
| 1581 | lua_pushvalue(L, -2); /* copy table */ | 1665 | lua_pushvalue(L, -2); /* copy table */ |
| 1582 | lua_setmetatable(L, -2); /* set table as metatable for strings */ | 1666 | lua_setmetatable(L, -2); /* set table as metatable for strings */ |
