[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: [patch] continue statement
- From: Wolfgang Oertl <wolfgang.oertl@...>
- Date: Mon, 12 Sep 2005 18:47:34 +0200
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 */