Skip Menu |

This queue is for tickets about the Lexical-Types CPAN distribution.

Report information
The Basics
Id: 100202
Status: resolved
Priority: 0/
Queue: Lexical-Types

People
Owner: Nobody in particular
Requestors: 'spro^^*%*^6ut# [...] &$%*c
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: (no value)
Fixed in: 0.14



Subject: [PATCH] Fix for 5.21.6-to-be
Given my Int ($x, ($y, $z), $t) = ("x", "y"); In 5.20.1 it parses as: 6 <;> nextstate(main 2 -e:1) v:{ ->7 e <2> aassign[t5] vKS ->f - <1> ex-list lKP ->a 7 <0> pushmark s ->8 8 <$> const(PV "x") s ->9 9 <$> const(PV "y") s ->a - <1> ex-list lKPRM* ->e a <0> padrange[$x:2,3] lRM/LVINTRO,1 ->b - <0> padsv[$x:2,3] lRM*/LVINTRO ->b c <@> list lKPRM* ->d b <0> padrange[$y:2,3; $z:2,3] lRM/LVINTRO,2 ->c - <0> padsv[$y:2,3] lRM*/LVINTRO ->- - <0> padsv[$z:2,3] lRM*/LVINTRO ->c d <0> padsv[$t:2,3] lRM*/LVINTRO ->e In 5.21.6-to-be: 6 <;> nextstate(main 3 -e:1) v:{ ->7 b <2> aassign[t5] vKS ->c - <1> ex-list lKP ->a 7 <0> pushmark s ->8 8 <$> const[PV "x"] s ->9 9 <$> const[PV "y"] s ->a - <1> ex-list lKPRM* ->b a <0> padrange[$x:3,4; $y:3,4; $z:3,4; $t:3,4] lRM/LVINTRO,4 ->b - <0> padsv[$x:3,4] lRM*/LVINTRO ->- - <1> ex-list lKPRM* ->- - <0> ex-pushmark sRM*/LVINTRO ->- - <0> padsv[$y:3,4] lRM*/LVINTRO ->- - <0> padsv[$z:3,4] lRM*/LVINTRO ->- - <0> padsv[$t:3,4] lRM*/LVINTRO ->- The inner list is optimised away, but still visible in the op tree. Also, I noticed that this comment in Types.xs is wrong: /* In a padrange sequence, either all lexicals are typed, or none are. * Thus we can stop at the first padsv op. However, note that these * lexicals can need to call different methods in different packages. */ $ perl5.20.1 -MO=Concise -e '(my main $a, my $b, my main $c) = ()' 6 <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v:{ ->3 5 <2> aassign[t4] vKS ->6 - <1> ex-list lK ->4 3 <0> pushmark s ->4 - <0> stub lP ->- - <1> ex-list lKPRM* ->5 4 <0> padrange[$a:1,2; $b:1,2; $c:1,2] lRM/LVINTRO,3 ->5 - <0> padsv[$a:1,2] lRM*/LVINTRO ->- - <0> padsv[$b:1,2] lRM*/LVINTRO ->- - <0> padsv[$c:1,2] lRM*/LVINTRO ->- -e syntax OK I don’t know whether that has any bearing on the correctness of the code, but I suspect there is a bug. The attached patch gets all the tests passing, but I don’t know whether I caught everything. Note that there are cases where the sibling of the padrange is actually a null op: $ ./perl -ILib -MO=Concise -e '@a[my $x, my $y, my $z]' 7 <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v:{ ->3 6 <@> aslice vK ->7 3 <0> padrange[$x:1,2; $y:1,2; $z:1,2] l/LVINTRO,3 ->4 - <1> ex-list lK ->4 - <0> ex-pushmark s ->- - <0> padsv[$x:1,2] lM/LVINTRO ->- - <0> padsv[$y:1,2] lM/LVINTRO ->- - <0> padsv[$z:1,2] lM/LVINTRO ->- 5 <1> rv2av[t2] sKR/1 ->6 4 <#> gv[*a] s ->5 -e syntax OK
Subject: open_7GEfVFih.txt
diff -rup Lexical-Types-0.13-k8xlVm-orig/Types.xs Lexical-Types-0.13-k8xlVm/Types.xs --- Lexical-Types-0.13-k8xlVm-orig/Types.xs 2014-10-04 15:58:49.000000000 -0700 +++ Lexical-Types-0.13-k8xlVm/Types.xs 2014-11-08 00:26:01.000000000 -0800 @@ -687,7 +687,9 @@ STATIC OP *lt_pp_padrange(pTHX) { base = PL_op->op_targ; count = PL_op->op_private & OPpPADRANGE_COUNTMASK; - for (i = 0, p = roi.padxv_start; i < count && p; ++i, p = OP_SIBLING(p)) { + for (i = 0, p = roi.padxv_start; i < count && p; ++i, p = p->op_next) { + while (p->op_type == OP_NULL) + p = p->op_next; lt_op_padxv_info oi; if (p->op_type == OP_PADSV && lt_padxv_map_fetch(p, &oi)) lt_op_padxv_info_call(&oi, PAD_SV(base + i)); @@ -806,7 +808,7 @@ STATIC int lt_maybe_padrange_setup(pTHX_ count = o->op_private & OPpPADRANGE_COUNTMASK; - for (i = 0, p = start; i < count && p; ++i, p = OP_SIBLING(p)) { + for (i = 0, p = start; i < count && p; ++i, p = p->op_next) { if (p->op_type == OP_PADSV) { /* In a padrange sequence, either all lexicals are typed, or none are. * Thus we can stop at the first padsv op. However, note that these @@ -858,8 +860,15 @@ STATIC void lt_peep_rec(pTHX_ OP *o, pta && !(o->op_flags & OPf_SPECIAL)) { /* A padrange op is guaranteed to have previously been a pushmark. * Moreover, for non-special padrange ops (i.e. that aren't for - * my (...) = @_), the original padxv ops are its siblings. */ - lt_maybe_padrange_setup(o, OP_SIBLING(o)); + * my (...) = @_), the first original padxv is its sibling or nephew. + */ + OP *kid = OP_SIBLING(o); + if (kid->op_type == OP_NULL && kid->op_flags & OPf_KIDS) { + kid = kUNOP->op_first; + if (kid->op_type == OP_NULL) + kid = OP_SIBLING(kid); + } + lt_maybe_padrange_setup(o, kid); } break; case OP_AASSIGN: {
Thanks for the patch. It has been published in version 0.14. Vincent