Deparse foreach state $x
authorFather Chrysostomos <sprout@cpan.org>
Tue, 7 Oct 2014 04:59:16 +0000 (21:59 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Tue, 7 Oct 2014 05:11:21 +0000 (22:11 -0700)
B::Deparse was emitting ‘foreach my’ instead of ‘foreach state’.

This example prints 1:

use feature ':all'; no warnings experimental;
sub f {
  my sub foo;
  foo(), return if @_;
  for state $x (1) {
    f(1);
    sub foo { print $x, "\n" }
  }
}
f()

If you change ‘state’ to ‘my’, it prints nothing.

So there is a difference between ‘for my’ and ‘for state’.  (At first
I thought there might not be.)

lib/B/Deparse.pm
lib/B/Deparse.t

index ed10826..76c6cc4 100644 (file)
@@ -35,7 +35,8 @@ BEGIN {
                OPpPAD_STATE PMf_SKIPWHITE RXf_SKIPWHITE
                RXf_PMf_CHARSET RXf_PMf_KEEPCOPY
                CVf_LOCKED OPpREVERSE_INPLACE OPpSUBSTR_REPL_FIRST
-               PMf_NONDESTRUCT OPpCONST_ARYBASE OPpEVAL_BYTES)) {
+               PMf_NONDESTRUCT OPpCONST_ARYBASE OPpEVAL_BYTES
+               SVpad_STATE)) {
        eval { import B $_ };
        no strict 'refs';
        *{$_} = sub () {0} unless *{$_}{CODE};
@@ -1278,8 +1279,10 @@ sub maybe_my {
                   && $op->name =~ /[ah]v\z/
                   && ($op->flags & (OPf_PARENS|OPf_REF)) == OPf_PARENS;
     if ($op->private & OPpLVAL_INTRO and not $self->{'avoid_local'}{$$op}) {
+       # Check $padname->FLAGS for statehood, rather than $op->private,
+       # because enteriter ops do not carry the flag.
        my $my =
-           $self->keyword($op->private & OPpPAD_STATE ? "state" : "my");
+           $self->keyword($padname->FLAGS & SVpad_STATE ? "state" : "my");
        if ($padname->FLAGS & SVpad_TYPED) {
            $my .= ' ' . $padname->SvSTASH->NAME;
        }
index 905cecf..61a2009 100644 (file)
@@ -487,6 +487,12 @@ foreach our $i (1, 2) {
     my $z = 1;
 }
 ####
+# foreach with state
+# CONTEXT use feature "state";
+foreach state $i (1, 2) {
+    state $z = 1;
+}
+####
 # reverse sort
 my @x;
 print reverse sort(@x);