1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
#!./perl -w
BEGIN { ## no critic strict
if ( $ENV{PERL_CORE} ) {
unshift @INC, '../../t/lib';
} else {
unshift @INC, 't';
}
require Config;
if ( ( $Config::Config{'extensions'} !~ /\bB\b/ ) ) {
print "1..0 # Skip -- Perl configured without B module\n";
exit 0;
}
}
use strict;
use warnings;
use Test::More tests => 4 * 3;
use B 'svref_2object';
# use Data::Dumper 'Dumper';
sub foo {
my ( $x, $y, $z );
# hh => {},
$z = $x * $y;
# hh => { mypragma => 42 }
use mypragma;
$z = $x + $y;
# hh => { mypragma => 0 }
no mypragma;
$z = $x - $y;
}
{
# Pragmas don't appear til they're used.
my $cop = find_op_cop( \&foo, qr/multiply/ );
isa_ok( $cop, 'B::COP', 'found pp_multiply opnode' );
my $rhe = $cop->hints_hash;
isa_ok( $rhe, 'B::RHE', 'got hints_hash' );
my $hints_hash = $rhe->HASH;
is( ref($hints_hash), 'HASH', 'Got hash reference' );
ok( not( exists $hints_hash->{mypragma} ), q[! exists mypragma] );
}
{
# Pragmas can be fetched.
my $cop = find_op_cop( \&foo, qr/add/ );
isa_ok( $cop, 'B::COP', 'found pp_add opnode' );
my $rhe = $cop->hints_hash;
isa_ok( $rhe, 'B::RHE', 'got hints_hash' );
my $hints_hash = $rhe->HASH;
is( ref($hints_hash), 'HASH', 'Got hash reference' );
is( $hints_hash->{mypragma}, 42, q[mypragma => 42] );
}
{
# Pragmas can be changed.
my $cop = find_op_cop( \&foo, qr/subtract/ );
isa_ok( $cop, 'B::COP', 'found pp_subtract opnode' );
my $rhe = $cop->hints_hash;
isa_ok( $rhe, 'B::RHE', 'got hints_hash' );
my $hints_hash = $rhe->HASH;
is( ref($hints_hash), 'HASH', 'Got hash reference' );
is( $hints_hash->{mypragma}, 0, q[mypragma => 0] );
}
exit;
our $COP;
sub find_op_cop {
my ( $sub, $op ) = @_;
my $cv = svref_2object($sub);
local $COP;
if ( not _find_op_cop( $cv->ROOT, $op ) ) {
$COP = undef;
}
return $COP;
}
{
# Make B::NULL objects evaluate as false.
package B::NULL;
use overload 'bool' => sub () { !!0 };
}
sub _find_op_cop {
my ( $op, $name ) = @_;
# Fail on B::NULL or whatever.
return 0 if not $op;
# Succeed when we find our match.
return 1 if $op->name =~ $name;
# Stash the latest seen COP opnode. This has our hints hash.
if ( $op->isa('B::COP') ) {
# print Dumper(
# { cop => $op,
# hints => $op->hints_hash->HASH
# }
# );
$COP = $op;
}
# Recurse depth first passing success up if it happens.
if ( $op->can('first') ) {
return 1 if _find_op_cop( $op->first, $name );
}
return 1 if _find_op_cop( $op->sibling, $name );
# Oh well. Hopefully our caller knows where to try next.
return 0;
}
|