[ 
https://issues.apache.org/jira/browse/GROOVY-6844?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Eric Milles reassigned GROOVY-6844:
-----------------------------------

    Assignee: Eric Milles

> "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
>            Assignee: Eric Milles
>            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}
> But 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
(v8.20.10#820010)

Reply via email to