[
https://issues.apache.org/jira/browse/GROOVY-6844?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18053119#comment-18053119
]
Eric Milles commented on GROOVY-6844:
-------------------------------------
https://github.com/apache/groovy/pull/2371/commits/6475e816aad2ea557014d520d8285d276460a659
> "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
> Labels: break
>
> 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:groovy}
> 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
> {code}
> 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)
> {code}
> {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)