Browse Source

generic for also coded to make test at the end of the loop

Roberto Ierusalimschy 23 years ago
parent
commit
af19d55635
5 changed files with 36 additions and 27 deletions
  1. 4 6
      ldebug.c
  2. 3 3
      lopcodes.c
  3. 5 2
      lopcodes.h
  4. 20 14
      lparser.c
  5. 4 2
      lvm.c

+ 4 - 6
ldebug.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: ldebug.c,v 1.112 2002/05/07 17:36:56 roberto Exp roberto $
+** $Id: ldebug.c,v 1.113 2002/05/09 14:14:34 roberto Exp roberto $
 ** Debug Interface
 ** Debug Interface
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -336,6 +336,9 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
         check(c < MAXSTACK && b < c);
         check(c < MAXSTACK && b < c);
         break;
         break;
       }
       }
+      case OP_TFORLOOP:
+        checkreg(pt, a+2+c);
+        /* go through */
       case OP_FORLOOP:
       case OP_FORLOOP:
         checkreg(pt, a+2);
         checkreg(pt, a+2);
         /* go through */
         /* go through */
@@ -347,11 +350,6 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
           pc += b;  /* do the jump */
           pc += b;  /* do the jump */
         break;
         break;
       }
       }
-      case OP_TFORLOOP: {
-        checkreg(pt, a+2+c);
-        check(pc+2 < pt->sizecode);  /* check skip */
-        break;
-      }
       case OP_CALL: {
       case OP_CALL: {
         if (b != 0) {
         if (b != 0) {
           checkreg(pt, a+b-1);
           checkreg(pt, a+b-1);

+ 3 - 3
lopcodes.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lopcodes.c,v 1.17 2002/04/24 20:07:46 roberto Exp roberto $
+** $Id: lopcodes.c,v 1.18 2002/05/06 15:51:41 roberto Exp roberto $
 ** extracted automatically from lopcodes.h by mkprint.lua
 ** extracted automatically from lopcodes.h by mkprint.lua
 ** DO NOT EDIT
 ** DO NOT EDIT
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
@@ -88,8 +88,8 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = {
  ,opmode(0,0,0,0, 0,0,iABC)		/* OP_TAILCALL */
  ,opmode(0,0,0,0, 0,0,iABC)		/* OP_TAILCALL */
  ,opmode(0,0,0,0, 0,0,iABC)		/* OP_RETURN */
  ,opmode(0,0,0,0, 0,0,iABC)		/* OP_RETURN */
  ,opmode(0,0,0,0, 0,0,iAsBx)		/* OP_FORLOOP */
  ,opmode(0,0,0,0, 0,0,iAsBx)		/* OP_FORLOOP */
- ,opmode(0,0,0,0, 0,0,iABC)		/* OP_TFORLOOP */
- ,opmode(0,0,0,0, 0,0,iABC)		/* OP_TFORPREP */
+ ,opmode(1,0,0,0, 0,0,iABC)		/* OP_TFORLOOP */
+ ,opmode(0,0,0,0, 0,0,iAsBx)		/* OP_TFORPREP */
  ,opmode(0,0,0,0, 0,0,iABx)		/* OP_SETLIST */
  ,opmode(0,0,0,0, 0,0,iABx)		/* OP_SETLIST */
  ,opmode(0,0,0,0, 0,0,iABx)		/* OP_SETLISTO */
  ,opmode(0,0,0,0, 0,0,iABx)		/* OP_SETLISTO */
  ,opmode(0,0,0,0, 0,0,iABC)		/* OP_CLOSE */
  ,opmode(0,0,0,0, 0,0,iABC)		/* OP_CLOSE */

+ 5 - 2
lopcodes.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lopcodes.h,v 1.95 2002/04/24 20:07:46 roberto Exp roberto $
+** $Id: lopcodes.h,v 1.96 2002/05/06 15:51:41 roberto Exp roberto $
 ** Opcodes for Lua virtual machine
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -170,7 +170,8 @@ OP_FORLOOP,/*	A sBx	R(A)+=R(A+2); if R(A) <?= R(A+1) then PC+= sBx	*/
 
 
 OP_TFORLOOP,/*	A C	R(A+2), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); 
 OP_TFORLOOP,/*	A C	R(A+2), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); 
                         if R(A+2) ~= nil then pc++			*/
                         if R(A+2) ~= nil then pc++			*/
-OP_TFORPREP,/*	A	if type(R(A)) == table then R(A+1):=R(A), R(A):=next */
+OP_TFORPREP,/*	A sBx	if type(R(A)) == table then R(A+1):=R(A), R(A):=next;
+			PC += sBx					*/
 
 
 OP_SETLIST,/*	A Bx	R(A)[Bx-Bx%FPF+i] := R(A+i), 1 <= i <= Bx%FPF+1	*/
 OP_SETLIST,/*	A Bx	R(A)[Bx-Bx%FPF+i] := R(A+i), 1 <= i <= Bx%FPF+1	*/
 OP_SETLISTO,/*	A Bx							*/
 OP_SETLISTO,/*	A Bx							*/
@@ -193,6 +194,8 @@ OP_CLOSURE/*	A Bx	R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n))	*/
   (2) In OP_RETURN, if (B == 0) then return up to `top'
   (2) In OP_RETURN, if (B == 0) then return up to `top'
 
 
   (3) For comparisons, B specifies what conditions the test should accept.
   (3) For comparisons, B specifies what conditions the test should accept.
+
+  (4) All `skips' (pc++) assume that next instruction is a jump
 ===========================================================================*/
 ===========================================================================*/
 
 
 
 

+ 20 - 14
lparser.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lparser.c,v 1.180 2002/05/10 17:02:32 roberto Exp roberto $
+** $Id: lparser.c,v 1.181 2002/05/10 19:22:11 roberto Exp roberto $
 ** Lua Parser
 ** Lua Parser
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -979,15 +979,16 @@ static void whilestat (LexState *ls, int line) {
   int whileinit, blockinit, expinit;
   int whileinit, blockinit, expinit;
   expdesc v;
   expdesc v;
   BlockCnt bl;
   BlockCnt bl;
-  next(ls);
-  whileinit = luaK_jump(fs);
+  next(ls);  /* skip WHILE */
+  whileinit = luaK_jump(fs);  /* jump to condition (which will be moved) */
   expinit = luaK_getlabel(fs);
   expinit = luaK_getlabel(fs);
-  expr(ls, &v);
+  expr(ls, &v);  /* parse condition */
   if (v.k == VK) v.k = VTRUE;  /* `trues' are all equal here */
   if (v.k == VK) v.k = VTRUE;  /* `trues' are all equal here */
   lineexp = ls->linenumber;
   lineexp = ls->linenumber;
   luaK_goiffalse(fs, &v);
   luaK_goiffalse(fs, &v);
-  luaK_dischargejpc(fs);
-  sizeexp = fs->pc - expinit;
+  luaK_concat(fs, &v.f, fs->jpc);
+  fs->jpc = NO_JUMP;
+  sizeexp = fs->pc - expinit;  /* size of expression code */
   if (sizeexp > MAXEXPWHILE) 
   if (sizeexp > MAXEXPWHILE) 
     luaX_syntaxerror(ls, "while condition too complex");
     luaX_syntaxerror(ls, "while condition too complex");
   for (i = 0; i < sizeexp; i++)  /* save `exp' code */
   for (i = 0; i < sizeexp; i++)  /* save `exp' code */
@@ -998,14 +999,15 @@ static void whilestat (LexState *ls, int line) {
   blockinit = luaK_getlabel(fs);
   blockinit = luaK_getlabel(fs);
   block(ls);
   block(ls);
   luaK_patchtohere(fs, whileinit);  /* initial jump jumps to here */
   luaK_patchtohere(fs, whileinit);  /* initial jump jumps to here */
+  /* move `exp' back to code */
   if (v.t != NO_JUMP) v.t += fs->pc - expinit;
   if (v.t != NO_JUMP) v.t += fs->pc - expinit;
   if (v.f != NO_JUMP) v.f += fs->pc - expinit;
   if (v.f != NO_JUMP) v.f += fs->pc - expinit;
   for (i=0; i<sizeexp; i++)
   for (i=0; i<sizeexp; i++)
     luaK_code(fs, codeexp[i], lineexp);
     luaK_code(fs, codeexp[i], lineexp);
-  luaK_patchlist(fs, v.t, blockinit);
-  luaK_patchtohere(fs, v.f);
   check_match(ls, TK_END, TK_WHILE, line);
   check_match(ls, TK_END, TK_WHILE, line);
   leaveblock(fs);
   leaveblock(fs);
+  luaK_patchlist(fs, v.t, blockinit);  /* true conditions go back to loop */
+  luaK_patchtohere(fs, v.f);  /* false conditions finish the loop */
 }
 }
 
 
 
 
@@ -1061,8 +1063,8 @@ static void fornum (LexState *ls, TString *varname, int line) {
   block(ls);
   block(ls);
   luaK_patchtohere(fs, prep-1);
   luaK_patchtohere(fs, prep-1);
   endfor = luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP);
   endfor = luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP);
+  luaK_fixline(fs, line);  /* pretend that `OP_FOR' starts the loop */
   luaK_patchlist(fs, endfor, prep);
   luaK_patchlist(fs, endfor, prep);
-  fs->f->lineinfo[endfor] = line;  /* pretend that `OP_FOR' starts the loop */
 }
 }
 
 
 
 
@@ -1070,6 +1072,7 @@ static void forlist (LexState *ls, TString *indexname) {
   /* forlist -> NAME {,NAME} IN explist1 DO body */
   /* forlist -> NAME {,NAME} IN explist1 DO body */
   FuncState *fs = ls->fs;
   FuncState *fs = ls->fs;
   expdesc e;
   expdesc e;
+  int line;
   int nvars = 0;
   int nvars = 0;
   int prep;
   int prep;
   int base = fs->freereg;
   int base = fs->freereg;
@@ -1081,16 +1084,19 @@ static void forlist (LexState *ls, TString *indexname) {
     next(ls);
     next(ls);
   }
   }
   check(ls, TK_IN);
   check(ls, TK_IN);
+  line = ls->linenumber;
   adjust_assign(ls, 3, explist1(ls, &e), &e);
   adjust_assign(ls, 3, explist1(ls, &e), &e);
   luaK_reserveregs(fs, nvars - 3);  /* registers for other variables */
   luaK_reserveregs(fs, nvars - 3);  /* registers for other variables */
-  luaK_codeABC(fs, OP_TFORPREP, base, 0, 0);
-  luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars - 3);
+  luaK_codeAsBx(fs, OP_TFORPREP, base, NO_JUMP);
   adjustlocalvars(ls, nvars);  /* scope for all variables */
   adjustlocalvars(ls, nvars);  /* scope for all variables */
-  prep = luaK_jump(fs);
   check(ls, TK_DO);
   check(ls, TK_DO);
+  prep = luaK_getlabel(fs);
   block(ls);
   block(ls);
-  luaK_patchlist(fs, luaK_jump(fs), prep-1);
-  luaK_patchtohere(fs, prep);
+  luaK_patchtohere(fs, prep-1);
+  removevars(fs->ls, fs->nactvar - nvars);  /* deactivate locals for next op. */
+  luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars - 3);
+  luaK_fixline(fs, line);  /* pretend that `OP_FOR' starts the loop */
+  luaK_patchlist(fs, luaK_jump(fs), prep);
 }
 }
 
 
 
 

+ 4 - 2
lvm.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lvm.c,v 1.229 2002/05/06 15:51:41 roberto Exp roberto $
+** $Id: lvm.c,v 1.230 2002/05/09 14:14:34 roberto Exp roberto $
 ** Lua virtual machine
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -548,7 +548,8 @@ StkId luaV_execute (lua_State *L) {
         L->top = ra+5;
         L->top = ra+5;
         luaD_call(L, ra+2, GETARG_C(i) + 1);
         luaD_call(L, ra+2, GETARG_C(i) + 1);
         L->top = L->ci->top;
         L->top = L->ci->top;
-        if (ttype(ra+2) != LUA_TNIL) pc++;  /* skip jump (keep looping) */
+        if (ttype(ra+2) == LUA_TNIL) pc++;  /* skip jump (break loop) */
+        else dojump(pc, GETARG_sBx(*pc) + 1);  /* else jump back */
         break;
         break;
       }
       }
       case OP_TFORPREP: {
       case OP_TFORPREP: {
@@ -557,6 +558,7 @@ StkId luaV_execute (lua_State *L) {
           setsvalue(ra, luaS_new(L, "next"));
           setsvalue(ra, luaS_new(L, "next"));
           luaV_gettable(L, gt(L), ra, ra);
           luaV_gettable(L, gt(L), ra, ra);
         }
         }
+        dojump(pc, GETARG_sBx(i));
         break;
         break;
       }
       }
       case OP_SETLIST:
       case OP_SETLIST: