lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hi all,

I find that without a "continue" statement some loops soon have
deeply nested if/else statements in them.  This patch adds
them to Lua 5.1-alpha.  It's also on the PowerPatches page of
the Lua wiki.

HTH,
Wolfgang Oertl

diff -ru lua-5.1-alpha-orig/src/llex.c lua-5.1-alpha/src/llex.c
--- lua-5.1-alpha-orig/src/llex.c	2005-05-17 21:49:15.000000000 +0200
+++ lua-5.1-alpha/src/llex.c	2005-09-11 01:02:58.000000000 +0200
@@ -33,7 +33,7 @@
 
 /* ORDER RESERVED */
 const char *const luaX_tokens [] = {
-    "and", "break", "do", "else", "elseif",
+    "and", "break", "continue", "do", "else", "elseif",
     "end", "false", "for", "function", "if",
     "in", "local", "nil", "not", "or", "repeat",
     "return", "then", "true", "until", "while",
diff -ru lua-5.1-alpha-orig/src/llex.h lua-5.1-alpha/src/llex.h
--- lua-5.1-alpha-orig/src/llex.h	2005-06-06 15:30:25.000000000 +0200
+++ lua-5.1-alpha/src/llex.h	2005-09-11 01:03:08.000000000 +0200
@@ -23,7 +23,7 @@
 */
 enum RESERVED {
   /* terminal symbols denoted by reserved words */
-  TK_AND = FIRST_RESERVED, TK_BREAK,
+  TK_AND = FIRST_RESERVED, TK_BREAK, TK_CONTINUE,
   TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,
   TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
   TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
diff -ru lua-5.1-alpha-orig/src/lparser.c lua-5.1-alpha/src/lparser.c
--- lua-5.1-alpha-orig/src/lparser.c	2005-08-29 22:49:21.000000000 +0200
+++ lua-5.1-alpha/src/lparser.c	2005-09-11 02:27:37.000000000 +0200
@@ -40,6 +40,7 @@
 typedef struct BlockCnt {
   struct BlockCnt *previous;  /* chain */
   int breaklist;  /* list of jumps out of this loop */
+  int continuelist;  /* list of jumps to the loop's test */
   lu_byte nactvar;  /* # active locals outside the breakable structure */
   lu_byte upval;  /* true if some variable in the block is an upvalue */
   lu_byte isbreakable;  /* true if `block' is a loop */
@@ -302,6 +303,7 @@
 
 static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) {
   bl->breaklist = NO_JUMP;
+  bl->continuelist = NO_JUMP;
   bl->isbreakable = isbreakable;
   bl->nactvar = fs->nactvar;
   bl->upval = 0;
@@ -1015,6 +1017,7 @@
   checknext(ls, TK_DO);
   block(ls);
   luaK_patchlist(fs, luaK_jump(fs), whileinit);
+  luaK_patchlist(fs, bl.continuelist, whileinit);  /* continue goes to start, too */
   check_match(ls, TK_END, TK_WHILE, line);
   leaveblock(fs);
   luaK_patchtohere(fs, condexit);  /* false conditions finish the loop */
@@ -1031,6 +1034,7 @@
   enterblock(fs, &bl2, 0);  /* scope block */
   next(ls);  /* skip REPEAT */
   chunk(ls);
+  luaK_patchtohere(fs, bl1.continuelist);
   check_match(ls, TK_UNTIL, TK_REPEAT, line);
   condexit = cond(ls);  /* read condition (inside scope block) */
   if (!bl2.upval) {  /* no upvalues? */
@@ -1071,6 +1075,7 @@
   block(ls);
   leaveblock(fs);  /* end of scope for declared variables */
   luaK_patchtohere(fs, prep);
+  luaK_patchtohere(fs, bl.previous->continuelist);	/* continue, if any, jumps to here */
   endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) :
                      luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars);
   luaK_fixline(fs, line);  /* pretend that `OP_FOR' starts the loop */
@@ -1281,6 +1286,17 @@
   luaK_ret(fs, first, nret);
 }
 
+static void continuestat(LexState *ls) {
+  /* stat -> CONTINUE */
+  FuncState *fs = ls->fs;
+  BlockCnt *bl = fs->bl;
+  next(ls);   /* skip CONTINUE */
+  while (bl && !bl->isbreakable)
+    bl = bl->previous;
+  if (!bl)
+    luaX_syntaxerror(ls, "no loop to continue");
+  luaK_concat(fs, &bl->continuelist, luaK_jump(fs));
+}
 
 static int statement (LexState *ls) {
   int line = ls->linenumber;  /* may be needed for error messages */
@@ -1328,6 +1344,10 @@
       breakstat(ls);
       return 1;  /* must be last statement */
     }
+    case TK_CONTINUE: {  /* stat -> continuestat */
+      continuestat(ls);
+      return 1;	  /* must be last statement */
+    }
     default: {
       exprstat(ls);
       return 0;  /* to avoid warnings */