From e07561e6ac7f381061f112bee32ebc779683a84c Mon Sep 17 00:00:00 2001 From: Father Chrysostomos Date: Mon, 9 Jul 2012 06:29:09 -0700 Subject: [PATCH] Clone state subs in anon subs MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Since state variables are not shared between closures, but only between invocations of the same closure, state subs should behave the same way. This was a little tricky. When we clone a sub, we now clone inner state subs at the same time. When walking through the pad, cloning items, we cannot simply clone the inner sub when we see it, because it may close over things we haven’t cloned yet: sub { state sub foo; my $x sub foo { $x } } We can’t just delay cloning it and do it afterwards, because they may be multiple subs closing over each other: sub { state sub foo; state sub bar; sub foo { \&bar } sub bar { \&foo } } So *all* the entries in the new pad must be filled before any inner subs can be cloned. So what we do is put a stub in place of the cloned sub. And then in a second pass clone the inner subs, reusing the stubs from the first pass. --- pad.c | 51 ++++++-- perly.act | 371 +++++++++++++++++++++++++++++---------------------------- perly.h | 2 +- perly.tab | 42 +++---- perly.y | 7 ++ t/cmd/lexsub.t | 30 ++++- 6 files changed, 281 insertions(+), 222 deletions(-) diff --git a/pad.c b/pad.c index 3bd44b2..e7252ff 100644 --- a/pad.c +++ b/pad.c @@ -1112,7 +1112,7 @@ the parent pad. #define CvCOMPILED(cv) CvROOT(cv) /* the CV does late binding of its lexicals */ -#define CvLATE(cv) (CvANON(cv) || SvTYPE(cv) == SVt_PVFM) +#define CvLATE(cv) (CvANON(cv) || CvCLONE(cv) || SvTYPE(cv) == SVt_PVFM) STATIC PADOFFSET @@ -1934,8 +1934,8 @@ the immediately surrounding code. =cut */ -CV * -Perl_cv_clone(pTHX_ CV *proto) +static CV * +S_cv_clone(pTHX_ CV *proto, CV *cv, CV *outside) { dVAR; I32 ix; @@ -1946,12 +1946,9 @@ Perl_cv_clone(pTHX_ CV *proto) SV** const ppad = AvARRAY(protopad); const I32 fname = AvFILLp(protopad_name); const I32 fpad = AvFILLp(protopad); - CV* cv; SV** outpad; - CV* outside; long depth; - - PERL_ARGS_ASSERT_CV_CLONE; + bool subclones = FALSE; assert(!CvUNIQUE(proto)); @@ -1963,9 +1960,10 @@ Perl_cv_clone(pTHX_ CV *proto) * to a prototype; we instead want the cloned parent who called us. */ - if (SvTYPE(proto) == SVt_PVCV) + if (!outside) { + if (SvTYPE(proto) == SVt_PVCV) outside = find_runcv(NULL); - else { + else { outside = CvOUTSIDE(proto); if ((CvCLONE(outside) && ! CvCLONED(outside)) || !CvPADLIST(outside) @@ -1975,9 +1973,10 @@ Perl_cv_clone(pTHX_ CV *proto) ); /* outside could be null */ } + } } depth = outside ? CvDEPTH(outside) : 0; - assert(depth || SvTYPE(proto) == SVt_PVFM); + assert(depth || cv || SvTYPE(proto) == SVt_PVFM); if (!depth) depth = 1; assert(SvTYPE(proto) == SVt_PVFM || CvPADLIST(outside)); @@ -1985,7 +1984,8 @@ Perl_cv_clone(pTHX_ CV *proto) ENTER; SAVESPTR(PL_compcv); - cv = PL_compcv = MUTABLE_CV(newSV_type(SvTYPE(proto))); + if (!cv) cv = MUTABLE_CV(newSV_type(SvTYPE(proto))); + PL_compcv = cv; CvFLAGS(cv) = CvFLAGS(proto) & ~(CVf_CLONE|CVf_WEAKOUTSIDE|CVf_CVGV_RC |CVf_SLABBED); CvCLONED_on(cv); @@ -2045,7 +2045,16 @@ Perl_cv_clone(pTHX_ CV *proto) if (!sv) { const char sigil = SvPVX_const(namesv)[0]; if (sigil == '&') - sv = SvREFCNT_inc(ppad[ix]); + /* If there are state subs, we need to clone them, too. + But they may need to close over variables we have + not cloned yet. So we will have to do a second + pass. Furthermore, there may be state subs clos- + 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]); else if (sigil == '@') sv = MUTABLE_SV(newAV()); else if (sigil == '%') @@ -2054,7 +2063,7 @@ Perl_cv_clone(pTHX_ CV *proto) sv = newSV(0); SvPADMY_on(sv); /* reset the 'assign only once' flag on each state var */ - if (SvPAD_STATE(namesv)) + if (sigil != '&' && SvPAD_STATE(namesv)) SvPADSTALE_on(sv); } } @@ -2068,6 +2077,14 @@ Perl_cv_clone(pTHX_ CV *proto) PL_curpad[ix] = sv; } + if (subclones) + for (ix = fpad; ix > 0; ix--) { + SV* const namesv = (ix <= fname) ? pname[ix] : NULL; + if (namesv && namesv != &PL_sv_undef && !SvFAKE(namesv) + && SvPVX_const(namesv)[0] == '&' && SvPAD_STATE(namesv)) + S_cv_clone(aTHX_ (CV *)ppad[ix], (CV *)PL_curpad[ix], cv); + } + DEBUG_Xv( PerlIO_printf(Perl_debug_log, "\nPad CV clone\n"); if (outside) cv_dump(outside, "Outside"); @@ -2099,6 +2116,14 @@ Perl_cv_clone(pTHX_ CV *proto) return cv; } +CV * +Perl_cv_clone(pTHX_ CV *proto) +{ + PERL_ARGS_ASSERT_CV_CLONE; + + return S_cv_clone(aTHX_ proto, NULL, NULL); +} + /* =for apidoc m|void|pad_fixup_inner_anons|PADLIST *padlist|CV *old_cv|CV *new_cv diff --git a/perly.act b/perly.act index 0ecccc6..df6d833 100644 --- a/perly.act +++ b/perly.act @@ -250,13 +250,20 @@ case 2: || strEQ(name, "UNITCHECK")) CvSPECIAL_on(PL_compcv); } + 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))) + CvCLONE_on(PL_compcv); PL_parser->in_my = 0; PL_parser->in_my_stash = NULL; ;} break; case 31: -#line 331 "perly.y" +#line 338 "perly.y" { SvREFCNT_inc_simple_void(PL_compcv); #ifdef MAD @@ -287,7 +294,7 @@ case 2: break; case 32: -#line 359 "perly.y" +#line 366 "perly.y" { /* Unimplemented "my sub foo { }" */ SvREFCNT_inc_simple_void(PL_compcv); @@ -302,7 +309,7 @@ case 2: break; case 33: -#line 371 "perly.y" +#line 378 "perly.y" { #ifdef MAD (yyval.opval) = package((ps[(3) - (4)].val.opval)); @@ -320,12 +327,12 @@ case 2: break; case 34: -#line 386 "perly.y" +#line 393 "perly.y" { CvSPECIAL_on(PL_compcv); /* It's a BEGIN {} */ ;} break; case 35: -#line 388 "perly.y" +#line 395 "perly.y" { SvREFCNT_inc_simple_void(PL_compcv); #ifdef MAD @@ -343,7 +350,7 @@ case 2: break; case 36: -#line 403 "perly.y" +#line 410 "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))); @@ -355,7 +362,7 @@ case 2: break; case 37: -#line 412 "perly.y" +#line 419 "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))); @@ -367,7 +374,7 @@ case 2: break; case 38: -#line 421 "perly.y" +#line 428 "perly.y" { const PADOFFSET offset = pad_findmy_pvs("$_", 0); (yyval.opval) = block_end((ps[(3) - (6)].val.ival), @@ -381,17 +388,17 @@ case 2: break; case 39: -#line 432 "perly.y" +#line 439 "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 434 "perly.y" +#line 441 "perly.y" { (yyval.opval) = newWHENOP(0, op_scope((ps[(2) - (2)].val.opval))); ;} break; case 41: -#line 436 "perly.y" +#line 443 "perly.y" { (yyval.opval) = block_end((ps[(3) - (8)].val.ival), newWHILEOP(0, 1, (LOOP*)(OP*)NULL, @@ -404,7 +411,7 @@ case 2: break; case 42: -#line 446 "perly.y" +#line 453 "perly.y" { (yyval.opval) = block_end((ps[(3) - (8)].val.ival), newWHILEOP(0, 1, (LOOP*)(OP*)NULL, @@ -417,7 +424,7 @@ case 2: break; case 43: -#line 457 "perly.y" +#line 464 "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, @@ -440,7 +447,7 @@ case 2: break; case 44: -#line 477 "perly.y" +#line 484 "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'); @@ -452,7 +459,7 @@ case 2: break; case 45: -#line 486 "perly.y" +#line 493 "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))); @@ -464,7 +471,7 @@ case 2: break; case 46: -#line 495 "perly.y" +#line 502 "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))); @@ -476,7 +483,7 @@ case 2: break; case 47: -#line 504 "perly.y" +#line 511 "perly.y" { /* a block is a loop that happens once */ (yyval.opval) = newWHILEOP(0, 1, (LOOP*)(OP*)NULL, @@ -485,7 +492,7 @@ case 2: break; case 48: -#line 510 "perly.y" +#line 517 "perly.y" { package((ps[(3) - (5)].val.opval)); if ((ps[(2) - (5)].val.opval)) { @@ -495,7 +502,7 @@ case 2: break; case 49: -#line 517 "perly.y" +#line 524 "perly.y" { /* a block is a loop that happens once */ (yyval.opval) = newWHILEOP(0, 1, (LOOP*)(OP*)NULL, @@ -508,7 +515,7 @@ case 2: break; case 50: -#line 527 "perly.y" +#line 534 "perly.y" { PL_parser->expect = XSTATE; (yyval.opval) = (ps[(1) - (2)].val.opval); @@ -517,7 +524,7 @@ case 2: break; case 51: -#line 533 "perly.y" +#line 540 "perly.y" { PL_parser->expect = XSTATE; (yyval.opval) = IF_MAD(newOP(OP_NULL, 0), (OP*)NULL); @@ -527,7 +534,7 @@ case 2: break; case 52: -#line 543 "perly.y" +#line 550 "perly.y" { OP *list; if ((ps[(2) - (2)].val.opval)) { OP *term = (ps[(2) - (2)].val.opval); @@ -551,55 +558,55 @@ case 2: break; case 53: -#line 566 "perly.y" +#line 573 "perly.y" { (yyval.opval) = NULL; ;} break; case 54: -#line 568 "perly.y" +#line 575 "perly.y" { (yyval.opval) = op_unscope((ps[(2) - (3)].val.opval)); ;} break; case 55: -#line 573 "perly.y" +#line 580 "perly.y" { (yyval.opval) = (OP*)NULL; ;} break; case 56: -#line 575 "perly.y" +#line 582 "perly.y" { (yyval.opval) = (ps[(1) - (1)].val.opval); ;} break; case 57: -#line 577 "perly.y" +#line 584 "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 581 "perly.y" +#line 588 "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 585 "perly.y" +#line 592 "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 589 "perly.y" +#line 596 "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 593 "perly.y" +#line 600 "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)); @@ -607,17 +614,17 @@ case 2: break; case 62: -#line 598 "perly.y" +#line 605 "perly.y" { (yyval.opval) = newWHENOP((ps[(3) - (3)].val.opval), op_scope((ps[(1) - (3)].val.opval))); ;} break; case 63: -#line 603 "perly.y" +#line 610 "perly.y" { (yyval.opval) = (OP*)NULL; ;} break; case 64: -#line 605 "perly.y" +#line 612 "perly.y" { ((ps[(2) - (2)].val.opval))->op_flags |= OPf_PARENS; (yyval.opval) = op_scope((ps[(2) - (2)].val.opval)); @@ -626,7 +633,7 @@ case 2: break; case 65: -#line 611 "perly.y" +#line 618 "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)), @@ -639,12 +646,12 @@ case 2: break; case 66: -#line 624 "perly.y" +#line 631 "perly.y" { (yyval.opval) = (OP*)NULL; ;} break; case 67: -#line 626 "perly.y" +#line 633 "perly.y" { (yyval.opval) = op_scope((ps[(2) - (2)].val.opval)); TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'o'); @@ -652,91 +659,91 @@ case 2: break; case 68: -#line 634 "perly.y" +#line 641 "perly.y" { (yyval.ival) = (PL_min_intro_pending && PL_max_intro_pending >= PL_min_intro_pending); intro_my(); ;} break; case 69: -#line 640 "perly.y" +#line 647 "perly.y" { (yyval.opval) = (OP*)NULL; ;} break; case 71: -#line 646 "perly.y" +#line 653 "perly.y" { YYSTYPE tmplval; (void)scan_num("1", &tmplval); (yyval.opval) = tmplval.opval; ;} break; case 73: -#line 654 "perly.y" +#line 661 "perly.y" { (yyval.opval) = invert(scalar((ps[(1) - (1)].val.opval))); ;} break; case 74: -#line 659 "perly.y" +#line 666 "perly.y" { (yyval.opval) = (ps[(1) - (1)].val.opval); intro_my(); ;} break; case 75: -#line 663 "perly.y" +#line 670 "perly.y" { (yyval.opval) = (ps[(1) - (1)].val.opval); intro_my(); ;} break; case 76: -#line 667 "perly.y" +#line 674 "perly.y" { (yyval.opval) = (ps[(1) - (1)].val.opval); intro_my(); ;} break; case 77: -#line 670 "perly.y" +#line 677 "perly.y" { (yyval.opval) = (ps[(1) - (1)].val.opval); ;} break; case 78: -#line 671 "perly.y" +#line 678 "perly.y" { (yyval.opval) = (OP*)NULL; ;} break; case 79: -#line 675 "perly.y" +#line 682 "perly.y" { (yyval.ival) = start_subparse(FALSE, 0); SAVEFREESV(PL_compcv); ;} break; case 80: -#line 681 "perly.y" +#line 688 "perly.y" { (yyval.ival) = start_subparse(FALSE, CVf_ANON); SAVEFREESV(PL_compcv); ;} break; case 81: -#line 686 "perly.y" +#line 693 "perly.y" { (yyval.ival) = start_subparse(TRUE, 0); SAVEFREESV(PL_compcv); ;} break; case 84: -#line 697 "perly.y" +#line 704 "perly.y" { (yyval.opval) = (OP*)NULL; ;} break; case 86: -#line 703 "perly.y" +#line 710 "perly.y" { (yyval.opval) = (OP*)NULL; ;} break; case 87: -#line 705 "perly.y" +#line 712 "perly.y" { (yyval.opval) = (ps[(2) - (2)].val.opval); TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),':'); ;} break; case 88: -#line 709 "perly.y" +#line 716 "perly.y" { (yyval.opval) = IF_MAD( newOP(OP_NULL, 0), (OP*)NULL @@ -746,14 +753,14 @@ case 2: break; case 89: -#line 719 "perly.y" +#line 726 "perly.y" { (yyval.opval) = (ps[(2) - (2)].val.opval); TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),':'); ;} break; case 90: -#line 723 "perly.y" +#line 730 "perly.y" { (yyval.opval) = IF_MAD( newOP(OP_NULL, 0), (OP*)NULL @@ -763,12 +770,12 @@ case 2: break; case 91: -#line 732 "perly.y" +#line 739 "perly.y" { (yyval.opval) = (ps[(1) - (1)].val.opval); ;} break; case 92: -#line 733 "perly.y" +#line 740 "perly.y" { (yyval.opval) = IF_MAD( newOP(OP_NULL,0), (OP*)NULL @@ -779,28 +786,28 @@ case 2: break; case 93: -#line 744 "perly.y" +#line 751 "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 748 "perly.y" +#line 755 "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 752 "perly.y" +#line 759 "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 760 "perly.y" +#line 767 "perly.y" { #ifdef MAD OP* op = newNULLLIST(); @@ -813,7 +820,7 @@ case 2: break; case 98: -#line 770 "perly.y" +#line 777 "perly.y" { OP* term = (ps[(3) - (3)].val.opval); DO_MAD( @@ -825,7 +832,7 @@ case 2: break; case 100: -#line 783 "perly.y" +#line 790 "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'); @@ -833,7 +840,7 @@ case 2: break; case 101: -#line 788 "perly.y" +#line 795 "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'); @@ -843,7 +850,7 @@ case 2: break; case 102: -#line 795 "perly.y" +#line 802 "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)), @@ -855,7 +862,7 @@ case 2: break; case 103: -#line 804 "perly.y" +#line 811 "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)))); @@ -864,7 +871,7 @@ case 2: break; case 104: -#line 810 "perly.y" +#line 817 "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)), @@ -873,7 +880,7 @@ case 2: break; case 105: -#line 816 "perly.y" +#line 823 "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)), @@ -884,14 +891,14 @@ case 2: break; case 106: -#line 824 "perly.y" +#line 831 "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 828 "perly.y" +#line 835 "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),'('); @@ -900,13 +907,13 @@ case 2: break; case 108: -#line 834 "perly.y" +#line 841 "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 837 "perly.y" +#line 844 "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))); @@ -914,7 +921,7 @@ case 2: break; case 112: -#line 852 "perly.y" +#line 859 "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),'{'); @@ -924,7 +931,7 @@ case 2: break; case 113: -#line 859 "perly.y" +#line 866 "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),']'); @@ -932,7 +939,7 @@ case 2: break; case 114: -#line 864 "perly.y" +#line 871 "perly.y" { (yyval.opval) = newBINOP(OP_AELEM, 0, ref(newAVREF((ps[(1) - (5)].val.opval)),OP_RV2AV), scalar((ps[(4) - (5)].val.opval))); @@ -943,7 +950,7 @@ case 2: break; case 115: -#line 872 "perly.y" +#line 879 "perly.y" { (yyval.opval) = newBINOP(OP_AELEM, 0, ref(newAVREF((ps[(1) - (4)].val.opval)),OP_RV2AV), scalar((ps[(3) - (4)].val.opval))); @@ -953,7 +960,7 @@ case 2: break; case 116: -#line 879 "perly.y" +#line 886 "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),'{'); @@ -963,7 +970,7 @@ case 2: break; case 117: -#line 886 "perly.y" +#line 893 "perly.y" { (yyval.opval) = newBINOP(OP_HELEM, 0, ref(newHVREF((ps[(1) - (6)].val.opval)),OP_RV2HV), jmaybe((ps[(4) - (6)].val.opval))); @@ -976,7 +983,7 @@ case 2: break; case 118: -#line 896 "perly.y" +#line 903 "perly.y" { (yyval.opval) = newBINOP(OP_HELEM, 0, ref(newHVREF((ps[(1) - (5)].val.opval)),OP_RV2HV), jmaybe((ps[(3) - (5)].val.opval))); @@ -988,7 +995,7 @@ case 2: break; case 119: -#line 905 "perly.y" +#line 912 "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'); @@ -998,7 +1005,7 @@ case 2: break; case 120: -#line 912 "perly.y" +#line 919 "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))))); @@ -1009,7 +1016,7 @@ case 2: break; case 121: -#line 921 "perly.y" +#line 928 "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))))); @@ -1019,7 +1026,7 @@ case 2: break; case 122: -#line 928 "perly.y" +#line 935 "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),'('); @@ -1028,7 +1035,7 @@ case 2: break; case 123: -#line 934 "perly.y" +#line 941 "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),')'); @@ -1038,7 +1045,7 @@ case 2: break; case 124: -#line 941 "perly.y" +#line 948 "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),']'); @@ -1046,7 +1053,7 @@ case 2: break; case 125: -#line 946 "perly.y" +#line 953 "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),')'); @@ -1056,21 +1063,21 @@ case 2: break; case 126: -#line 956 "perly.y" +#line 963 "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 960 "perly.y" +#line 967 "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 964 "perly.y" +#line 971 "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))); @@ -1079,49 +1086,49 @@ case 2: break; case 129: -#line 970 "perly.y" +#line 977 "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 974 "perly.y" +#line 981 "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 978 "perly.y" +#line 985 "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 982 "perly.y" +#line 989 "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 986 "perly.y" +#line 993 "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 990 "perly.y" +#line 997 "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 994 "perly.y" +#line 1001 "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({ @@ -1136,28 +1143,28 @@ case 2: break; case 136: -#line 1006 "perly.y" +#line 1013 "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 1010 "perly.y" +#line 1017 "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 1014 "perly.y" +#line 1021 "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 1018 "perly.y" +#line 1025 "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 @@ -1167,14 +1174,14 @@ case 2: break; case 140: -#line 1028 "perly.y" +#line 1035 "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 1032 "perly.y" +#line 1039 "perly.y" { (yyval.opval) = IF_MAD( newUNOP(OP_NULL, 0, (ps[(2) - (2)].val.opval)), (ps[(2) - (2)].val.opval) @@ -1184,21 +1191,21 @@ case 2: break; case 142: -#line 1039 "perly.y" +#line 1046 "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 1043 "perly.y" +#line 1050 "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 1047 "perly.y" +#line 1054 "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'); @@ -1206,7 +1213,7 @@ case 2: break; case 145: -#line 1052 "perly.y" +#line 1059 "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'); @@ -1214,7 +1221,7 @@ case 2: break; case 146: -#line 1057 "perly.y" +#line 1064 "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'); @@ -1222,7 +1229,7 @@ case 2: break; case 147: -#line 1062 "perly.y" +#line 1069 "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'); @@ -1230,7 +1237,7 @@ case 2: break; case 148: -#line 1071 "perly.y" +#line 1078 "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),']'); @@ -1238,7 +1245,7 @@ case 2: break; case 149: -#line 1076 "perly.y" +#line 1083 "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),']'); @@ -1246,7 +1253,7 @@ case 2: break; case 150: -#line 1081 "perly.y" +#line 1088 "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),';'); @@ -1255,7 +1262,7 @@ case 2: break; case 151: -#line 1087 "perly.y" +#line 1094 "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),';'); @@ -1264,7 +1271,7 @@ case 2: break; case 152: -#line 1093 "perly.y" +#line 1100 "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'); @@ -1274,21 +1281,21 @@ case 2: break; case 153: -#line 1104 "perly.y" +#line 1111 "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 1108 "perly.y" +#line 1115 "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 1112 "perly.y" +#line 1119 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED, op_prepend_elem(OP_LIST, @@ -1303,7 +1310,7 @@ case 2: break; case 156: -#line 1124 "perly.y" +#line 1131 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED, op_append_elem(OP_LIST, @@ -1319,7 +1326,7 @@ case 2: break; case 157: -#line 1137 "perly.y" +#line 1144 "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(); @@ -1330,7 +1337,7 @@ case 2: break; case 158: -#line 1145 "perly.y" +#line 1152 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED, op_prepend_elem(OP_LIST, (ps[(4) - (5)].val.opval), @@ -1342,7 +1349,7 @@ case 2: break; case 163: -#line 1161 "perly.y" +#line 1168 "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),':'); @@ -1350,26 +1357,26 @@ case 2: break; case 164: -#line 1166 "perly.y" +#line 1173 "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 1170 "perly.y" +#line 1177 "perly.y" { (yyval.opval) = (ps[(1) - (1)].val.opval); ;} break; case 166: -#line 1172 "perly.y" +#line 1179 "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 1176 "perly.y" +#line 1183 "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),')'); @@ -1377,12 +1384,12 @@ case 2: break; case 168: -#line 1181 "perly.y" +#line 1188 "perly.y" { (yyval.opval) = IF_MAD(newUNOP(OP_NULL,0,(ps[(1) - (1)].val.opval)), (ps[(1) - (1)].val.opval)); ;} break; case 169: -#line 1183 "perly.y" +#line 1190 "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),')'); @@ -1390,37 +1397,37 @@ case 2: break; case 170: -#line 1188 "perly.y" +#line 1195 "perly.y" { (yyval.opval) = (ps[(1) - (1)].val.opval); ;} break; case 171: -#line 1190 "perly.y" +#line 1197 "perly.y" { (yyval.opval) = (ps[(1) - (1)].val.opval); ;} break; case 172: -#line 1192 "perly.y" +#line 1199 "perly.y" { (yyval.opval) = (ps[(1) - (1)].val.opval); ;} break; case 173: -#line 1194 "perly.y" +#line 1201 "perly.y" { (yyval.opval) = (ps[(1) - (1)].val.opval); ;} break; case 174: -#line 1196 "perly.y" +#line 1203 "perly.y" { (yyval.opval) = newUNOP(OP_AV2ARYLEN, 0, ref((ps[(1) - (1)].val.opval), OP_AV2ARYLEN));;} break; case 175: -#line 1198 "perly.y" +#line 1205 "perly.y" { (yyval.opval) = (ps[(1) - (1)].val.opval); ;} break; case 176: -#line 1200 "perly.y" +#line 1207 "perly.y" { (yyval.opval) = op_prepend_elem(OP_ASLICE, newOP(OP_PUSHMARK, 0), newLISTOP(OP_ASLICE, 0, @@ -1432,7 +1439,7 @@ case 2: break; case 177: -#line 1209 "perly.y" +#line 1216 "perly.y" { (yyval.opval) = op_prepend_elem(OP_HSLICE, newOP(OP_PUSHMARK, 0), newLISTOP(OP_HSLICE, 0, @@ -1446,17 +1453,17 @@ case 2: break; case 178: -#line 1220 "perly.y" +#line 1227 "perly.y" { (yyval.opval) = (ps[(1) - (1)].val.opval); ;} break; case 179: -#line 1222 "perly.y" +#line 1229 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, 0, scalar((ps[(1) - (1)].val.opval))); ;} break; case 180: -#line 1224 "perly.y" +#line 1231 "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),')'); @@ -1464,7 +1471,7 @@ case 2: break; case 181: -#line 1229 "perly.y" +#line 1236 "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)))); @@ -1480,7 +1487,7 @@ case 2: break; case 182: -#line 1242 "perly.y" +#line 1249 "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'); @@ -1488,7 +1495,7 @@ case 2: break; case 183: -#line 1247 "perly.y" +#line 1254 "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'); @@ -1496,74 +1503,74 @@ case 2: break; case 184: -#line 1252 "perly.y" +#line 1259 "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 1256 "perly.y" +#line 1263 "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 1260 "perly.y" +#line 1267 "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 1264 "perly.y" +#line 1271 "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 1268 "perly.y" +#line 1275 "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 1272 "perly.y" +#line 1279 "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 1276 "perly.y" +#line 1283 "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 1280 "perly.y" +#line 1287 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar((ps[(1) - (1)].val.opval))); ;} break; case 192: -#line 1282 "perly.y" +#line 1289 "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 1285 "perly.y" +#line 1292 "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 1289 "perly.y" +#line 1296 "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),'('); @@ -1572,12 +1579,12 @@ case 2: break; case 195: -#line 1295 "perly.y" +#line 1302 "perly.y" { (yyval.opval) = (ps[(1) - (1)].val.opval); ;} break; case 196: -#line 1297 "perly.y" +#line 1304 "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),')'); @@ -1585,13 +1592,13 @@ case 2: break; case 197: -#line 1302 "perly.y" +#line 1309 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar((ps[(1) - (1)].val.opval))); ;} break; case 198: -#line 1305 "perly.y" +#line 1312 "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); @@ -1603,7 +1610,7 @@ case 2: break; case 199: -#line 1314 "perly.y" +#line 1321 "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),'('); @@ -1612,7 +1619,7 @@ case 2: break; case 200: -#line 1320 "perly.y" +#line 1327 "perly.y" { if ( (ps[(1) - (1)].val.opval)->op_type != OP_TRANS && (ps[(1) - (1)].val.opval)->op_type != OP_TRANSR @@ -1626,7 +1633,7 @@ case 2: break; case 201: -#line 1331 "perly.y" +#line 1338 "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),')'); @@ -1634,7 +1641,7 @@ case 2: break; case 204: -#line 1338 "perly.y" +#line 1345 "perly.y" { (yyval.opval) = newLISTOP(OP_DIE, 0, newOP(OP_PUSHMARK, 0), newSVOP(OP_CONST, 0, newSVpvs("Unimplemented"))); @@ -1643,7 +1650,7 @@ case 2: break; case 206: -#line 1348 "perly.y" +#line 1355 "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'); @@ -1654,14 +1661,14 @@ case 2: break; case 207: -#line 1356 "perly.y" +#line 1363 "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 1363 "perly.y" +#line 1370 "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),')'); @@ -1669,7 +1676,7 @@ case 2: break; case 209: -#line 1368 "perly.y" +#line 1375 "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),')'); @@ -1677,104 +1684,104 @@ case 2: break; case 210: -#line 1373 "perly.y" +#line 1380 "perly.y" { (yyval.opval) = (ps[(1) - (1)].val.opval); ;} break; case 211: -#line 1375 "perly.y" +#line 1382 "perly.y" { (yyval.opval) = (ps[(1) - (1)].val.opval); ;} break; case 212: -#line 1377 "perly.y" +#line 1384 "perly.y" { (yyval.opval) = (ps[(1) - (1)].val.opval); ;} break; case 213: -#line 1382 "perly.y" +#line 1389 "perly.y" { (yyval.opval) = (OP*)NULL; ;} break; case 214: -#line 1384 "perly.y" +#line 1391 "perly.y" { (yyval.opval) = (ps[(1) - (1)].val.opval); ;} break; case 215: -#line 1388 "perly.y" +#line 1395 "perly.y" { (yyval.opval) = (OP*)NULL; ;} break; case 216: -#line 1390 "perly.y" +#line 1397 "perly.y" { (yyval.opval) = (ps[(1) - (1)].val.opval); ;} break; case 217: -#line 1396 "perly.y" +#line 1403 "perly.y" { PL_parser->in_my = 0; (yyval.opval) = my((ps[(1) - (1)].val.opval)); ;} break; case 218: -#line 1400 "perly.y" +#line 1407 "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 1406 "perly.y" +#line 1413 "perly.y" { (yyval.opval) = newSVREF((ps[(2) - (2)].val.opval)); TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'$'); ;} break; case 220: -#line 1412 "perly.y" +#line 1419 "perly.y" { (yyval.opval) = newAVREF((ps[(2) - (2)].val.opval)); TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'@'); ;} break; case 221: -#line 1418 "perly.y" +#line 1425 "perly.y" { (yyval.opval) = newHVREF((ps[(2) - (2)].val.opval)); TOKEN_GETMAD((ps[(1) - (2)].val.i_tkval),(yyval.opval),'%'); ;} break; case 222: -#line 1424 "perly.y" +#line 1431 "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 1430 "perly.y" +#line 1437 "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 1437 "perly.y" +#line 1444 "perly.y" { (yyval.opval) = scalar((ps[(1) - (1)].val.opval)); ;} break; case 225: -#line 1439 "perly.y" +#line 1446 "perly.y" { (yyval.opval) = scalar((ps[(1) - (1)].val.opval)); ;} break; case 226: -#line 1441 "perly.y" +#line 1448 "perly.y" { (yyval.opval) = op_scope((ps[(1) - (1)].val.opval)); ;} break; case 227: -#line 1444 "perly.y" +#line 1451 "perly.y" { (yyval.opval) = (ps[(1) - (1)].val.opval); ;} break; @@ -1785,6 +1792,6 @@ case 2: /* Generated from: - * 46a0f37bedef614c67088ca538be1a60acad74ce92b27d0244bd16b23eb7fd8d perly.y + * 38ce4bf3d0e9f8cfd35795d89907c7d03583b561b55406230d749c80d62d5e06 perly.y * 4a3ced51fe6585f6ec59e65e1ffd74bc976c498b0e6992eaab337219fee72e51 regen_perly.pl * ex: set ro: */ diff --git a/perly.h b/perly.h index 1758c41..ae7b1f5 100644 --- a/perly.h +++ b/perly.h @@ -268,6 +268,6 @@ typedef union YYSTYPE /* Generated from: - * 46a0f37bedef614c67088ca538be1a60acad74ce92b27d0244bd16b23eb7fd8d perly.y + * 38ce4bf3d0e9f8cfd35795d89907c7d03583b561b55406230d749c80d62d5e06 perly.y * 4a3ced51fe6585f6ec59e65e1ffd74bc976c498b0e6992eaab337219fee72e51 regen_perly.pl * ex: set ro: */ diff --git a/perly.tab b/perly.tab index e404319..c46250e 100644 --- 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, 358, 370, 386, 385, 402, 411, 420, 431, - 433, 435, 445, 455, 476, 485, 494, 503, 510, 509, - 526, 532, 542, 566, 567, 572, 574, 576, 580, 584, - 588, 592, 597, 603, 604, 610, 624, 625, 634, 640, - 641, 646, 649, 653, 658, 662, 666, 670, 671, 675, - 681, 686, 691, 692, 697, 698, 703, 704, 708, 718, - 722, 732, 733, 743, 747, 751, 755, 759, 769, 778, - 782, 787, 794, 803, 809, 815, 823, 827, 834, 833, - 844, 845, 849, 858, 863, 871, 878, 885, 895, 904, - 911, 920, 927, 933, 940, 945, 955, 959, 963, 969, - 973, 977, 981, 985, 989, 993, 1005, 1009, 1013, 1017, - 1027, 1031, 1038, 1042, 1046, 1051, 1056, 1061, 1070, 1075, - 1080, 1086, 1092, 1103, 1107, 1111, 1123, 1136, 1144, 1156, - 1157, 1158, 1159, 1160, 1165, 1169, 1171, 1175, 1180, 1182, - 1187, 1189, 1191, 1193, 1195, 1197, 1199, 1208, 1219, 1221, - 1223, 1228, 1241, 1246, 1251, 1255, 1259, 1263, 1267, 1271, - 1275, 1279, 1281, 1284, 1288, 1294, 1296, 1301, 1304, 1313, - 1320, 1319, 1335, 1336, 1337, 1343, 1347, 1355, 1362, 1367, - 1372, 1374, 1376, 1381, 1383, 1388, 1389, 1395, 1399, 1405, - 1411, 1417, 1423, 1429, 1436, 1438, 1440, 1443 + 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 }; #endif @@ -1113,6 +1113,6 @@ static const toketypes yy_type_tab[] = }; /* Generated from: - * 46a0f37bedef614c67088ca538be1a60acad74ce92b27d0244bd16b23eb7fd8d perly.y + * 38ce4bf3d0e9f8cfd35795d89907c7d03583b561b55406230d749c80d62d5e06 perly.y * 4a3ced51fe6585f6ec59e65e1ffd74bc976c498b0e6992eaab337219fee72e51 regen_perly.pl * ex: set ro: */ diff --git a/perly.y b/perly.y index 0b94075..4613f04 100644 --- a/perly.y +++ b/perly.y @@ -324,6 +324,13 @@ barestmt: PLUGSTMT || strEQ(name, "UNITCHECK")) CvSPECIAL_on(PL_compcv); } + 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))) + CvCLONE_on(PL_compcv); PL_parser->in_my = 0; PL_parser->in_my_stash = NULL; } diff --git a/t/cmd/lexsub.t b/t/cmd/lexsub.t index d940d1c..e285a84 100644 --- a/t/cmd/lexsub.t +++ b/t/cmd/lexsub.t @@ -8,7 +8,7 @@ BEGIN { *bar::like = *like; } no warnings 'deprecated'; -plan 58; +plan 62; # -------------------- our -------------------- # @@ -199,18 +199,16 @@ package main; # Since state vars inside anonymous subs are cloned at the same time as the # anonymous subs containing them, the same should happen for state subs. sub make_closure { - state $x = shift; + my $x = shift; sub { state sub foo { $x } - eval {foo} + foo } } $sub1 = make_closure 48; $sub2 = make_closure 49; is &$sub1, 48, 'state sub in closure (1)'; -on; is &$sub2, 49, 'state sub in closure (2)'; -off; # But we need to test that state subs actually do persist from one invoca- # tion of a named sub to another (i.e., that they are not my subs). { @@ -238,6 +236,28 @@ on; off; } } +# And we also need to test that multiple state subs can close over each +# other’s entries in the parent subs pad, and that cv_clone is not con- +# fused by that. +sub make_anon_with_state_sub{ + sub { + state sub s1; + state sub s2 { \&s1 } + sub s1 { \&s2 } + if (@_) { return \&s1 } + is s1,\&s2, 'state sub in anon closure closing over sibling state sub'; + is s2,\&s1, 'state sub in anon closure closing over sibling state sub'; + } +} +{ + my $s = make_anon_with_state_sub; + &$s; + + # And make sure the state subs were actually cloned. + isnt make_anon_with_state_sub->(0), &$s(0), + 'state subs in anon subs are cloned'; + is &$s(0), &$s(0), 'but only when the anon sub is cloned'; +} { state sub BEGIN { exit }; pass 'state subs are never special blocks'; -- 1.8.3.1