You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@groovy.apache.org by Paul King <pa...@asert.com.au> on 2022/02/01 06:36:42 UTC

Re: What is proper use of `break labelid`?

Hi Fred,

I think you have discovered a potential short-coming in the compiler.
The intention is to mostly follow Java behavior.

A "break someLabel" statement should break out of an enclosed
statement having label "someLabel" (A) or the current
for/while/do/switch if no label is given (B). If an unknown label is
given, there should be a compile error (C). Currently, if the label is
known but not in the "Java correct" scope, we are getting (B) instead
of (C). So, it's not actually doing a GOTO "exit" in your example but
is exiting the "for".

int i = 5
for (int j=0; j<2; j++) { break exit }
i += 10
exit:
i += 100
assert i == 115

However, "continue exit" is actually doing a goto to "exit".

The code was written before my time, I'll have to dive in further to
work out if this is a feature or bug. The code does seem to be giving
more flexibility than what Java would do. It is probably worth
creating an issue so that we can follow through whether we have the
correct behavior. I'd recommend in the meantime following Java style,
that should give the behavior Java folks would expect with the current
implementation and would not change if we removed the current extra
flexibility.

Cheers, Paul.

On Tue, Feb 1, 2022 at 7:55 AM Fred Eisele <fr...@gmail.com> wrote:
>
> I am seeing some inconsistency in the documentation for use of breaking to labels.
>
> This indicates that groovy works similar to fortran, goto label.
> https://groovy-lang.org/semantics.html#_labeled_statements
>
> for (int j=0;j<i;j++) {
>    println "j=$j"
>    if (j == 5) { break exit }
> }
> exit: println "i=$i"
>
>
> In other places it sounds more like java.
> https://stackoverflow.com/questions/6126702/java-groovy-double-for-statement-question
>
> outerLoop:
> for (...) {
>     for (...) {
>         if (...) {
>             break outerLoop;
>         }
>     }
> }

Fwd: What is proper use of `break labelid`?

Posted by Fred Eisele <fr...@gmail.com>.
Thanks for the clarification.
The following is a sample to illustrate your points.
(sorry about the previous premature incomplete post)

```groovy
for (int x=1;x<7;x++) {
  println "x = $x"
  before: do {
    println('before')
  } while(false)

  println('between_1')
  during: do {
     println('during')
     switch(x) {
       //case 1: break before
       case 2: break during
       //case 3: break after
       //case 4: continue before
       //case 5: continue during
       //case 6: continue after
     }
  } while (false)

  println('between_2')
  after: do {
     println('after')
  } while (false)
}
```
Which is roughly the same as the following psuedo groovy (scopes and blocks
replaced with goto).
```psuedo_groovy
for (int x=1;x<7;x++) {
  println "x = $x"
  before_continue:
    println('before')
  before_break:

  println('between_1')
  during_continue:
     println('during')
     switch(x) {
       //case 1: goto before_break
       case 2: goto during_break
       //case 3: goto after_break
       //case 4: goto before_continue
       //case 5: goto during_continue
       //case 6: goto after_continue
     }
  during_break:

  println('between_2')
  after_continue:
     println('after')
  after_break:
}
```

Re: What is proper use of `break labelid`?

Posted by Fred Eisele <fr...@gmail.com>.
Thanks for the clarification.
The following

```groovy
def trial(x) {
  before: {statement_1
  }
  during: {
    statement_2
  }
  after: {
    statement_3
  }
}
```

Re: What is proper use of `break labelid`?

Posted by Jochen Theodorou <bl...@gmx.org>.
On 01.02.22 07:36, Paul King wrote:
> Hi Fred,
>
> I think you have discovered a potential short-coming in the compiler.
> The intention is to mostly follow Java behavior.

mostly, yes

> A "break someLabel" statement should break out of an enclosed
> statement having label "someLabel" (A) or the current
> for/while/do/switch if no label is given (B). If an unknown label is
> given, there should be a compile error (C). Currently, if the label is
> known but not in the "Java correct" scope, we are getting (B) instead
> of (C). So, it's not actually doing a GOTO "exit" in your example but
> is exiting the "for".
>
> int i = 5
> for (int j=0; j<2; j++) { break exit }
> i += 10
> exit:
> i += 100
> assert i == 115

I do not fully recall what I thought back then how this was supposed to
be useful. As a "break the loop and then goto the given label" it sound
too complicated for anyone who is not used to old programming languages.
Plus the concept is somewhat foreign in itself - to Java. Plus (again)
it is not even working like that!

> However, "continue exit" is actually doing a goto to "exit".

Now this was actually intentionally

> The code was written before my time, I'll have to dive in further to
> work out if this is a feature or bug.

First might be a "bug", second a feature... but none we advertised.

A loop consists basically (simplified too) of a loop-start, loop-body
and loop-end. loop-start or end may contain a condition and based on the
condition you jump to the body or to after the loop-end in the bytecode.
This allows the implementation of do-while, while and for-loops.
Now a break (without label) is a jump "out" of the loop, which means to
after the loop-end. And a continue (without label) is a jump to the
loop-condition in either loop-end or loop-start.
With label a break is to do the same, just that it allows to jump from a
nested to an outer loop-end. Similar for continue.

Since in bytecode this is all flat and scopes do not exist in the same
way, break and continue are actually goto instructions there (in Java too).

So I think the idea back then was to allow at least the continue to work
as a kind of goto. Actually it was the result of the implementation back
then, so idea is maybe too much. I wanted to discuss it, but nobody was
interested in discussing, thus the implementation stayed as is. I do not
remember that part of the code so clearly right now - so not sure if
there is potential for simplification - but to be more like Java, some
checks would have to be added mostly.

bye Jochen