File Coverage

blib/lib/NEXT.pm
Criterion Covered Total %
statement 131 148 88.5
branch 41 52 78.8
condition 24 38 63.1
subroutine 18 18 100.0
pod n/a
total 214 256 83.5


line stmt bran cond sub pod time code
1             package NEXT;
2              
3 6     6   375701 use Carp;
  6         55  
  6         407  
4 6     6   39 use strict;
  6         9  
  6         139  
5 6     6   29 use warnings;
  6         10  
  6         203  
6 6     6   7755 use overload ();
  6         6396  
  6         514  
7              
8             our $VERSION = '0.67_03';
9              
10             sub NEXT::ELSEWHERE::ancestors
11             {
12 22     22   55 my @inlist = shift;
13 22         34 my @outlist = ();
14 22         57 while (my $next = shift @inlist) {
15 132         205 push @outlist, $next;
16 6     6   49 no strict 'refs';
  6         13  
  6         747  
17 132         141 unshift @inlist, @{"$outlist[-1]::ISA"};
  132         414  
18             }
19 22         83 return @outlist;
20             }
21              
22             sub NEXT::ELSEWHERE::ordered_ancestors
23             {
24 3     3   8 my @inlist = shift;
25 3         7 my @outlist = ();
26 3         13 while (my $next = shift @inlist) {
27 7         11 push @outlist, $next;
28 6     6   44 no strict 'refs';
  6         11  
  6         835  
29 7         10 push @inlist, @{"$outlist[-1]::ISA"};
  7         30  
30             }
31 3 50       58 return sort { $a->isa($b) ? -1
  6 100       44  
32             : $b->isa($a) ? +1
33             : 0 } @outlist;
34             }
35              
36             sub NEXT::ELSEWHERE::buildAUTOLOAD
37             {
38 48     48   149 my $autoload_name = caller() . '::AUTOLOAD';
39              
40 6     6   45 no strict 'refs';
  6         11  
  6         2068  
41 48         219 *{$autoload_name} = sub {
42 54     54   10239 my ($self) = @_;
43 54         79 my $depth = 1;
44 54   50     400 until (((caller($depth))[3]||q{}) !~ /^\(eval\)$/) { $depth++ }
  1         6  
45 54         210 my $caller = (caller($depth))[3];
46 54   66     159 my $wanted = $NEXT::AUTOLOAD || $autoload_name;
47 54         83 undef $NEXT::AUTOLOAD;
48 54         101 my ($caller_class, $caller_method) = do { $caller =~ m{(.*)::(.*)}g };
  54         301  
49 54         84 my ($wanted_class, $wanted_method) = do { $wanted =~ m{(.*)::(.*)}g };
  54         184  
50 54 100       515 croak "Can't call $wanted from $caller"
51             unless $caller_method eq $wanted_method;
52              
53 51 50 66     241 my $key = ref $self && overload::Overloaded($self)
54             ? overload::StrVal($self) : $self;
55              
56             local ($NEXT::NEXT{$key,$wanted_method}, $NEXT::SEEN) =
57 51         5608 ($NEXT::NEXT{$key,$wanted_method}, $NEXT::SEEN);
58              
59 51 100       161 unless ($NEXT::NEXT{$key,$wanted_method}) {
60 22   66     85 my @forebears =
61             NEXT::ELSEWHERE::ancestors ref $self || $self,
62             $wanted_class;
63 22         54 while (@forebears) {
64 35 100       84 last if shift @forebears eq $caller_class
65             }
66 6     6   48 no strict 'refs';
  6         12  
  6         2451  
67             # Use *{"..."} when first accessing the CODE slot, to make sure
68             # any typeglob stub is upgraded to a full typeglob.
69 17         69 @{$NEXT::NEXT{$key,$wanted_method}} =
70             map {
71 22 100       78 my $stash = \%{"${_}::"};
  73         94  
  73         131  
72             ($stash->{$caller_method} && (*{"${_}::$caller_method"}{CODE}))
73 47         269 ? *{$stash->{$caller_method}}{CODE}
74 73 100 100     182 : () } @forebears
75             unless $wanted_method eq 'AUTOLOAD';
76 8         24 @{$NEXT::NEXT{$key,$wanted_method}} =
77             map {
78 35         46 my $stash = \%{"${_}::"};
  35         46  
79 35 100 100     76 ($stash->{AUTOLOAD} && (*{"${_}::AUTOLOAD"}{CODE}))
80             ? "${_}::AUTOLOAD"
81             : () } @forebears
82 22 100       38 unless @{$NEXT::NEXT{$key,$wanted_method}||[]};
  22 100       114  
83 22         62 $NEXT::SEEN->{$key,*{$caller}{CODE}}++;
  22         111  
84             }
85 51         73 my $call_method = shift @{$NEXT::NEXT{$key,$wanted_method}};
  51         160  
86 51   100     84 while (do { $wanted_class =~ /^NEXT\b.*\b(UNSEEN|DISTINCT)\b/ }
  60   100     347  
87             && defined $call_method
88             && $NEXT::SEEN->{$key,$call_method}++) {
89 9         16 $call_method = shift @{$NEXT::NEXT{$key,$wanted_method}};
  9         25  
90             }
91 51 100       117 unless (defined $call_method) {
92 7 100       11 return unless do { $wanted_class =~ /^NEXT:.*:ACTUAL/ };
  7         207  
93 2         7 (local $Carp::CarpLevel)++;
94 2         449 croak qq(Can't locate object method "$wanted_method" ),
95             qq(via package "$caller_class");
96             };
97 44 100       251 return $self->$call_method(@_[1..$#_]) if ref $call_method eq 'CODE';
98 6     6   49 no strict 'refs';
  6         10  
  6         960  
99 10 100       17 do { ($wanted_method=${$caller_class."::AUTOLOAD"}) =~ s/.*::// }
  8         9  
  8         43  
100             if $wanted_method eq 'AUTOLOAD';
101 10         27 $$call_method = $caller_class."::NEXT::".$wanted_method;
102 10         28 return $call_method->(@_);
103 48         449 };
104             }
105              
106 6     6   52 no strict 'vars';
  6         12  
  6         1398  
107             package NEXT; NEXT::ELSEWHERE::buildAUTOLOAD();
108             package NEXT::UNSEEN; @ISA = 'NEXT'; NEXT::ELSEWHERE::buildAUTOLOAD();
109             package NEXT::DISTINCT; @ISA = 'NEXT'; NEXT::ELSEWHERE::buildAUTOLOAD();
110             package NEXT::ACTUAL; @ISA = 'NEXT'; NEXT::ELSEWHERE::buildAUTOLOAD();
111             package NEXT::ACTUAL::UNSEEN; @ISA = 'NEXT'; NEXT::ELSEWHERE::buildAUTOLOAD();
112             package NEXT::ACTUAL::DISTINCT; @ISA = 'NEXT'; NEXT::ELSEWHERE::buildAUTOLOAD();
113             package NEXT::UNSEEN::ACTUAL; @ISA = 'NEXT'; NEXT::ELSEWHERE::buildAUTOLOAD();
114             package NEXT::DISTINCT::ACTUAL; @ISA = 'NEXT'; NEXT::ELSEWHERE::buildAUTOLOAD();
115              
116             package
117             EVERY;
118              
119             sub EVERY::ELSEWHERE::buildAUTOLOAD {
120 12     12   36 my $autoload_name = caller() . '::AUTOLOAD';
121              
122 6     6   42 no strict 'refs';
  6         11  
  6         1567  
123 12         54 *{$autoload_name} = sub {
124 5     5   1465 my ($self) = @_;
125 5         11 my $depth = 1;
126 5   50     53 until (((caller($depth))[3]||q{}) !~ /^\(eval\)$/) { $depth++ }
  0         0  
127 5         25 my $caller = (caller($depth))[3];
128 5   33     16 my $wanted = $EVERY::AUTOLOAD || $autoload_name;
129 5         12 undef $EVERY::AUTOLOAD;
130 5         8 my ($wanted_class, $wanted_method) = do { $wanted =~ m{(.*)::(.*)}g };
  5         31  
131              
132 5 100 66     29 my $key = ref($self) && overload::Overloaded($self)
133             ? overload::StrVal($self) : $self;
134              
135             local $NEXT::ALREADY_IN_EVERY{$key,$wanted_method} =
136 5         333 $NEXT::ALREADY_IN_EVERY{$key,$wanted_method};
137              
138 5 100       34 return if $NEXT::ALREADY_IN_EVERY{$key,$wanted_method}++;
139              
140 3   33     16 my @forebears = NEXT::ELSEWHERE::ordered_ancestors ref $self || $self,
141             $wanted_class;
142 3 100       6 @forebears = reverse @forebears if do { $wanted_class =~ /\bLAST\b/ };
  3         22  
143 6     6   56 no strict 'refs';
  6         11  
  6         2852  
144 3         6 my %seen;
145 3 50       13 my @every = map { my $sub = "${_}::$wanted_method";
  7         16  
146 7 100 66     10 !*{$sub}{CODE} || $seen{$sub}++ ? () : $sub
147             } @forebears
148             unless $wanted_method eq 'AUTOLOAD';
149              
150 3         8 my $want = wantarray;
151 3 50       8 if (@every) {
152 3 100       13 if ($want) {
    50          
153 1         2 return map {($_, [$self->$_(@_[1..$#_])])} @every;
  1         14  
154             }
155             elsif (defined $want) {
156 2         4 return { map {($_, scalar($self->$_(@_[1..$#_])))}
  4         36  
157             @every
158             };
159             }
160             else {
161 0           $self->$_(@_[1..$#_]) for @every;
162 0           return;
163             }
164             }
165              
166 0           @every = map { my $sub = "${_}::AUTOLOAD";
  0            
167 0 0 0       !*{$sub}{CODE} || $seen{$sub}++ ? () : "${_}::AUTOLOAD"
168             } @forebears;
169 0 0         if ($want) {
    0          
170 0           return map { $$_ = ref($self)."::EVERY::".$wanted_method;
  0            
171 0           ($_, [$self->$_(@_[1..$#_])]);
172             } @every;
173             }
174             elsif (defined $want) {
175 0           return { map { $$_ = ref($self)."::EVERY::".$wanted_method;
  0            
176 0           ($_, scalar($self->$_(@_[1..$#_])))
177             } @every
178             };
179             }
180             else {
181 0           for (@every) {
182 0           $$_ = ref($self)."::EVERY::".$wanted_method;
183 0           $self->$_(@_[1..$#_]);
184             }
185 0           return;
186             }
187 12         146 };
188             }
189              
190             package EVERY::LAST; @ISA = 'EVERY'; EVERY::ELSEWHERE::buildAUTOLOAD();
191             package
192             EVERY; @ISA = 'NEXT'; EVERY::ELSEWHERE::buildAUTOLOAD();
193              
194             1;
195              
196             __END__