[ 
https://issues.apache.org/jira/browse/GROOVY-6844?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16342210#comment-16342210
 ] 

Evermind commented on GROOVY-6844:
----------------------------------

After a few exploration I got the conclusion that break <label> seems only work 
for labels placed before a loop control statement i.e. for and while. If label 
is placed elsewhere, the break <label> statement just ignores <label> and break 
from current loop level.

It's astonishing nowhere mentioned this behavior in the document and other 
materials, and compiler just ignores the misplaced label without error or 
runtime exception. Even example in document doesn't work.

* mentioned document and example is in 
[http://groovy-lang.org/semantics.html|http://groovy-lang.org/semantics.html,] 
section 1.5.

> "Break label" instruction broken when combining nested loops with 
> "old-school" labeled code blocks
> --------------------------------------------------------------------------------------------------
>
>                 Key: GROOVY-6844
>                 URL: https://issues.apache.org/jira/browse/GROOVY-6844
>             Project: Groovy
>          Issue Type: Bug
>          Components: Compiler
>    Affects Versions: 2.3.2
>            Reporter: Davide Cavestro
>            Priority: Major
>
> I've seen in groovy _the break statement with named label is only allowed 
> inside loops_, in fact executing the following snippet from groovyConsole
> {code}
> foo: {
>     println "foo"
>     break foo
> }
> {code}
> I get this output {quote}
> 2 compilation errors:
> the break statement with named label is only allowed inside loops
>  at line: 5, column: 13
> break to missing label
>  at line: 5, column: 13
> {quote}
> Bu this morning a colleague of mine discovered that if you combine 
> *old-school label definition* with a *break label used within two nested 
> loops* you obtain no compile/runtime errors. Instead the executed logic is 
> not the expected one, at least not what you would expect when you write that 
> kind of code.
> It seems that the _break label_ instruction simply breaks the innermost loop 
> execution, continuing with the outer one (hence ignoring the label).
> Follows a test based on the example took from 
> http://docs.codehaus.org/display/GROOVY/JN2535-Control:
> Its output shows how the labeled code block  is *re-executed after the 
> {{break}}*
> {code:title=Foo.groovy}
> def i=0, j=0
> outer: {
>   println "executing outer block"
>   while( i<5 ){ //labelling a while loop is especially useful...
>     j= 0
>     i++
>   println "executing outer while, i: $i, j: $j"
>     while( j<5 ){
>       j++
>   println "executing inner while, i: $i, j: $j"
>       if( i==3 && j==2 ) break outer
>             //...because we can break out of a specified labelled while loop
>     }
>   }
> }
> assert i==3 && j==2
> {code}
> This is its execution output:
> {quote}
> executing outer block
> executing outer while, i: 1, j: 0
> executing inner while, i: 1, j: 1
> executing inner while, i: 1, j: 2
> executing inner while, i: 1, j: 3
> executing inner while, i: 1, j: 4
> executing inner while, i: 1, j: 5
> executing outer while, i: 2, j: 0
> executing inner while, i: 2, j: 1
> executing inner while, i: 2, j: 2
> executing inner while, i: 2, j: 3
> executing inner while, i: 2, j: 4
> executing inner while, i: 2, j: 5
> executing outer while, i: 3, j: 0
> executing inner while, i: 3, j: 1
> executing inner while, i: 3, j: 2
> executing outer while, i: 4, j: 0
> executing inner while, i: 4, j: 1
> executing inner while, i: 4, j: 2
> executing inner while, i: 4, j: 3
> executing inner while, i: 4, j: 4
> executing inner while, i: 4, j: 5
> executing outer while, i: 5, j: 0
> executing inner while, i: 5, j: 1
> executing inner while, i: 5, j: 2
> executing inner while, i: 5, j: 3
> executing inner while, i: 5, j: 4
> executing inner while, i: 5, j: 5
> Exception in thread "main" Assertion failed: 
> assert i==3 && j==2
>        ||   |
>        5|   false
>         false
>       at 
> org.codehaus.groovy.runtime.InvokerHelper.assertFailed(InvokerHelper.java:398)
>       at 
> org.codehaus.groovy.runtime.ScriptBytecodeAdapter.assertFailed(ScriptBytecodeAdapter.java:646)
>       at Bar.main(Bar.groovy:27)
> {quote}
> Follows the java counterpart, whose output shows how the labeled code block  
> is not executed after the {{break}}
> {code:title=Foo.java}
> public class Foo {
>     public static void main(String[] args) {
>         int i = 0, j = 0;
>         outer: {
>             println("executing outer block");
>             while (i < 5) { // labelling a while loop is especially useful...
>                 j = 0;
>                 i++;
>                 println("executing outer while, i: " + i + ", j: " + j);
>                 while (j < 5) {
>                     j++;
>                     println("executing inner while, i: " + i + ", j: " + j);
>                     if (i == 3 && j == 2)
>                         break outer;
>                     // ...because we can break out of a specified labelled 
> while loop
>                 }
>             }
>         }
>         assert i == 3 && j == 2;
>     }
>     static void println(String s) {
>         System.out.println(s);
>     }
> }
> {code}
> And this is its execution output {quote}executing outer block
> executing outer while, i: 1, j: 0
> executing inner while, i: 1, j: 1
> executing inner while, i: 1, j: 2
> executing inner while, i: 1, j: 3
> executing inner while, i: 1, j: 4
> executing inner while, i: 1, j: 5
> executing outer while, i: 2, j: 0
> executing inner while, i: 2, j: 1
> executing inner while, i: 2, j: 2
> executing inner while, i: 2, j: 3
> executing inner while, i: 2, j: 4
> executing inner while, i: 2, j: 5
> executing outer while, i: 3, j: 0
> executing inner while, i: 3, j: 1
> executing inner while, i: 3, j: 2
> {quote}
> (even running it with assertions enabled through the {{-ea}} switch)



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Reply via email to