New semantics for the integer 'for' loop

The numerical 'for' loop over integers now uses a precomputed counter
to control its number of iteractions. This change eliminates several
weird cases caused by overflows (wrap-around) in the control variable.
(It also ensures that every integer loop halts.)

Also, the special opcodes for the usual case of step==1 were removed.
(The new code is already somewhat complex for the usual case,
but efficient.)
diff --git a/ljumptab.h b/ljumptab.h
index 9fa72a7..fa4277c 100644
--- a/ljumptab.h
+++ b/ljumptab.h
@@ -99,8 +99,6 @@
 &&L_OP_RETURN,
 &&L_OP_RETURN0,
 &&L_OP_RETURN1,
-&&L_OP_FORLOOP1,
-&&L_OP_FORPREP1,
 &&L_OP_FORLOOP,
 &&L_OP_FORPREP,
 &&L_OP_TFORPREP,
diff --git a/lopcodes.c b/lopcodes.c
index 3f0d551..c35a0aa 100644
--- a/lopcodes.c
+++ b/lopcodes.c
@@ -93,8 +93,6 @@
  ,opmode(0, 1, 0, 0, iABC)		/* OP_RETURN */
  ,opmode(0, 0, 0, 0, iABC)		/* OP_RETURN0 */
  ,opmode(0, 0, 0, 0, iABC)		/* OP_RETURN1 */
- ,opmode(0, 0, 0, 1, iABx)		/* OP_FORLOOP1 */
- ,opmode(0, 0, 0, 1, iABx)		/* OP_FORPREP1 */
  ,opmode(0, 0, 0, 1, iABx)		/* OP_FORLOOP */
  ,opmode(0, 0, 0, 1, iABx)		/* OP_FORPREP */
  ,opmode(0, 0, 0, 0, iABx)		/* OP_TFORPREP */
diff --git a/lopcodes.h b/lopcodes.h
index 3e10025..f867a01 100644
--- a/lopcodes.h
+++ b/lopcodes.h
@@ -280,10 +280,6 @@
 OP_RETURN0,/*	  	return 						*/
 OP_RETURN1,/*	A 	return R(A)					*/
 
-OP_FORLOOP1,/*	A Bx	R(A)++;
-			if R(A) <= R(A+1) then { pc-=Bx; R(A+3)=R(A) }	*/
-OP_FORPREP1,/*	A Bx	R(A)--; pc+=Bx					*/
-
 OP_FORLOOP,/*	A Bx	R(A)+=R(A+2);
 			if R(A) <?= R(A+1) then { pc-=Bx; R(A+3)=R(A) }	*/
 OP_FORPREP,/*	A Bx	R(A)-=R(A+2); pc+=Bx				*/
diff --git a/lopnames.h b/lopnames.h
index 96d901a..dfca34d 100644
--- a/lopnames.h
+++ b/lopnames.h
@@ -84,8 +84,6 @@
   "RETURN",
   "RETURN0",
   "RETURN1",
-  "FORLOOP1",
-  "FORPREP1",
   "FORLOOP",
   "FORPREP",
   "TFORPREP",
diff --git a/lparser.c b/lparser.c
index 3887958..8ffd974 100644
--- a/lparser.c
+++ b/lparser.c
@@ -1371,18 +1371,14 @@
 
 /*
 ** Read an expression and generate code to put its results in next
-** stack slot. Return true if expression is a constant integer and,
-** if 'i' is not-zero, its value is equal to 'i'.
+** stack slot.
 **
 */
-static int exp1 (LexState *ls, int i) {
+static void exp1 (LexState *ls) {
   expdesc e;
-  int res;
   expr(ls, &e);
-  res = luaK_isKint(&e) && (i == 0 || i == e.u.ival);
   luaK_exp2nextreg(ls->fs, &e);
   lua_assert(e.k == VNONRELOC);
-  return res;
 }
 
 
@@ -1403,31 +1399,29 @@
 
 
 /*
-** Generate code for a 'for' loop. 'kind' can be zero (a common for
-** loop), one (a basic for loop, with integer values and increment of
-** 1), or two (a generic for loop).
+** Generate code for a 'for' loop.
 */
-static void forbody (LexState *ls, int base, int line, int nvars, int kind) {
+static void forbody (LexState *ls, int base, int line, int nvars, int isgen) {
   /* forbody -> DO block */
-  static OpCode forprep[3] = {OP_FORPREP, OP_FORPREP1, OP_TFORPREP};
-  static OpCode forloop[3] = {OP_FORLOOP, OP_FORLOOP1, OP_TFORLOOP};
+  static OpCode forprep[2] = {OP_FORPREP, OP_TFORPREP};
+  static OpCode forloop[2] = {OP_FORLOOP, OP_TFORLOOP};
   BlockCnt bl;
   FuncState *fs = ls->fs;
   int prep, endfor;
   checknext(ls, TK_DO);
-  prep = luaK_codeABx(fs, forprep[kind], base, 0);
+  prep = luaK_codeABx(fs, forprep[isgen], base, 0);
   enterblock(fs, &bl, 0);  /* scope for declared variables */
   adjustlocalvars(ls, nvars);
   luaK_reserveregs(fs, nvars);
   block(ls);
   leaveblock(fs);  /* end of scope for declared variables */
   fixforjump(fs, prep, luaK_getlabel(fs), 0);
-  if (kind == 2) {  /* generic for? */
+  if (isgen) {  /* generic for? */
     luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars);
     luaK_fixline(fs, line);
     base += 2;  /* base for 'OP_TFORLOOP' (skips function and state) */
   }
-  endfor = luaK_codeABx(fs, forloop[kind], base, 0);
+  endfor = luaK_codeABx(fs, forloop[isgen], base, 0);
   fixforjump(fs, endfor, prep + 1, 1);
   luaK_fixline(fs, line);
 }
@@ -1437,26 +1431,22 @@
   /* fornum -> NAME = exp,exp[,exp] forbody */
   FuncState *fs = ls->fs;
   int base = fs->freereg;
-  int basicfor = 1;  /* true if it is a "basic" 'for' (integer + 1) */
   new_localvarliteral(ls, "(for index)");
   new_localvarliteral(ls, "(for limit)");
   new_localvarliteral(ls, "(for step)");
   new_localvar(ls, varname);
   checknext(ls, '=');
-  if (!exp1(ls, 0))  /* initial value not an integer? */
-    basicfor = 0;  /* not a basic 'for' */
+  exp1(ls);  /* initial value */
   checknext(ls, ',');
-  exp1(ls, 0);  /* limit */
-  if (testnext(ls, ',')) {
-    if (!exp1(ls, 1))  /* optional step not 1? */
-      basicfor = 0;  /* not a basic 'for' */
-  }
+  exp1(ls);  /* limit */
+  if (testnext(ls, ','))
+    exp1(ls);  /* optional step */
   else {  /* default step = 1 */
     luaK_int(fs, fs->freereg, 1);
     luaK_reserveregs(fs, 1);
   }
   adjustlocalvars(ls, 3);  /* control variables */
-  forbody(ls, base, line, 1, basicfor);
+  forbody(ls, base, line, 1, 0);
 }
 
 
@@ -1484,7 +1474,7 @@
   adjust_assign(ls, 4, explist(ls, &e), &e);
   adjustlocalvars(ls, 4);  /* control variables */
   luaK_checkstack(fs, 3);  /* extra space to call generator */
-  forbody(ls, base, line, nvars - 4, 2);
+  forbody(ls, base, line, nvars - 4, 1);
 }
 
 
@@ -1633,7 +1623,7 @@
       luaO_pushfstring(ls->L, "unknown attribute '%s'", getstr(attr)));
   new_localvar(ls, str_checkname(ls));
   checknext(ls, '=');
-  exp1(ls, 0);
+  exp1(ls);
   markupval(fs, fs->nactvar);
   fs->bl->insidetbc = 1;  /* in the scope of a to-be-closed variable */
   adjustlocalvars(ls, 1);
diff --git a/lvm.c b/lvm.c
index 23e7ff7..75b05f0 100644
--- a/lvm.c
+++ b/lvm.c
@@ -148,35 +148,34 @@
 
 /*
 ** Try to convert a 'for' limit to an integer, preserving the semantics
-** of the loop.  (The following explanation assumes a non-negative step;
+** of the loop.  (The following explanation assumes a positive step;
 ** it is valid for negative steps mutatis mutandis.)
 ** If the limit is an integer or can be converted to an integer,
 ** rounding down, that is it.
-** Otherwise, check whether the limit can be converted to a float.  If
-** the number is too large, it is OK to set the limit as LUA_MAXINTEGER,
-** which means no limit.  If the number is too negative, the loop
-** should not run, because any initial integer value is larger than the
-** limit. So, it sets the limit to LUA_MININTEGER. 'stopnow' corrects
-** the extreme case when the initial value is LUA_MININTEGER, in which
-** case the LUA_MININTEGER limit would still run the loop once.
+** Otherwise, check whether the limit can be converted to a float. If
+** the float is too large, clip it to LUA_MAXINTEGER.  If the float
+** is too negative, the loop should not run, because any initial
+** integer value is greater than such limit; so, it sets 'stopnow'.
+** (For this latter case, no integer limit would be correct; even a
+** limit of LUA_MININTEGER would run the loop once for an initial
+** value equal to LUA_MININTEGER.)
 */
-static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step,
+static int forlimit (const TValue *lim, lua_Integer *p, lua_Integer step,
                      int *stopnow) {
   *stopnow = 0;  /* usually, let loops run */
-  if (ttisinteger(obj))
-    *p = ivalue(obj);
-  else if (!luaV_tointeger(obj, p, (step < 0 ? 2 : 1))) {
+  if (!luaV_tointeger(lim, p, (step < 0 ? 2 : 1))) {
     /* not coercible to in integer */
-    lua_Number n;  /* try to convert to float */
-    if (!tonumber(obj, &n)) /* cannot convert to float? */
+    lua_Number flim;  /* try to convert to float */
+    if (!tonumber(lim, &flim)) /* cannot convert to float? */
       return 0;  /* not a number */
-    if (luai_numlt(0, n)) {  /* if true, float is larger than max integer */
-      *p = LUA_MAXINTEGER;
-      if (step < 0) *stopnow = 1;
+    /* 'flim' is a float out of integer bounds */
+    if (luai_numlt(0, flim)) {  /* if it is positive, it is too large */
+      *p = LUA_MAXINTEGER;  /* truncate */
+      if (step < 0) *stopnow = 1;  /* initial value must be less than it */
     }
-    else {  /* float is less than min integer */
-      *p = LUA_MININTEGER;
-      if (step >= 0) *stopnow = 1;
+    else {  /* it is less than min integer */
+      *p = LUA_MININTEGER;  /* truncate */
+      if (step > 0) *stopnow = 1;  /* initial value must be greater than it */
     }
   }
   return 1;
@@ -1636,85 +1635,87 @@
         }
         return;
       }
-      vmcase(OP_FORLOOP1) {
-        lua_Integer idx = intop(+, ivalue(s2v(ra)), 1); /* increment index */
-        lua_Integer limit = ivalue(s2v(ra + 1));
-        if (idx <= limit) {
-          pc -= GETARG_Bx(i);  /* jump back */
-          chgivalue(s2v(ra), idx);  /* update internal index... */
-          setivalue(s2v(ra + 3), idx);  /* ...and external index */
-        }
-        updatetrap(ci);
-        vmbreak;
-      }
-      vmcase(OP_FORPREP1) {
-        TValue *init = s2v(ra);
-        TValue *plimit = s2v(ra + 1);
-        lua_Integer ilimit, initv;
-        int stopnow;
-        if (unlikely(!forlimit(plimit, &ilimit, 1, &stopnow))) {
-          savestate(L, ci);  /* for the error message */
-          luaG_forerror(L, plimit, "limit");
-        }
-        initv = (stopnow ? 0 : ivalue(init));
-        setivalue(plimit, ilimit);
-        setivalue(init, intop(-, initv, 1));
-        pc += GETARG_Bx(i);
-        vmbreak;
-      }
       vmcase(OP_FORLOOP) {
-        if (ttisinteger(s2v(ra))) {  /* integer loop? */
-          lua_Integer step = ivalue(s2v(ra + 2));
-          lua_Integer idx = intop(+, ivalue(s2v(ra)), step); /* new index */
-          lua_Integer limit = ivalue(s2v(ra + 1));
-          if ((0 < step) ? (idx <= limit) : (limit <= idx)) {
+        if (ttisinteger(s2v(ra + 2))) {  /* integer loop? */
+          lua_Unsigned count = l_castS2U(ivalue(s2v(ra)));
+          if (count > 0) {  /* still more iterations? */
+            lua_Integer step = ivalue(s2v(ra + 2));
+            lua_Integer idx = ivalue(s2v(ra + 3));
+            idx = intop(+, idx, step);  /* add step to index */
+            chgivalue(s2v(ra), count - 1);  /* update counter... */
+            setivalue(s2v(ra + 3), idx);  /* ...and index */
             pc -= GETARG_Bx(i);  /* jump back */
-            chgivalue(s2v(ra), idx);  /* update internal index... */
-            setivalue(s2v(ra + 3), idx);  /* ...and external index */
           }
         }
         else {  /* floating loop */
           lua_Number step = fltvalue(s2v(ra + 2));
           lua_Number limit = fltvalue(s2v(ra + 1));
-          lua_Number idx = fltvalue(s2v(ra));
+          lua_Number idx = fltvalue(s2v(ra + 3));
           idx = luai_numadd(L, idx, step);  /* inc. index */
           if (luai_numlt(0, step) ? luai_numle(idx, limit)
                                   : luai_numle(limit, idx)) {
+            setfltvalue(s2v(ra + 3), idx);  /* update index */
             pc -= GETARG_Bx(i);  /* jump back */
-            chgfltvalue(s2v(ra), idx);  /* update internal index... */
-            setfltvalue(s2v(ra + 3), idx);  /* ...and external index */
           }
         }
-        updatetrap(ci);
+        updatetrap(ci);  /* allows a signal to break the loop */
         vmbreak;
       }
       vmcase(OP_FORPREP) {
-        TValue *init = s2v(ra);
+        TValue *pinit = s2v(ra);
         TValue *plimit = s2v(ra + 1);
         TValue *pstep = s2v(ra + 2);
         lua_Integer ilimit;
         int stopnow;
-        if (ttisinteger(init) && ttisinteger(pstep) &&
+        savestate(L, ci);  /* in case of errors */
+        if (ttisinteger(pinit) && ttisinteger(pstep) &&
             forlimit(plimit, &ilimit, ivalue(pstep), &stopnow)) {
-          /* all values are integer */
-          lua_Integer initv = (stopnow ? 0 : ivalue(init));
-          setivalue(plimit, ilimit);
-          setivalue(init, intop(-, initv, ivalue(pstep)));
+          /* integer loop */
+          lua_Integer init = ivalue(pinit);
+          lua_Integer step = ivalue(pstep);
+          setivalue(s2v(ra + 3), init);  /* control variable */
+          if (step == 0)
+            luaG_runerror(L, "'for' step is zero");
+          else if (stopnow)
+            pc += GETARG_Bx(i) + 1;  /* skip the loop */
+          else if (step > 0) {  /* ascending loop? */
+            if (init > ilimit)
+              pc += GETARG_Bx(i) + 1;  /* skip the loop */
+            else {
+              lua_Unsigned count = l_castS2U(ilimit) - l_castS2U(init);
+              if (step != 1)  /* avoid division in the too common case */
+                count /= l_castS2U(step);
+              setivalue(s2v(ra), count);
+            }
+          }
+          else {  /* descending loop */
+            if (init < ilimit)
+              pc += GETARG_Bx(i) + 1;  /* skip the loop */
+            else {
+              lua_Unsigned count = l_castS2U(init) - l_castS2U(ilimit);
+              count /= -l_castS2U(step);
+              setivalue(s2v(ra), count);
+            }
+          }
         }
         else {  /* try making all values floats */
-          lua_Number ninit; lua_Number nlimit; lua_Number nstep;
-          savestate(L, ci);  /* in case of errors */
-          if (unlikely(!tonumber(plimit, &nlimit)))
+          lua_Number init; lua_Number flimit; lua_Number step;
+          if (unlikely(!tonumber(plimit, &flimit)))
             luaG_forerror(L, plimit, "limit");
-          setfltvalue(plimit, nlimit);
-          if (unlikely(!tonumber(pstep, &nstep)))
+          setfltvalue(plimit, flimit);
+          if (unlikely(!tonumber(pstep, &step)))
             luaG_forerror(L, pstep, "step");
-          setfltvalue(pstep, nstep);
-          if (unlikely(!tonumber(init, &ninit)))
-            luaG_forerror(L, init, "initial value");
-          setfltvalue(init, luai_numsub(L, ninit, nstep));
+          setfltvalue(pstep, step);
+          if (unlikely(!tonumber(pinit, &init)))
+            luaG_forerror(L, pinit, "initial value");
+          if (step == 0)
+            luaG_runerror(L, "'for' step is zero");
+          if (luai_numlt(0, step) ? luai_numlt(flimit, init)
+                                   : luai_numlt(init, flimit))
+            pc += GETARG_Bx(i) + 1;  /* skip the loop */
+          else
+            setfltvalue(s2v(ra + 3), init);  /* control variable */
         }
-        pc += GETARG_Bx(i);
         vmbreak;
       }
       vmcase(OP_TFORPREP) {
diff --git a/manual/manual.of b/manual/manual.of
index 8a8ebad..b7ced44 100644
--- a/manual/manual.of
+++ b/manual/manual.of
@@ -594,7 +594,7 @@
 The collector starts a new cycle when the use of memory
 hits @M{n%} of the use after the previous collection.
 Larger values make the collector less aggressive.
-Values smaller than 100 mean the collector will not wait to
+Values less than 100 mean the collector will not wait to
 start a new cycle.
 A value of 200 means that the collector waits for the total memory in use
 to double before starting a new cycle.
@@ -608,7 +608,7 @@
 kilobyte of memory allocated.
 Larger values make the collector more aggressive but also increase
 the size of each incremental step.
-You should not use values smaller than 100,
+You should not use values less than 100,
 because they make the collector too slow and
 can result in the collector never finishing a cycle.
 The default value is 100;  the maximum value is 1000.
@@ -1004,7 +1004,7 @@
 (note the mandatory enclosing brackets),
 where @rep{XXX} is a sequence of one or more hexadecimal digits
 representing the character code point.
-This code point can be any value smaller than @M{2@sp{31}}.
+This code point can be any value less than @M{2@sp{31}}.
 (Lua uses the original UTF-8 specification here.)
 
 Literal strings can also be defined using a long format
@@ -1370,74 +1370,50 @@
 The @Rw{for} statement has two forms:
 one numerical and one generic.
 
+@sect4{@title{The numerical @Rw{for} loop}
+
 The numerical @Rw{for} loop repeats a block of code while a
-control variable runs through an arithmetic progression.
+control variable goes through an arithmetic progression.
 It has the following syntax:
 @Produc{
 @producname{stat}@producbody{@Rw{for} @bnfNter{Name} @bnfter{=}
   exp @bnfter{,} exp @bnfopt{@bnfter{,} exp} @Rw{do} block @Rw{end}}
 }
-The @emph{block} is repeated for @emph{name} starting at the value of
-the first @emph{exp}, until it passes the second @emph{exp} by steps of the
-third @emph{exp}.
-More precisely, a @Rw{for} statement like
-@verbatim{
-for v = @rep{e1}, @rep{e2}, @rep{e3} do @rep{block} end
-}
-is equivalent to the code:
-@verbatim{
-do
-  local @rep{var}, @rep{limit}, @rep{step} = tonumber(@rep{e1}), tonumber(@rep{e2}), tonumber(@rep{e3})
-  if not (@rep{var} and @rep{limit} and @rep{step}) then error() end
-  @rep{var} = @rep{var} - @rep{step}
-  while true do
-    @rep{var} = @rep{var} + @rep{step}
-    if (@rep{step} >= 0 and @rep{var} > @rep{limit}) or (@rep{step} < 0 and @rep{var} < @rep{limit}) then
-      break
-    end
-    local v = @rep{var}
-    @rep{block}
-  end
-end
-}
+The given identifier (@bnfNter{Name}) defines the control variable,
+which is local to the loop body (@emph{block}).
 
-Note the following:
-@itemize{
+The loop starts by evaluating once the three control expressions;
+they must all result in numbers.
+Their values are called respectively
+the @emph{initial value}, the @emph{limit}, and the @emph{step}.
+If the step is absent, it defaults @N{to 1}.
+Then the loop body is repeated with the value of the control variable
+going through an arithmetic progression,
+starting at the initial value,
+with a common difference given by the step,
+until that value passes the limit.
+A negative step makes a decreasing sequence;
+a step equal to zero raises an error.
+If the initial value is already greater than the limit
+(or less than, if the step is negative), the body is not executed.
 
-@item{
-All three control expressions are evaluated only once,
-before the loop starts.
-They must all result in numbers.
-}
+If both the initial value and the step are integers,
+the loop is done with integers;
+in this case, the range of the control variable is limited
+by the range of integers.
+Otherwise, the loop is done with floats.
+(Beware of floating-point accuracy in this case.)
 
-@item{
-@T{@rep{var}}, @T{@rep{limit}}, and @T{@rep{step}} are invisible variables.
-The names shown here are for explanatory purposes only.
-}
-
-@item{
-If the third expression (the step) is absent,
-then a step @N{of 1} is used.
-}
-
-@item{
-You can use @Rw{break} and @Rw{goto} to exit a @Rw{for} loop.
-}
-
-@item{
-The loop variable @T{v} is local to the loop body.
+You should not change the value of the control variable
+during the loop.
 If you need its value after the loop,
 assign it to another variable before exiting the loop.
-}
-
-@item{
-The values in @rep{var}, @rep{limit}, and @rep{step}
-can be integers or floats.
-All operations on them respect the usual rules in Lua.
-}
 
 }
 
+@sect4{@title{The generic @Rw{for} loop}
+
+
 The generic @Rw{for} statement works over functions,
 called @def{iterators}.
 On each iteration, the iterator function is called to produce a new value,
@@ -1499,6 +1475,8 @@
 
 }
 
+}
+
 @sect3{funcstat| @title{Function Calls as Statements}
 To allow possible side-effects,
 function calls can be executed as statements:
@@ -1819,7 +1797,7 @@
 and @T{a >= b} is translated to @T{b <= a}.
 
 Following the @x{IEEE 754} standard,
-@x{NaN} is considered neither smaller than,
+@x{NaN} is considered neither less than,
 nor equal to, nor greater than any value (including itself).
 
 }
@@ -2171,7 +2149,7 @@
 @index{multiple return}
 There is a system-dependent limit on the number of values
 that a function may return.
-This limit is guaranteed to be larger than 1000.
+This limit is guaranteed to be greater than 1000.
 
 The @emphx{colon} syntax
 is used for defining @def{methods},
@@ -2367,7 +2345,7 @@
 within the space allocated for the stack,
 that is, indices up to the stack size.
 (Note that 0 is never an acceptable index.)
-Indices to upvalues @see{c-closure} larger than the real number
+Indices to upvalues @see{c-closure} greater than the real number
 of upvalues in the current @N{C function} are also acceptable (but invalid).
 Except when noted otherwise,
 functions in the API work with acceptable indices.
@@ -2879,7 +2857,7 @@
 (that is, that you can safely push up to @id{n} values into it).
 It returns false if it cannot fulfill the request,
 either because it would cause the stack
-to be larger than a fixed maximum size
+to be greater than a fixed maximum size
 (typically at least several thousand elements) or
 because it cannot allocate memory for the extra space.
 This function never shrinks the stack;
@@ -4053,7 +4031,7 @@
 
 Accepts any index, @N{or 0},
 and sets the stack top to this index.
-If the new top is larger than the old one,
+If the new top is greater than the old one,
 then the new elements are filled with @nil.
 If @id{index} @N{is 0}, then all stack elements are removed.
 
@@ -5056,7 +5034,7 @@
 @item{
 Finish by calling @T{luaL_pushresultsize(&b, sz)},
 where @id{sz} is the total size of the resulting string
-copied into that space (which may be smaller than or
+copied into that space (which may be less than or
 equal to the preallocated size).
 }
 
@@ -7336,7 +7314,7 @@
 valid sequences (well formed and not overlong).
 By default, they only accept byte sequences
 that result in valid Unicode code points,
-rejecting values larger than @T{10FFFF} and surrogates.
+rejecting values greater than @T{10FFFF} and surrogates.
 A boolean argument @id{nonstrict}, when available,
 lifts these checks,
 so that all values up to @T{0x7FFFFFFF} are accepted.
@@ -7572,7 +7550,7 @@
 
 @LibEntry{math.ceil (x)|
 
-Returns the smallest integral value larger than or equal to @id{x}.
+Returns the smallest integral value greater than or equal to @id{x}.
 
 }
 
@@ -7597,7 +7575,7 @@
 
 @LibEntry{math.floor (x)|
 
-Returns the largest integral value smaller than or equal to @id{x}.
+Returns the largest integral value less than or equal to @id{x}.
 
 }
 
@@ -7611,7 +7589,7 @@
 @LibEntry{math.huge|
 
 The float value @idx{HUGE_VAL},
-a value larger than any other numeric value.
+a value greater than any other numeric value.
 
 }
 
@@ -8352,7 +8330,7 @@
 @N{level 1} is the function that called @id{getinfo}
 (except for tail calls, which do not count on the stack);
 and so on.
-If @id{f} is a number larger than the number of active functions,
+If @id{f} is a number greater than the number of active functions,
 then @id{getinfo} returns @nil.
 
 The returned table can contain all the fields returned by @Lid{lua_getinfo},
@@ -8746,6 +8724,12 @@
 }
 
 @item{
+The semantics of the numerical @Rw{for} loop
+over integers changed in some details.
+In particular, the control variable never wraps around.
+}
+
+@item{
 When a coroutine finishes with an error,
 its stack is unwound (to run any pending closing methods).
 }
diff --git a/testes/code.lua b/testes/code.lua
index 834ff5e..128ca2c 100644
--- a/testes/code.lua
+++ b/testes/code.lua
@@ -303,9 +303,9 @@
 
 -- basic 'for' loops
 check(function () for i = -10, 10.5 do end end,
-'LOADI', 'LOADK', 'LOADI', 'FORPREP1', 'FORLOOP1', 'RETURN0')
+'LOADI', 'LOADK', 'LOADI', 'FORPREP', 'FORLOOP', 'RETURN0')
 check(function () for i = 0xfffffff, 10.0, 1 do end end,
-'LOADK', 'LOADF', 'LOADI', 'FORPREP1', 'FORLOOP1', 'RETURN0')
+'LOADK', 'LOADF', 'LOADI', 'FORPREP', 'FORLOOP', 'RETURN0')
 
 -- bug in constant folding for 5.1
 check(function () return -nil end, 'LOADNIL', 'UNM', 'RETURN1')
diff --git a/testes/db.lua b/testes/db.lua
index 976962b..0858dd2 100644
--- a/testes/db.lua
+++ b/testes/db.lua
@@ -162,7 +162,7 @@
 end
 ]], {1,2,1,2,1,3})
 
-test([[for i=1,4 do a=1 end]], {1,1,1,1,1})
+test([[for i=1,4 do a=1 end]], {1,1,1,1}, true)
 
 
 do   -- testing line info/trace with large gaps in source
diff --git a/testes/nextvar.lua b/testes/nextvar.lua
index d2306ed..e769ccd 100644
--- a/testes/nextvar.lua
+++ b/testes/nextvar.lua
@@ -76,7 +76,7 @@
   a = math.ceil(a*1.3)
 end
 
- 
+
 local function check (t, na, nh)
   local a, h = T.querytab(t)
   if a ~= na or h ~= nh then
@@ -100,7 +100,7 @@
 for i=1,lim do
   s = s..i..','
   local s = s
-  for k=0,lim do 
+  for k=0,lim do
     local t = load(s..'}', '')()
     assert(#t == i)
     check(t, fb(i), mp2(k))
@@ -279,7 +279,7 @@
 end
 
 
--- 
+--
 
 local function checknext (a)
   local b = {}
@@ -500,7 +500,7 @@
   mt.__newindex = nil
   mt.__len = nil
   local tab2 = {}
-  local u2 = T.newuserdata(0) 
+  local u2 = T.newuserdata(0)
   debug.setmetatable(u2, {__newindex = function (_, k, v) tab2[k] = v end})
   table.move(u, 1, 4, 1, u2)
   assert(#tab2 == 4 and tab2[1] == tab[1] and tab2[4] == tab[4])
@@ -601,6 +601,69 @@
 
 end
 
+
+do   -- testing other strange cases for numeric 'for'
+
+  local function checkfor (from, to, step, t)
+    local c = 0
+    for i = from, to, step do
+      c = c + 1
+      assert(i == t[c])
+    end
+    assert(c == #t)
+  end
+
+  local maxi = math.maxinteger
+  local mini = math.mininteger
+
+  checkfor(mini, maxi, maxi, {mini, -1, maxi - 1})
+
+  checkfor(mini, math.huge, maxi, {mini, -1, maxi - 1})
+
+  checkfor(maxi, mini, mini, {maxi, -1})
+
+  checkfor(maxi, mini, -maxi, {maxi, 0, -maxi})
+
+  checkfor(maxi, -math.huge, mini, {maxi, -1})
+
+  checkfor(maxi, mini, 1, {})
+  checkfor(mini, maxi, -1, {})
+
+  checkfor(maxi - 6, maxi, 3, {maxi - 6, maxi - 3, maxi})
+  checkfor(mini + 4, mini, -2, {mini + 4, mini + 2, mini})
+
+  local step = maxi // 10
+  local c = mini
+  for i = mini, maxi, step do
+    assert(i == c)
+    c = c + step
+  end
+
+  c = maxi
+  for i = maxi, mini, -step do
+    assert(i == c)
+    c = c - step
+  end
+
+  checkfor(maxi, maxi, maxi, {maxi})
+  checkfor(maxi, maxi, mini, {maxi})
+  checkfor(mini, mini, maxi, {mini})
+  checkfor(mini, mini, mini, {mini})
+end
+
+
+checkerror("'for' step is zero", function ()
+  for i = 1, 10, 0 do end
+end)
+
+checkerror("'for' step is zero", function ()
+  for i = 1, -10, 0 do end
+end)
+
+checkerror("'for' step is zero", function ()
+  for i = 1.0, -10, 0.0 do end
+end)
+
 collectgarbage()
 
 
@@ -657,7 +720,7 @@
 -- testing ipairs with metamethods
 a = {n=10}
 setmetatable(a, { __index = function (t,k)
-                     if k <= t.n then return k * 10 end 
+                     if k <= t.n then return k * 10 end
                   end})
 i = 0
 for k,v in ipairs(a) do