This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Clone my subs on scope entry
authorFather Chrysostomos <sprout@cpan.org>
Fri, 3 Aug 2012 16:23:15 +0000 (09:23 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Sun, 16 Sep 2012 05:45:05 +0000 (22:45 -0700)
The pad slot for a my sub now holds a stub with a prototype CV
attached to it by proto magic.

The prototype is cloned on scope entry.  The stub in the pad is used
when cloning, so any code that references the sub before scope entry
will be able to see that stub become defined, making these behave
similarly:

    our $x;
    BEGIN { $x = \&foo }
    sub foo { }

    our $x;
    my sub foo { }
    BEGIN { $x = \&foo }

Constants are currently not cloned, but that may cause bugs in
pad_push.  I’ll have to look into that.

On scope exit, lexical CVs go through leave_scope’s SAVEt_CLEARSV sec-
tion, like lexical variables.  If the sub is referenced elsewhere, it
is abandoned, and its proto magic is stolen and attached to a new stub
stored in the pad.  If the sub is not referenced elsewhere, it is
undefined via cv_undef.

To clone my subs on scope entry, we create a sequence of introcv and
clonecv ops.  See the huge comment in block_end that explains why we
need two separate ops for each CV.

To allow my subs to be defined in inner subs (my sub foo; sub { sub
foo {} }), pad_add_name_pvn and S_pad_findlex now upgrade the entry
for a my sub to a CV to begin with, so that fake entries added to pads
(fake entries are those that reference outer pads) can share the same
CV.  Otherwise newMYSUB would have to add the CV to every pad that
closes over the ‘my sub’ declaration.  newMYSUB no longer throws away
the initial value replacing it with a new one.

Prototypes are not currently visible to sub calls at compile time,
because the lexer sees the empty stub.  A future commit will
solve that.

When I added name heks to CV’s I made mistakes in a few places, by not
turning on the CVf_NAMED flag, or by not clearing the field when free-
ing the hek.  Those code paths were not exercised enough by state
subs, so the problems did not show up till now.  So this commit fixes
those, too.

One of the tests in lexsub.t, involving foreach loops, was incorrect,
and has been fixed.  Another test has been added to the end for a par-
ticular case of state subs closing over my subs that I broke when ini-
tially trying to get sibling my subs to close over each other, before
I had separate introcv and clonecv ops.

12 files changed:
embed.fnc
embed.h
op.c
pad.c
perly.act
perly.h
perly.tab
perly.y
pp.c
proto.h
scope.c
t/cmd/lexsub.t

index 99b168b..14f3e20 100644 (file)
--- a/embed.fnc
+++ b/embed.fnc
@@ -2312,7 +2312,7 @@ Apd       |void   |pad_setsv      |PADOFFSET po|NN SV* sv
 #endif
 pd     |void   |pad_block_start|int full
 pd     |U32    |intro_my
-pd     |void   |pad_leavemy
+pd     |OP *   |pad_leavemy
 pd     |void   |pad_swipe      |PADOFFSET po|bool refadjust
 #if defined(PERL_IN_PAD_C)
 sd     |void   |pad_reset
@@ -2326,6 +2326,7 @@ sd        |void   |cv_dump        |NN const CV *cv|NN const char *title
 #  endif
 #endif
 Apd    |CV*    |cv_clone       |NN CV* proto
+pd     |CV*    |cv_clone_into  |NN CV* proto|NN CV *target
 pd     |void   |pad_fixup_inner_anons|NN PADLIST *padlist|NN CV *old_cv|NN CV *new_cv
 pdX    |void   |pad_push       |NN PADLIST *padlist|int depth
 ApdR   |HV*    |pad_compname_type|const PADOFFSET po
diff --git a/embed.h b/embed.h
index 655a0a1..a65cfd4 100644 (file)
--- a/embed.h
+++ b/embed.h
 #define coresub_op(a,b,c)      Perl_coresub_op(aTHX_ a,b,c)
 #define create_eval_scope(a)   Perl_create_eval_scope(aTHX_ a)
 #define cv_ckproto_len_flags(a,b,c,d,e)        Perl_cv_ckproto_len_flags(aTHX_ a,b,c,d,e)
+#define cv_clone_into(a,b)     Perl_cv_clone_into(aTHX_ a,b)
 #define cv_forget_slab(a)      Perl_cv_forget_slab(aTHX_ a)
 #define cvgv_set(a,b)          Perl_cvgv_set(aTHX_ a,b)
 #define cvstash_set(a,b)       Perl_cvstash_set(aTHX_ a,b)
diff --git a/op.c b/op.c
index 36341c2..63e98b1 100644 (file)
--- a/op.c
+++ b/op.c
@@ -2894,6 +2894,7 @@ Perl_block_end(pTHX_ I32 floor, OP *seq)
     dVAR;
     const int needblockscope = PL_hints & HINT_BLOCK_SCOPE;
     OP* retval = scalarseq(seq);
+    OP *o;
 
     CALL_BLOCK_HOOKS(bhk_pre_end, &retval);
 
@@ -2901,7 +2902,66 @@ Perl_block_end(pTHX_ I32 floor, OP *seq)
     CopHINTS_set(&PL_compiling, PL_hints);
     if (needblockscope)
        PL_hints |= HINT_BLOCK_SCOPE; /* propagate out */
-    pad_leavemy();
+    o = pad_leavemy();
+
+    if (o) {
+       /* pad_leavemy has created a sequence of introcv ops for all my
+          subs declared in the block.  We have to replicate that list with
+          clonecv ops, to deal with this situation:
+
+              sub {
+                  my sub s1;
+                  my sub s2;
+                  sub s1 { state sub foo { \&s2 } }
+              }->()
+
+          Originally, I was going to have introcv clone the CV and turn
+          off the stale flag.  Since &s1 is declared before &s2, the
+          introcv op for &s1 is executed (on sub entry) before the one for
+          &s2.  But the &foo sub inside &s1 (which is cloned when &s1 is
+          cloned, since it is a state sub) closes over &s2 and expects
+          to see it in its outer CV’s pad.  If the introcv op clones &s1,
+          then &s2 is still marked stale.  Since &s1 is not active, and
+          &foo closes over &s1’s implicit entry for &s2, we get a ‘Varia-
+          ble will not stay shared’ warning.  Because it is the same stub
+          that will be used when the introcv op for &s2 is executed, clos-
+          ing over it is safe.  Hence, we have to turn off the stale flag
+          on all lexical subs in the block before we clone any of them.
+          Hence, having introcv clone the sub cannot work.  So we create a
+          list of ops like this:
+
+              lineseq
+                 |
+                 +-- introcv
+                 |
+                 +-- introcv
+                 |
+                 +-- introcv
+                 |
+                 .
+                 .
+                 .
+                 |
+                 +-- clonecv
+                 |
+                 +-- clonecv
+                 |
+                 +-- clonecv
+                 |
+                 .
+                 .
+                 .
+        */
+       OP *kid = o->op_flags & OPf_KIDS ? cLISTOPo->op_first : o;
+       OP * const last = o->op_flags & OPf_KIDS ? cLISTOPo->op_last : o;
+       for (;; kid = kid->op_sibling) {
+           OP *newkid = newOP(OP_CLONECV, 0);
+           newkid->op_targ = kid->op_targ;
+           o = op_append_elem(OP_LINESEQ, o, newkid);
+           if (kid == last) break;
+       }
+       retval = op_prepend_elem(OP_LINESEQ, o, retval);
+    }
 
     CALL_BLOCK_HOOKS(bhk_post_end, &retval);
 
@@ -6874,6 +6934,7 @@ Perl_newMYSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
     PADNAME *name;
     PADOFFSET pax = o->op_targ;
     CV *outcv = CvOUTSIDE(PL_compcv);
+    HEK *hek = NULL;
 
     PERL_ARGS_ASSERT_NEWMYSUB;
 
@@ -6916,14 +6977,38 @@ Perl_newMYSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
        goto done;
     }
 
-    if (SvTYPE(*spot) != SVt_PVCV) {   /* Maybe prototype now, and had at
-                                          maximum a prototype before. */
-       SvREFCNT_dec(*spot);
-       *spot = NULL;
+    if (PadnameIsSTATE(name))
+       cv = *spot;
+    else {
+       MAGIC *mg;
+       assert (SvTYPE(*spot) == SVt_PVCV);
+       if (CvROOT(*spot)) {
+           cv = *spot;
+           *svspot = newSV_type(SVt_PVCV);
+           SvPADMY_on(*spot);
+       }
+       if (CvNAMED(*spot))
+           hek = CvNAME_HEK(*spot);
+       else {
+           SvANY(*spot)->xcv_gv_u.xcv_hek = hek =
+               share_hek(
+                   PadnamePV(name)+1,
+                   PadnameLEN(name)-1 * (PadnameUTF8(name) ? -1 : 1), 0
+               );
+           CvNAMED_on(*spot);
+       }
+       mg = mg_find(*svspot, PERL_MAGIC_proto);
+       if (mg) {
+           assert(mg->mg_obj);
+           cv = (CV *)mg->mg_obj;
+       }
+       else {
+           sv_magic(*svspot, &PL_sv_undef, PERL_MAGIC_proto, NULL, 0);
+           mg = mg_find(*svspot, PERL_MAGIC_proto);
+       }
+       spot = (CV **)(svspot = &mg->mg_obj);
     }
 
-    cv = *spot;
-
     if (!block || !ps || *ps || attrs
        || (CvFLAGS(compcv) & CVf_BUILTIN_ATTRS)
 #ifdef PERL_MAD
@@ -7027,20 +7112,17 @@ Perl_newMYSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
                   && block->op_type != OP_NULL
 #endif
        ) {
-           cv_flags_t existing_builtin_attrs = CvFLAGS(cv) & CVf_BUILTIN_ATTRS;
+           cv_flags_t preserved_flags =
+               CvFLAGS(cv) & (CVf_BUILTIN_ATTRS|CVf_NAMED);
            PADLIST *const temp_padl = CvPADLIST(cv);
            CV *const temp_cv = CvOUTSIDE(cv);
            const cv_flags_t other_flags =
                CvFLAGS(cv) & (CVf_SLABBED|CVf_WEAKOUTSIDE);
            OP * const cvstart = CvSTART(cv);
 
-           assert(CvWEAKOUTSIDE(cv));
-           assert(CvNAMED(cv));
-           assert(CvNAME_HEK(cv));
-
            SvPOK_off(cv);
            CvFLAGS(cv) =
-               CvFLAGS(compcv) | existing_builtin_attrs | CVf_NAMED;
+               CvFLAGS(compcv) | preserved_flags;
            CvOUTSIDE(cv) = CvOUTSIDE(compcv);
            CvOUTSIDE_SEQ(cv) = CvOUTSIDE_SEQ(compcv);
            CvPADLIST(cv) = CvPADLIST(compcv);
@@ -7071,8 +7153,12 @@ Perl_newMYSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
     else {
        cv = compcv;
        *spot = cv;
+    }
+    if (!CvNAME_HEK(cv)) {
        SvANY(cv)->xcv_gv_u.xcv_hek =
-           share_hek(PadnamePV(name)+1,
+        hek
+         ? share_hek_hek(hek)
+         : share_hek(PadnamePV(name)+1,
                      PadnameLEN(name)-1 * (PadnameUTF8(name) ? -1 : 1),
                      0);
        CvNAMED_on(cv);
diff --git a/pad.c b/pad.c
index d320004..7a3fad4 100644 (file)
--- a/pad.c
+++ b/pad.c
@@ -381,7 +381,8 @@ Perl_cv_undef(pTHX_ CV *cv)
 #endif
     SvPOK_off(MUTABLE_SV(cv));         /* forget prototype */
     sv_unmagic((SV *)cv, PERL_MAGIC_checkcall);
-    if (CvNAMED(cv)) unshare_hek(CvNAME_HEK(cv));
+    if (CvNAMED(cv)) unshare_hek(CvNAME_HEK(cv)),
+                    SvANY(cv)->xcv_gv_u.xcv_hek = NULL;
     else            CvGV_set(cv, NULL);
 
     /* This statement and the subsequence if block was pad_undef().  */
@@ -646,6 +647,8 @@ Perl_pad_add_name_pvn(pTHX_ const char *namepv, STRLEN namelen,
        sv_upgrade(PL_curpad[offset], SVt_PVAV);
     else if (namelen != 0 && *namepv == '%')
        sv_upgrade(PL_curpad[offset], SVt_PVHV);
+    else if (namelen != 0 && *namepv == '&')
+       sv_upgrade(PL_curpad[offset], SVt_PVCV);
     assert(SvPADMY(PL_curpad[offset]));
     DEBUG_Xv(PerlIO_printf(Perl_debug_log,
                           "Pad addname: %ld \"%s\" new lex=0x%"UVxf"\n",
@@ -1298,6 +1301,8 @@ S_pad_findlex(pTHX_ const char *namepv, STRLEN namelen, U32 flags, const CV* cv,
                        *out_capture = sv_2mortal(MUTABLE_SV(newAV()));
                    else if (namelen != 0 && *namepv == '%')
                        *out_capture = sv_2mortal(MUTABLE_SV(newHV()));
+                   else if (namelen != 0 && *namepv == '&')
+                       *out_capture = sv_2mortal(newSV_type(SVt_PVCV));
                    else
                        *out_capture = sv_newmortal();
                }
@@ -1531,11 +1536,12 @@ lexicals in this scope and warn of any lexicals that never got introduced.
 =cut
 */
 
-void
+OP *
 Perl_pad_leavemy(pTHX)
 {
     dVAR;
     I32 off;
+    OP *o = NULL;
     SV * const * const svp = AvARRAY(PL_comppad_name);
 
     PL_pad_reset_pending = FALSE;
@@ -1552,7 +1558,7 @@ Perl_pad_leavemy(pTHX)
     }
     /* "Deintroduce" my variables that are leaving with this scope. */
     for (off = AvFILLp(PL_comppad_name); off > PL_comppad_name_fill; off--) {
-       const SV * const sv = svp[off];
+       SV * const sv = svp[off];
        if (sv && sv != &PL_sv_undef && !SvFAKE(sv)
            && COP_SEQ_RANGE_HIGH(sv) == PERL_PADSEQ_INTRO)
        {
@@ -1563,6 +1569,12 @@ Perl_pad_leavemy(pTHX)
                (unsigned long)COP_SEQ_RANGE_LOW(sv),
                (unsigned long)COP_SEQ_RANGE_HIGH(sv))
            );
+           if (!PadnameIsSTATE(sv) && !PadnameIsOUR(sv)
+            && *PadnamePV(sv) == '&' && PadnameLEN(sv) > 1) {
+               OP *kid = newOP(OP_INTROCV, 0);
+               kid->op_targ = off;
+               o = op_prepend_elem(OP_LINESEQ, kid, o);
+           }
        }
     }
     PL_cop_seqmax++;
@@ -1570,6 +1582,7 @@ Perl_pad_leavemy(pTHX)
        PL_cop_seqmax++;
     DEBUG_Xv(PerlIO_printf(Perl_debug_log,
            "Pad leavemy: seq = %ld\n", (long)PL_cop_seqmax));
+    return o;
 }
 
 /*
@@ -2038,9 +2051,32 @@ S_cv_clone_pad(pTHX_ CV *proto, CV *cv, CV *outside)
                       ing over other state subs’ entries, so we have
                       to put a stub here and then clone into it on the
                       second pass. */
-                   sv = SvPAD_STATE(namesv) && !CvCLONED(ppad[ix])
-                       ? (subclones = 1, newSV_type(SVt_PVCV))
-                       : SvREFCNT_inc(ppad[ix]);
+                   if (SvPAD_STATE(namesv) && !CvCLONED(ppad[ix])) {
+                       assert(SvTYPE(ppad[ix]) == SVt_PVCV);
+                       subclones = 1;
+                       sv = newSV_type(SVt_PVCV);
+                   }
+                   else if (PadnameLEN(namesv)>1 && !PadnameIsOUR(namesv))
+                   {
+                       /* my sub */
+                       /* This is actually a stub with a proto CV attached
+                          to it by magic.  Since the stub itself is used
+                          when the proto is cloned, we need a new stub
+                          that nonetheless shares the same proto.
+                        */
+                       MAGIC * const mg =
+                           mg_find(ppad[ix], PERL_MAGIC_proto);
+                       assert(mg);
+                       assert(mg->mg_obj);
+                       assert(SvTYPE(ppad[ix]) == SVt_PVCV);
+                       assert(CvNAME_HEK((CV *)ppad[ix]));
+                       sv = newSV_type(SVt_PVCV);
+                       SvANY((CV *)sv)->xcv_gv_u.xcv_hek =
+                           share_hek_hek(CvNAME_HEK((CV *)ppad[ix]));
+                       CvNAMED_on(sv);
+                       sv_magic(sv,mg->mg_obj,PERL_MAGIC_proto,NULL,0);
+                   }
+                   else sv = SvREFCNT_inc(ppad[ix]);
                 else if (sigil == '@')
                    sv = MUTABLE_SV(newAV());
                 else if (sigil == '%')
@@ -2087,7 +2123,10 @@ S_cv_clone(pTHX_ CV *proto, CV *cv, CV *outside)
     CvFILE(cv)         = CvDYNFILE(proto) ? savepv(CvFILE(proto))
                                           : CvFILE(proto);
     if (CvNAMED(proto))
+    {
         SvANY(cv)->xcv_gv_u.xcv_hek = share_hek_hek(CvNAME_HEK(proto));
+        CvNAMED_on(cv);
+    }
     else CvGV_set(cv,CvGV(proto));
     CvSTASH_set(cv, CvSTASH(proto));
     OP_REFCNT_LOCK;
@@ -2141,6 +2180,15 @@ Perl_cv_clone(pTHX_ CV *proto)
     return S_cv_clone(aTHX_ proto, NULL, NULL);
 }
 
+/* Called only by pp_clonecv */
+CV *
+Perl_cv_clone_into(pTHX_ CV *proto, CV *target)
+{
+    PERL_ARGS_ASSERT_CV_CLONE_INTO;
+    cv_undef(target);
+    return S_cv_clone(aTHX_ proto, target, NULL);
+}
+
 /*
 =for apidoc m|void|pad_fixup_inner_anons|PADLIST *padlist|CV *old_cv|CV *new_cv
 
index df6d833..064bd8c 100644 (file)
--- a/perly.act
+++ b/perly.act
@@ -253,9 +253,11 @@ case 2:
                          else
                          /* State subs inside anonymous subs need to be
                             clonable themselves. */
-                         /* XXX This will need adjustment for state subs
-                                inside my subs. */
-                         if (CvANON(CvOUTSIDE(PL_compcv)))
+                         if (CvANON(CvOUTSIDE(PL_compcv))
+                          || CvCLONE(CvOUTSIDE(PL_compcv))
+                          || !PadnameIsSTATE(PadlistNAMESARRAY(CvPADLIST(
+                                               CvOUTSIDE(PL_compcv)
+                                            ))[(ps[(2) - (3)].val.opval)->op_targ]))
                              CvCLONE_on(PL_compcv);
                          PL_parser->in_my = 0;
                          PL_parser->in_my_stash = NULL;
@@ -263,7 +265,7 @@ case 2:
     break;
 
   case 31:
-#line 338 "perly.y"
+#line 340 "perly.y"
     {
                          SvREFCNT_inc_simple_void(PL_compcv);
 #ifdef MAD
@@ -294,7 +296,7 @@ case 2:
     break;
 
   case 32:
-#line 366 "perly.y"
+#line 368 "perly.y"
     {
                          /* Unimplemented "my sub foo { }" */
                          SvREFCNT_inc_simple_void(PL_compcv);
@@ -309,7 +311,7 @@ case 2:
     break;
 
   case 33:
-#line 378 "perly.y"
+#line 380 "perly.y"
     {
 #ifdef MAD
                          (yyval.opval) = package((ps[(3) - (4)].val.opval));
@@ -327,12 +329,12 @@ case 2:
     break;
 
   case 34:
-#line 393 "perly.y"
+#line 395 "perly.y"
     { CvSPECIAL_on(PL_compcv); /* It's a BEGIN {} */ ;}
     break;
 
   case 35:
-#line 395 "perly.y"
+#line 397 "perly.y"
     {
                          SvREFCNT_inc_simple_void(PL_compcv);
 #ifdef MAD
@@ -350,7 +352,7 @@ case 2:
     break;
 
   case 36:
-#line 410 "perly.y"
+#line 412 "perly.y"
     {
                          (yyval.opval) = block_end((ps[(3) - (7)].val.ival),
                              newCONDOP(0, (ps[(4) - (7)].val.opval), op_scope((ps[(6) - (7)].val.opval)), (ps[(7) - (7)].val.opval)));
@@ -362,7 +364,7 @@ case 2:
     break;
 
   case 37:
-#line 419 "perly.y"
+#line 421 "perly.y"
     {
                          (yyval.opval) = block_end((ps[(3) - (7)].val.ival),
                              newCONDOP(0, (ps[(4) - (7)].val.opval), op_scope((ps[(6) - (7)].val.opval)), (ps[(7) - (7)].val.opval)));
@@ -374,7 +376,7 @@ case 2:
     break;
 
   case 38:
-#line 428 "perly.y"
+#line 430 "perly.y"
     {
                          const PADOFFSET offset = pad_findmy_pvs("$_", 0);
                          (yyval.opval) = block_end((ps[(3) - (6)].val.ival),
@@ -388,17 +390,17 @@ case 2:
     break;
 
   case 39:
-#line 439 "perly.y"
+#line 441 "perly.y"
     { (yyval.opval) = block_end((ps[(3) - (6)].val.ival), newWHENOP((ps[(4) - (6)].val.opval), op_scope((ps[(6) - (6)].val.opval)))); ;}
     break;
 
   case 40:
-#line 441 "perly.y"
+#line 443 "perly.y"
     { (yyval.opval) = newWHENOP(0, op_scope((ps[(2) - (2)].val.opval))); ;}
     break;
 
   case 41:
-#line 443 "perly.y"
+#line 445 "perly.y"
     {
                          (yyval.opval) = block_end((ps[(3) - (8)].val.ival),
                                  newWHILEOP(0, 1, (LOOP*)(OP*)NULL,
@@ -411,7 +413,7 @@ case 2:
     break;
 
   case 42:
-#line 453 "perly.y"
+#line 455 "perly.y"
     {
                          (yyval.opval) = block_end((ps[(3) - (8)].val.ival),
                                  newWHILEOP(0, 1, (LOOP*)(OP*)NULL,
@@ -424,7 +426,7 @@ case 2:
     break;
 
   case 43:
-#line 464 "perly.y"
+#line 466 "perly.y"
     {
                          OP *initop = IF_MAD((ps[(4) - (11)].val.opval) ? (ps[(4) - (11)].val.opval) : newOP(OP_NULL, 0), (ps[(4) - (11)].val.opval));
                          OP *forop = newWHILEOP(0, 1, (LOOP*)(OP*)NULL,
@@ -447,7 +449,7 @@ case 2:
     break;
 
   case 44:
-#line 484 "perly.y"
+#line 486 "perly.y"
     {
                          (yyval.opval) = block_end((ps[(3) - (9)].val.ival), newFOROP(0, (ps[(4) - (9)].val.opval), (ps[(6) - (9)].val.opval), (ps[(8) - (9)].val.opval), (ps[(9) - (9)].val.opval)));
                          TOKEN_GETMAD((ps[(1) - (9)].val.i_tkval),(yyval.opval),'W');
@@ -459,7 +461,7 @@ case 2:
     break;
 
   case 45:
-#line 493 "perly.y"
+#line 495 "perly.y"
     {
                          (yyval.opval) = block_end((ps[(4) - (8)].val.ival), newFOROP(0,
                                      op_lvalue((ps[(2) - (8)].val.opval), OP_ENTERLOOP), (ps[(5) - (8)].val.opval), (ps[(7) - (8)].val.opval), (ps[(8) - (8)].val.opval)));
@@ -471,7 +473,7 @@ case 2:
     break;
 
   case 46:
-#line 502 "perly.y"
+#line 504 "perly.y"
     {
                          (yyval.opval) = block_end((ps[(3) - (7)].val.ival),
                                  newFOROP(0, (OP*)NULL, (ps[(4) - (7)].val.opval), (ps[(6) - (7)].val.opval), (ps[(7) - (7)].val.opval)));
@@ -483,7 +485,7 @@ case 2:
     break;
 
   case 47:
-#line 511 "perly.y"
+#line 513 "perly.y"
     {
                          /* a block is a loop that happens once */
                          (yyval.opval) = newWHILEOP(0, 1, (LOOP*)(OP*)NULL,
@@ -492,7 +494,7 @@ case 2:
     break;
 
   case 48:
-#line 517 "perly.y"
+#line 519 "perly.y"
     {
                          package((ps[(3) - (5)].val.opval));
                          if ((ps[(2) - (5)].val.opval)) {
@@ -502,7 +504,7 @@ case 2:
     break;
 
   case 49:
-#line 524 "perly.y"
+#line 526 "perly.y"
     {
                          /* a block is a loop that happens once */
                          (yyval.opval) = newWHILEOP(0, 1, (LOOP*)(OP*)NULL,
@@ -515,7 +517,7 @@ case 2:
     break;
 
   case 50:
-#line 534 "perly.y"
+#line 536 "perly.y"
     {
                          PL_parser->expect = XSTATE;
                          (yyval.opval) = (ps[(1) - (2)].val.opval);
@@ -524,7 +526,7 @@ case 2:
     break;
 
   case 51:
-#line 540 "perly.y"
+#line 542 "perly.y"
     {
                          PL_parser->expect = XSTATE;
                          (yyval.opval) = IF_MAD(newOP(OP_NULL, 0), (OP*)NULL);
@@ -534,7 +536,7 @@ case 2:
     break;
 
   case 52:
-#line 550 "perly.y"
+#line 552 "perly.y"
     { OP *list;
                          if ((ps[(2) - (2)].val.opval)) {
                              OP *term = (ps[(2) - (2)].val.opval);
@@ -558,55 +560,55 @@ case 2:
     break;
 
   case 53:
-#line 573 "perly.y"
+#line 575 "perly.y"
     { (yyval.opval) = NULL; ;}
     break;
 
   case 54:
-#line 575 "perly.y"
+#line 577 "perly.y"
     { (yyval.opval) = op_unscope((ps[(2) - (3)].val.opval)); ;}
     break;
 
   case 55:
-#line 580 "perly.y"
+#line 582 "perly.y"
     { (yyval.opval) = (OP*)NULL; ;}
     break;
 
   case 56:
-#line 582 "perly.y"
+#line 584 "perly.y"
     { (yyval.opval) = (ps[(1) - (1)].val.opval); ;}
     break;
 
   case 57:
-#line 584 "perly.y"
+#line 586 "perly.y"
     { (yyval.opval) = newLOGOP(OP_AND, 0, (ps[(3) - (3)].val.opval), (ps[(1) - (3)].val.opval));
                          TOKEN_GETMAD((ps[(2) - (3)].val.i_tkval),(yyval.opval),'i');
                        ;}
     break;
 
   case 58:
-#line 588 "perly.y"
+#line 590 "perly.y"
     { (yyval.opval) = newLOGOP(OP_OR, 0, (ps[(3) - (3)].val.opval), (ps[(1) - (3)].val.opval));
                          TOKEN_GETMAD((ps[(2) - (3)].val.i_tkval),(yyval.opval),'i');
                        ;}
     break;
 
   case 59:
-#line 592 "perly.y"
+#line 594 "perly.y"
     { (yyval.opval) = newLOOPOP(OPf_PARENS, 1, scalar((ps[(3) - (3)].val.opval)), (ps[(1) - (3)].val.opval));
                          TOKEN_GETMAD((ps[(2) - (3)].val.i_tkval),(yyval.opval),'w');
                        ;}
     break;
 
   case 60:
-#line 596 "perly.y"
+#line 598 "perly.y"
     { (yyval.opval) = newLOOPOP(OPf_PARENS, 1, (ps[(3) - (3)].val.opval), (ps[(1) - (3)].val.opval));
                          TOKEN_GETMAD((ps[(2) - (3)].val.i_tkval),(yyval.opval),'w');
                        ;}
     break;
 
   case 61:
-#line 600 "perly.y"
+#line 602 "perly.y"
     { (yyval.opval) = newFOROP(0, (OP*)NULL, (ps[(3) - (3)].val.opval), (ps[(1) - (3)].val.opval), (OP*)NULL);
                          TOKEN_GETMAD((ps[(2) - (3)].val.i_tkval),(yyval.opval),'w');
                          PL_parser->copline = (line_t)IVAL((ps[(2) - (3)].val.i_tkval));
@@ -614,17 +616,17 @@ case 2:
     break;
 
   case 62:
-#line 605 "perly.y"
+#line 607 "perly.y"
     { (yyval.opval) = newWHENOP((ps[(3) - (3)].val.opval), op_scope((ps[(1) - (3)].val.opval))); ;}
     break;
 
   case 63:
-#line 610 "perly.y"
+#line 612 "perly.y"
     { (yyval.opval) = (OP*)NULL; ;}
     break;
 
   case 64:
-#line 612 "perly.y"
+#line 614 "perly.y"
     {
                          ((ps[(2) - (2)].val.opval))->op_flags |= OPf_PARENS;
                          (yyval.opval) = op_scope((ps[(2) - (2)].val.opval));
@@ -633,7 +635,7 @@ case 2:
     break;
 
   case 65:
-#line 618 "perly.y"
+#line 620 "perly.y"
     { PL_parser->copline = (line_t)IVAL((ps[(1) - (6)].val.i_tkval));
                            (yyval.opval) = newCONDOP(0,
                                newSTATEOP(OPf_SPECIAL,NULL,(ps[(3) - (6)].val.opval)),
@@ -646,12 +648,12 @@ case 2:
     break;
 
   case 66:
-#line 631 "perly.y"
+#line 633 "perly.y"
     { (yyval.opval) = (OP*)NULL; ;}
     break;
 
   case 67:
-#line 633 "perly.y"
+#line 635 "perly.y"
     {
                          (yyval.opval) = op_scope((ps[(2) - (2)].val.opval));
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'o');
@@ -659,91 +661,91 @@ case 2:
     break;
 
   case 68:
-#line 641 "perly.y"
+#line 643 "perly.y"
     { (yyval.ival) = (PL_min_intro_pending &&
                            PL_max_intro_pending >=  PL_min_intro_pending);
                          intro_my(); ;}
     break;
 
   case 69:
-#line 647 "perly.y"
+#line 649 "perly.y"
     { (yyval.opval) = (OP*)NULL; ;}
     break;
 
   case 71:
-#line 653 "perly.y"
+#line 655 "perly.y"
     { YYSTYPE tmplval;
                          (void)scan_num("1", &tmplval);
                          (yyval.opval) = tmplval.opval; ;}
     break;
 
   case 73:
-#line 661 "perly.y"
+#line 663 "perly.y"
     { (yyval.opval) = invert(scalar((ps[(1) - (1)].val.opval))); ;}
     break;
 
   case 74:
-#line 666 "perly.y"
+#line 668 "perly.y"
     { (yyval.opval) = (ps[(1) - (1)].val.opval); intro_my(); ;}
     break;
 
   case 75:
-#line 670 "perly.y"
+#line 672 "perly.y"
     { (yyval.opval) = (ps[(1) - (1)].val.opval); intro_my(); ;}
     break;
 
   case 76:
-#line 674 "perly.y"
+#line 676 "perly.y"
     { (yyval.opval) = (ps[(1) - (1)].val.opval); intro_my(); ;}
     break;
 
   case 77:
-#line 677 "perly.y"
+#line 679 "perly.y"
     { (yyval.opval) = (ps[(1) - (1)].val.opval); ;}
     break;
 
   case 78:
-#line 678 "perly.y"
+#line 680 "perly.y"
     { (yyval.opval) = (OP*)NULL; ;}
     break;
 
   case 79:
-#line 682 "perly.y"
+#line 684 "perly.y"
     { (yyval.ival) = start_subparse(FALSE, 0);
                            SAVEFREESV(PL_compcv); ;}
     break;
 
   case 80:
-#line 688 "perly.y"
+#line 690 "perly.y"
     { (yyval.ival) = start_subparse(FALSE, CVf_ANON);
                            SAVEFREESV(PL_compcv); ;}
     break;
 
   case 81:
-#line 693 "perly.y"
+#line 695 "perly.y"
     { (yyval.ival) = start_subparse(TRUE, 0);
                            SAVEFREESV(PL_compcv); ;}
     break;
 
   case 84:
-#line 704 "perly.y"
+#line 706 "perly.y"
     { (yyval.opval) = (OP*)NULL; ;}
     break;
 
   case 86:
-#line 710 "perly.y"
+#line 712 "perly.y"
     { (yyval.opval) = (OP*)NULL; ;}
     break;
 
   case 87:
-#line 712 "perly.y"
+#line 714 "perly.y"
     { (yyval.opval) = (ps[(2) - (2)].val.opval);
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),':');
                        ;}
     break;
 
   case 88:
-#line 716 "perly.y"
+#line 718 "perly.y"
     { (yyval.opval) = IF_MAD(
                                    newOP(OP_NULL, 0),
                                    (OP*)NULL
@@ -753,14 +755,14 @@ case 2:
     break;
 
   case 89:
-#line 726 "perly.y"
+#line 728 "perly.y"
     { (yyval.opval) = (ps[(2) - (2)].val.opval);
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),':');
                        ;}
     break;
 
   case 90:
-#line 730 "perly.y"
+#line 732 "perly.y"
     { (yyval.opval) = IF_MAD(
                                    newOP(OP_NULL, 0),
                                    (OP*)NULL
@@ -770,12 +772,12 @@ case 2:
     break;
 
   case 91:
-#line 739 "perly.y"
+#line 741 "perly.y"
     { (yyval.opval) = (ps[(1) - (1)].val.opval); ;}
     break;
 
   case 92:
-#line 740 "perly.y"
+#line 742 "perly.y"
     { (yyval.opval) = IF_MAD(
                                    newOP(OP_NULL,0),
                                    (OP*)NULL
@@ -786,28 +788,28 @@ case 2:
     break;
 
   case 93:
-#line 751 "perly.y"
+#line 753 "perly.y"
     { (yyval.opval) = newLOGOP(OP_AND, 0, (ps[(1) - (3)].val.opval), (ps[(3) - (3)].val.opval));
                          TOKEN_GETMAD((ps[(2) - (3)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 94:
-#line 755 "perly.y"
+#line 757 "perly.y"
     { (yyval.opval) = newLOGOP(IVAL((ps[(2) - (3)].val.i_tkval)), 0, (ps[(1) - (3)].val.opval), (ps[(3) - (3)].val.opval));
                          TOKEN_GETMAD((ps[(2) - (3)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 95:
-#line 759 "perly.y"
+#line 761 "perly.y"
     { (yyval.opval) = newLOGOP(OP_DOR, 0, (ps[(1) - (3)].val.opval), (ps[(3) - (3)].val.opval));
                          TOKEN_GETMAD((ps[(2) - (3)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 97:
-#line 767 "perly.y"
+#line 769 "perly.y"
     {
 #ifdef MAD
                          OP* op = newNULLLIST();
@@ -820,7 +822,7 @@ case 2:
     break;
 
   case 98:
-#line 777 "perly.y"
+#line 779 "perly.y"
     { 
                          OP* term = (ps[(3) - (3)].val.opval);
                          DO_MAD(
@@ -832,7 +834,7 @@ case 2:
     break;
 
   case 100:
-#line 790 "perly.y"
+#line 792 "perly.y"
     { (yyval.opval) = convert(IVAL((ps[(1) - (3)].val.i_tkval)), OPf_STACKED,
                                op_prepend_elem(OP_LIST, newGVREF(IVAL((ps[(1) - (3)].val.i_tkval)),(ps[(2) - (3)].val.opval)), (ps[(3) - (3)].val.opval)) );
                          TOKEN_GETMAD((ps[(1) - (3)].val.i_tkval),(yyval.opval),'o');
@@ -840,7 +842,7 @@ case 2:
     break;
 
   case 101:
-#line 795 "perly.y"
+#line 797 "perly.y"
     { (yyval.opval) = convert(IVAL((ps[(1) - (5)].val.i_tkval)), OPf_STACKED,
                                op_prepend_elem(OP_LIST, newGVREF(IVAL((ps[(1) - (5)].val.i_tkval)),(ps[(3) - (5)].val.opval)), (ps[(4) - (5)].val.opval)) );
                          TOKEN_GETMAD((ps[(1) - (5)].val.i_tkval),(yyval.opval),'o');
@@ -850,7 +852,7 @@ case 2:
     break;
 
   case 102:
-#line 802 "perly.y"
+#line 804 "perly.y"
     { (yyval.opval) = convert(OP_ENTERSUB, OPf_STACKED,
                                op_append_elem(OP_LIST,
                                    op_prepend_elem(OP_LIST, scalar((ps[(1) - (6)].val.opval)), (ps[(5) - (6)].val.opval)),
@@ -862,7 +864,7 @@ case 2:
     break;
 
   case 103:
-#line 811 "perly.y"
+#line 813 "perly.y"
     { (yyval.opval) = convert(OP_ENTERSUB, OPf_STACKED,
                                op_append_elem(OP_LIST, scalar((ps[(1) - (3)].val.opval)),
                                    newUNOP(OP_METHOD, 0, (ps[(3) - (3)].val.opval))));
@@ -871,7 +873,7 @@ case 2:
     break;
 
   case 104:
-#line 817 "perly.y"
+#line 819 "perly.y"
     { (yyval.opval) = convert(OP_ENTERSUB, OPf_STACKED,
                                op_append_elem(OP_LIST,
                                    op_prepend_elem(OP_LIST, (ps[(2) - (3)].val.opval), (ps[(3) - (3)].val.opval)),
@@ -880,7 +882,7 @@ case 2:
     break;
 
   case 105:
-#line 823 "perly.y"
+#line 825 "perly.y"
     { (yyval.opval) = convert(OP_ENTERSUB, OPf_STACKED,
                                op_append_elem(OP_LIST,
                                    op_prepend_elem(OP_LIST, (ps[(2) - (5)].val.opval), (ps[(4) - (5)].val.opval)),
@@ -891,14 +893,14 @@ case 2:
     break;
 
   case 106:
-#line 831 "perly.y"
+#line 833 "perly.y"
     { (yyval.opval) = convert(IVAL((ps[(1) - (2)].val.i_tkval)), 0, (ps[(2) - (2)].val.opval));
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 107:
-#line 835 "perly.y"
+#line 837 "perly.y"
     { (yyval.opval) = convert(IVAL((ps[(1) - (4)].val.i_tkval)), 0, (ps[(3) - (4)].val.opval));
                          TOKEN_GETMAD((ps[(1) - (4)].val.i_tkval),(yyval.opval),'o');
                          TOKEN_GETMAD((ps[(2) - (4)].val.i_tkval),(yyval.opval),'(');
@@ -907,13 +909,13 @@ case 2:
     break;
 
   case 108:
-#line 841 "perly.y"
+#line 843 "perly.y"
     { SvREFCNT_inc_simple_void(PL_compcv);
                          (yyval.opval) = newANONATTRSUB((ps[(2) - (3)].val.ival), 0, (OP*)NULL, (ps[(3) - (3)].val.opval)); ;}
     break;
 
   case 109:
-#line 844 "perly.y"
+#line 846 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                                 op_append_elem(OP_LIST,
                                   op_prepend_elem(OP_LIST, (ps[(4) - (5)].val.opval), (ps[(5) - (5)].val.opval)), (ps[(1) - (5)].val.opval)));
@@ -921,7 +923,7 @@ case 2:
     break;
 
   case 112:
-#line 859 "perly.y"
+#line 861 "perly.y"
     { (yyval.opval) = newBINOP(OP_GELEM, 0, (ps[(1) - (5)].val.opval), scalar((ps[(3) - (5)].val.opval)));
                            PL_parser->expect = XOPERATOR;
                          TOKEN_GETMAD((ps[(2) - (5)].val.i_tkval),(yyval.opval),'{');
@@ -931,7 +933,7 @@ case 2:
     break;
 
   case 113:
-#line 866 "perly.y"
+#line 868 "perly.y"
     { (yyval.opval) = newBINOP(OP_AELEM, 0, oopsAV((ps[(1) - (4)].val.opval)), scalar((ps[(3) - (4)].val.opval)));
                          TOKEN_GETMAD((ps[(2) - (4)].val.i_tkval),(yyval.opval),'[');
                          TOKEN_GETMAD((ps[(4) - (4)].val.i_tkval),(yyval.opval),']');
@@ -939,7 +941,7 @@ case 2:
     break;
 
   case 114:
-#line 871 "perly.y"
+#line 873 "perly.y"
     { (yyval.opval) = newBINOP(OP_AELEM, 0,
                                        ref(newAVREF((ps[(1) - (5)].val.opval)),OP_RV2AV),
                                        scalar((ps[(4) - (5)].val.opval)));
@@ -950,7 +952,7 @@ case 2:
     break;
 
   case 115:
-#line 879 "perly.y"
+#line 881 "perly.y"
     { (yyval.opval) = newBINOP(OP_AELEM, 0,
                                        ref(newAVREF((ps[(1) - (4)].val.opval)),OP_RV2AV),
                                        scalar((ps[(3) - (4)].val.opval)));
@@ -960,7 +962,7 @@ case 2:
     break;
 
   case 116:
-#line 886 "perly.y"
+#line 888 "perly.y"
     { (yyval.opval) = newBINOP(OP_HELEM, 0, oopsHV((ps[(1) - (5)].val.opval)), jmaybe((ps[(3) - (5)].val.opval)));
                            PL_parser->expect = XOPERATOR;
                          TOKEN_GETMAD((ps[(2) - (5)].val.i_tkval),(yyval.opval),'{');
@@ -970,7 +972,7 @@ case 2:
     break;
 
   case 117:
-#line 893 "perly.y"
+#line 895 "perly.y"
     { (yyval.opval) = newBINOP(OP_HELEM, 0,
                                        ref(newHVREF((ps[(1) - (6)].val.opval)),OP_RV2HV),
                                        jmaybe((ps[(4) - (6)].val.opval)));
@@ -983,7 +985,7 @@ case 2:
     break;
 
   case 118:
-#line 903 "perly.y"
+#line 905 "perly.y"
     { (yyval.opval) = newBINOP(OP_HELEM, 0,
                                        ref(newHVREF((ps[(1) - (5)].val.opval)),OP_RV2HV),
                                        jmaybe((ps[(3) - (5)].val.opval)));
@@ -995,7 +997,7 @@ case 2:
     break;
 
   case 119:
-#line 912 "perly.y"
+#line 914 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                                   newCVREF(0, scalar((ps[(1) - (4)].val.opval))));
                          TOKEN_GETMAD((ps[(2) - (4)].val.i_tkval),(yyval.opval),'a');
@@ -1005,7 +1007,7 @@ case 2:
     break;
 
   case 120:
-#line 919 "perly.y"
+#line 921 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                                   op_append_elem(OP_LIST, (ps[(4) - (5)].val.opval),
                                       newCVREF(0, scalar((ps[(1) - (5)].val.opval)))));
@@ -1016,7 +1018,7 @@ case 2:
     break;
 
   case 121:
-#line 928 "perly.y"
+#line 930 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                                   op_append_elem(OP_LIST, (ps[(3) - (4)].val.opval),
                                               newCVREF(0, scalar((ps[(1) - (4)].val.opval)))));
@@ -1026,7 +1028,7 @@ case 2:
     break;
 
   case 122:
-#line 935 "perly.y"
+#line 937 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                                   newCVREF(0, scalar((ps[(1) - (3)].val.opval))));
                          TOKEN_GETMAD((ps[(2) - (3)].val.i_tkval),(yyval.opval),'(');
@@ -1035,7 +1037,7 @@ case 2:
     break;
 
   case 123:
-#line 941 "perly.y"
+#line 943 "perly.y"
     { (yyval.opval) = newSLICEOP(0, (ps[(5) - (6)].val.opval), (ps[(2) - (6)].val.opval));
                          TOKEN_GETMAD((ps[(1) - (6)].val.i_tkval),(yyval.opval),'(');
                          TOKEN_GETMAD((ps[(3) - (6)].val.i_tkval),(yyval.opval),')');
@@ -1045,7 +1047,7 @@ case 2:
     break;
 
   case 124:
-#line 948 "perly.y"
+#line 950 "perly.y"
     { (yyval.opval) = newSLICEOP(0, (ps[(3) - (4)].val.opval), (ps[(1) - (4)].val.opval));
                          TOKEN_GETMAD((ps[(2) - (4)].val.i_tkval),(yyval.opval),'[');
                          TOKEN_GETMAD((ps[(4) - (4)].val.i_tkval),(yyval.opval),']');
@@ -1053,7 +1055,7 @@ case 2:
     break;
 
   case 125:
-#line 953 "perly.y"
+#line 955 "perly.y"
     { (yyval.opval) = newSLICEOP(0, (ps[(4) - (5)].val.opval), (OP*)NULL);
                          TOKEN_GETMAD((ps[(1) - (5)].val.i_tkval),(yyval.opval),'(');
                          TOKEN_GETMAD((ps[(2) - (5)].val.i_tkval),(yyval.opval),')');
@@ -1063,21 +1065,21 @@ case 2:
     break;
 
   case 126:
-#line 963 "perly.y"
+#line 965 "perly.y"
     { (yyval.opval) = newASSIGNOP(OPf_STACKED, (ps[(1) - (3)].val.opval), IVAL((ps[(2) - (3)].val.i_tkval)), (ps[(3) - (3)].val.opval));
                          TOKEN_GETMAD((ps[(2) - (3)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 127:
-#line 967 "perly.y"
+#line 969 "perly.y"
     { (yyval.opval) = newBINOP(IVAL((ps[(2) - (3)].val.i_tkval)), 0, scalar((ps[(1) - (3)].val.opval)), scalar((ps[(3) - (3)].val.opval)));
                          TOKEN_GETMAD((ps[(2) - (3)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 128:
-#line 971 "perly.y"
+#line 973 "perly.y"
     {   if (IVAL((ps[(2) - (3)].val.i_tkval)) != OP_REPEAT)
                                scalar((ps[(1) - (3)].val.opval));
                            (yyval.opval) = newBINOP(IVAL((ps[(2) - (3)].val.i_tkval)), 0, (ps[(1) - (3)].val.opval), scalar((ps[(3) - (3)].val.opval)));
@@ -1086,49 +1088,49 @@ case 2:
     break;
 
   case 129:
-#line 977 "perly.y"
+#line 979 "perly.y"
     { (yyval.opval) = newBINOP(IVAL((ps[(2) - (3)].val.i_tkval)), 0, scalar((ps[(1) - (3)].val.opval)), scalar((ps[(3) - (3)].val.opval)));
                          TOKEN_GETMAD((ps[(2) - (3)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 130:
-#line 981 "perly.y"
+#line 983 "perly.y"
     { (yyval.opval) = newBINOP(IVAL((ps[(2) - (3)].val.i_tkval)), 0, scalar((ps[(1) - (3)].val.opval)), scalar((ps[(3) - (3)].val.opval)));
                          TOKEN_GETMAD((ps[(2) - (3)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 131:
-#line 985 "perly.y"
+#line 987 "perly.y"
     { (yyval.opval) = newBINOP(IVAL((ps[(2) - (3)].val.i_tkval)), 0, scalar((ps[(1) - (3)].val.opval)), scalar((ps[(3) - (3)].val.opval)));
                          TOKEN_GETMAD((ps[(2) - (3)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 132:
-#line 989 "perly.y"
+#line 991 "perly.y"
     { (yyval.opval) = newBINOP(IVAL((ps[(2) - (3)].val.i_tkval)), 0, scalar((ps[(1) - (3)].val.opval)), scalar((ps[(3) - (3)].val.opval)));
                          TOKEN_GETMAD((ps[(2) - (3)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 133:
-#line 993 "perly.y"
+#line 995 "perly.y"
     { (yyval.opval) = newBINOP(IVAL((ps[(2) - (3)].val.i_tkval)), 0, scalar((ps[(1) - (3)].val.opval)), scalar((ps[(3) - (3)].val.opval)));
                          TOKEN_GETMAD((ps[(2) - (3)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 134:
-#line 997 "perly.y"
+#line 999 "perly.y"
     { (yyval.opval) = newBINOP(IVAL((ps[(2) - (3)].val.i_tkval)), 0, scalar((ps[(1) - (3)].val.opval)), scalar((ps[(3) - (3)].val.opval)));
                          TOKEN_GETMAD((ps[(2) - (3)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 135:
-#line 1001 "perly.y"
+#line 1003 "perly.y"
     {
                          (yyval.opval) = newRANGE(IVAL((ps[(2) - (3)].val.i_tkval)), scalar((ps[(1) - (3)].val.opval)), scalar((ps[(3) - (3)].val.opval)));
                          DO_MAD({
@@ -1143,28 +1145,28 @@ case 2:
     break;
 
   case 136:
-#line 1013 "perly.y"
+#line 1015 "perly.y"
     { (yyval.opval) = newLOGOP(OP_AND, 0, (ps[(1) - (3)].val.opval), (ps[(3) - (3)].val.opval));
                          TOKEN_GETMAD((ps[(2) - (3)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 137:
-#line 1017 "perly.y"
+#line 1019 "perly.y"
     { (yyval.opval) = newLOGOP(OP_OR, 0, (ps[(1) - (3)].val.opval), (ps[(3) - (3)].val.opval));
                          TOKEN_GETMAD((ps[(2) - (3)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 138:
-#line 1021 "perly.y"
+#line 1023 "perly.y"
     { (yyval.opval) = newLOGOP(OP_DOR, 0, (ps[(1) - (3)].val.opval), (ps[(3) - (3)].val.opval));
                          TOKEN_GETMAD((ps[(2) - (3)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 139:
-#line 1025 "perly.y"
+#line 1027 "perly.y"
     { (yyval.opval) = bind_match(IVAL((ps[(2) - (3)].val.i_tkval)), (ps[(1) - (3)].val.opval), (ps[(3) - (3)].val.opval));
                          TOKEN_GETMAD((ps[(2) - (3)].val.i_tkval),
                                ((yyval.opval)->op_type == OP_NOT
@@ -1174,14 +1176,14 @@ case 2:
     break;
 
   case 140:
-#line 1035 "perly.y"
+#line 1037 "perly.y"
     { (yyval.opval) = newUNOP(OP_NEGATE, 0, scalar((ps[(2) - (2)].val.opval)));
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 141:
-#line 1039 "perly.y"
+#line 1041 "perly.y"
     { (yyval.opval) = IF_MAD(
                                    newUNOP(OP_NULL, 0, (ps[(2) - (2)].val.opval)),
                                    (ps[(2) - (2)].val.opval)
@@ -1191,21 +1193,21 @@ case 2:
     break;
 
   case 142:
-#line 1046 "perly.y"
+#line 1048 "perly.y"
     { (yyval.opval) = newUNOP(OP_NOT, 0, scalar((ps[(2) - (2)].val.opval)));
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 143:
-#line 1050 "perly.y"
+#line 1052 "perly.y"
     { (yyval.opval) = newUNOP(OP_COMPLEMENT, 0, scalar((ps[(2) - (2)].val.opval)));
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 144:
-#line 1054 "perly.y"
+#line 1056 "perly.y"
     { (yyval.opval) = newUNOP(OP_POSTINC, 0,
                                        op_lvalue(scalar((ps[(1) - (2)].val.opval)), OP_POSTINC));
                          TOKEN_GETMAD((ps[(2) - (2)].val.i_tkval),(yyval.opval),'o');
@@ -1213,7 +1215,7 @@ case 2:
     break;
 
   case 145:
-#line 1059 "perly.y"
+#line 1061 "perly.y"
     { (yyval.opval) = newUNOP(OP_POSTDEC, 0,
                                        op_lvalue(scalar((ps[(1) - (2)].val.opval)), OP_POSTDEC));
                          TOKEN_GETMAD((ps[(2) - (2)].val.i_tkval),(yyval.opval),'o');
@@ -1221,7 +1223,7 @@ case 2:
     break;
 
   case 146:
-#line 1064 "perly.y"
+#line 1066 "perly.y"
     { (yyval.opval) = newUNOP(OP_PREINC, 0,
                                        op_lvalue(scalar((ps[(2) - (2)].val.opval)), OP_PREINC));
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'o');
@@ -1229,7 +1231,7 @@ case 2:
     break;
 
   case 147:
-#line 1069 "perly.y"
+#line 1071 "perly.y"
     { (yyval.opval) = newUNOP(OP_PREDEC, 0,
                                        op_lvalue(scalar((ps[(2) - (2)].val.opval)), OP_PREDEC));
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'o');
@@ -1237,7 +1239,7 @@ case 2:
     break;
 
   case 148:
-#line 1078 "perly.y"
+#line 1080 "perly.y"
     { (yyval.opval) = newANONLIST((ps[(2) - (3)].val.opval));
                          TOKEN_GETMAD((ps[(1) - (3)].val.i_tkval),(yyval.opval),'[');
                          TOKEN_GETMAD((ps[(3) - (3)].val.i_tkval),(yyval.opval),']');
@@ -1245,7 +1247,7 @@ case 2:
     break;
 
   case 149:
-#line 1083 "perly.y"
+#line 1085 "perly.y"
     { (yyval.opval) = newANONLIST((OP*)NULL);
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'[');
                          TOKEN_GETMAD((ps[(2) - (2)].val.i_tkval),(yyval.opval),']');
@@ -1253,7 +1255,7 @@ case 2:
     break;
 
   case 150:
-#line 1088 "perly.y"
+#line 1090 "perly.y"
     { (yyval.opval) = newANONHASH((ps[(2) - (4)].val.opval));
                          TOKEN_GETMAD((ps[(1) - (4)].val.i_tkval),(yyval.opval),'{');
                          TOKEN_GETMAD((ps[(3) - (4)].val.i_tkval),(yyval.opval),';');
@@ -1262,7 +1264,7 @@ case 2:
     break;
 
   case 151:
-#line 1094 "perly.y"
+#line 1096 "perly.y"
     { (yyval.opval) = newANONHASH((OP*)NULL);
                          TOKEN_GETMAD((ps[(1) - (3)].val.i_tkval),(yyval.opval),'{');
                          TOKEN_GETMAD((ps[(2) - (3)].val.i_tkval),(yyval.opval),';');
@@ -1271,7 +1273,7 @@ case 2:
     break;
 
   case 152:
-#line 1100 "perly.y"
+#line 1102 "perly.y"
     { SvREFCNT_inc_simple_void(PL_compcv);
                          (yyval.opval) = newANONATTRSUB((ps[(2) - (5)].val.ival), (ps[(3) - (5)].val.opval), (ps[(4) - (5)].val.opval), (ps[(5) - (5)].val.opval));
                          TOKEN_GETMAD((ps[(1) - (5)].val.i_tkval),(yyval.opval),'o');
@@ -1281,21 +1283,21 @@ case 2:
     break;
 
   case 153:
-#line 1111 "perly.y"
+#line 1113 "perly.y"
     { (yyval.opval) = dofile((ps[(2) - (2)].val.opval), IVAL((ps[(1) - (2)].val.i_tkval)));
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 154:
-#line 1115 "perly.y"
+#line 1117 "perly.y"
     { (yyval.opval) = newUNOP(OP_NULL, OPf_SPECIAL, op_scope((ps[(2) - (2)].val.opval)));
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'D');
                        ;}
     break;
 
   case 155:
-#line 1119 "perly.y"
+#line 1121 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB,
                            OPf_SPECIAL|OPf_STACKED,
                            op_prepend_elem(OP_LIST,
@@ -1310,7 +1312,7 @@ case 2:
     break;
 
   case 156:
-#line 1131 "perly.y"
+#line 1133 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB,
                            OPf_SPECIAL|OPf_STACKED,
                            op_append_elem(OP_LIST,
@@ -1326,7 +1328,7 @@ case 2:
     break;
 
   case 157:
-#line 1144 "perly.y"
+#line 1146 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
                            op_prepend_elem(OP_LIST,
                                scalar(newCVREF(0,scalar((ps[(2) - (4)].val.opval)))), (OP*)NULL)); dep();
@@ -1337,7 +1339,7 @@ case 2:
     break;
 
   case 158:
-#line 1152 "perly.y"
+#line 1154 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
                            op_prepend_elem(OP_LIST,
                                (ps[(4) - (5)].val.opval),
@@ -1349,7 +1351,7 @@ case 2:
     break;
 
   case 163:
-#line 1168 "perly.y"
+#line 1170 "perly.y"
     { (yyval.opval) = newCONDOP(0, (ps[(1) - (5)].val.opval), (ps[(3) - (5)].val.opval), (ps[(5) - (5)].val.opval));
                          TOKEN_GETMAD((ps[(2) - (5)].val.i_tkval),(yyval.opval),'?');
                          TOKEN_GETMAD((ps[(4) - (5)].val.i_tkval),(yyval.opval),':');
@@ -1357,26 +1359,26 @@ case 2:
     break;
 
   case 164:
-#line 1173 "perly.y"
+#line 1175 "perly.y"
     { (yyval.opval) = newUNOP(OP_REFGEN, 0, op_lvalue((ps[(2) - (2)].val.opval),OP_REFGEN));
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 165:
-#line 1177 "perly.y"
+#line 1179 "perly.y"
     { (yyval.opval) = (ps[(1) - (1)].val.opval); ;}
     break;
 
   case 166:
-#line 1179 "perly.y"
+#line 1181 "perly.y"
     { (yyval.opval) = localize((ps[(2) - (2)].val.opval),IVAL((ps[(1) - (2)].val.i_tkval)));
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'k');
                        ;}
     break;
 
   case 167:
-#line 1183 "perly.y"
+#line 1185 "perly.y"
     { (yyval.opval) = sawparens(IF_MAD(newUNOP(OP_NULL,0,(ps[(2) - (3)].val.opval)), (ps[(2) - (3)].val.opval)));
                          TOKEN_GETMAD((ps[(1) - (3)].val.i_tkval),(yyval.opval),'(');
                          TOKEN_GETMAD((ps[(3) - (3)].val.i_tkval),(yyval.opval),')');
@@ -1384,12 +1386,12 @@ case 2:
     break;
 
   case 168:
-#line 1188 "perly.y"
+#line 1190 "perly.y"
     { (yyval.opval) = IF_MAD(newUNOP(OP_NULL,0,(ps[(1) - (1)].val.opval)), (ps[(1) - (1)].val.opval)); ;}
     break;
 
   case 169:
-#line 1190 "perly.y"
+#line 1192 "perly.y"
     { (yyval.opval) = sawparens(newNULLLIST());
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'(');
                          TOKEN_GETMAD((ps[(2) - (2)].val.i_tkval),(yyval.opval),')');
@@ -1397,37 +1399,37 @@ case 2:
     break;
 
   case 170:
-#line 1195 "perly.y"
+#line 1197 "perly.y"
     { (yyval.opval) = (ps[(1) - (1)].val.opval); ;}
     break;
 
   case 171:
-#line 1197 "perly.y"
+#line 1199 "perly.y"
     { (yyval.opval) = (ps[(1) - (1)].val.opval); ;}
     break;
 
   case 172:
-#line 1199 "perly.y"
+#line 1201 "perly.y"
     { (yyval.opval) = (ps[(1) - (1)].val.opval); ;}
     break;
 
   case 173:
-#line 1201 "perly.y"
+#line 1203 "perly.y"
     { (yyval.opval) = (ps[(1) - (1)].val.opval); ;}
     break;
 
   case 174:
-#line 1203 "perly.y"
+#line 1205 "perly.y"
     { (yyval.opval) = newUNOP(OP_AV2ARYLEN, 0, ref((ps[(1) - (1)].val.opval), OP_AV2ARYLEN));;}
     break;
 
   case 175:
-#line 1205 "perly.y"
+#line 1207 "perly.y"
     { (yyval.opval) = (ps[(1) - (1)].val.opval); ;}
     break;
 
   case 176:
-#line 1207 "perly.y"
+#line 1209 "perly.y"
     { (yyval.opval) = op_prepend_elem(OP_ASLICE,
                                newOP(OP_PUSHMARK, 0),
                                    newLISTOP(OP_ASLICE, 0,
@@ -1439,7 +1441,7 @@ case 2:
     break;
 
   case 177:
-#line 1216 "perly.y"
+#line 1218 "perly.y"
     { (yyval.opval) = op_prepend_elem(OP_HSLICE,
                                newOP(OP_PUSHMARK, 0),
                                    newLISTOP(OP_HSLICE, 0,
@@ -1453,17 +1455,17 @@ case 2:
     break;
 
   case 178:
-#line 1227 "perly.y"
+#line 1229 "perly.y"
     { (yyval.opval) = (ps[(1) - (1)].val.opval); ;}
     break;
 
   case 179:
-#line 1229 "perly.y"
+#line 1231 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, 0, scalar((ps[(1) - (1)].val.opval))); ;}
     break;
 
   case 180:
-#line 1231 "perly.y"
+#line 1233 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar((ps[(1) - (3)].val.opval)));
                          TOKEN_GETMAD((ps[(2) - (3)].val.i_tkval),(yyval.opval),'(');
                          TOKEN_GETMAD((ps[(3) - (3)].val.i_tkval),(yyval.opval),')');
@@ -1471,7 +1473,7 @@ case 2:
     break;
 
   case 181:
-#line 1236 "perly.y"
+#line 1238 "perly.y"
     {
                          (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                                op_append_elem(OP_LIST, (ps[(3) - (4)].val.opval), scalar((ps[(1) - (4)].val.opval))));
@@ -1487,7 +1489,7 @@ case 2:
     break;
 
   case 182:
-#line 1249 "perly.y"
+#line 1251 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                            op_append_elem(OP_LIST, (ps[(3) - (3)].val.opval), scalar((ps[(2) - (3)].val.opval))));
                          TOKEN_GETMAD((ps[(1) - (3)].val.i_tkval),(yyval.opval),'o');
@@ -1495,7 +1497,7 @@ case 2:
     break;
 
   case 183:
-#line 1254 "perly.y"
+#line 1256 "perly.y"
     { (yyval.opval) = newOP(IVAL((ps[(1) - (1)].val.i_tkval)), OPf_SPECIAL);
                            PL_hints |= HINT_BLOCK_SCOPE;
                          TOKEN_GETMAD((ps[(1) - (1)].val.i_tkval),(yyval.opval),'o');
@@ -1503,74 +1505,74 @@ case 2:
     break;
 
   case 184:
-#line 1259 "perly.y"
+#line 1261 "perly.y"
     { (yyval.opval) = newLOOPEX(IVAL((ps[(1) - (2)].val.i_tkval)),(ps[(2) - (2)].val.opval));
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 185:
-#line 1263 "perly.y"
+#line 1265 "perly.y"
     { (yyval.opval) = newUNOP(OP_NOT, 0, scalar((ps[(2) - (2)].val.opval)));
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 186:
-#line 1267 "perly.y"
+#line 1269 "perly.y"
     { (yyval.opval) = newOP(IVAL((ps[(1) - (1)].val.i_tkval)), 0);
                          TOKEN_GETMAD((ps[(1) - (1)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 187:
-#line 1271 "perly.y"
+#line 1273 "perly.y"
     { (yyval.opval) = newUNOP(IVAL((ps[(1) - (2)].val.i_tkval)), 0, (ps[(2) - (2)].val.opval));
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 188:
-#line 1275 "perly.y"
+#line 1277 "perly.y"
     { (yyval.opval) = newUNOP(IVAL((ps[(1) - (2)].val.i_tkval)), 0, (ps[(2) - (2)].val.opval));
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 189:
-#line 1279 "perly.y"
+#line 1281 "perly.y"
     { (yyval.opval) = newOP(OP_REQUIRE, (ps[(1) - (1)].val.i_tkval) ? OPf_SPECIAL : 0);
                          TOKEN_GETMAD((ps[(1) - (1)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 190:
-#line 1283 "perly.y"
+#line 1285 "perly.y"
     { (yyval.opval) = newUNOP(OP_REQUIRE, (ps[(1) - (2)].val.i_tkval) ? OPf_SPECIAL : 0, (ps[(2) - (2)].val.opval));
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 191:
-#line 1287 "perly.y"
+#line 1289 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar((ps[(1) - (1)].val.opval))); ;}
     break;
 
   case 192:
-#line 1289 "perly.y"
+#line 1291 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                            op_append_elem(OP_LIST, (ps[(2) - (2)].val.opval), scalar((ps[(1) - (2)].val.opval)))); ;}
     break;
 
   case 193:
-#line 1292 "perly.y"
+#line 1294 "perly.y"
     { (yyval.opval) = newOP(IVAL((ps[(1) - (1)].val.i_tkval)), 0);
                          TOKEN_GETMAD((ps[(1) - (1)].val.i_tkval),(yyval.opval),'o');
                        ;}
     break;
 
   case 194:
-#line 1296 "perly.y"
+#line 1298 "perly.y"
     { (yyval.opval) = newOP(IVAL((ps[(1) - (3)].val.i_tkval)), 0);
                          TOKEN_GETMAD((ps[(1) - (3)].val.i_tkval),(yyval.opval),'o');
                          TOKEN_GETMAD((ps[(2) - (3)].val.i_tkval),(yyval.opval),'(');
@@ -1579,12 +1581,12 @@ case 2:
     break;
 
   case 195:
-#line 1302 "perly.y"
+#line 1304 "perly.y"
     { (yyval.opval) = (ps[(1) - (1)].val.opval); ;}
     break;
 
   case 196:
-#line 1304 "perly.y"
+#line 1306 "perly.y"
     { (yyval.opval) = (ps[(1) - (3)].val.opval);
                          TOKEN_GETMAD((ps[(2) - (3)].val.i_tkval),(yyval.opval),'(');
                          TOKEN_GETMAD((ps[(3) - (3)].val.i_tkval),(yyval.opval),')');
@@ -1592,13 +1594,13 @@ case 2:
     break;
 
   case 197:
-#line 1309 "perly.y"
+#line 1311 "perly.y"
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                                scalar((ps[(1) - (1)].val.opval))); ;}
     break;
 
   case 198:
-#line 1312 "perly.y"
+#line 1314 "perly.y"
     { (yyval.opval) = (IVAL((ps[(1) - (3)].val.i_tkval)) == OP_NOT)
                            ? newUNOP(IVAL((ps[(1) - (3)].val.i_tkval)), 0, newSVOP(OP_CONST, 0, newSViv(0)))
                            : newOP(IVAL((ps[(1) - (3)].val.i_tkval)), OPf_SPECIAL);
@@ -1610,7 +1612,7 @@ case 2:
     break;
 
   case 199:
-#line 1321 "perly.y"
+#line 1323 "perly.y"
     { (yyval.opval) = newUNOP(IVAL((ps[(1) - (4)].val.i_tkval)), 0, (ps[(3) - (4)].val.opval));
                          TOKEN_GETMAD((ps[(1) - (4)].val.i_tkval),(yyval.opval),'o');
                          TOKEN_GETMAD((ps[(2) - (4)].val.i_tkval),(yyval.opval),'(');
@@ -1619,7 +1621,7 @@ case 2:
     break;
 
   case 200:
-#line 1327 "perly.y"
+#line 1329 "perly.y"
     {
                            if (   (ps[(1) - (1)].val.opval)->op_type != OP_TRANS
                                && (ps[(1) - (1)].val.opval)->op_type != OP_TRANSR
@@ -1633,7 +1635,7 @@ case 2:
     break;
 
   case 201:
-#line 1338 "perly.y"
+#line 1340 "perly.y"
     { (yyval.opval) = pmruntime((ps[(1) - (5)].val.opval), (ps[(4) - (5)].val.opval), 1, (ps[(2) - (5)].val.ival));
                          TOKEN_GETMAD((ps[(3) - (5)].val.i_tkval),(yyval.opval),'(');
                          TOKEN_GETMAD((ps[(5) - (5)].val.i_tkval),(yyval.opval),')');
@@ -1641,7 +1643,7 @@ case 2:
     break;
 
   case 204:
-#line 1345 "perly.y"
+#line 1347 "perly.y"
     {
                          (yyval.opval) = newLISTOP(OP_DIE, 0, newOP(OP_PUSHMARK, 0),
                                newSVOP(OP_CONST, 0, newSVpvs("Unimplemented")));
@@ -1650,7 +1652,7 @@ case 2:
     break;
 
   case 206:
-#line 1355 "perly.y"
+#line 1357 "perly.y"
     { (yyval.opval) = my_attrs((ps[(2) - (3)].val.opval),(ps[(3) - (3)].val.opval));
                          DO_MAD(
                              token_getmad((ps[(1) - (3)].val.i_tkval),(yyval.opval),'d');
@@ -1661,14 +1663,14 @@ case 2:
     break;
 
   case 207:
-#line 1363 "perly.y"
+#line 1365 "perly.y"
     { (yyval.opval) = localize((ps[(2) - (2)].val.opval),IVAL((ps[(1) - (2)].val.i_tkval)));
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'d');
                        ;}
     break;
 
   case 208:
-#line 1370 "perly.y"
+#line 1372 "perly.y"
     { (yyval.opval) = sawparens((ps[(2) - (3)].val.opval));
                          TOKEN_GETMAD((ps[(1) - (3)].val.i_tkval),(yyval.opval),'(');
                          TOKEN_GETMAD((ps[(3) - (3)].val.i_tkval),(yyval.opval),')');
@@ -1676,7 +1678,7 @@ case 2:
     break;
 
   case 209:
-#line 1375 "perly.y"
+#line 1377 "perly.y"
     { (yyval.opval) = sawparens(newNULLLIST());
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'(');
                          TOKEN_GETMAD((ps[(2) - (2)].val.i_tkval),(yyval.opval),')');
@@ -1684,104 +1686,104 @@ case 2:
     break;
 
   case 210:
-#line 1380 "perly.y"
+#line 1382 "perly.y"
     { (yyval.opval) = (ps[(1) - (1)].val.opval); ;}
     break;
 
   case 211:
-#line 1382 "perly.y"
+#line 1384 "perly.y"
     { (yyval.opval) = (ps[(1) - (1)].val.opval); ;}
     break;
 
   case 212:
-#line 1384 "perly.y"
+#line 1386 "perly.y"
     { (yyval.opval) = (ps[(1) - (1)].val.opval); ;}
     break;
 
   case 213:
-#line 1389 "perly.y"
+#line 1391 "perly.y"
     { (yyval.opval) = (OP*)NULL; ;}
     break;
 
   case 214:
-#line 1391 "perly.y"
+#line 1393 "perly.y"
     { (yyval.opval) = (ps[(1) - (1)].val.opval); ;}
     break;
 
   case 215:
-#line 1395 "perly.y"
+#line 1397 "perly.y"
     { (yyval.opval) = (OP*)NULL; ;}
     break;
 
   case 216:
-#line 1397 "perly.y"
+#line 1399 "perly.y"
     { (yyval.opval) = (ps[(1) - (1)].val.opval); ;}
     break;
 
   case 217:
-#line 1403 "perly.y"
+#line 1405 "perly.y"
     { PL_parser->in_my = 0; (yyval.opval) = my((ps[(1) - (1)].val.opval)); ;}
     break;
 
   case 218:
-#line 1407 "perly.y"
+#line 1409 "perly.y"
     { (yyval.opval) = newCVREF(IVAL((ps[(1) - (2)].val.i_tkval)),(ps[(2) - (2)].val.opval));
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'&');
                        ;}
     break;
 
   case 219:
-#line 1413 "perly.y"
+#line 1415 "perly.y"
     { (yyval.opval) = newSVREF((ps[(2) - (2)].val.opval));
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'$');
                        ;}
     break;
 
   case 220:
-#line 1419 "perly.y"
+#line 1421 "perly.y"
     { (yyval.opval) = newAVREF((ps[(2) - (2)].val.opval));
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'@');
                        ;}
     break;
 
   case 221:
-#line 1425 "perly.y"
+#line 1427 "perly.y"
     { (yyval.opval) = newHVREF((ps[(2) - (2)].val.opval));
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'%');
                        ;}
     break;
 
   case 222:
-#line 1431 "perly.y"
+#line 1433 "perly.y"
     { (yyval.opval) = newAVREF((ps[(2) - (2)].val.opval));
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'l');
                        ;}
     break;
 
   case 223:
-#line 1437 "perly.y"
+#line 1439 "perly.y"
     { (yyval.opval) = newGVREF(0,(ps[(2) - (2)].val.opval));
                          TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'*');
                        ;}
     break;
 
   case 224:
-#line 1444 "perly.y"
+#line 1446 "perly.y"
     { (yyval.opval) = scalar((ps[(1) - (1)].val.opval)); ;}
     break;
 
   case 225:
-#line 1446 "perly.y"
+#line 1448 "perly.y"
     { (yyval.opval) = scalar((ps[(1) - (1)].val.opval)); ;}
     break;
 
   case 226:
-#line 1448 "perly.y"
+#line 1450 "perly.y"
     { (yyval.opval) = op_scope((ps[(1) - (1)].val.opval)); ;}
     break;
 
   case 227:
-#line 1451 "perly.y"
+#line 1453 "perly.y"
     { (yyval.opval) = (ps[(1) - (1)].val.opval); ;}
     break;
 
@@ -1792,6 +1794,6 @@ case 2:
     
 
 /* Generated from:
- * 38ce4bf3d0e9f8cfd35795d89907c7d03583b561b55406230d749c80d62d5e06 perly.y
+ * 22767f994fcf1e0f0dfc8c69fd8218ca01b59a2ba367fa36181bfaa804e8af87 perly.y
  * 4a3ced51fe6585f6ec59e65e1ffd74bc976c498b0e6992eaab337219fee72e51 regen_perly.pl
  * ex: set ro: */
diff --git a/perly.h b/perly.h
index ae7b1f5..7fc431d 100644 (file)
--- a/perly.h
+++ b/perly.h
@@ -268,6 +268,6 @@ typedef union YYSTYPE
 
 
 /* Generated from:
- * 38ce4bf3d0e9f8cfd35795d89907c7d03583b561b55406230d749c80d62d5e06 perly.y
+ * 22767f994fcf1e0f0dfc8c69fd8218ca01b59a2ba367fa36181bfaa804e8af87 perly.y
  * 4a3ced51fe6585f6ec59e65e1ffd74bc976c498b0e6992eaab337219fee72e51 regen_perly.pl
  * ex: set ro: */
index c46250e..8086644 100644 (file)
--- a/perly.tab
+++ b/perly.tab
@@ -183,26 +183,26 @@ static const yytype_uint16 yyrline[] =
        0,   141,   141,   140,   150,   149,   159,   158,   171,   170,
      183,   182,   195,   194,   206,   216,   226,   229,   239,   244,
      245,   255,   256,   265,   273,   277,   284,   293,   295,   300,
-     318,   317,   365,   377,   393,   392,   409,   418,   427,   438,
-     440,   442,   452,   462,   483,   492,   501,   510,   517,   516,
-     533,   539,   549,   573,   574,   579,   581,   583,   587,   591,
-     595,   599,   604,   610,   611,   617,   631,   632,   641,   647,
-     648,   653,   656,   660,   665,   669,   673,   677,   678,   682,
-     688,   693,   698,   699,   704,   705,   710,   711,   715,   725,
-     729,   739,   740,   750,   754,   758,   762,   766,   776,   785,
-     789,   794,   801,   810,   816,   822,   830,   834,   841,   840,
-     851,   852,   856,   865,   870,   878,   885,   892,   902,   911,
-     918,   927,   934,   940,   947,   952,   962,   966,   970,   976,
-     980,   984,   988,   992,   996,  1000,  1012,  1016,  1020,  1024,
-    1034,  1038,  1045,  1049,  1053,  1058,  1063,  1068,  1077,  1082,
-    1087,  1093,  1099,  1110,  1114,  1118,  1130,  1143,  1151,  1163,
-    1164,  1165,  1166,  1167,  1172,  1176,  1178,  1182,  1187,  1189,
-    1194,  1196,  1198,  1200,  1202,  1204,  1206,  1215,  1226,  1228,
-    1230,  1235,  1248,  1253,  1258,  1262,  1266,  1270,  1274,  1278,
-    1282,  1286,  1288,  1291,  1295,  1301,  1303,  1308,  1311,  1320,
-    1327,  1326,  1342,  1343,  1344,  1350,  1354,  1362,  1369,  1374,
-    1379,  1381,  1383,  1388,  1390,  1395,  1396,  1402,  1406,  1412,
-    1418,  1424,  1430,  1436,  1443,  1445,  1447,  1450
+     318,   317,   367,   379,   395,   394,   411,   420,   429,   440,
+     442,   444,   454,   464,   485,   494,   503,   512,   519,   518,
+     535,   541,   551,   575,   576,   581,   583,   585,   589,   593,
+     597,   601,   606,   612,   613,   619,   633,   634,   643,   649,
+     650,   655,   658,   662,   667,   671,   675,   679,   680,   684,
+     690,   695,   700,   701,   706,   707,   712,   713,   717,   727,
+     731,   741,   742,   752,   756,   760,   764,   768,   778,   787,
+     791,   796,   803,   812,   818,   824,   832,   836,   843,   842,
+     853,   854,   858,   867,   872,   880,   887,   894,   904,   913,
+     920,   929,   936,   942,   949,   954,   964,   968,   972,   978,
+     982,   986,   990,   994,   998,  1002,  1014,  1018,  1022,  1026,
+    1036,  1040,  1047,  1051,  1055,  1060,  1065,  1070,  1079,  1084,
+    1089,  1095,  1101,  1112,  1116,  1120,  1132,  1145,  1153,  1165,
+    1166,  1167,  1168,  1169,  1174,  1178,  1180,  1184,  1189,  1191,
+    1196,  1198,  1200,  1202,  1204,  1206,  1208,  1217,  1228,  1230,
+    1232,  1237,  1250,  1255,  1260,  1264,  1268,  1272,  1276,  1280,
+    1284,  1288,  1290,  1293,  1297,  1303,  1305,  1310,  1313,  1322,
+    1329,  1328,  1344,  1345,  1346,  1352,  1356,  1364,  1371,  1376,
+    1381,  1383,  1385,  1390,  1392,  1397,  1398,  1404,  1408,  1414,
+    1420,  1426,  1432,  1438,  1445,  1447,  1449,  1452
 };
 #endif
 
@@ -1113,6 +1113,6 @@ static const toketypes yy_type_tab[] =
 };
 
 /* Generated from:
- * 38ce4bf3d0e9f8cfd35795d89907c7d03583b561b55406230d749c80d62d5e06 perly.y
+ * 22767f994fcf1e0f0dfc8c69fd8218ca01b59a2ba367fa36181bfaa804e8af87 perly.y
  * 4a3ced51fe6585f6ec59e65e1ffd74bc976c498b0e6992eaab337219fee72e51 regen_perly.pl
  * ex: set ro: */
diff --git a/perly.y b/perly.y
index 4613f04..a6d2a7b 100644 (file)
--- a/perly.y
+++ b/perly.y
@@ -327,9 +327,11 @@ barestmt:  PLUGSTMT
                          else
                          /* State subs inside anonymous subs need to be
                             clonable themselves. */
-                         /* XXX This will need adjustment for state subs
-                                inside my subs. */
-                         if (CvANON(CvOUTSIDE(PL_compcv)))
+                         if (CvANON(CvOUTSIDE(PL_compcv))
+                          || CvCLONE(CvOUTSIDE(PL_compcv))
+                          || !PadnameIsSTATE(PadlistNAMESARRAY(CvPADLIST(
+                                               CvOUTSIDE(PL_compcv)
+                                            ))[$2->op_targ]))
                              CvCLONE_on(PL_compcv);
                          PL_parser->in_my = 0;
                          PL_parser->in_my_stash = NULL;
diff --git a/pp.c b/pp.c
index 51b6788..6448462 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -154,12 +154,35 @@ PP(pp_padcv)
 
 PP(pp_introcv)
 {
-    DIE(aTHX_ "panic: introcv");
+    dVAR; dTARGET;
+    SvPADSTALE_off(TARG);
+    return NORMAL;
 }
 
 PP(pp_clonecv)
 {
-    DIE(aTHX_ "panic: clonecv");
+    dVAR; dTARGET;
+    MAGIC * const mg = mg_find(TARG, PERL_MAGIC_proto);
+    assert(SvTYPE(TARG) == SVt_PVCV);
+    assert(mg);
+    assert(mg->mg_obj);
+    if (CvISXSUB(mg->mg_obj)) { /* constant */
+       /* XXX Should we clone it here? */
+       /* XXX Does this play nicely with pad_push? */
+       /* If this changes to use SAVECLEARSV, we can move the SAVECLEARSV
+          to introcv and remove the SvPADSTALE_off. */
+       SAVEPADSVANDMORTALIZE(ARGTARG);
+       PAD_SVl(ARGTARG) = mg->mg_obj;
+    }
+    else {
+       if (CvROOT(mg->mg_obj)) {
+           assert(CvCLONE(mg->mg_obj));
+           assert(!CvCLONED(mg->mg_obj));
+       }
+       cv_clone_into((CV *)mg->mg_obj,(CV *)TARG);
+       SAVECLEARSV(PAD_SVl(ARGTARG));
+    }
+    return NORMAL;
 }
 
 /* Translations. */
diff --git a/proto.h b/proto.h
index c09d5fe..49e5c35 100644 (file)
--- a/proto.h
+++ b/proto.h
@@ -691,6 +691,12 @@ PERL_CALLCONV CV*  Perl_cv_clone(pTHX_ CV* proto)
 #define PERL_ARGS_ASSERT_CV_CLONE      \
        assert(proto)
 
+PERL_CALLCONV CV*      Perl_cv_clone_into(pTHX_ CV* proto, CV *target)
+                       __attribute__nonnull__(pTHX_1)
+                       __attribute__nonnull__(pTHX_2);
+#define PERL_ARGS_ASSERT_CV_CLONE_INTO \
+       assert(proto); assert(target)
+
 PERL_CALLCONV SV*      Perl_cv_const_sv(pTHX_ const CV *const cv)
                        __attribute__warn_unused_result__;
 
@@ -2974,7 +2980,7 @@ PERL_CALLCONV void        Perl_pad_fixup_inner_anons(pTHX_ PADLIST *padlist, CV *old_cv
        assert(padlist); assert(old_cv); assert(new_cv)
 
 PERL_CALLCONV void     Perl_pad_free(pTHX_ PADOFFSET po);
-PERL_CALLCONV void     Perl_pad_leavemy(pTHX);
+PERL_CALLCONV OP *     Perl_pad_leavemy(pTHX);
 PERL_CALLCONV PADLIST* Perl_pad_new(pTHX_ int flags)
                        __attribute__malloc__
                        __attribute__warn_unused_result__;
diff --git a/scope.c b/scope.c
index acd04e7..c21fea0 100644 (file)
--- a/scope.c
+++ b/scope.c
@@ -916,8 +916,11 @@ Perl_leave_scope(pTHX_ I32 base)
                if (SvTYPE(sv) == SVt_PVHV)
                    Perl_hv_kill_backrefs(aTHX_ MUTABLE_HV(sv));
                if (SvMAGICAL(sv))
-                   sv_unmagic(sv, PERL_MAGIC_backref),
+               {
+                 sv_unmagic(sv, PERL_MAGIC_backref);
+                 if (SvTYPE(sv) != SVt_PVCV)
                    mg_free(sv);
+               }
 
                switch (SvTYPE(sv)) {
                case SVt_NULL:
@@ -929,7 +932,15 @@ Perl_leave_scope(pTHX_ I32 base)
                    hv_clear(MUTABLE_HV(sv));
                    break;
                case SVt_PVCV:
-                   Perl_croak(aTHX_ "panic: leave_scope pad code");
+               {
+                   HEK * const hek = CvNAME_HEK((CV *)sv);
+                   assert(hek);
+                   share_hek_hek(hek);
+                   cv_undef((CV *)sv);
+                   SvANY((CV *)sv)->xcv_gv_u.xcv_hek = hek;
+                   CvNAMED_on(sv);
+                   break;
+               }
                default:
                    SvOK_off(sv);
                    break;
@@ -942,6 +953,34 @@ Perl_leave_scope(pTHX_ I32 base)
                switch (SvTYPE(sv)) {   /* Console ourselves with a new value */
                case SVt_PVAV:  *(SV**)ptr = MUTABLE_SV(newAV());       break;
                case SVt_PVHV:  *(SV**)ptr = MUTABLE_SV(newHV());       break;
+               case SVt_PVCV:
+               {
+                   SV ** const svp = (SV **)ptr;
+                   MAGIC *mg = SvMAGIC(sv);
+                   MAGIC **tomg = &SvMAGIC(sv);
+
+                   /* Create a stub */
+                   *svp = newSV_type(SVt_PVCV);
+
+                   /* Share name */
+                   assert(CvNAMED(sv));
+                   SvANY((CV *)*svp)->xcv_gv_u.xcv_hek =
+                       share_hek_hek(SvANY((CV *)sv)->xcv_gv_u.xcv_hek);
+                   CvNAMED_on(*svp);
+
+                   /* Steal magic */
+                   while (mg) {
+                       if (mg->mg_type == PERL_MAGIC_proto) break;
+                       mg = *(tomg = &mg->mg_moremagic);
+                   }
+                   assert(mg);
+                   *tomg = mg->mg_moremagic;
+                   mg->mg_moremagic = SvMAGIC(*svp);
+                   SvMAGIC(*svp) = mg;
+                   mg_magical(*svp);
+                   mg_magical(sv);
+                   break;
+               }
                default:        *(SV**)ptr = newSV(0);          break;
                }
                SvREFCNT_dec(sv);       /* Cast current value to the winds. */
index fa4ccdc..348facf 100644 (file)
@@ -8,7 +8,7 @@ BEGIN {
     *bar::like = *like;
 }
 no warnings 'deprecated';
-plan 106;
+plan 107;
 
 # -------------------- our -------------------- #
 
@@ -84,9 +84,6 @@ sub bar::c { 43 }
 
 # -------------------- state -------------------- #
 
-sub on { $::TODO = ' ' }
-sub off { $::TODO = undef }
-
 use 5.01; # state
 {
   state sub foo { 44 }
@@ -415,33 +412,31 @@ sub mmake_closure {
 }
 $sub1 = mmake_closure 48;
 $sub2 = mmake_closure 49;
-on;
-is eval { &$sub1 }, 48, 'my sub in closure (1)';
-is eval { &$sub2 }, 49, 'my sub in closure (2)';
+is &$sub1, 48, 'my sub in closure (1)';
+is &$sub2, 49, 'my sub in closure (2)';
 # Test that they are cloned in named subs.
 {
   use warnings;
   my $w;
   local $SIG{__WARN__} = sub { $w .= shift };
   eval '#line 65 teetet
-    sub foom {
+    sub mfoom {
       my $x = shift;
       my sub poom { $x }
-      eval{\&poom}
+      \&poom
     }
   ';
   is $w, undef, 'my subs get no "Variable will not stay shared" messages';
-  my $poom = foom(27);
-  my $poom2 = foom(678);
-  is eval { $poom->() }, 27, 'my subs closing over outer my var (1)';
-  is eval { $poom2->() }, 678, 'my subs closing over outer my var (2)';
+  my $poom = mfoom(27);
+  my $poom2 = mfoom(678);
+  is $poom->(), 27, 'my subs closing over outer my var (1)';
+  is $poom2->(), 678, 'my subs closing over outer my var (2)';
   my $x = 43;
   my sub aoeu;
   for $x (765) {
     my sub etetetet { $x }
-    my sub aoeu { $x }
+    sub aoeu { $x }
     is etetetet, 765, 'my sub respects for() localisation';
-off;
     is aoeu, 43, 'unless it is declared outside the for loop';
   }
 }
@@ -463,11 +458,9 @@ sub make_anon_with_my_sub{
   &$s;
 
   # And make sure the my subs were actually cloned.
-on;
   isnt make_anon_with_my_sub->(0), &$s(0),
     'my subs in anon subs are cloned';
   isnt &$s(0), &$s(0), 'at each invocation of the enclosing sub';
-off;
 }
 {
   my sub BEGIN { exit };
@@ -485,3 +478,13 @@ off;
   is $w, "Subroutine redef redefined at pygpyf line 56.\n",
          "sub redefinition warnings from my subs";
 }
+
+# -------------------- Interactions (and misc tests) -------------------- #
+
+is sub {
+    my sub s1;
+    my sub s2 { 3 };
+    sub s1 { state sub foo { \&s2 } foo }
+    s1
+  }->()(), 3, 'state sub inside my sub closing over my sub uncle';
+