  lua-l archive

• Subject: RE: Re: why no "continue" statement for loops?
• From: "Bilyk, Alex" <ABilyk@...>
• Date: Wed, 18 Jun 2003 14:45:48 -0700

```Very neat and practical idea, IMHO! I miss "break N" on occasion in C++. I don't ever remember wanting "continue N" but for the sake of consistency it would fly for me.

Alex

-----Original Message-----
From: 	lb@get.it.pl [mailto:lb@get.it.pl]
Sent:	Wednesday, June 18, 2003 1:28 AM
To:	Lua list
Subject:	Re: why no "continue" statement for loops?

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'

```