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 | |
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
-rw-r--r-- | lcode.c | 6 | ||||
-rw-r--r-- | ldebug.c | 4 | ||||
-rw-r--r-- | lobject.c | 4 | ||||
-rw-r--r-- | lstrlib.c | 80 | ||||
-rw-r--r-- | ltable.c | 6 | ||||
-rw-r--r-- | ltm.c | 5 | ||||
-rw-r--r-- | lvm.c | 60 | ||||
-rw-r--r-- | lvm.h | 9 |
8 files changed, 126 insertions, 48 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.c,v 2.130 2017/10/04 21:56:32 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 2.131 2017/11/07 17:20:42 roberto Exp roberto $ |
3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -611,7 +611,7 @@ static void luaK_float (FuncState *fs, int reg, lua_Number f) { | |||
611 | TValue v; | 611 | TValue v; |
612 | lua_Integer fi; | 612 | lua_Integer fi; |
613 | setfltvalue(&v, f); | 613 | setfltvalue(&v, f); |
614 | if (luaV_tointeger(&v, &fi, 0) && | 614 | if (luaV_flttointeger(&v, &fi, 0) && |
615 | l_castS2U(fi) + MAXARG_sBx <= l_castS2U(MAXARG_Bx)) | 615 | l_castS2U(fi) + MAXARG_sBx <= l_castS2U(MAXARG_Bx)) |
616 | luaK_codeAsBx(fs, OP_LOADF, reg, cast_int(fi)); | 616 | luaK_codeAsBx(fs, OP_LOADF, reg, cast_int(fi)); |
617 | else | 617 | else |
@@ -1146,7 +1146,7 @@ static int validop (int op, TValue *v1, TValue *v2) { | |||
1146 | case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: | 1146 | case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: |
1147 | case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT: { /* conversion errors */ | 1147 | case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT: { /* conversion errors */ |
1148 | lua_Integer i; | 1148 | lua_Integer i; |
1149 | return (tointeger(v1, &i) && tointeger(v2, &i)); | 1149 | return (tointegerns(v1, &i) && tointegerns(v2, &i)); |
1150 | } | 1150 | } |
1151 | case LUA_OPDIV: case LUA_OPIDIV: case LUA_OPMOD: /* division by 0 */ | 1151 | case LUA_OPDIV: case LUA_OPIDIV: case LUA_OPMOD: /* division by 0 */ |
1152 | return (nvalue(v2) != 0); | 1152 | return (nvalue(v2) != 0); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldebug.c,v 2.140 2017/11/07 13:25:26 roberto Exp roberto $ | 2 | ** $Id: ldebug.c,v 2.141 2017/11/07 17:20:42 roberto Exp roberto $ |
3 | ** Debug Interface | 3 | ** Debug Interface |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -670,7 +670,7 @@ l_noret luaG_opinterror (lua_State *L, const TValue *p1, | |||
670 | */ | 670 | */ |
671 | l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) { | 671 | l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) { |
672 | lua_Integer temp; | 672 | lua_Integer temp; |
673 | if (!tointeger(p1, &temp)) | 673 | if (!tointegerns(p1, &temp)) |
674 | p2 = p1; | 674 | p2 = p1; |
675 | luaG_runerror(L, "number%s has no integer representation", varinfo(L, p2)); | 675 | luaG_runerror(L, "number%s has no integer representation", varinfo(L, p2)); |
676 | } | 676 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lobject.c,v 2.117 2017/07/07 16:34:32 roberto Exp roberto $ | 2 | ** $Id: lobject.c,v 2.118 2017/10/10 20:05:40 roberto Exp roberto $ |
3 | ** Some generic functions over Lua objects | 3 | ** Some generic functions over Lua objects |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -127,7 +127,7 @@ int luaO_rawarith (lua_State *L, int op, const TValue *p1, const TValue *p2, | |||
127 | case LUA_OPSHL: case LUA_OPSHR: | 127 | case LUA_OPSHL: case LUA_OPSHR: |
128 | case LUA_OPBNOT: { /* operate only on integers */ | 128 | case LUA_OPBNOT: { /* operate only on integers */ |
129 | lua_Integer i1; lua_Integer i2; | 129 | lua_Integer i1; lua_Integer i2; |
130 | if (tointeger(p1, &i1) && tointeger(p2, &i2)) { | 130 | if (tointegerns(p1, &i1) && tointegerns(p2, &i2)) { |
131 | setivalue(res, intarith(L, op, i1, i2)); | 131 | setivalue(res, intarith(L, op, i1, i2)); |
132 | return 1; | 132 | return 1; |
133 | } | 133 | } |
@@ -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 | }; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltable.c,v 2.124 2017/06/12 14:21:44 roberto Exp roberto $ | 2 | ** $Id: ltable.c,v 2.125 2017/06/29 15:06:44 roberto Exp roberto $ |
3 | ** Lua tables (hash) | 3 | ** Lua tables (hash) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -495,7 +495,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { | |||
495 | if (ttisnil(key)) luaG_runerror(L, "table index is nil"); | 495 | if (ttisnil(key)) luaG_runerror(L, "table index is nil"); |
496 | else if (ttisfloat(key)) { | 496 | else if (ttisfloat(key)) { |
497 | lua_Integer k; | 497 | lua_Integer k; |
498 | if (luaV_tointeger(key, &k, 0)) { /* does index fit in an integer? */ | 498 | if (luaV_flttointeger(key, &k, 0)) { /* does index fit in an integer? */ |
499 | setivalue(&aux, k); | 499 | setivalue(&aux, k); |
500 | key = &aux; /* insert it as an integer */ | 500 | key = &aux; /* insert it as an integer */ |
501 | } | 501 | } |
@@ -604,7 +604,7 @@ const TValue *luaH_get (Table *t, const TValue *key) { | |||
604 | case LUA_TNIL: return luaO_nilobject; | 604 | case LUA_TNIL: return luaO_nilobject; |
605 | case LUA_TNUMFLT: { | 605 | case LUA_TNUMFLT: { |
606 | lua_Integer k; | 606 | lua_Integer k; |
607 | if (luaV_tointeger(key, &k, 0)) /* index is int? */ | 607 | if (luaV_flttointeger(key, &k, 0)) /* index is an integral? */ |
608 | return luaH_getint(t, k); /* use specialized version */ | 608 | return luaH_getint(t, k); /* use specialized version */ |
609 | /* else... */ | 609 | /* else... */ |
610 | } /* FALLTHROUGH */ | 610 | } /* FALLTHROUGH */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltm.c,v 2.45 2017/10/04 15:49:05 roberto Exp $ | 2 | ** $Id: ltm.c,v 2.47 2017/11/07 13:25:26 roberto Exp roberto $ |
3 | ** Tag methods | 3 | ** Tag methods |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -153,8 +153,7 @@ void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, | |||
153 | /* call never returns, but to avoid warnings: *//* FALLTHROUGH */ | 153 | /* call never returns, but to avoid warnings: *//* FALLTHROUGH */ |
154 | case TM_BAND: case TM_BOR: case TM_BXOR: | 154 | case TM_BAND: case TM_BOR: case TM_BXOR: |
155 | case TM_SHL: case TM_SHR: case TM_BNOT: { | 155 | case TM_SHL: case TM_SHR: case TM_BNOT: { |
156 | lua_Number dummy; | 156 | if (ttisnumber(p1) && ttisnumber(p2)) |
157 | if (tonumber(p1, &dummy) && tonumber(p2, &dummy)) | ||
158 | luaG_tointerror(L, p1, p2); | 157 | luaG_tointerror(L, p1, p2); |
159 | else | 158 | else |
160 | luaG_opinterror(L, p1, p2, "perform bitwise operation on"); | 159 | luaG_opinterror(L, p1, p2, "perform bitwise operation on"); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.306 2017/11/07 13:25:26 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.307 2017/11/07 17:20:42 roberto Exp roberto $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -74,7 +74,7 @@ int luaV_tonumber_ (const TValue *obj, lua_Number *n) { | |||
74 | *n = cast_num(ivalue(obj)); | 74 | *n = cast_num(ivalue(obj)); |
75 | return 1; | 75 | return 1; |
76 | } | 76 | } |
77 | else if (cvt2num(obj) && /* string convertible to number? */ | 77 | else if (cvt2num(obj) && /* string coercible to number? */ |
78 | luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) { | 78 | luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) { |
79 | *n = nvalue(&v); /* convert result of 'luaO_str2num' to a float */ | 79 | *n = nvalue(&v); /* convert result of 'luaO_str2num' to a float */ |
80 | return 1; | 80 | return 1; |
@@ -85,15 +85,15 @@ int luaV_tonumber_ (const TValue *obj, lua_Number *n) { | |||
85 | 85 | ||
86 | 86 | ||
87 | /* | 87 | /* |
88 | ** try to convert a value to an integer, rounding according to 'mode': | 88 | ** try to convert a float to an integer, rounding according to 'mode': |
89 | ** mode == 0: accepts only integral values | 89 | ** mode == 0: accepts only integral values |
90 | ** mode == 1: takes the floor of the number | 90 | ** mode == 1: takes the floor of the number |
91 | ** mode == 2: takes the ceil of the number | 91 | ** mode == 2: takes the ceil of the number |
92 | */ | 92 | */ |
93 | int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) { | 93 | int luaV_flttointeger (const TValue *obj, lua_Integer *p, int mode) { |
94 | TValue v; | 94 | if (!ttisfloat(obj)) |
95 | again: | 95 | return 0; |
96 | if (ttisfloat(obj)) { | 96 | else { |
97 | lua_Number n = fltvalue(obj); | 97 | lua_Number n = fltvalue(obj); |
98 | lua_Number f = l_floor(n); | 98 | lua_Number f = l_floor(n); |
99 | if (n != f) { /* not an integral value? */ | 99 | if (n != f) { /* not an integral value? */ |
@@ -103,16 +103,23 @@ int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) { | |||
103 | } | 103 | } |
104 | return lua_numbertointeger(f, p); | 104 | return lua_numbertointeger(f, p); |
105 | } | 105 | } |
106 | else if (ttisinteger(obj)) { | 106 | } |
107 | |||
108 | |||
109 | /* | ||
110 | ** try to convert a value to an integer. ("Fast track" is handled | ||
111 | ** by macro 'tointeger'.) | ||
112 | */ | ||
113 | int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) { | ||
114 | TValue v; | ||
115 | if (cvt2num(obj) && luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) | ||
116 | obj = &v; /* change string to its corresponding number */ | ||
117 | if (ttisinteger(obj)) { | ||
107 | *p = ivalue(obj); | 118 | *p = ivalue(obj); |
108 | return 1; | 119 | return 1; |
109 | } | 120 | } |
110 | else if (cvt2num(obj) && | 121 | else |
111 | luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) { | 122 | return luaV_flttointeger(obj, p, mode); |
112 | obj = &v; | ||
113 | goto again; /* convert result from 'luaO_str2num' to an integer */ | ||
114 | } | ||
115 | return 0; /* conversion failed */ | ||
116 | } | 123 | } |
117 | 124 | ||
118 | 125 | ||
@@ -120,9 +127,9 @@ int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) { | |||
120 | ** Try to convert a 'for' limit to an integer, preserving the semantics | 127 | ** Try to convert a 'for' limit to an integer, preserving the semantics |
121 | ** of the loop. (The following explanation assumes a non-negative step; | 128 | ** of the loop. (The following explanation assumes a non-negative step; |
122 | ** it is valid for negative steps mutatis mutandis.) | 129 | ** it is valid for negative steps mutatis mutandis.) |
123 | ** If the limit can be converted to an integer, rounding down, that is | 130 | ** If the limit is an integer or can be converted to an integer, |
124 | ** it. | 131 | ** rounding down, that is it. |
125 | ** Otherwise, check whether the limit can be converted to a number. If | 132 | ** Otherwise, check whether the limit can be converted to a float. If |
126 | ** the number is too large, it is OK to set the limit as LUA_MAXINTEGER, | 133 | ** the number is too large, it is OK to set the limit as LUA_MAXINTEGER, |
127 | ** which means no limit. If the number is too negative, the loop | 134 | ** which means no limit. If the number is too negative, the loop |
128 | ** should not run, because any initial integer value is larger than the | 135 | ** should not run, because any initial integer value is larger than the |
@@ -133,7 +140,10 @@ int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) { | |||
133 | static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step, | 140 | static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step, |
134 | int *stopnow) { | 141 | int *stopnow) { |
135 | *stopnow = 0; /* usually, let loops run */ | 142 | *stopnow = 0; /* usually, let loops run */ |
136 | if (!luaV_tointeger(obj, p, (step < 0 ? 2 : 1))) { /* not fit in integer? */ | 143 | if (ttisinteger(obj)) |
144 | *p = ivalue(obj); | ||
145 | else if (!luaV_tointeger(obj, p, (step < 0 ? 2 : 1))) { | ||
146 | /* not coercible to in integer */ | ||
137 | lua_Number n; /* try to convert to float */ | 147 | lua_Number n; /* try to convert to float */ |
138 | if (!tonumber(obj, &n)) /* cannot convert to float? */ | 148 | if (!tonumber(obj, &n)) /* cannot convert to float? */ |
139 | return 0; /* not a number */ | 149 | return 0; /* not a number */ |
@@ -411,7 +421,7 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { | |||
411 | return 0; /* only numbers can be equal with different variants */ | 421 | return 0; /* only numbers can be equal with different variants */ |
412 | else { /* two numbers with different variants */ | 422 | else { /* two numbers with different variants */ |
413 | lua_Integer i1, i2; /* compare them as integers */ | 423 | lua_Integer i1, i2; /* compare them as integers */ |
414 | return (tointeger(t1, &i1) && tointeger(t2, &i2) && i1 == i2); | 424 | return (tointegerns(t1, &i1) && tointegerns(t2, &i2) && i1 == i2); |
415 | } | 425 | } |
416 | } | 426 | } |
417 | /* values have same type and same variant */ | 427 | /* values have same type and same variant */ |
@@ -1144,7 +1154,7 @@ void luaV_execute (lua_State *L) { | |||
1144 | TValue *rb = vRB(i); | 1154 | TValue *rb = vRB(i); |
1145 | TValue *rc = vRC(i); | 1155 | TValue *rc = vRC(i); |
1146 | lua_Integer ib; lua_Integer ic; | 1156 | lua_Integer ib; lua_Integer ic; |
1147 | if (tointeger(rb, &ib) && tointeger(rc, &ic)) { | 1157 | if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) { |
1148 | setivalue(s2v(ra), intop(&, ib, ic)); | 1158 | setivalue(s2v(ra), intop(&, ib, ic)); |
1149 | } | 1159 | } |
1150 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BAND)); } | 1160 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BAND)); } |
@@ -1154,7 +1164,7 @@ void luaV_execute (lua_State *L) { | |||
1154 | TValue *rb = vRB(i); | 1164 | TValue *rb = vRB(i); |
1155 | TValue *rc = vRC(i); | 1165 | TValue *rc = vRC(i); |
1156 | lua_Integer ib; lua_Integer ic; | 1166 | lua_Integer ib; lua_Integer ic; |
1157 | if (tointeger(rb, &ib) && tointeger(rc, &ic)) { | 1167 | if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) { |
1158 | setivalue(s2v(ra), intop(|, ib, ic)); | 1168 | setivalue(s2v(ra), intop(|, ib, ic)); |
1159 | } | 1169 | } |
1160 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BOR)); } | 1170 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BOR)); } |
@@ -1164,7 +1174,7 @@ void luaV_execute (lua_State *L) { | |||
1164 | TValue *rb = vRB(i); | 1174 | TValue *rb = vRB(i); |
1165 | TValue *rc = vRC(i); | 1175 | TValue *rc = vRC(i); |
1166 | lua_Integer ib; lua_Integer ic; | 1176 | lua_Integer ib; lua_Integer ic; |
1167 | if (tointeger(rb, &ib) && tointeger(rc, &ic)) { | 1177 | if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) { |
1168 | setivalue(s2v(ra), intop(^, ib, ic)); | 1178 | setivalue(s2v(ra), intop(^, ib, ic)); |
1169 | } | 1179 | } |
1170 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BXOR)); } | 1180 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BXOR)); } |
@@ -1174,7 +1184,7 @@ void luaV_execute (lua_State *L) { | |||
1174 | TValue *rb = vRB(i); | 1184 | TValue *rb = vRB(i); |
1175 | TValue *rc = vRC(i); | 1185 | TValue *rc = vRC(i); |
1176 | lua_Integer ib; lua_Integer ic; | 1186 | lua_Integer ib; lua_Integer ic; |
1177 | if (tointeger(rb, &ib) && tointeger(rc, &ic)) { | 1187 | if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) { |
1178 | setivalue(s2v(ra), luaV_shiftl(ib, ic)); | 1188 | setivalue(s2v(ra), luaV_shiftl(ib, ic)); |
1179 | } | 1189 | } |
1180 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHL)); } | 1190 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHL)); } |
@@ -1184,7 +1194,7 @@ void luaV_execute (lua_State *L) { | |||
1184 | TValue *rb = vRB(i); | 1194 | TValue *rb = vRB(i); |
1185 | TValue *rc = vRC(i); | 1195 | TValue *rc = vRC(i); |
1186 | lua_Integer ib; lua_Integer ic; | 1196 | lua_Integer ib; lua_Integer ic; |
1187 | if (tointeger(rb, &ib) && tointeger(rc, &ic)) { | 1197 | if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) { |
1188 | setivalue(s2v(ra), luaV_shiftl(ib, -ic)); | 1198 | setivalue(s2v(ra), luaV_shiftl(ib, -ic)); |
1189 | } | 1199 | } |
1190 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHR)); } | 1200 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHR)); } |
@@ -1248,7 +1258,7 @@ void luaV_execute (lua_State *L) { | |||
1248 | vmcase(OP_BNOT) { | 1258 | vmcase(OP_BNOT) { |
1249 | TValue *rb = vRB(i); | 1259 | TValue *rb = vRB(i); |
1250 | lua_Integer ib; | 1260 | lua_Integer ib; |
1251 | if (tointeger(rb, &ib)) { | 1261 | if (tointegerns(rb, &ib)) { |
1252 | setivalue(s2v(ra), intop(^, ~l_castS2U(0), ib)); | 1262 | setivalue(s2v(ra), intop(^, ~l_castS2U(0), ib)); |
1253 | } | 1263 | } |
1254 | else { | 1264 | else { |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.h,v 2.45 2017/06/29 15:06:44 roberto Exp roberto $ | 2 | ** $Id: lvm.h,v 2.46 2017/07/07 16:34:32 roberto Exp roberto $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -53,6 +53,12 @@ | |||
53 | (ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger(o,i,LUA_FLOORN2I)) | 53 | (ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger(o,i,LUA_FLOORN2I)) |
54 | 54 | ||
55 | 55 | ||
56 | /* convert an object to an integer (without string coercion) */ | ||
57 | #define tointegerns(o,i) \ | ||
58 | (ttisinteger(o) ? (*(i) = ivalue(o), 1) \ | ||
59 | : luaV_flttointeger(o,i,LUA_FLOORN2I)) | ||
60 | |||
61 | |||
56 | #define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2)) | 62 | #define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2)) |
57 | 63 | ||
58 | #define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2) | 64 | #define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2) |
@@ -100,6 +106,7 @@ LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); | |||
100 | LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); | 106 | LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); |
101 | LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n); | 107 | LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n); |
102 | LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode); | 108 | LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode); |
109 | LUAI_FUNC int luaV_flttointeger (const TValue *obj, lua_Integer *p, int mode); | ||
103 | LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key, | 110 | LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key, |
104 | StkId val, const TValue *slot); | 111 | StkId val, const TValue *slot); |
105 | LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key, | 112 | LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key, |