>> - NEXT doesn't work inside SWITCH:
>>
>> http://www.template-toolkit.org/pipermail/templates/2001-June/001035.html
>>
>> I can test and send a patch if you want.
>
> Yes please.
Ok. FOREACH and WHILE now get a LOOP: label, and NEXT and LAST
now generate "next LOOP;" and "last LOOP;". However, the original
code allows naked "NEXT" or "LAST" (which behave like STOP). I
didn't want to change this behavior, so NEXT and LAST only get
the LOOP label inside loops (except in the top-level atomexpr FOREACH
and atomexpr WHILE cases, which should be ok).
Patches to Template/Directive.pm and parser/Parser.yp, as well
as additions to t/foreach.t and t/while.t are attached.
By the way, I came across another arcane bug:
NEXT FOREACH k = [1];
is legal syntax but is an infinite loop, since $_[0]->{ INFOR } in
Parser.yp is not set when the NEXT is parsed, so it generates a
plain "next;" rather than calling $factor->next(). I don't see
an easy, clean fix.
Regards,
Craig
--- virgin/Template-Toolkit-2.03a/lib/Template/Directive.pm Fri Jun 15 06:51:55
2001
+++ Template-Toolkit-2.03a/lib/Template/Directive.pm Thu Jun 21 23:04:26 2001
@@ -417,7 +417,7 @@
$loop_save;
\$stash->set('loop', \$list);
eval {
- while (! \$error) {
+LOOP: while (! \$error) {
$loop_set;
$block;
(\$value, \$error) = \$list->get_next();
@@ -440,7 +440,7 @@
sub next {
return <<EOF;
(\$value, \$error) = \$list->get_next();
-next;
+next LOOP;
EOF
}
@@ -518,6 +518,7 @@
# WHILE
do {
my \$failsafe = $WHILE_MAX;
+LOOP:
while (--\$failsafe && ($expr)) {
$block
}
@@ -699,7 +700,7 @@
#------------------------------------------------------------------------
sub break {
- return 'last;';
+ return 'last LOOP;';
}
#------------------------------------------------------------------------
--- virgin/Template-Toolkit-2.03a/parser/Parser.yp Thu Jun 14 06:20:12 2001
+++ Template-Toolkit-2.03a/parser/Parser.yp Thu Jun 21 23:28:51 2001
@@ -119,10 +119,14 @@
| RETURN { $factory->return() }
| STOP { $factory->stop() }
| CLEAR { "\$output = '';"; }
- | LAST { 'last;' }
+ | LAST { $_[0]->{ INFOR } || $_[0]->{ INWHILE }
+ ? 'last LOOP;'
+ : 'last;' }
| NEXT { $_[0]->{ INFOR }
? $factory->next()
- : 'next;' }
+ : ($_[0]->{ INWHILE }
+ ? 'next LOOP;'
+ : 'next;') }
| wrapper
| filter
;
@@ -160,8 +164,9 @@
#loop: FOR loopvar ';'
# block END { $factory->foreach(@{$_[2]}, $_[4]) }
| atomexpr FOR loopvar { $factory->foreach(@{$_[3]}, $_[1]) }
- | WHILE expr ';'
- block END { $factory->while(@_[2, 4]) }
+ | WHILE expr ';' { $_[0]->{ INWHILE }++ }
+ block END { $_[0]->{ INWHILE }--;
+ $factory->while(@_[2, 5]) }
| atomexpr WHILE expr { $factory->while(@_[3, 1]) }
;
--- virgin/Template-Toolkit-2.03a/t/foreach.t Fri Jun 15 07:30:56 2001
+++ Template-Toolkit-2.03a/t/foreach.t Thu Jun 21 23:47:02 2001
@@ -535,7 +535,77 @@
* 1
* 2
* 3
-
-
-
-
+-- test --
+[%
+ FOREACH i = [1 .. 10];
+ SWITCH i;
+ CASE 5;
+ NEXT;
+ CASE 8;
+ LAST;
+ END;
+ "$i\n";
+ END;
+-%]
+-- expect --
+1
+2
+3
+4
+6
+7
+-- test --
+[%
+ FOREACH i = [1 .. 10];
+ IF 1;
+ IF i == 5; NEXT; END;
+ IF i == 8; LAST; END;
+ END;
+ "$i\n";
+ END;
+-%]
+-- expect --
+1
+2
+3
+4
+6
+7
+-- test --
+[%
+ FOREACH i = [1 .. 4];
+ FOREACH j = [1 .. 4];
+ k = 1;
+ SWITCH j;
+ CASE 2;
+ LAST FOREACH k = [ 1 .. 2 ];
+ CASE 3;
+ NEXT IF j == 3;
+ END;
+ "$i,$j,$k\n";
+ END;
+ END;
+-%]
+-- expect --
+1,1,1
+1,2,1
+1,4,1
+2,1,1
+2,2,1
+2,4,1
+3,1,1
+3,2,1
+3,4,1
+4,1,1
+4,2,1
+4,4,1
+-- test --
+[%
+ LAST FOREACH k = [ 1 .. 4];
+ "$k\n";
+ # Should finish loop with k = 4. Instead this is an infinite loop!!
+ #NEXT FOREACH k = [ 1 .. 4];
+ #"$k\n";
+-%]
+-- expect --
+1
--- virgin/Template-Toolkit-2.03a/t/while.t Tue Sep 12 08:25:25 2000
+++ Template-Toolkit-2.03a/t/while.t Thu Jun 21 23:48:31 2001
@@ -127,3 +127,84 @@
Reset list
* x-ray
* zulu
+-- test --
+[%
+ i = 1;
+ WHILE i <= 10;
+ SWITCH i;
+ CASE 5;
+ i = i + 1;
+ NEXT;
+ CASE 8;
+ LAST;
+ END;
+ "$i\n";
+ i = i + 1;
+ END;
+-%]
+-- expect --
+1
+2
+3
+4
+6
+7
+-- test --
+[%
+ i = 1;
+ WHILE i <= 10;
+ IF 1;
+ IF i == 5; i = i + 1; NEXT; END;
+ IF i == 8; LAST; END;
+ END;
+ "$i\n";
+ i = i + 1;
+ END;
+-%]
+-- expect --
+1
+2
+3
+4
+6
+7
+-- test --
+[%
+ i = 1;
+ WHILE i <= 4;
+ j = 1;
+ WHILE j <= 4;
+ k = 1;
+ SWITCH j;
+ CASE 2;
+ LAST WHILE k == 1;
+ CASE 3;
+ IF j == 3; j = j + 1; NEXT; END;
+ END;
+ "$i,$j,$k\n";
+ j = j + 1;
+ END;
+ i = i + 1;
+ END;
+-%]
+-- expect --
+1,1,1
+1,2,1
+1,4,1
+2,1,1
+2,2,1
+2,4,1
+3,1,1
+3,2,1
+3,4,1
+4,1,1
+4,2,1
+4,4,1
+-- test --
+[%
+ k = 1;
+ LAST WHILE k == 1;
+ "$k\n";
+-%]
+-- expect --
+1