>>   - 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


Reply via email to