diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2014-05-09 11:20:52 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2014-05-09 11:20:52 -0300 |
commit | 06dc893f88641e1df6a455c1f24ecaf9ce484d8d (patch) | |
tree | 208a9fedb091a09663316c3fdcca9fc0bb96a7fe /lvm.c | |
parent | a09bd5961594dad90ffc381bf93c288e7322c2b7 (diff) | |
download | lua-06dc893f88641e1df6a455c1f24ecaf9ce484d8d.tar.gz lua-06dc893f88641e1df6a455c1f24ecaf9ce484d8d.tar.bz2 lua-06dc893f88641e1df6a455c1f24ecaf9ce484d8d.zip |
in 'for' loops, make the limit an integer whenever initial value and
step are integers
Diffstat (limited to 'lvm.c')
-rw-r--r-- | lvm.c | 43 |
1 files changed, 40 insertions, 3 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.204 2014/04/30 19:29:51 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.205 2014/05/01 18:18:06 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 | */ |
@@ -143,6 +143,41 @@ int luaV_tostring (lua_State *L, StkId obj) { | |||
143 | } | 143 | } |
144 | 144 | ||
145 | 145 | ||
146 | /* | ||
147 | ** Try to convert a 'for' limit to an integer, preserving the | ||
148 | ** semantics of the loop. | ||
149 | ** (The following explanation assumes a non-negative step; it is valid | ||
150 | ** for negative steps, mutatis mutandis.) | ||
151 | ** If the limit can be converted to an integer, rounding down, that is | ||
152 | ** it. | ||
153 | ** Otherwise, check whether the limit can be converted to a number. If | ||
154 | ** the number is too large, it is OK to set the limit as LUA_MAXINTEGER, | ||
155 | ** which means no limit. If the number is too negative, the loop | ||
156 | ** should not run, because any initial integer value is larger than the | ||
157 | ** limit. So, it sets the limit to LUA_MININTEGER. 'stopnow' corrects | ||
158 | ** the extreme case when the initial value is LUA_MININTEGER, in which | ||
159 | ** case the LUA_MININTEGER limit would run the loop once. | ||
160 | */ | ||
161 | static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step, | ||
162 | int *stopnow) { | ||
163 | *stopnow = 0; /* usually, let loops run */ | ||
164 | if (!tointeger_aux(obj, p, (step < 0))) { /* does not fit in integer? */ | ||
165 | lua_Number n; /* try to convert to float */ | ||
166 | if (!tonumber(obj, &n)) /* cannot convert to float? */ | ||
167 | return 0; /* not a number */ | ||
168 | if (n > 0) { /* if true, float is larger than max integer */ | ||
169 | *p = LUA_MAXINTEGER; | ||
170 | if (step < 0) *stopnow = 1; | ||
171 | } | ||
172 | else { /* float is smaller than min integer */ | ||
173 | *p = LUA_MININTEGER; | ||
174 | if (step >= 0) *stopnow = 1; | ||
175 | } | ||
176 | } | ||
177 | return 1; | ||
178 | } | ||
179 | |||
180 | |||
146 | void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { | 181 | void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { |
147 | int loop; | 182 | int loop; |
148 | for (loop = 0; loop < MAXTAGLOOP; loop++) { | 183 | for (loop = 0; loop < MAXTAGLOOP; loop++) { |
@@ -980,11 +1015,13 @@ void luaV_execute (lua_State *L) { | |||
980 | TValue *plimit = ra + 1; | 1015 | TValue *plimit = ra + 1; |
981 | TValue *pstep = ra + 2; | 1016 | TValue *pstep = ra + 2; |
982 | lua_Integer ilimit; | 1017 | lua_Integer ilimit; |
1018 | int stopnow; | ||
983 | if (ttisinteger(init) && ttisinteger(pstep) && | 1019 | if (ttisinteger(init) && ttisinteger(pstep) && |
984 | tointeger_aux(plimit, &ilimit, (ivalue(pstep) < 0))) { | 1020 | forlimit(plimit, &ilimit, ivalue(pstep), &stopnow)) { |
985 | /* all values are integer */ | 1021 | /* all values are integer */ |
986 | setivalue(init, ivalue(init) - ivalue(pstep)); | 1022 | lua_Integer initv = (stopnow ? 0 : ivalue(init)); |
987 | setivalue(plimit, ilimit); | 1023 | setivalue(plimit, ilimit); |
1024 | setivalue(init, initv - ivalue(pstep)); | ||
988 | } | 1025 | } |
989 | else { /* try making all values floats */ | 1026 | else { /* try making all values floats */ |
990 | lua_Number ninit; lua_Number nlimit; lua_Number nstep; | 1027 | lua_Number ninit; lua_Number nlimit; lua_Number nstep; |