summaryrefslogtreecommitdiff
path: root/lvm.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2014-05-09 11:20:52 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2014-05-09 11:20:52 -0300
commit06dc893f88641e1df6a455c1f24ecaf9ce484d8d (patch)
tree208a9fedb091a09663316c3fdcca9fc0bb96a7fe /lvm.c
parenta09bd5961594dad90ffc381bf93c288e7322c2b7 (diff)
downloadlua-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.c43
1 files changed, 40 insertions, 3 deletions
diff --git a/lvm.c b/lvm.c
index 026e943d..3854c90a 100644
--- a/lvm.c
+++ b/lvm.c
@@ -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*/
161static 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
146void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { 181void 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;