Browse Source

Details

In the generic for loop, it is simpler for OP_TFORLOOP to use the
same 'ra' as OP_TFORCALL. Moreover, the internal names of the loop
temporaries "(for ...)" don't need to leak internal details (even
because the numerical for loop doesn't have a fixed role for each of
its temporaries).
Roberto Ierusalimschy 6 years ago
parent
commit
be8445d7e4
3 changed files with 13 additions and 13 deletions
  1. 6 7
      lparser.c
  2. 2 3
      lvm.c
  3. 5 3
      testes/files.lua

+ 6 - 7
lparser.c

@@ -1527,7 +1527,6 @@ static void forbody (LexState *ls, int base, int line, int nvars, int isgen) {
   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[isgen], base, 0);
   fixforjump(fs, endfor, prep + 1, 1);
@@ -1539,9 +1538,9 @@ static void fornum (LexState *ls, TString *varname, int line) {
   /* fornum -> NAME = exp,exp[,exp] forbody */
   FuncState *fs = ls->fs;
   int base = fs->freereg;
-  new_localvarliteral(ls, "(for index)");
-  new_localvarliteral(ls, "(for limit)");
-  new_localvarliteral(ls, "(for step)");
+  new_localvarliteral(ls, "(for state)");
+  new_localvarliteral(ls, "(for state)");
+  new_localvarliteral(ls, "(for state)");
   new_localvar(ls, varname);
   checknext(ls, '=');
   exp1(ls);  /* initial value */
@@ -1566,10 +1565,10 @@ static void forlist (LexState *ls, TString *indexname) {
   int line;
   int base = fs->freereg;
   /* create control variables */
-  new_localvarliteral(ls, "(for generator)");
   new_localvarliteral(ls, "(for state)");
-  new_localvarliteral(ls, "(for control)");
-  new_localvarliteral(ls, "(for toclose)");
+  new_localvarliteral(ls, "(for state)");
+  new_localvarliteral(ls, "(for state)");
+  new_localvarliteral(ls, "(for state)");
   /* create declared variables */
   new_localvar(ls, indexname);
   while (testnext(ls, ',')) {

+ 2 - 3
lvm.c

@@ -1746,14 +1746,13 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
         Protect(luaD_call(L, ra + 4, GETARG_C(i)));  /* do the call */
         updatestack(ci);  /* stack may have changed */
         i = *(pc++);  /* go to next instruction */
-        ra += 2;  /* adjust for next instruction */
         lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i));
         goto l_tforloop;
       }
       vmcase(OP_TFORLOOP) {
         l_tforloop:
-        if (!ttisnil(s2v(ra + 2))) {  /* continue loop? */
-          setobjs2s(L, ra, ra + 2);  /* save control variable */
+        if (!ttisnil(s2v(ra + 4))) {  /* continue loop? */
+          setobjs2s(L, ra + 2, ra + 4);  /* save control variable */
           pc -= GETARG_Bx(i);  /* jump back */
         }
         vmbreak;

+ 5 - 3
testes/files.lua

@@ -427,10 +427,12 @@ do   -- testing closing file in line iteration
   -- get the to-be-closed variable from a loop
   local function gettoclose (lv)
     lv = lv + 1
-    for i = 1, math.maxinteger do
+    local stvar = 0   -- to-be-closed is 4th state variable in the loop
+    for i = 1, 1000 do
       local n, v = debug.getlocal(lv, i)
-      if n == "(for toclose)" then
-        return v
+      if n == "(for state)" then
+        stvar = stvar + 1
+        if stvar == 4 then return v end
       end
     end
   end