File Coverage

blib/lib/mro/EVERY.pm
Criterion Covered Total %
statement 37 37 100.0
branch 6 10 60.0
condition n/a
subroutine 13 13 100.0
pod n/a
total 56 60 93.3


line stmt bran cond sub pod time code
1             ########################################################################
2             # housekeeping
3             ########################################################################
4              
5             package mro::EVERY v0.1.4;
6 9     9   6324 use v5.24;
  9         26  
7 9     9   41 use mro;
  9         14  
  9         46  
8              
9 9     9   204 use Carp qw( croak );
  9         14  
  9         455  
10 9     9   48 use List::Util qw( uniq );
  9         14  
  9         971  
11 9     9   61 use Scalar::Util qw( blessed );
  9         15  
  9         429  
12 9     9   54 use Symbol qw( qualify_to_ref );
  9         27  
  9         5417  
13              
14             ########################################################################
15             # package varaibles
16             ########################################################################
17              
18             our @CARP_NOT = ( __PACKAGE__, qw( mro ) );
19             my $find_subs = '';
20             my $with_auto = '';
21              
22             ########################################################################
23             # utility subs
24             ########################################################################
25              
26             my $find_name
27             = sub
28             {
29             my $proto = shift;
30             my $auto = shift;
31             my ($name) = $auto =~ m{ (\w+) $}x;
32             my $class = blessed $proto || $proto;
33              
34             $proto->can( $name )
35             or croak "Botched EVERY: '$proto' cannot '$name'";
36              
37             # if they handle this via AUTOLOAD then we have
38             # problem at this point, see find_with_autoload.
39             #
40             # if the dispatching class has no ancestors then
41             # treat it as its own ancestor.
42            
43             local $" = ',';
44             my @isa = $class->mro::get_linear_isa->@*;
45              
46             # uniq avoids case of multiple-dispatch of
47             # hardwired inherited methods at multiple
48             # places in the tree.
49              
50             my @found
51             = uniq
52             grep
53             {
54             $_
55             }
56             map
57             {
58             *{ qualify_to_ref $name => $_ }{ CODE }
59             }
60             @isa
61             or
62             croak "Bogus $proto: '$name' not in @isa";
63              
64             @found
65             };
66              
67             my $find_with_autoload
68             = sub
69             {
70             my $proto = shift;
71             my $auto = shift;
72             my ($name) = $auto =~ m{ (\w+) $}x;
73              
74             $proto->can( $name )
75             or croak "Botched EVERY: '$proto' cannot '$name'";
76            
77             local $" = ',';
78             my @isa = $proto->mro::get_linear_isa->@*;
79              
80             # uniq avoids multiple-dispatch in case where
81             # AUTOLOAD handling $name is inherited.
82              
83             my @found
84             = uniq
85             grep
86             {
87             $_
88             }
89             map
90             {
91             *{ qualify_to_ref $name => $_ }{ CODE }
92             or
93             do
94             {
95             my $isa = qualify_to_ref ISA => $_;
96             my $ref = qualify_to_ref AUTOLOAD => $_;
97              
98             local *$isa = [];
99              
100             # at this point can is isolated to the
101             # single pacakge.
102              
103             my $al
104             = $_->can( $name )
105             ? *{ $ref }{ CODE }
106             : ''
107             ;
108              
109             $al
110             ? sub
111             {
112             # at this point if package can $name and
113             # has an AUTOLOAD but not the named sub.
114             #
115             # install $AUTOLOAD and bon voyage!
116              
117             local *{ $ref } = $auto;
118             goto &$al;
119             }
120             : ()
121             ;
122             }
123             }
124             @isa
125             or
126             croak "Bogus $proto: '$name' & AUTOLOAD not in @isa";
127              
128             @found
129             };
130              
131             sub import
132             {
133 9     9   80 shift; # discard this package
134              
135 9         18 for( @_ )
136             {
137 4 50       24 m{^ autoload $}x and $with_auto = 1;
138 4 50       12 m{^ noautoload $}x and $with_auto = '';
139             }
140              
141             $find_subs
142 9 100       38 = $with_auto
143             ? $find_with_autoload
144             : $find_name
145             ;
146              
147             return
148 9         81 }
149              
150             ########################################################################
151             # pseudo-packages
152             ########################################################################
153              
154             package EVERY;
155 9     9   102 use v5.22;
  9         27  
156 9     9   52 use Carp qw( croak );
  9         16  
  9         1165  
157              
158             our @CARP_NOT = ( __PACKAGE__, qw( mro ) );
159             our $AUTOLOAD = '';
160              
161             AUTOLOAD
162             {
163 26 50   26   87280 my $proto = shift
164             or croak "Bogus EVERY, called without an object.";
165              
166             # remaining arguments left on the stack.
167              
168             $proto->$_( @_ )
169 26         87 for $proto->$find_subs( $AUTOLOAD );
170             }
171              
172             package EVERY::LAST;
173 9     9   179 use v5.22;
  9         30  
174 9     9   52 use Carp qw( croak );
  9         14  
  9         1324  
175              
176             our @CARP_NOT = ( __PACKAGE__, qw( mro ) );
177             our $AUTOLOAD = '';
178              
179             AUTOLOAD
180             {
181 26 50   26   19712 my $proto = shift
182             or croak "Bogus EVERY::LAST, called without an object.";
183              
184             # remaining arguments left on the stack.
185              
186             $proto->$_( @_ )
187 26         72 for reverse $proto->$find_subs( $AUTOLOAD );
188             }
189              
190             # keep require happy
191             1
192             __END__