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   363019 use Carp;
  6         55  
  6         401  
4 6     6   37 use strict;
  6         9  
  6         117  
5 6     6   28 use warnings;
  6         9  
  6         170  
6 6     6   8057 use overload ();
  6         6555  
  6         479  
7              
8             our $VERSION = '0.69';
9              
10             sub NEXT::ELSEWHERE::ancestors
11             {
12 22     22   48 my @inlist = shift;
13 22         34 my @outlist = ();
14 22         55 while (my $next = shift @inlist) {
15 132         192 push @outlist, $next;
16 6     6   43 no strict 'refs';
  6         11  
  6         748  
17 132         142 unshift @inlist, @{"$outlist[-1]::ISA"};
  132         427  
18             }
19 22         76 return @outlist;
20             }
21              
22             sub NEXT::ELSEWHERE::ordered_ancestors
23             {
24 3     3   8 my @inlist = shift;
25 3         6 my @outlist = ();
26 3         11 while (my $next = shift @inlist) {
27 7         10 push @outlist, $next;
28 6     6   49 no strict 'refs';
  6         10  
  6         822  
29 7         9 push @inlist, @{"$outlist[-1]::ISA"};
  7         35  
30             }
31 3 50       14 return sort { $a->isa($b) ? -1
  6 100       38  
32             : $b->isa($a) ? +1
33             : 0 } @outlist;
34             }
35              
36             sub NEXT::ELSEWHERE::buildAUTOLOAD
37             {
38 48     48   145 my $autoload_name = caller() . '::AUTOLOAD';
39              
40 6     6   42 no strict 'refs';
  6         11  
  6         1856  
41 48         218 *{$autoload_name} = sub {
42 54     54   9976 my ($self) = @_;
43 54         83 my $depth = 1;
44 54   50     377 until (((caller($depth))[3]||q{}) !~ /^\(eval\)$/) { $depth++ }
  1         5  
45 54         208 my $caller = (caller($depth))[3];
46 54   66     143 my $wanted = $NEXT::AUTOLOAD || $autoload_name;
47 54         86 undef $NEXT::AUTOLOAD;
48 54         64 my ($caller_class, $caller_method) = do { $caller =~ m{(.*)::(.*)}g };
  54         287  
49 54         80 my ($wanted_class, $wanted_method) = do { $wanted =~ m{(.*)::(.*)}g };
  54         208  
50 54 100       521 croak "Can't call $wanted from $caller"
51             unless $caller_method eq $wanted_method;
52              
53 51 50 66     195 my $key = ref $self && overload::Overloaded($self)
54             ? overload::StrVal($self) : $self;
55              
56             local ($NEXT::NEXT{$key,$wanted_method}, $NEXT::SEEN) =
57 51         5878 ($NEXT::NEXT{$key,$wanted_method}, $NEXT::SEEN);
58              
59 51 100       161 unless ($NEXT::NEXT{$key,$wanted_method}) {
60 22   66     81 my @forebears =
61             NEXT::ELSEWHERE::ancestors ref $self || $self,
62             $wanted_class;
63 22         52 while (@forebears) {
64 35 100       102 last if shift @forebears eq $caller_class
65             }
66 6     6   47 no strict 'refs';
  6         11  
  6         2327  
67             # Use *{"..."} when first accessing the CODE slot, to make sure
68             # any typeglob stub is upgraded to a full typeglob.
69 17         83 @{$NEXT::NEXT{$key,$wanted_method}} =
70             map {
71 22 100       61 my $stash = \%{"${_}::"};
  73         91  
  73         137  
72             ($stash->{$caller_method} && (*{"${_}::$caller_method"}{CODE}))
73 47         284 ? *{$stash->{$caller_method}}{CODE}
74 73 100 100     169 : () } @forebears
75             unless $wanted_method eq 'AUTOLOAD';
76 8         25 @{$NEXT::NEXT{$key,$wanted_method}} =
77             map {
78 35         42 my $stash = \%{"${_}::"};
  35         53  
79 35 100 100     71 ($stash->{AUTOLOAD} && (*{"${_}::AUTOLOAD"}{CODE}))
80             ? "${_}::AUTOLOAD"
81             : () } @forebears
82 22 100       36 unless @{$NEXT::NEXT{$key,$wanted_method}||[]};
  22 100       97  
83 22         46 $NEXT::SEEN->{$key,*{$caller}{CODE}}++;
  22         104  
84             }
85 51         77 my $call_method = shift @{$NEXT::NEXT{$key,$wanted_method}};
  51         130  
86 51   100     76 while (do { $wanted_class =~ /^NEXT\b.*\b(UNSEEN|DISTINCT)\b/ }
  60   100     322  
87             && defined $call_method
88             && $NEXT::SEEN->{$key,$call_method}++) {
89 9         15 $call_method = shift @{$NEXT::NEXT{$key,$wanted_method}};
  9         36  
90             }
91 51 100       136 unless (defined $call_method) {
92 7 100       11 return unless do { $wanted_class =~ /^NEXT:.*:ACTUAL/ };
  7         188  
93 2         7 (local $Carp::CarpLevel)++;
94 2         403 croak qq(Can't locate object method "$wanted_method" ),
95             qq(via package "$caller_class");
96             };
97 44 100       184 return $self->$call_method(@_[1..$#_]) if ref $call_method eq 'CODE';
98 6     6   46 no strict 'refs';
  6         12  
  6         1065  
99 10 100       18 do { ($wanted_method=${$caller_class."::AUTOLOAD"}) =~ s/.*::// }
  8         10  
  8         41  
100             if $wanted_method eq 'AUTOLOAD';
101 10         31 $$call_method = $caller_class."::NEXT::".$wanted_method;
102 10         29 return $call_method->(@_);
103 48         390 };
104             }
105              
106 6     6   64 no strict 'vars';
  6         10  
  6         1346  
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   34 my $autoload_name = caller() . '::AUTOLOAD';
121              
122 6     6   42 no strict 'refs';
  6         12  
  6         1575  
123 12         58 *{$autoload_name} = sub {
124 5     5   1335 my ($self) = @_;
125 5         8 my $depth = 1;
126 5   50     56 until (((caller($depth))[3]||q{}) !~ /^\(eval\)$/) { $depth++ }
  0         0  
127 5         38 my $caller = (caller($depth))[3];
128 5   33     14 my $wanted = $EVERY::AUTOLOAD || $autoload_name;
129 5         10 undef $EVERY::AUTOLOAD;
130 5         7 my ($wanted_class, $wanted_method) = do { $wanted =~ m{(.*)::(.*)}g };
  5         43  
131              
132 5 100 66     27 my $key = ref($self) && overload::Overloaded($self)
133             ? overload::StrVal($self) : $self;
134              
135             local $NEXT::ALREADY_IN_EVERY{$key,$wanted_method} =
136 5         323 $NEXT::ALREADY_IN_EVERY{$key,$wanted_method};
137              
138 5 100       35 return if $NEXT::ALREADY_IN_EVERY{$key,$wanted_method}++;
139              
140 3   33     14 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         23  
143 6     6   46 no strict 'refs';
  6         10  
  6         3069  
144 3         7 my %seen;
145 3 50       14 my @every = map { my $sub = "${_}::$wanted_method";
  7         30  
146 7 100 66     12 !*{$sub}{CODE} || $seen{$sub}++ ? () : $sub
147             } @forebears
148             unless $wanted_method eq 'AUTOLOAD';
149              
150 3         9 my $want = wantarray;
151 3 50       8 if (@every) {
152 3 100       9 if ($want) {
    50          
153 1         2 return map {($_, [$self->$_(@_[1..$#_])])} @every;
  1         12  
154             }
155             elsif (defined $want) {
156 2         3 return { map {($_, scalar($self->$_(@_[1..$#_])))}
  4         43  
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         109 };
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__