B-DeparseTree
view release on metacpan or search on metacpan
lib/B/DeparseTree/TreeMain.pm view on Meta::CPAN
$body = sprintf " (%s);", $ar->[1];
}
} else {
$body = ";";
}
push @ret, sprintf "sub %s%s\n", $ar->[0], $body;
}
delete $self->{'protos_todo'};
return @ret;
}
# This gets called automatically when option:
# -MO="DeparseTree,sC" is added
# Running this prints out the program text.
sub compile {
my(@args) = @_;
return sub {
my $self = B::DeparseTree->new(@args);
# First deparse command-line args
if (defined $^I) { # deparse -i
print q(BEGIN { $^I = ).perlstring($^I).qq(; }\n);
}
if ($^W) { # deparse -w
print qq(BEGIN { \$^W = $^W; }\n);
}
if ($/ ne "\n" or defined $O::savebackslash) { # deparse -l and -0
my $fs = perlstring($/) || 'undef';
my $bs = perlstring($O::savebackslash) || 'undef';
print qq(BEGIN { \$/ = $fs; \$\\ = $bs; }\n);
}
my @BEGINs = B::begin_av->isa("B::AV") ? B::begin_av->ARRAY : ();
my @UNITCHECKs = B::unitcheck_av->isa("B::AV")
? B::unitcheck_av->ARRAY
: ();
my @CHECKs = B::check_av->isa("B::AV") ? B::check_av->ARRAY : ();
my @INITs = B::init_av->isa("B::AV") ? B::init_av->ARRAY : ();
my @ENDs = B::end_av->isa("B::AV") ? B::end_av->ARRAY : ();
if ($] < 5.020) {
for my $block (@BEGINs, @UNITCHECKs, @CHECKs, @INITs, @ENDs) {
$self->B::Deparse::todo($block, 0);
}
} else {
my @names = qw(BEGIN UNITCHECK CHECK INIT END);
my @blocks = (\@BEGINs, \@UNITCHECKs, \@CHECKs, \@INITs, \@ENDs);
while (@names) {
my ($name, $blocks) = (shift @names, shift @blocks);
for my $block (@$blocks) {
$self->todo($block, 0, $name);
}
}
}
$self->B::Deparse::stash_subs();
local($SIG{"__DIE__"}) =
sub {
if ($self->{'curcop'}) {
my $cop = $self->{'curcop'};
my($line, $file) = ($cop->line, $cop->file);
print STDERR "While deparsing $file near line $line,\n";
}
use Data::Printer;
my @bt = caller(1);
p @bt;
};
$self->{'curcv'} = main_cv;
$self->{'curcvlex'} = undef;
print $self->extract_prototypes;
@{$self->{'subs_todo'}} =
sort {$a->[0] <=> $b->[0]} @{$self->{'subs_todo'}};
my $root = main_root;
local $B::overlay = {};
if ($] < 5.021) {
unless (B::Deparse::null $root) {
$self->pessimise($root, main_start);
# Print deparsed program
print $self->deparse_root($root)->{text}, "\n";
}
} else {
unless (B::Deparse::null $root) {
$self->B::Deparse::pad_subs($self->{'curcv'});
# Check for a stub-followed-by-ex-cop, resulting from a program
# consisting solely of sub declarations. For backward-compati-
# bility (and sane output) we donât want to emit the stub.
# leave
# enter
# stub
# ex-nextstate (or ex-dbstate)
my $kid;
if ( $root->name eq 'leave'
and ($kid = $root->first)->name eq 'enter'
and !B::Deparse::null($kid = $kid->sibling) and $kid->name eq 'stub'
and !B::Deparse::null($kid = $kid->sibling) and $kid->name eq 'null'
and class($kid) eq 'COP' and B::Deparse::null $kid->sibling )
{
# ignore deparsing routine
} else {
$self->pessimise($root, main_start);
# Print deparsed program
my $root_tree = $self->deparse_root($root);
print $root_tree->{text}, "\n";
}
}
}
my @text;
while (scalar(@{$self->{'subs_todo'}})) {
push @text, $self->next_todo->{text};
}
print join("", @text), "\n" if @text;
# Print __DATA__ section, if necessary
no strict 'refs';
my $laststash = defined $self->{'curcop'}
? $self->{'curcop'}->stash->NAME : $self->{'curstash'};
if (defined *{$laststash."::DATA"}{IO}) {
print $self->keyword("package") . " $laststash;\n"
unless $laststash eq $self->{'curstash'};
print $self->keyword("__DATA__") . "\n";
print readline(*{$laststash."::DATA"});
}
}
}
( run in 1.394 second using v1.01-cache-2.11-cpan-75ffa21a3d4 )