Skip to content

Commit 198c546

Browse files
committed
Perl_scalar: explicitly handle OP_ASLICE case
`Perl_scalar` does not explicitly handle the OP_ASLICE case and consequently some OPs are not nulled, even though the user-visible behaviour would suggest that has happened. For example, `my $y = @x[4,3,2];` would give the optree: ``` b <;> nextstate(main 9 -e:1) v:%,us,{,fea=15 ->c i <1> padsv_store[$y:9,10] vKS/LVINTRO ->j h <@> aslice sK ->i c <0> pushmark s ->d - <1> ex-list lK ->g - <0> ex-pushmark s ->d d <$> const(IV 4) s ->e e <$> const(IV 3) s ->f f <$> const(IV 2) s ->g g <0> padav[@x:8,10] sR ->h ``` After this commit: ``` b <;> nextstate(main 9 -e:1) v:%,us,{,fea=15 ->c g <1> padsv_store[$y:9,10] vKS/LVINTRO ->h f <@> aslice sK ->g c <0> pushmark s ->d - <1> ex-list lK ->e - <0> ex-pushmark v ->- - <0> ex-const v ->- - <0> ex-const v ->d d <$> const(IV 2) s ->e e <0> padav[@x:8,10] sR ->f ``` The user-visible behaviour should be unchanged, but now only one element of @x will be removed, rather than three with two of them being immediately discarded.
1 parent 1107db1 commit 198c546

File tree

1 file changed

+13
-0
lines changed

1 file changed

+13
-0
lines changed

op.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2027,6 +2027,19 @@ Perl_scalar(pTHX_ OP *o)
20272027
case OP_LIST:
20282028
kid = cLISTOPo->op_first;
20292029
goto do_kids;
2030+
case OP_ASLICE: {
2031+
OP * first = cLISTOPo->op_first;
2032+
assert(OP_TYPE_IS(first, OP_PUSHMARK));
2033+
assert(first->op_moresib);
2034+
OP * sib = OpSIBLING(first);
2035+
if(OP_TYPE_IS_OR_WAS(sib, OP_LIST)) {
2036+
kid = cLISTOPx(sib)->op_first;
2037+
goto do_kids;
2038+
}
2039+
if (o->op_flags & OPf_KIDS)
2040+
next_kid = cUNOPo->op_first; /* do all kids */
2041+
break;
2042+
}
20302043
case OP_LSLICE:
20312044
assert(OP_TYPE_IS_OR_WAS(cLISTOPo->op_first, OP_LIST));
20322045
kid = cLISTOPx(cLISTOPo->op_first)->op_first;

0 commit comments

Comments
 (0)