This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
OP_SASSIGN: make op_first==op_last for UNOP
authorDavid Mitchell <davem@iabyn.com>
Thu, 29 Sep 2016 15:03:05 +0000 (16:03 +0100)
committerDavid Mitchell <davem@iabyn.com>
Thu, 29 Sep 2016 16:26:44 +0000 (17:26 +0100)
Occasionally (e.g. $x ||= 1) an OP_SASSIGN operator only has a single
arg. The previous two commits made OP_SASSIGN always be allocated as a
BINOP, and if necessary, set op_last to NULL when there's only s single
arg.

This commit instead sets op_last equal to op_first for this case (similar
to how a LISTOP with a single arg is handled). This removes the need for
special handling in S_finalize_op().

op.c

diff --git a/op.c b/op.c
index a7652d5..5621d07 100644 (file)
--- a/op.c
+++ b/op.c
@@ -2651,7 +2651,6 @@ S_finalize_op(pTHX_ OP* o)
               || type == OP_CUSTOM
               || type == OP_NULL /* new_logop does this */
               );
-        if (type == OP_SASSIGN) has_last = 0; /* XXX tmp hack for unary assign */
 
         for (kid = cUNOPo->op_first; kid; kid = OpSIBLING(kid)) {
 #  ifdef PERL_OP_PARENT
@@ -2661,9 +2660,7 @@ S_finalize_op(pTHX_ OP* o)
                 assert(kid->op_sibparent == o);
             }
 #  else
-            if (has_last && !OpHAS_SIBLING(kid)
-            /* {and,or,xor}assign use a hackish unop'y sassign without last */
-                && (OP_TYPE_ISNT(o, OP_SASSIGN) || cLISTOPo->op_last))
+            if (has_last && !OpHAS_SIBLING(kid))
                 assert(kid == cLISTOPo->op_last);
 #  endif
         }
@@ -6509,9 +6506,10 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
 
     if (optype) {
        if (optype == OP_ANDASSIGN || optype == OP_ORASSIGN || optype == OP_DORASSIGN) {
+            right = scalar(right);
            return newLOGOP(optype, 0,
                op_lvalue(scalar(left), optype),
-               newBINOP(OP_SASSIGN, OPpASSIGN_BACKWARDS<<8, scalar(right), NULL));
+               newBINOP(OP_SASSIGN, OPpASSIGN_BACKWARDS<<8, right, right));
        }
        else {
            return newBINOP(optype, OPf_STACKED,