File Coverage

blib/lib/Contextual/Diag/Value.pm
Criterion Covered Total %
statement 55 55 100.0
branch 8 8 100.0
condition n/a
subroutine 12 12 100.0
pod 3 3 100.0
total 78 78 100.0


line stmt bran cond sub pod time code
1             package Contextual::Diag::Value;
2 2     2   35 use 5.010;
  2         7  
3 2     2   10 use strict;
  2         4  
  2         41  
4 2     2   9 use warnings;
  2         5  
  2         88  
5              
6             our $VERSION = "0.04";
7              
8 2     2   13 use Scalar::Util ();
  2         3  
  2         648  
9              
10             my %DATA;
11             my %OVERLOAD;
12              
13             sub new {
14 29     29 1 266 my ($class, $value, %overload) = @_;
15              
16             # Use inside-out to prevent infinite recursion
17 29         80 my $self = bless \my $scalar => $class;
18 29         87 my $id = Scalar::Util::refaddr $self;
19 29         118 $DATA{$id} = {
20             value => $value,
21             overload => \%overload,
22             };
23 29         173 return $self;
24             }
25              
26             BEGIN {
27 2     2   21 my %CONTEXT_MAP = (
28             q{""} => 'STR',
29             '0+' => 'NUM',
30             'bool' => 'BOOL',
31             '${}' => 'SCALARREF',
32             '@{}' => 'ARRAYREF',
33             '&{}' => 'CODEREF',
34             '%{}' => 'HASHREF',
35             '*{}' => 'GLOBREF',
36             );
37              
38             %OVERLOAD = map {
39 2         10 my $context = $CONTEXT_MAP{$_};
  16         31  
40              
41             $_ => sub {
42 18     18   68 my $self = shift;
43              
44 18         43 my $id = Scalar::Util::refaddr $self;
45 18         42 my $data = $DATA{$id};
46 18         39 my $code = $data->{overload}->{$context};
47 18         37 my $value = $data->{value};
48 18         48 return $code->($value);
49             }
50 16         198 } keys %CONTEXT_MAP,
51             }
52              
53 2     2   15 use overload %OVERLOAD, fallback => 1;
  2         5  
  2         22  
54              
55             sub can {
56 5     5 1 4069 my ($invocant) = @_;
57 5 100       20 if (ref $invocant) {
58 3         7 our $AUTOLOAD = 'can';
59 3         11 goto &AUTOLOAD;
60             }
61 2         38 return $invocant->SUPER::can(@_[1..$#_]);
62             }
63              
64             sub isa {
65 6     6 1 17 my ($invocant) = @_;
66 6 100       21 if (ref $invocant) {
67 3         8 our $AUTOLOAD = 'isa';
68 3         10 goto &AUTOLOAD;
69             }
70 3         62 return $invocant->SUPER::isa(@_[1..$#_]);
71             }
72              
73             sub AUTOLOAD {
74 8     8   34 my $self = shift;
75 8         12 our $AUTOLOAD;
76              
77 8 100       19 unless (ref $self) {
78 1         15 die "cannot AUTOLOAD in class call"
79             }
80              
81 7         14 my $obj = do {
82 7         16 my $id = Scalar::Util::refaddr $self;
83 7         14 my $data = $DATA{$id};
84 7         13 my $code = $data->{overload}->{OBJREF};
85 7         13 my $value = $data->{value};
86 7         17 $code->($value);
87             };
88              
89 7 100       66 my ($method) = $AUTOLOAD =~ m{ .* :: (.*) }xms ? $1 : $AUTOLOAD;
90 7         81 return $obj->$method(@_);
91             }
92              
93             sub DESTROY {
94 29     29   3328 my $self = shift;
95 29         70 my $id = Scalar::Util::refaddr $self;
96 29         417 delete $DATA{$id};
97 29         264 return;
98             }
99              
100             1;
101             __END__