Skip Menu |

This queue is for tickets about the Syntax-Keyword-Try CPAN distribution.

Report information
The Basics
Id: 123040
Status: resolved
Priority: 0/
Queue: Syntax-Keyword-Try

People
Owner: leonerd-cpan [...] leonerd.org.uk
Requestors: simcop [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: 0.07
Fixed in: 0.08



Subject: Bug with redo/next/last
Example at: https://perlbot.pl/p/8pp2ky The error isn't immediately clear what the problem is (without knowing perl internals) and the caveat that it doesn't work isn't documented with the module. Enclosing the use of next/redo/last inside a do{} block works around the issue. Show quoted text
--- Error --- ARGH: Unsure how to handle OP_(NEXT|LAST|REDO) with a sibling at (IRC) line 30.
--- Code below --- use v5.26; use Syntax::Keyword::Try; # This loop works. for my $i (1..10) { try { say "$i, 1"; do {next}; say "$i, 2"; } catch { say "$i, 3"; } finally { say "$i, 4"; } say "$i, 5"; } # This loop doesn't work. for my $i (1..10) { try { say "$i, 1"; next; say "$i, 2"; } catch { say "$i, 3"; } finally { say "$i, 4"; } say "$i, 5"; }
A test case with an unconditional 'next' doesn't really convey a reasonable example, but one that is interesting is one that looks conditional in source code, but becomes unconditional due to constant folding, for example: use constant {debug => 1}; use Syntax::Keyword::Try; # try can apply loop controls for my $i (1..10) { try { say "foo"; last if debug; say "foo"; } catch { say "foo"} finally {say "foo"} } -- Paul Evans
Patch attached. -- Paul Evans
Subject: rt123040.patch
=== modified file 'lib/Syntax/Keyword/Try.xs' --- lib/Syntax/Keyword/Try.xs 2017-08-13 22:10:09 +0000 +++ lib/Syntax/Keyword/Try.xs 2017-09-14 12:20:54 +0000 @@ -279,10 +279,7 @@ case OP_LAST: case OP_REDO: { - OP *stateop; - - if(OpSIBLING(op)) - croak("ARGH: Unsure how to handle OP_(NEXT|LAST|REDO) with a sibling"); + OP *stateop, *afterop = OpSIBLING(op); *op_ptr = newLISTOP(OP_SCOPE, 0, stateop = newSTATEOP_nowarnings(), @@ -290,6 +287,9 @@ (*op_ptr)->op_next = stateop; stateop->op_next = op; + if(afterop) { + OpMORESIB_set(*op_ptr, afterop); + } } break; === modified file 't/11loop.t' --- t/11loop.t 2016-11-24 09:30:23 +0000 +++ t/11loop.t 2017-09-14 12:20:54 +0000 @@ -21,10 +21,12 @@ is( $count, 2, 'try{redo} works' ); $count = 0; + my $after = 0; LOOP2: { try { last LOOP2; + $after++; # just to put a statement after 'last' } catch { } $count++;
On Thu Sep 14 08:21:34 2017, PEVANS wrote: Show quoted text
> Patch attached.
Oops. That double-freed on perl 5.14/5.16. Updated attached that passes on everything 5.14 -> 5.26. -- Paul Evans
Subject: rt123040-a2.patch
=== modified file 'lib/Syntax/Keyword/Try.xs' --- lib/Syntax/Keyword/Try.xs 2017-08-13 22:10:09 +0000 +++ lib/Syntax/Keyword/Try.xs 2017-09-14 12:30:42 +0000 @@ -279,10 +279,7 @@ case OP_LAST: case OP_REDO: { - OP *stateop; - - if(OpSIBLING(op)) - croak("ARGH: Unsure how to handle OP_(NEXT|LAST|REDO) with a sibling"); + OP *stateop, *afterop = OpSIBLING(op); *op_ptr = newLISTOP(OP_SCOPE, 0, stateop = newSTATEOP_nowarnings(), @@ -290,6 +287,10 @@ (*op_ptr)->op_next = stateop; stateop->op_next = op; + if(afterop) { + OpMORESIB_set(op, NULL); + OpMORESIB_set(*op_ptr, afterop); + } } break; === modified file 't/11loop.t' --- t/11loop.t 2016-11-24 09:30:23 +0000 +++ t/11loop.t 2017-09-14 11:36:57 +0000 @@ -21,10 +21,12 @@ is( $count, 2, 'try{redo} works' ); $count = 0; + my $after = 0; LOOP2: { try { last LOOP2; + $after++; # just to put a statement after 'last' } catch { } $count++;
Was fixed by 0.08 -- Paul Evans