Răsfoiți Sursa

'for' loop uses integers when possible

Roberto Ierusalimschy 12 ani în urmă
părinte
comite
bb1851ce98
1 a modificat fișierele cu 33 adăugiri și 16 ștergeri
  1. 33 16
      lvm.c

+ 33 - 16
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 2.160 2013/04/25 16:07:52 roberto Exp roberto $
+** $Id: lvm.c,v 2.161 2013/04/25 19:12:41 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -805,27 +805,44 @@ void luaV_execute (lua_State *L) {
         }
       )
       vmcase(OP_FORLOOP,
-        lua_Number step = nvalue(ra+2);
-        lua_Number idx = luai_numadd(L, nvalue(ra), step); /* increment index */
-        lua_Number limit = nvalue(ra+1);
-        if (luai_numlt(L, 0, step) ? luai_numle(L, idx, limit)
-                                   : luai_numle(L, limit, idx)) {
-          ci->u.l.savedpc += GETARG_sBx(i);  /* jump back */
-          setnvalue(ra, idx);  /* update internal index... */
-          setnvalue(ra+3, idx);  /* ...and external index */
+        if (ttisinteger(ra)) {  /* integer count? */
+          lua_Integer step = ivalue(ra + 2);
+          lua_Integer idx = ivalue(ra) + step; /* increment index */
+          lua_Integer limit = ivalue(ra + 1);
+          if ((0 < step) ? (idx <= limit) : (limit <= idx)) {
+            ci->u.l.savedpc += GETARG_sBx(i);  /* jump back */
+            setivalue(ra, idx);  /* update internal index... */
+            setivalue(ra + 3, idx);  /* ...and external index */
+          }
+        }
+        else {  /* floating count */
+          lua_Number step = fltvalue(ra + 2);
+          lua_Number idx = luai_numadd(L, fltvalue(ra), step); /* inc. index */
+          lua_Number limit = fltvalue(ra + 1);
+          if (luai_numlt(L, 0, step) ? luai_numle(L, idx, limit)
+                                     : luai_numle(L, limit, idx)) {
+            ci->u.l.savedpc += GETARG_sBx(i);  /* jump back */
+            setnvalue(ra, idx);  /* update internal index... */
+            setnvalue(ra + 3, idx);  /* ...and external index */
+          }
         }
       )
       vmcase(OP_FORPREP,
         const TValue *init = ra;
         const TValue *plimit = ra+1;
         const TValue *pstep = ra+2;
-        if (!tonumber(init, ra))
-          luaG_runerror(L, LUA_QL("for") " initial value must be a number");
-        else if (!tonumber(plimit, ra+1))
-          luaG_runerror(L, LUA_QL("for") " limit must be a number");
-        else if (!tonumber(pstep, ra+2))
-          luaG_runerror(L, LUA_QL("for") " step must be a number");
-        setnvalue(ra, luai_numsub(L, nvalue(ra), nvalue(pstep)));
+        if (ttisinteger(ra) && ttisinteger(ra + 1) && ttisinteger(ra + 2)) {
+          setivalue(ra, ivalue(ra) - ivalue(pstep));
+        }
+        else {  /* try with floats */
+          if (!tonumber(init, ra))
+            luaG_runerror(L, LUA_QL("for") " initial value must be a number");
+          else if (!tonumber(plimit, ra+1))
+            luaG_runerror(L, LUA_QL("for") " limit must be a number");
+          else if (!tonumber(pstep, ra+2))
+            luaG_runerror(L, LUA_QL("for") " step must be a number");
+          setnvalue(ra, luai_numsub(L, fltvalue(ra), fltvalue(pstep)));
+        }
         ci->u.l.savedpc += GETARG_sBx(i);
       )
       vmcasenb(OP_TFORCALL,