goto clear_pmop;
case OP_SPLIT:
- if ( (o->op_private & OPpSPLIT_ASSIGN)
- && !(o->op_flags & OPf_STACKED))
+ if ( (o->op_private & OPpSPLIT_ASSIGN) /* @array = split */
+ && !(o->op_flags & OPf_STACKED)) /* @{expr} = split */
{
if (o->op_private & OPpSPLIT_LEX)
pad_free(cPMOPo->op_pmreplrootu.op_pmtargetoff);
if (type != OP_SPLIT)
/* At this point o is a LISTOP, but OP_SPLIT is a PMOP; let
* ck_split() create a real PMOP and leave the op's type as listop
- * for for now. Otherwise op_free() etc will crash.
+ * for now. Otherwise op_free() etc will crash.
*/
OpTYPE_set(o, type);
* constant), or convert expr into a runtime regcomp op sequence (if it's
* not)
*
- * Flags currently has 2 bits or meaning:
+ * Flags currently has 2 bits of meaning:
* 1: isreg indicates that the pattern is part of a regex construct, eg
* $x =~ /pattern/ or split /pattern/, as opposed to $x =~ $pattern or
* split "pattern", which aren't. In the former case, expr will be a list
}
/* optimise @a = split(...) into:
- * local/my @a: split(..., @a), where @a is not flattened
- * other arrays: split(...) where @a is attached to
- * the split op itself
- */
+ * @{expr}: split(..., @{expr}) (where @a is not flattened)
+ * @a, my @a, local @a: split(...) (where @a is attached to
+ * the split op itself)
+ */
if ( right
&& right->op_type == OP_SPLIT
{
OP *gvop = NULL;
- if (!(left->op_private & OPpLVAL_INTRO) &&
- ( (left->op_type == OP_RV2AV &&
- (gvop=((UNOP*)left)->op_first)->op_type==OP_GV)
- || left->op_type == OP_PADAV )
- )
+ if ( ( left->op_type == OP_RV2AV
+ && (gvop=((UNOP*)left)->op_first)->op_type==OP_GV)
+ || left->op_type == OP_PADAV)
{
- /* @pkg or @lex, but not 'local @pkg' nor 'my @lex' */
+ /* @pkg or @lex or local @pkg' or 'my @lex' */
OP *tmpop;
- PMOP * const pm = (PMOP*)right;
if (gvop) {
#ifdef USE_ITHREADS
- pm->op_pmreplrootu.op_pmtargetoff
+ ((PMOP*)right)->op_pmreplrootu.op_pmtargetoff
= cPADOPx(gvop)->op_padix;
cPADOPx(gvop)->op_padix = 0; /* steal it */
#else
- pm->op_pmreplrootu.op_pmtargetgv
+ ((PMOP*)right)->op_pmreplrootu.op_pmtargetgv
= MUTABLE_GV(cSVOPx(gvop)->op_sv);
cSVOPx(gvop)->op_sv = NULL; /* steal it */
#endif
left->op_private & OPpOUR_INTRO;
}
else {
- pm->op_pmreplrootu.op_pmtargetoff = left->op_targ;
+ ((PMOP*)right)->op_pmreplrootu.op_pmtargetoff = left->op_targ;
left->op_targ = 0; /* steal it */
right->op_private |= OPpSPLIT_LEX;
}
+ right->op_private |= left->op_private & OPpLVAL_INTRO;
detach_split:
tmpop = cUNOPo->op_first; /* to list (nulled) */
/* "I don't know and I don't care." */
return right;
}
- else if (left->op_type == OP_RV2AV
- || left->op_type == OP_PADAV)
- {
- /* 'local @pkg' or 'my @lex' */
+ else if (left->op_type == OP_RV2AV) {
+ /* @{expr} */
OP *pushop = cUNOPx(cBINOPo->op_last)->op_first;
assert(OpSIBLING(pushop) == left);
kid = cLISTOPo->op_first;
if (kid->op_type != OP_MATCH || kid->op_flags & OPf_STACKED) {
- /* remove match expression, and replace with new optree with
+ /* remove match expression, and replace with new optree with
* a match op at its head */
op_sibling_splice(o, NULL, 1, NULL);
/* pmruntime will handle split " " behavior with flag==2 */
* into its place, then convert the match op into a split op. i.e.
*
* SPLIT MATCH SPLIT(ex-MATCH)
- * | | |
- * MATCH - A - B - C => R - A - B - C => R - A - B - C
- * | | |
- * R X - Y X - Y
+ * | | |
+ * MATCH - A - B - C => R - A - B - C => R - A - B - C
+ * | | |
+ * R X - Y X - Y
* |
* X - Y
*
case OP_PADAV:
case OP_PADHV:
(*scalars_p) += 2;
+ /* if !top, could be e.g. @a[0,1] */
if (top && (o->op_flags & OPf_REF))
return (o->op_private & OPpLVAL_INTRO)
? AAS_MY_AGG : AAS_LEX_AGG;
if (cUNOPx(o)->op_first->op_type != OP_GV)
return AAS_DANGEROUS; /* @{expr}, %{expr} */
/* @pkg, %pkg */
+ /* if !top, could be e.g. @a[0,1] */
if (top && (o->op_flags & OPf_REF))
return AAS_PKG_AGG;
return AAS_DANGEROUS;
return AAS_PKG_SCALAR; /* $pkg */
case OP_SPLIT:
- if (1) { /* XXX this condition is wrong - fix later
- if (cLISTOPo->op_first->op_type == OP_PUSHRE) {
- */
- /* "@foo = split... " optimises away the aassign and stores its
- * destination array in the OP_PUSHRE that precedes it.
- * A flattened array is always dangerous.
+ if (o->op_private & OPpSPLIT_ASSIGN) {
+ /* the assign in @a = split() has been optimised away
+ * and the @a attached directly to the split op
+ * Treat the array as appearing on the RHS, i.e.
+ * ... = (@a = split)
+ * is treated like
+ * ... = @a;
*/
+
+ if (o->op_flags & OPf_STACKED)
+ /* @{expr} = split() - the array expression is tacked
+ * on as an extra child to split - process kid */
+ return S_aassign_scan(aTHX_ cLISTOPo->op_last, rhs,
+ top, scalars_p);
+
+ /* ... else array is directly attached to split op */
(*scalars_p) += 2;
- return AAS_DANGEROUS;
+ if (PL_op->op_private & OPpSPLIT_LEX)
+ return (o->op_private & OPpLVAL_INTRO)
+ ? AAS_MY_AGG : AAS_LEX_AGG;
+ else
+ return AAS_PKG_AGG;
}
- break;
+ (*scalars_p)++;
+ /* other args of split can't be returned */
+ return AAS_SAFE_SCALAR;
case OP_UNDEF:
/* undef counts as a scalar on the RHS: