http://www.perlmonks.org?node_id=1013695


in reply to How does 'goto LABEL' search for its label?

I believe it is a rather simple search up the call stack. And all of your examples agree with that. Don't confuse that with searching up a "stack" of nested (or even prior) lexical blocks.

A 'goto' is visible inside of the bounds of the dynamic scope where it lives. The two things that most clearly define a dynamic scope are: sub, eval. This certainly includes the subs that you can define without using the 'sub' keyword by passing a block to a sub with a prototype that starts with a '&' character. It is less clear how similar the separation is for similar scopes that can be built in a lot of places in Perl, including: map, grep, s///e, sort.

So apparently, the construct containing the label has to have been executed once.

Not true. The construct just mustn't be optimized away as happens when you give an 'if' statement an expression that is known to be false at compile time.

$ perl -wE 'sub g() { label: say "here" }; g; goto label' here Can't find label label at -e line 1.

Of course. g() has already returned by the time you execute "goto label", so the contents of g()'s dynamic scope are not present further up the call stack, so Perl can't find the "label:".

As for there being a new warning for "if(1){X:...} goto X:", I lack the details for why this got deprecated. It seems to go rather farther than any prior restrictions and seems likely to run afoul of rather typical "use of 'goto' for error handling" that I've seen (though not frequently):

... if( ... ) { goto ERR; } ... if( $fatal ) { ERR: ... clean up after fatal error ... }

- tye        

Replies are listed 'Best First'.
Re^2: How does 'goto LABEL' search for its label? (call stack)
by moritz (Cardinal) on Jan 17, 2013 at 17:41 UTC

    Thanks tye, your reply did clear up a few things.

    I had two problems with my mental model. I didn't remember that that if (0) { } gets optimized away. I also wrongly assumed that each block produces a stack frame.

    As for there being a new warning for "if(1){X:...} goto X:", I lack the details for why this got deprecated.

    I didn't find many details either, just that without it, the implementation of lexpads would be much simpler and saner.

    Now I must go back and study the crufty error handling code I inherited, and see if it can be rescued (or if I can safely argue that it must be rewritten to use something saner).

      just that without it, the implementation of lexpads would be much simpler and saner.

      Yeah, that would have been my best guess. I'm curious about how "much" simplification we are talking about. But I'll go digging in the p5p archives for more details if I find the time and motivation. :)

      I wonder if the complications could be avoided by having behavior closer to this pseudo-Perl code:

      if( $fatal ) ERR: { ... }

      So that the destination for "goto ERR;" would be the start of the lexical block instead of the first line in the lexical block.

      It would be nice if a label pointing to the first line of a lexical block could just be moved to point to the start of the lexical block, avoiding the complexity and the need for deprecation. That is:

      if( $fatal ) { OK: ... no need to deprecate this ... } if( $fatal ) { my $foo; BAD: ... "goto BAD" from outside this block deprecated ... }

      But, if one ends up using a Perl that has the deprecation but doesn't implement my idea, then it should often be relatively easy to rewrite the code to be more like:

      ... if( $whatever ) { goto ERR; } ... if( $fatal ) { # Used to be "ERR:" here goto ERR; } return ...; ERR: ... code moved from if( $fatal ) ...

      - tye        

Re^2: How does 'goto LABEL' search for its label? (do-blocks)
by LanX (Saint) on Jan 17, 2013 at 18:50 UTC
    > As for there being a new warning for if(1){X:...} goto X:, I lack the details for why this got deprecated.

    It's analogous to if(0) the constant block is optimized to a do-block¹ ...

    > perl -MO=Deparse -E'if (1) { label: say 1;}; goto label' BEGIN { $^H{'feature_say'} = q(1); $^H{'feature_state'} = q(1); $^H{'feature_switch'} = q(1); } do { label: say 1 }; goto label;

    ... which seems to fall into the same category like other loop-like-blocks:

    ATM I have only 5.10 available. Could someone please test this with >= 5.12?

    perl -wE'do { label: say 1;}; goto label'

    EDIT: removed exit

    Update

    here test code w/o endless looping.

    perl -wE'my $x=0;do { label: say $x++; die if $x>1}; goto label' 0 1 Died at -e line 1.

    Update

    Thanks to davido for testing

    [davido]: LanX: perl -E 'goto IN; do{ IN: say "Hello world\n";};' does + produce the warning on 5.16.2.

    Cheers Rolf

    ¹) which is somehow strange, I expected a simple bare block.