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   322275 use Carp;
  6         46  
  6         349  
4 6     6   32 use strict;
  6         9  
  6         104  
5 6     6   23 use warnings;
  6         9  
  6         174  
6 6     6   6462 use overload ();
  6         5790  
  6         483  
7              
8             our $VERSION = '0.68';
9              
10             sub NEXT::ELSEWHERE::ancestors
11             {
12 22     22   41 my @inlist = shift;
13 22         51 my @outlist = ();
14 22         48 while (my $next = shift @inlist) {
15 132         211 push @outlist, $next;
16 6     6   40 no strict 'refs';
  6         12  
  6         645  
17 132         107 unshift @inlist, @{"$outlist[-1]::ISA"};
  132         353  
18             }
19 22         64 return @outlist;
20             }
21              
22             sub NEXT::ELSEWHERE::ordered_ancestors
23             {
24 3     3   6 my @inlist = shift;
25 3         5 my @outlist = ();
26 3         12 while (my $next = shift @inlist) {
27 7         11 push @outlist, $next;
28 6     6   37 no strict 'refs';
  6         9  
  6         753  
29 7         6 push @inlist, @{"$outlist[-1]::ISA"};
  7         34  
30             }
31 3 50       19 return sort { $a->isa($b) ? -1
  6 100       30  
32             : $b->isa($a) ? +1
33             : 0 } @outlist;
34             }
35              
36             sub NEXT::ELSEWHERE::buildAUTOLOAD
37             {
38 48     48   123 my $autoload_name = caller() . '::AUTOLOAD';
39              
40 6     6   38 no strict 'refs';
  6         9  
  6         1563  
41 48         195 *{$autoload_name} = sub {
42 54     54   8970 my ($self) = @_;
43 54         66 my $depth = 1;
44 54   50     338 until (((caller($depth))[3]||q{}) !~ /^\(eval\)$/) { $depth++ }
  1         5  
45 54         177 my $caller = (caller($depth))[3];
46 54   66     127 my $wanted = $NEXT::AUTOLOAD || $autoload_name;
47 54         73 undef $NEXT::AUTOLOAD;
48 54         55 my ($caller_class, $caller_method) = do { $caller =~ m{(.*)::(.*)}g };
  54         251  
49 54         71 my ($wanted_class, $wanted_method) = do { $wanted =~ m{(.*)::(.*)}g };
  54         150  
50 54 100       418 croak "Can't call $wanted from $caller"
51             unless $caller_method eq $wanted_method;
52              
53 51 50 66     159 my $key = ref $self && overload::Overloaded($self)
54             ? overload::StrVal($self) : $self;
55              
56             local ($NEXT::NEXT{$key,$wanted_method}, $NEXT::SEEN) =
57 51         4560 ($NEXT::NEXT{$key,$wanted_method}, $NEXT::SEEN);
58              
59 51 100       152 unless ($NEXT::NEXT{$key,$wanted_method}) {
60 22   66     70 my @forebears =
61             NEXT::ELSEWHERE::ancestors ref $self || $self,
62             $wanted_class;
63 22         44 while (@forebears) {
64 35 100       67 last if shift @forebears eq $caller_class
65             }
66 6     6   39 no strict 'refs';
  6         9  
  6         2144  
67             # Use *{"..."} when first accessing the CODE slot, to make sure
68             # any typeglob stub is upgraded to a full typeglob.
69 17         55 @{$NEXT::NEXT{$key,$wanted_method}} =
70             map {
71 22 100       115 my $stash = \%{"${_}::"};
  73         70  
  73         113  
72             ($stash->{$caller_method} && (*{"${_}::$caller_method"}{CODE}))
73 47         221 ? *{$stash->{$caller_method}}{CODE}
74 73 100 100     150 : () } @forebears
75             unless $wanted_method eq 'AUTOLOAD';
76 8         17 @{$NEXT::NEXT{$key,$wanted_method}} =
77             map {
78 35         33 my $stash = \%{"${_}::"};
  35         40  
79 35 100 100     55 ($stash->{AUTOLOAD} && (*{"${_}::AUTOLOAD"}{CODE}))
80             ? "${_}::AUTOLOAD"
81             : () } @forebears
82 22 100       28 unless @{$NEXT::NEXT{$key,$wanted_method}||[]};
  22 100       83  
83 22         49 $NEXT::SEEN->{$key,*{$caller}{CODE}}++;
  22         99  
84             }
85 51         64 my $call_method = shift @{$NEXT::NEXT{$key,$wanted_method}};
  51         121  
86 51   100     67 while (do { $wanted_class =~ /^NEXT\b.*\b(UNSEEN|DISTINCT)\b/ }
  60   100     313  
87             && defined $call_method
88             && $NEXT::SEEN->{$key,$call_method}++) {
89 9         17 $call_method = shift @{$NEXT::NEXT{$key,$wanted_method}};
  9         22  
90             }
91 51 100       91 unless (defined $call_method) {
92 7 100       10 return unless do { $wanted_class =~ /^NEXT:.*:ACTUAL/ };
  7         178  
93 2         8 (local $Carp::CarpLevel)++;
94 2         476 croak qq(Can't locate object method "$wanted_method" ),
95             qq(via package "$caller_class");
96             };
97 44 100       169 return $self->$call_method(@_[1..$#_]) if ref $call_method eq 'CODE';
98 6     6   48 no strict 'refs';
  6         9  
  6         810  
99 10 100       14 do { ($wanted_method=${$caller_class."::AUTOLOAD"}) =~ s/.*::// }
  8         8  
  8         32  
100             if $wanted_method eq 'AUTOLOAD';
101 10         21 $$call_method = $caller_class."::NEXT::".$wanted_method;
102 10         22 return $call_method->(@_);
103 48         376 };
104             }
105              
106 6     6   65 no strict 'vars';
  6         11  
  6         1173  
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   31 my $autoload_name = caller() . '::AUTOLOAD';
121              
122 6     6   36 no strict 'refs';
  6         22  
  6         1324  
123 12         48 *{$autoload_name} = sub {
124 5     5   1051 my ($self) = @_;
125 5         8 my $depth = 1;
126 5   50     38 until (((caller($depth))[3]||q{}) !~ /^\(eval\)$/) { $depth++ }
  0         0  
127 5         20 my $caller = (caller($depth))[3];
128 5   33     14 my $wanted = $EVERY::AUTOLOAD || $autoload_name;
129 5         6 undef $EVERY::AUTOLOAD;
130 5         6 my ($wanted_class, $wanted_method) = do { $wanted =~ m{(.*)::(.*)}g };
  5         25  
131              
132 5 100 66     23 my $key = ref($self) && overload::Overloaded($self)
133             ? overload::StrVal($self) : $self;
134              
135             local $NEXT::ALREADY_IN_EVERY{$key,$wanted_method} =
136 5         265 $NEXT::ALREADY_IN_EVERY{$key,$wanted_method};
137              
138 5 100       27 return if $NEXT::ALREADY_IN_EVERY{$key,$wanted_method}++;
139              
140 3   33     12 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         16  
143 6     6   39 no strict 'refs';
  6         9  
  6         2467  
144 3         5 my %seen;
145 3 50       9 my @every = map { my $sub = "${_}::$wanted_method";
  7         13  
146 7 100 66     19 !*{$sub}{CODE} || $seen{$sub}++ ? () : $sub
147             } @forebears
148             unless $wanted_method eq 'AUTOLOAD';
149              
150 3         6 my $want = wantarray;
151 3 50       8 if (@every) {
152 3 100       6 if ($want) {
    50          
153 1         2 return map {($_, [$self->$_(@_[1..$#_])])} @every;
  1         9  
154             }
155             elsif (defined $want) {
156 2         11 return { map {($_, scalar($self->$_(@_[1..$#_])))}
  4         22  
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         116 };
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__