lua-users home
lua-l archive

[patch] continue statement

[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 */

AltStyle によって変換されたページ (->オリジナル) /