diff options
author | Father Chrysostomos <sprout@cpan.org> | 2010-12-08 16:52:08 -0800 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2010-12-08 16:52:32 -0800 |
commit | a1fba7eb664f6fea65549e94672040d8e47c905e (patch) | |
tree | e4796dcd38c011b1967e5c74c5d95d0d21f5de68 /op.c | |
parent | 9f0564c6a634ece822d85183eb4065e894294d7f (diff) | |
download | perl-a1fba7eb664f6fea65549e94672040d8e47c905e.tar.gz |
[perl #68658] attributes turn "state" into "my"
This is for two reasons:
• In S_my_kid, the attribute-handling code comes before the code that
marks the padop as being a state instead of a my, which it knows to
do based on the value of PL_parser->in_my. The attribute-handling
code begins by setting PL_parser->in_my to FALSE, preventing the
code that follows from doing its job.
So now PL_parser->in_my is read at the top of S_my_kid, before the
attribute code, with the statehood recorded in a boolean. Then the
code that marks the padop as being state checks that boolean
instead of in_my.
• A lexical variable declaration that has an attribute and is assigned
to in the same expression compiles to something similar to:
(attributes->import(... \$x ...), my $x) = 3;
where the list is actually in scalar context, returning the my $x
which is then assigned to (something that cannot be expressed
directly in Perl syntax). So Perl_ck_sassign needs to take that list
op into account when creating the ‘once’ op that actually makes
state assignment work. Up till now it was just looking for a padsv
on its LHS. This commit makes it check also for a list op whose last
item is a padsv.
Diffstat (limited to 'op.c')
-rw-r--r-- | op.c | 11 |
1 files changed, 9 insertions, 2 deletions
@@ -2143,6 +2143,7 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp) { dVAR; I32 type; + const bool stately = PL_parser && PL_parser->in_my == KEY_state; PERL_ARGS_ASSERT_MY_KID; @@ -2213,7 +2214,7 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp) } o->op_flags |= OPf_MOD; o->op_private |= OPpLVAL_INTRO; - if (PL_parser->in_my == KEY_state) + if (stately) o->op_private |= OPpPAD_STATE; return o; } @@ -7937,7 +7938,13 @@ Perl_ck_sassign(pTHX_ OP *o) } if (kid->op_sibling) { OP *kkid = kid->op_sibling; - if (kkid->op_type == OP_PADSV + /* For state variable assignment, kkid is a list op whose op_last + is a padsv. */ + if ((kkid->op_type == OP_PADSV || + (kkid->op_type == OP_LIST && + (kkid = cLISTOPx(kkid)->op_last)->op_type == OP_PADSV + ) + ) && (kkid->op_private & OPpLVAL_INTRO) && SvPAD_STATE(*av_fetch(PL_comppad_name, kkid->op_targ, FALSE))) { const PADOFFSET target = kkid->op_targ; |