diff options
author | David Mitchell <davem@iabyn.com> | 2016-07-20 17:31:00 +0100 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2016-08-03 20:54:40 +0100 |
commit | bc304ab29c846b89ecada79bc60b7a841981bab2 (patch) | |
tree | 6c8d62530332f13bca949b7345cd8496ffe98733 /lib/B/Deparse.pm | |
parent | 4fa06845e75d453a3101cff32e24c5b743f9819e (diff) | |
download | perl-bc304ab29c846b89ecada79bc60b7a841981bab2.tar.gz |
deparse pragmas before subs
Currently something like this:
use strict;
sub f {
print;
}
print;
deparses as:
sub f {
use strict;
print $_;
}
use strict;
print $_;
(Note where the 'strict's appear). Although ugly, this is semantically
correct for most pragmas. However, it breaks down for "use feature
'signatures'", since that needs to appear before the sub if the
deparsing of the sub's header is altered to reflect signature syntax or
not, based on whether the pragma is in scope.
This commit changes the deparsing of each nextstate op so that it outputs
any pragmas which reflect changes since the last nextstate's hints etc,
*before* deparsing any subs whose COP is less than that of the new
nextstate. After this commit, the code above deparses as:
use strict;
sub f {
print $_;
}
print $_;
It also allows some hacky code to be removed from Deparse.pm that
ensured that "no warnings experimental::lexical_subs" appeared before
each lexical sub was deparsed.
[ This fix is not comprehensive; a fuller fix comes in a few commits time ]
Diffstat (limited to 'lib/B/Deparse.pm')
-rw-r--r-- | lib/B/Deparse.pm | 64 |
1 files changed, 19 insertions, 45 deletions
diff --git a/lib/B/Deparse.pm b/lib/B/Deparse.pm index 7e4c55ce1a..1ee584e8fb 100644 --- a/lib/B/Deparse.pm +++ b/lib/B/Deparse.pm @@ -495,46 +495,8 @@ sub next_todo { my $ent = shift @{$self->{'subs_todo'}}; my $cv = $ent->[1]; if (ref $ent->[3]) { # lexical sub + # emit the sub. my @text; - - # At this point, we may not yet have deparsed the hints that allow - # lexical subroutines to be recognized. So adjust the current - # hints and deparse them. - # When lex subs cease being experimental, we should be able to - # remove this code. - { - local $^H = $self->{'hints'}; - local %^H = %{ $self->{'hinthash'} || {} }; - local ${^WARNING_BITS} = $self->{'warnings'}; - feature->import("lexical_subs"); - warnings->unimport("experimental::lexical_subs"); - # Here we depend on the fact that individual features - # will always set the feature bundle to ‘custom’ - # (== $feature::hint_mask). If we had another specific bundle - # enabled previously, normalise it. - if (($self->{'hints'} & $feature::hint_mask) - != $feature::hint_mask) - { - if ($self->{'hinthash'}) { - delete $self->{'hinthash'}{$_} - for grep /^feature_/, keys %{$self->{'hinthash'}}; - } - else { $self->{'hinthash'} = {} } - $self->{'hinthash'} - = _features_from_bundle(@$self{'hints','hinthash'}); - } - push @text, $self->declare_hinthash($self->{'hinthash'}, \%^H, - $self->{indent_size}, $^H); - push @text, $self->declare_warnings($self->{'warnings'}, - ${^WARNING_BITS}) - unless ($self->{'warnings'} // 'u') - eq (${^WARNING_BITS } // 'u'); - $self->{'warnings'} = ${^WARNING_BITS}; - $self->{'hints'} = $^H; - $self->{'hinthash'} = {%^H}; - } - - # Now emit the sub itself. my $padname = $ent->[3]; my $flags = $padname->FLAGS; push @text, @@ -560,6 +522,7 @@ sub next_todo { } return join "", @text; } + my $gv = $cv->GV; my $name = $ent->[3] // $self->gv_name($gv); if ($ent->[2]) { @@ -1946,11 +1909,7 @@ sub pp_nextstate { my($op, $cx) = @_; $self->{'curcop'} = $op; my @text; - push @text, $self->cop_subs($op); - if (@text) { - # Special marker to swallow up the semicolon - push @text, "\cK"; - } + my $stash = $op->stashpv; if ($stash ne $self->{'curstash'}) { push @text, $self->keyword("package") . " $stash;\n"; @@ -2029,6 +1988,21 @@ sub pp_nextstate { $self->{'hinthash'} = $newhh; } + my @subs = $self->cop_subs($op); + if (@subs) { + # Special marker to swallow up the semicolon + push @subs, "\cK"; + } + push @text, @subs; + + # cop_subs above may have changed the package; restore it + $stash = $op->stashpv; + if ($stash ne $self->{'curstash'}) { + push @text, $self->keyword("package") . " $stash;\n"; + $self->{'curstash'} = $stash; + } + + # This should go after of any branches that add statements, to # increase the chances that it refers to the same line it did in # the original program. @@ -6316,7 +6290,7 @@ which is not, consequently, deparsed correctly. =item * Lexical (my) variables declared in scopes external to a subroutine -appear in code2ref output text as package variables. This is a tricky +appear in coderef2text output text as package variables. This is a tricky problem, as perl has no native facility for referring to a lexical variable defined within a different scope, although L<PadWalker> is a good start. |