B-Tap

 view release on metacpan or  search on metacpan

lib/Devel/CodeObserver.pm  view on Meta::CPAN

package Devel::CodeObserver;
use strict;
use warnings;
use utf8;
use 5.010_001;

our $VERSION = "0.16";

our @WARNINGS;

use B qw(class ppname);
use B::Tap qw(tap);
use B::Tools qw(op_walk);
use Data::Dumper ();

sub new {
    my $class = shift;
    my %args = @_==1 ? %{$_[0]} : @_;
    bless {%args}, $class;
}

sub null {
    my $op = shift;
    return class($op) eq "NULL";
}

sub call {
    my ($class,$code) = @_;

    my $cv = B::svref_2object($code);

    my @tap_results;

    my $root = $cv->ROOT;
    # local $B::overlay = {};
    if (not null $root) {
        op_walk {
            if (need_hook($_)) {
                my @buf = ($_);
                tap($_, $cv->ROOT, \@buf);
                push @tap_results, \@buf;
            }
        } $cv->ROOT;
    }
    if (0) {
        require B::Concise;
        my $walker = B::Concise::compile('', '', $code);
        $walker->();
    }

    my $retval = $code->();

    return (
        $retval,
        Devel::CallTrace::Result->new(
            code => $code,
            tap_results => [grep { @$_ > 1 } @tap_results],
        )
    );
}

sub need_hook {
    my $op = shift;
    return 1 if $op->name eq 'entersub';
    return 1 if $op->name eq 'padsv';
    return 1 if $op->name eq 'aelem';
    return 1 if $op->name eq 'helem';
    return 1 if $op->name eq 'null' && ppname($op->targ) eq 'pp_rv2sv';
    return 0;
}

package Devel::CallTrace::Result;

use Try::Tiny;
use constant { DEBUG => 0 };

sub new {
    my $class = shift;
    my %args = @_==1 ? %{$_[0]} : @_;
    bless {%args}, $class;
}

sub dump_pairs {
    my ($self) = @_;
    my $tap_results = $self->{tap_results};
    my $code = $self->{code};

    # We should load B::Deparse lazily. Because loading B::Deparse is really slow.
    # It's really big module.
    #
    # And so, this module is mainly used for testing. And this part is only required if
    # the test case was failed. I make faster the passed test case.
    require B::Deparse;

    my @pairs;



( run in 0.593 second using v1.01-cache-2.11-cpan-39bf76dae61 )