Explorar o código

simpler implementation of for loops

Roberto Ierusalimschy %!s(int64=24) %!d(string=hai) anos
pai
achega
3b6f8bfbe6
Modificáronse 4 ficheiros con 29 adicións e 29 borrados
  1. 12 1
      lcode.c
  2. 2 1
      lcode.h
  3. 2 2
      lparser.c
  4. 13 25
      lvm.c

+ 12 - 1
lcode.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.c,v 1.57 2001/01/19 13:20:30 roberto Exp roberto $
+** $Id: lcode.c,v 1.58 2001/01/29 13:14:49 roberto Exp roberto $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -59,6 +59,17 @@ static void luaK_fixjump (FuncState *fs, int pc, int dest) {
 }
 
 
+/*
+** prep-for instructions (OP_FORPREP & OP_LFORPREP) have a negated jump,
+** as they simulate the real jump...
+*/
+void luaK_fixfor (FuncState *fs, int pc, int dest) {
+  Instruction *jmp = &fs->f->code[pc];
+  int offset = dest-(pc+1);
+  SETARG_S(*jmp, -offset);
+}
+
+
 static int luaK_getjump (FuncState *fs, int pc) {
   int offset = GETARG_S(fs->f->code[pc]);
   if (offset == NO_JUMP)  /* point to itself represents end of list */

+ 2 - 1
lcode.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.h,v 1.17 2000/11/30 18:50:47 roberto Exp roberto $
+** $Id: lcode.h,v 1.18 2000/12/04 18:33:40 roberto Exp roberto $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -53,6 +53,7 @@ int luaK_code1 (FuncState *fs, OpCode o, int arg1);
 int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2);
 int luaK_jump (FuncState *fs);
 void luaK_patchlist (FuncState *fs, int list, int target);
+void luaK_fixfor (FuncState *fs, int pc, int dest);
 void luaK_concat (FuncState *fs, int *l1, int l2);
 void luaK_goiftrue (FuncState *fs, expdesc *v, int keepvalue);
 int luaK_getlabel (FuncState *fs);

+ 2 - 2
lparser.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 1.125 2001/01/19 13:20:30 roberto Exp roberto $
+** $Id: lparser.c,v 1.126 2001/01/29 13:14:49 roberto Exp roberto $
 ** LL(1) Parser and code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -854,7 +854,7 @@ static void forbody (LexState *ls, int nvar, OpCode prepfor, OpCode loopfor) {
   adjustlocalvars(ls, nvar);  /* scope for control variables */
   block(ls);
   luaK_patchlist(fs, luaK_code1(fs, loopfor, NO_JUMP), blockinit);
-  luaK_patchlist(fs, prep, luaK_getlabel(fs));
+  luaK_fixfor(fs, prep, luaK_getlabel(fs));
   removelocalvars(ls, nvar);
 }
 

+ 13 - 25
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 1.158 2001/01/26 18:43:22 roberto Exp roberto $
+** $Id: lvm.c,v 1.159 2001/01/29 13:02:20 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -330,7 +330,7 @@ static void adjust_varargs (lua_State *L, StkId base, int nfixargs) {
 
 
 
-#define dojump(pc, i)	{ int d = GETARG_S(i); pc += d; }
+#define dojump(pc, i)	((pc) += GETARG_S(i))
 
 /*
 ** Executes the given Lua function. Parameters are between [base,top).
@@ -615,19 +615,15 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
         break;
       }
       case OP_FORPREP: {
+        int jmp = GETARG_S(i);
         if (tonumber(top-1))
           luaD_error(L, "`for' step must be a number");
         if (tonumber(top-2))
           luaD_error(L, "`for' limit must be a number");
         if (tonumber(top-3))
           luaD_error(L, "`for' initial value must be a number");
-        if (nvalue(top-1) > 0 ?
-            nvalue(top-3) > nvalue(top-2) :
-            nvalue(top-3) < nvalue(top-2)) {  /* `empty' loop? */
-          top -= 3;  /* remove control variables */
-          dojump(pc, i);  /* jump to loop end */
-        }
-        break;
+        pc += -jmp;  /* "jump" to loop end (delta is negated here) */
+        goto forloop;  /* do not increment index */
       }
       case OP_FORLOOP: {
         lua_assert(ttype(top-1) == LUA_TNUMBER);
@@ -635,6 +631,7 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
         if (ttype(top-3) != LUA_TNUMBER)
           luaD_error(L, "`for' index must be a number");
         nvalue(top-3) += nvalue(top-1);  /* increment index */
+      forloop:
         if (nvalue(top-1) > 0 ?
             nvalue(top-3) > nvalue(top-2) :
             nvalue(top-3) < nvalue(top-2))
@@ -644,24 +641,15 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
         break;
       }
       case OP_LFORPREP: {
-        int n;
-        Hash *t;
+        int jmp = GETARG_S(i);
         if (ttype(top-1) != LUA_TTABLE)
           luaD_error(L, "`for' table must be a table");
-        t = hvalue(top-1);
-        n = luaH_nexti(t, -1);
-        if (n == -1) {  /* `empty' loop? */
-          top--;  /* remove table */
-          dojump(pc, i);  /* jump to loop end */
-        }
-        else {
-          Node *node = node(t, n);
-          top += 3;  /* index,key,value */
-          setnvalue(top-3, n);  /* index */
-          setobj(top-2, key(node));
-          setobj(top-1, val(node));
-        }
-        break;
+        top += 3;  /* index,key,value */
+        setnvalue(top-3, -1);  /* initial index */
+        setnilvalue(top-2);
+        setnilvalue(top-1);
+        pc += -jmp;  /* "jump" to loop end (delta is negated here) */
+        /* go through */
       }
       case OP_LFORLOOP: {
         Hash *t = hvalue(top-4);