B-DeparseTree
view release on metacpan or search on metacpan
lib/B/DeparseTree/TreeMain.pm view on Meta::CPAN
}
sub const_dumper
{
my $self = shift;
my($sv, $cx) = @_;
my $ref = $sv->object_2svref();
my $dumper = Data::Dumper->new([$$ref], ['$v']);
$dumper->Purity(1)->Terse(1)->Deparse(1)->Indent(0)->Useqq(1)->Sortkeys(1);
my $str = $dumper->Dump();
if ($str =~ /^\$v/) {
# FIXME: ???
return info_from_text($sv, $self, ['${my', $str, '\$v}'], 'const_dumper_my', {});
} else {
return $self->info_from_string("constant string", $sv, $str);
}
}
# This is a special case of scopeop and lineseq, for the case of the
# main_root.
sub deparse_root {
my $self = shift;
my($op) = @_;
local(@$self{qw'curstash warnings hints hinthash'})
= @$self{qw'curstash warnings hints hinthash'};
my @ops;
return if B::Deparse::null $op->first; # Can happen, e.g., for Bytecode without -k
for (my $kid = $op->first->sibling; !B::Deparse::null($kid); $kid = $kid->sibling) {
push @ops, $kid;
}
my $fn = sub {
my ($exprs, $i, $info, $parent) = @_;
my $text = $info->{text};
my $op = $ops[$i];
$text =~ s/\f//;
$text =~ s/\n$//;
$text =~ s/;\n?\z//;
$text =~ s/^\((.+)\)$/$1/;
$info->{type} = $op->name;
$info->{op} = $op;
$self->{optree}{$$op} = $info;
$info->{text} = $text;
$info->{parent} = $$parent if $parent;
push @$exprs, $info;
};
my $info = $self->walk_lineseq($op, \@ops, $fn);
my @skipped_ops;
if (exists $info->{other_ops}) {
@skipped_ops = @{$info->{other_ops}};
push @skipped_ops, $op->first;
} else {
@skipped_ops = ($op->first);
}
$info->{other_ops} = \@skipped_ops;
return $info;
}
sub update_node($$$$)
{
my ($self, $node, $prev_expr, $op) = @_;
$node->{prev_expr} = $prev_expr;
my $addr = $prev_expr->{addr};
if ($addr && ! exists $self->{optree}{$addr}) {
$self->{optree}{$addr} = $node if $op;
}
}
sub walk_lineseq
{
my ($self, $op, $kids, $callback) = @_;
my @kids = @$kids;
my @body = (); # Accumulated node structures
my $expr;
my $prev_expr = undef;
my $fix_cop = undef;
for (my $i = 0; $i < @kids; $i++) {
if (B::Deparse::is_state $kids[$i]) {
$expr = ($self->deparse($kids[$i], 0, $op));
$callback->(\@body, $i, $expr, $op);
$prev_expr = $expr;
if ($fix_cop) {
$fix_cop->{text} = $expr->{text};
}
$i++;
if ($i > $#kids) {
last;
}
}
if (B::Deparse::is_for_loop($kids[$i])) {
print "YYY for loop\n" if $ENV{'DEBUG_DEPARSETREE'};
my $loop_expr = $self->for_loop($kids[$i], 0);
$callback->(\@body,
$i += $kids[$i]->sibling->name eq "unstack" ? 2 : 1,
$loop_expr);
$prev_expr = $loop_expr;
next;
}
$expr = $self->deparse($kids[$i], (@kids != 1)/2, $op);
# Perform semantic action on $expr accumulating the result
# in @body. $op is the parent, and $i is the child position
$callback->(\@body, $i, $expr, $op);
unless (exists $expr->{prev_expr}) {
$self->update_node($expr, $prev_expr, $op);
}
$prev_expr = $expr;
if ($fix_cop) {
$fix_cop->{text} = $expr->{text};
}
# If the text portion of a COP is empty, set up to fill it in
# from the text portion of the next node.
if (B::class($op) eq "COP" && !$expr->{text}) {
$fix_cop = $op;
} else {
$fix_cop = undef;
}
}
( run in 0.485 second using v1.01-cache-2.11-cpan-2398b32b56e )