[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re[2]: why no "continue" statement for loops?
- From: lb@...
- Date: Wed, 18 Jun 2003 10:28:29 +0200
Programming would be sometimes easier if it was a possibility to break
or continue any of a few nested loops. For example:
a = 0
while a < 10 do
a = a + 1
if a == 5 then continue end
b = 0
while b < 10 do
b = b + 1
if b == 5 then continue end
if a == 9 and b == 9 then
break 2 -- break the `while a < 10' loop
end
if a == b then
continue 2 -- next iteration of the `while a < 10' loop
end
print(a, b)
end
end
Here is a patch to lparser.c:
/* put this at the beginning of the file */
#include <math.h>
#define LUA_MAXBREAKLEVEL 100
/* ... */
/* replace `breakstat' (and `continuestat' if you have it) functions with the following
code */
static void breakstat (LexState *ls) {
/* stat -> BREAK [loop number] */
FuncState *fs = ls->fs;
BlockCnt *bl = fs->bl;
int upval = 0;
int levels = 1;
next(ls); /* skip BREAK */
if (testnext(ls, TK_NUMBER)) {
if (ls->t.seminfo.r != floor(ls->t.seminfo.r))
luaX_syntaxerror(ls, "loop block number must be integer");
levels = (int) ls->t.seminfo.r;
if (levels < 1 || levels > LUA_MAXBREAKLEVEL)
luaX_syntaxerror(ls, "loop block number out of range");
}
while (levels-- > 0) {
while (bl && !bl->isbreakable) {
upval |= bl->upval;
bl = bl->previous;
}
if (bl && levels > 0)
bl = bl->previous;
}
if (!bl)
luaX_syntaxerror(ls, "no loop to break");
if (upval)
luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
}
static void continuestat (LexState *ls) {
/* stat -> CONTINUE [loop number] */
FuncState *fs = ls->fs;
BlockCnt *bl = fs->bl;
int levels = 1;
next(ls); /* skip CONTINUE */
if (testnext(ls, TK_NUMBER)) {
if (ls->t.seminfo.r != floor(ls->t.seminfo.r))
luaX_syntaxerror(ls, "loop block number must be integer");
levels = (int) ls->t.seminfo.r;
if (levels < 1 || levels > LUA_MAXBREAKLEVEL)
luaX_syntaxerror(ls, "loop block number out of range");
}
while (levels-- > 0) {
while (bl && !bl->isbreakable)
bl = bl->previous;
if (bl && levels > 0)
bl = bl->previous;
}
if (!bl)
luaX_syntaxerror(ls, "no loop to continue");
luaK_concat(fs, &bl->continuelist, luaK_jump(fs));
}
And here is test code:
--
-- `break N' and `continue N' statement test
--
for i = 1, 5 do
for j = 1, 6 do
if j == 1 then continue end
if j == 5 then continue 2 end
if i == 4 and j == 4 then break 2 end
print(i, j)
end
end
print(loadstring("for i = 1, 2 do for j = 1, 2 do break 2.00001 end end"))
print(loadstring("for i = 1, 2 do break 2 end"))
--
-- the result is:
--
-- 1 2
-- 1 3
-- 1 4
-- 2 2
-- 2 3
-- 2 4
-- 3 2
-- 3 3
-- 3 4
-- 4 2
-- 4 3
-- nil [string "for i = 1, 2 do for j = 1, 2 do break 2.00001 end end"]:1: loop block number must be integer near `end'
-- nil [string "for i = 1, 2 do break 2 end"]:1: no loop to break near `end'