File Coverage

blib/lib/Class/C3.pm
Criterion Covered Total %
statement 76 163 46.6
branch 11 66 16.6
condition 0 15 0.0
subroutine 25 32 78.1
pod 3 3 100.0
total 115 279 41.2


line stmt bran cond sub pod time code
1             package Class::C3;
2              
3 21     21   1511737 use strict;
  21     1   168  
  21         495  
  1         78301  
  1         15  
  1         26  
4 21     21   86 use warnings;
  21     1   32  
  21         3561  
  1         5  
  1         1  
  1         180  
5              
6             our $VERSION = '0.34';
7              
8             our $C3_IN_CORE;
9             our $C3_XS;
10              
11             BEGIN {
12 21 50 0 21   135     if($] > 5.009_004) {
  1 0 0 1   5  
    50          
    0          
13 21         32         $C3_IN_CORE = 1;
  1         1  
14 21         2616         require mro;
  1         124  
15                 }
16                 elsif($C3_XS or not defined $C3_XS) {
17 0         0         my $error = do {
  0         0  
18 0         0             local $@;
  0         0  
19 0         0             eval { require Class::C3::XS };
  0         0  
  0         0  
  0         0  
20 0         0             $@;
  0         0  
21                     };
22              
23 0 0       0         if ($error) {
  0 0       0  
24 0 0       0             die $error if $error !~ /\blocate\b/;
  0 0       0  
25              
26 0 0       0             if ($C3_XS) {
  0 0       0  
27 0         0                 require Carp;
  0         0  
28 0         0                 Carp::croak( "XS explicitly requested but Class::C3::XS is not available" );
  0         0  
29                         }
30              
31 0         0             require Algorithm::C3;
  0         0  
32 0         0             require Class::C3::next;
  0         0  
33                     }
34                     else {
35 0         0             $C3_XS = 1;
  0         0  
36                     }
37                 }
38             }
39              
40             # this is our global stash of both
41             # MRO's and method dispatch tables
42             # the structure basically looks like
43             # this:
44             #
45             # $MRO{$class} = {
46             # MRO => [ <class precedence list> ],
47             # methods => {
48             # orig => <original location of method>,
49             # code => \&<ref to original method>
50             # },
51             # has_overload_fallback => (1 | 0)
52             # }
53             #
54             our %MRO;
55              
56             # use these for debugging ...
57 0     0   0 sub _dump_MRO_table { %MRO }
58             our $TURN_OFF_C3 = 0;
59              
60             # state tracking for initialize()/uninitialize()
61             our $_initialized = 0;
62              
63             sub import {
64 85     85   7509     my $class = caller();
65             # skip if the caller is main::
66             # since that is clearly not relevant
67 85 100       1542     return if $class eq 'main';
68              
69 83 50       154     return if $TURN_OFF_C3;
70 83 50       274     mro::set_mro($class, 'c3') if $C3_IN_CORE;
71              
72             # make a note to calculate $class
73             # during INIT phase
74 83 50       13994     $MRO{$class} = undef unless exists $MRO{$class};
75             }
76              
77             ## initializers
78              
79             # This prevents silly warnings when Class::C3 is
80             # used explicitly along with MRO::Compat under 5.9.5+
81              
82 21     21   91 { no warnings 'redefine';
  21     1   28  
  21         6220  
  1         4  
  1         2  
  1         297  
83              
84             sub initialize {
85 22     22 1 10025     %next::METHOD_CACHE = ();
86             # why bother if we don't have anything ...
87 22 50       94     return unless keys %MRO;
88 22 50       66     if($C3_IN_CORE) {
89 22         281         mro::set_mro($_, 'c3') for keys %MRO;
90                 }
91                 else {
92 0 0       0         if($_initialized) {
93 0         0             uninitialize();
94 0         0             $MRO{$_} = undef foreach keys %MRO;
95                     }
96 0         0         _calculate_method_dispatch_tables();
97 0         0         _apply_method_dispatch_tables();
98 0         0         $_initialized = 1;
99                 }
100             }
101              
102             sub uninitialize {
103             # why bother if we don't have anything ...
104 4     4 1 3540     %next::METHOD_CACHE = ();
105 4 50       14     return unless keys %MRO;
106 4 50       10     if($C3_IN_CORE) {
107 4         30         mro::set_mro($_, 'dfs') for keys %MRO;
108                 }
109                 else {
110 0         0         _remove_method_dispatch_tables();
111 0         0         $_initialized = 0;
112                 }
113             }
114              
115 1     1 1 543 sub reinitialize { goto &initialize }
116              
117             } # end of "no warnings 'redefine'"
118              
119             ## functions for applying C3 to classes
120              
121             sub _calculate_method_dispatch_tables {
122 0 0   0   0     return if $C3_IN_CORE;
123 0         0     my %merge_cache;
124 0         0     foreach my $class (keys %MRO) {
125 0         0         _calculate_method_dispatch_table($class, \%merge_cache);
126                 }
127             }
128              
129             sub _calculate_method_dispatch_table {
130 0 0   0   0     return if $C3_IN_CORE;
131 0         0     my ($class, $merge_cache) = @_;
132 21     21   124     no strict 'refs';
  21     1   43  
  21         5745  
  1         6  
  1         2  
  1         265  
133 0         0     my @MRO = calculateMRO($class, $merge_cache);
134 0         0     $MRO{$class} = { MRO => \@MRO };
135 0         0     my $has_overload_fallback;
136                 my %methods;
137             # NOTE:
138             # we do @MRO[1 .. $#MRO] here because it
139             # makes no sense to interrogate the class
140             # which you are calculating for.
141 0         0     foreach my $local (@MRO[1 .. $#MRO]) {
142             # if overload has tagged this module to
143             # have use "fallback", then we want to
144             # grab that value
145 0         0         $has_overload_fallback = ${"${local}::()"}
146 0 0 0     0             if !defined $has_overload_fallback && defined ${"${local}::()"};
  0         0  
147 0         0         foreach my $method (grep { defined &{"${local}::$_"} } keys %{"${local}::"}) {
  0         0  
  0         0  
  0         0  
148             # skip if already overridden in local class
149 0 0       0             next unless !defined *{"${class}::$method"}{CODE};
  0         0  
150                         $methods{$method} = {
151                             orig => "${local}::$method",
152 0         0                 code => \&{"${local}::$method"}
153 0 0       0             } unless exists $methods{$method};
154                     }
155                 }
156             # now stash them in our %MRO table
157 0         0     $MRO{$class}->{methods} = \%methods;
158 0         0     $MRO{$class}->{has_overload_fallback} = $has_overload_fallback;
159             }
160              
161             sub _apply_method_dispatch_tables {
162 0 0   0   0     return if $C3_IN_CORE;
163 0         0     foreach my $class (keys %MRO) {
164 0         0         _apply_method_dispatch_table($class);
165                 }
166             }
167              
168             sub _apply_method_dispatch_table {
169 0 0   0   0     return if $C3_IN_CORE;
170 0         0     my $class = shift;
171 21     21   123     no strict 'refs';
  21     1   33  
  21         4738  
  1         6  
  1         1  
  1         225  
172 0         0     ${"${class}::()"} = $MRO{$class}->{has_overload_fallback}
173 0         0         if !defined &{"${class}::()"}
174 0 0 0     0            && defined $MRO{$class}->{has_overload_fallback};
175 0         0     foreach my $method (keys %{$MRO{$class}->{methods}}) {
  0         0  
176 0 0       0         if ( $method =~ /^\(/ ) {
177 0         0             my $orig = $MRO{$class}->{methods}->{$method}->{orig};
178 0 0       0             ${"${class}::$method"} = $$orig if defined $$orig;
  0         0  
179                     }
180 0         0         *{"${class}::$method"} = $MRO{$class}->{methods}->{$method}->{code};
  0         0  
181                 }
182             }
183              
184             sub _remove_method_dispatch_tables {
185 0 0   0   0     return if $C3_IN_CORE;
186 0         0     foreach my $class (keys %MRO) {
187 0         0         _remove_method_dispatch_table($class);
188                 }
189             }
190              
191             sub _remove_method_dispatch_table {
192 0 0   0   0     return if $C3_IN_CORE;
193 0         0     my $class = shift;
194 21     21   123     no strict 'refs';
  21     1   36  
  21         3394  
  1         6  
  1         2  
  1         153  
195 0 0       0     delete ${"${class}::"}{"()"} if $MRO{$class}->{has_overload_fallback};
  0         0  
196 0         0     foreach my $method (keys %{$MRO{$class}->{methods}}) {
  0         0  
197 0         0         delete ${"${class}::"}{$method}
198 0         0             if defined *{"${class}::${method}"}{CODE} &&
199 0 0 0     0                (*{"${class}::${method}"}{CODE} eq $MRO{$class}->{methods}->{$method}->{code});
  0         0  
200                 }
201             }
202              
203             sub calculateMRO {
204                 my ($class, $merge_cache) = @_;
205              
206                 return Algorithm::C3::merge($class, sub {
207 21     21   128         no strict 'refs';
  21     1   46  
  21         1881  
  1         5  
  1         2  
  1         93  
208                     @{$_[0] . '::ISA'};
209                 }, $merge_cache);
210             }
211              
212             # Method overrides to support 5.9.5+ or Class::C3::XS
213              
214 16     16   58 sub _core_calculateMRO { @{mro::get_linear_isa($_[0], 'c3')} }
  16         223  
215              
216             if($C3_IN_CORE) {
217 21     21   116     no warnings 'redefine';
  21     1   31  
  21         1093  
  1         5  
  1         8  
  1         53  
218                 *Class::C3::calculateMRO = \&_core_calculateMRO;
219             }
220             elsif($C3_XS) {
221 21     21   120     no warnings 'redefine';
  21     1   55  
  21         1227  
  1         5  
  1         2  
  1         53  
222                 *Class::C3::calculateMRO = \&Class::C3::XS::calculateMRO;
223                 *Class::C3::_calculate_method_dispatch_table
224                     = \&Class::C3::XS::_calculate_method_dispatch_table;
225             }
226              
227             1;
228              
229             __END__
230            
231             =pod
232            
233             =head1 NAME
234            
235             Class::C3 - A pragma to use the C3 method resolution order algorithm
236            
237             =head1 SYNOPSIS
238            
239             # NOTE - DO NOT USE Class::C3 directly as a user, use MRO::Compat instead!
240             package ClassA;
241             use Class::C3;
242             sub hello { 'A::hello' }
243            
244             package ClassB;
245             use base 'ClassA';
246             use Class::C3;
247            
248             package ClassC;
249             use base 'ClassA';
250             use Class::C3;
251            
252             sub hello { 'C::hello' }
253            
254             package ClassD;
255             use base ('ClassB', 'ClassC');
256             use Class::C3;
257            
258             # Classic Diamond MI pattern
259             # <A>
260             # / \
261             # <B> <C>
262             # \ /
263             # <D>
264            
265             package main;
266            
267             # initializez the C3 module
268             # (formerly called in INIT)
269             Class::C3::initialize();
270            
271             print join ', ' => Class::C3::calculateMRO('ClassD'); # prints ClassD, ClassB, ClassC, ClassA
272            
273             print ClassD->hello(); # prints 'C::hello' instead of the standard p5 'A::hello'
274            
275             ClassD->can('hello')->(); # can() also works correctly
276             UNIVERSAL::can('ClassD', 'hello'); # as does UNIVERSAL::can()
277            
278             =head1 DESCRIPTION
279            
280             This is pragma to change Perl 5's standard method resolution order from depth-first left-to-right
281             (a.k.a - pre-order) to the more sophisticated C3 method resolution order.
282            
283             B<NOTE:> YOU SHOULD NOT USE THIS MODULE DIRECTLY - The feature provided
284             is integrated into perl version >= 5.9.5, and you should use L<MRO::Compat>
285             instead, which will use the core implementation in newer perls, but fallback
286             to using this implementation on older perls.
287            
288             =head2 What is C3?
289            
290             C3 is the name of an algorithm which aims to provide a sane method resolution order under multiple
291             inheritance. It was first introduced in the language Dylan (see links in the L<SEE ALSO> section),
292             and then later adopted as the preferred MRO (Method Resolution Order) for the new-style classes in
293             Python 2.3. Most recently it has been adopted as the 'canonical' MRO for Perl 6 classes, and the
294             default MRO for Parrot objects as well.
295            
296             =head2 How does C3 work.
297            
298             C3 works by always preserving local precedence ordering. This essentially means that no class will
299             appear before any of its subclasses. Take the classic diamond inheritance pattern for instance:
300            
301             <A>
302             / \
303             <B> <C>
304             \ /
305             <D>
306            
307             The standard Perl 5 MRO would be (D, B, A, C). The result being that B<A> appears before B<C>, even
308             though B<C> is the subclass of B<A>. The C3 MRO algorithm however, produces the following MRO
309             (D, B, C, A), which does not have this same issue.
310            
311             This example is fairly trivial, for more complex examples and a deeper explanation, see the links in
312             the L<SEE ALSO> section.
313            
314             =head2 How does this module work?
315            
316             This module uses a technique similar to Perl 5's method caching. When C<Class::C3::initialize> is
317             called, this module calculates the MRO of all the classes which called C<use Class::C3>. It then
318             gathers information from the symbol tables of each of those classes, and builds a set of method
319             aliases for the correct dispatch ordering. Once all these C3-based method tables are created, it
320             then adds the method aliases into the local classes symbol table.
321            
322             The end result is actually classes with pre-cached method dispatch. However, this caching does not
323             do well if you start changing your C<@ISA> or messing with class symbol tables, so you should consider
324             your classes to be effectively closed. See the L<CAVEATS> section for more details.
325            
326             =head1 OPTIONAL LOWERCASE PRAGMA
327            
328             This release also includes an optional module B<c3> in the F<opt/> folder. I did not include this in
329             the regular install since lowercase module names are considered I<"bad"> by some people. However I
330             think that code looks much nicer like this:
331            
332             package MyClass;
333             use c3;
334            
335             This is more clunky:
336            
337             package MyClass;
338             use Class::C3;
339            
340             But hey, it's your choice, that's why it is optional.
341            
342             =head1 FUNCTIONS
343            
344             =over 4
345            
346             =item B<calculateMRO ($class)>
347            
348             Given a C<$class> this will return an array of class names in the proper C3 method resolution order.
349            
350             =item B<initialize>
351            
352             This B<must be called> to initialize the C3 method dispatch tables, this module B<will not work> if
353             you do not do this. It is advised to do this as soon as possible B<after> loading any classes which
354             use C3. Here is a quick code example:
355            
356             package Foo;
357             use Class::C3;
358             # ... Foo methods here
359            
360             package Bar;
361             use Class::C3;
362             use base 'Foo';
363             # ... Bar methods here
364            
365             package main;
366            
367             Class::C3::initialize(); # now it is safe to use Foo and Bar
368            
369             This function used to be called automatically for you in the INIT phase of the perl compiler, but
370             that lead to warnings if this module was required at runtime. After discussion with my user base
371             (the L<DBIx::Class> folks), we decided that calling this in INIT was more of an annoyance than a
372             convenience. I apologize to anyone this causes problems for (although I would be very surprised if I had
373             any other users other than the L<DBIx::Class> folks). The simplest solution of course is to define
374             your own INIT method which calls this function.
375            
376             NOTE:
377            
378             If C<initialize> detects that C<initialize> has already been executed, it will L</uninitialize> and
379             clear the MRO cache first.
380            
381             =item B<uninitialize>
382            
383             Calling this function results in the removal of all cached methods, and the restoration of the old Perl 5
384             style dispatch order (depth-first, left-to-right).
385            
386             =item B<reinitialize>
387            
388             This is an alias for L</initialize> above.
389            
390             =back
391            
392             =head1 METHOD REDISPATCHING
393            
394             It is always useful to be able to re-dispatch your method call to the "next most applicable method". This
395             module provides a pseudo package along the lines of C<SUPER::> or C<NEXT::> which will re-dispatch the
396             method along the C3 linearization. This is best shown with an example.
397            
398             # a classic diamond MI pattern ...
399             # <A>
400             # / \
401             # <B> <C>
402             # \ /
403             # <D>
404            
405             package ClassA;
406             use Class::C3;
407             sub foo { 'ClassA::foo' }
408            
409             package ClassB;
410             use base 'ClassA';
411             use Class::C3;
412             sub foo { 'ClassB::foo => ' . (shift)->next::method() }
413            
414             package ClassC;
415             use base 'ClassA';
416             use Class::C3;
417             sub foo { 'ClassC::foo => ' . (shift)->next::method() }
418            
419             package ClassD;
420             use base ('ClassB', 'ClassC');
421             use Class::C3;
422             sub foo { 'ClassD::foo => ' . (shift)->next::method() }
423            
424             print ClassD->foo; # prints out "ClassD::foo => ClassB::foo => ClassC::foo => ClassA::foo"
425            
426             A few things to note. First, we do not require you to add on the method name to the C<next::method>
427             call (this is unlike C<NEXT::> and C<SUPER::> which do require that). This helps to enforce the rule
428             that you cannot dispatch to a method of a different name (this is how C<NEXT::> behaves as well).
429            
430             The next thing to keep in mind is that you will need to pass all arguments to C<next::method>. It can
431             not automatically use the current C<@_>.
432            
433             If C<next::method> cannot find a next method to re-dispatch the call to, it will throw an exception.
434             You can use C<next::can> to see if C<next::method> will succeed before you call it like so:
435            
436             $self->next::method(@_) if $self->next::can;
437            
438             Additionally, you can use C<maybe::next::method> as a shortcut to only call the next method if it exists.
439             The previous example could be simply written as:
440            
441             $self->maybe::next::method(@_);
442            
443             There are some caveats about using C<next::method>, see below for those.
444            
445             =head1 CAVEATS
446            
447             This module used to be labeled as I<experimental>, however it has now been pretty heavily tested by
448             the good folks over at L<DBIx::Class> and I am confident this module is perfectly usable for
449             whatever your needs might be.
450            
451             But there are still caveats, so here goes ...
452            
453             =over 4
454            
455             =item Use of C<SUPER::>.
456            
457             The idea of C<SUPER::> under multiple inheritance is ambiguous, and generally not recommended anyway.
458             However, its use in conjunction with this module is very much not recommended, and in fact very
459             discouraged. The recommended approach is to instead use the supplied C<next::method> feature, see
460             more details on its usage above.
461            
462             =item Changing C<@ISA>.
463            
464             It is the author's opinion that changing C<@ISA> at runtime is pure insanity anyway. However, people
465             do it, so I must caveat. Any changes to the C<@ISA> will not be reflected in the MRO calculated by this
466             module, and therefore probably won't even show up. If you do this, you will need to call C<reinitialize>
467             in order to recalculate B<all> method dispatch tables. See the C<reinitialize> documentation and an example
468             in F<t/20_reinitialize.t> for more information.
469            
470             =item Adding/deleting methods from class symbol tables.
471            
472             This module calculates the MRO for each requested class by interrogating the symbol tables of said classes.
473             So any symbol table manipulation which takes place after our INIT phase is run will not be reflected in
474             the calculated MRO. Just as with changing the C<@ISA>, you will need to call C<reinitialize> for any
475             changes you make to take effect.
476            
477             =item Calling C<next::method> from methods defined outside the class
478            
479             There is an edge case when using C<next::method> from within a subroutine which was created in a different
480             module than the one it is called from. It sounds complicated, but it really isn't. Here is an example which
481             will not work correctly:
482            
483             *Foo::foo = sub { (shift)->next::method(@_) };
484            
485             The problem exists because the anonymous subroutine being assigned to the glob C<*Foo::foo> will show up
486             in the call stack as being called C<__ANON__> and not C<foo> as you might expect. Since C<next::method>
487             uses C<caller> to find the name of the method it was called in, it will fail in this case.
488            
489             But fear not, there is a simple solution. The module C<Sub::Name> will reach into the perl internals and
490             assign a name to an anonymous subroutine for you. Simply do this:
491            
492             use Sub::Name 'subname';
493             *Foo::foo = subname 'Foo::foo' => sub { (shift)->next::method(@_) };
494            
495             and things will Just Work. Of course this is not always possible to do, but to be honest, I just can't
496             manage to find a workaround for it, so until someone gives me a working patch this will be a known
497             limitation of this module.
498            
499             =back
500            
501             =head1 COMPATIBILITY
502            
503             If your software requires Perl 5.9.5 or higher, you do not need L<Class::C3>, you can simply C<use mro 'c3'>, and not worry about C<initialize()>, avoid some of the above caveats, and get the best possible performance. See L<mro> for more details.
504            
505             If your software is meant to work on earlier Perls, use L<Class::C3> as documented here. L<Class::C3> will detect Perl 5.9.5+ and take advantage of the core support when available.
506            
507             =head1 Class::C3::XS
508            
509             This module will load L<Class::C3::XS> if it's installed and you are running on a Perl version older than 5.9.5. The optional module will be automatically installed for you if a C compiler is available, as it results in significant performance improvements (but unlike the 5.9.5+ core support, it still has all of the same caveats as L<Class::C3>).
510            
511             =head1 CODE COVERAGE
512            
513             L<Devel::Cover> was reporting 94.4% overall test coverage earlier in this module's life. Currently, the test suite does things that break under coverage testing, but it is fair to assume the coverage is still close to that value.
514            
515             =head1 SEE ALSO
516            
517             =head2 The original Dylan paper
518            
519             =over 4
520            
521             =item L<https://web.archive.org/web/20000817033012id_/http://www.webcom.com/haahr/dylan/linearization-oopsla96.html>
522            
523             =back
524            
525             =head2 The prototype Perl 6 Object Model uses C3
526            
527             =over 4
528            
529             =item L<http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/>
530            
531             =back
532            
533             =head2 Parrot now uses C3
534            
535             =over 4
536            
537             =item L<http://aspn.activestate.com/ASPN/Mail/Message/perl6-internals/2746631>
538            
539             =item L<http://use.perl.org/~autrijus/journal/25768>
540            
541             =back
542            
543             =head2 Python 2.3 MRO related links
544            
545             =over 4
546            
547             =item L<http://www.python.org/2.3/mro.html>
548            
549             =item L<http://www.python.org/2.2.2/descrintro.html#mro>
550            
551             =back
552            
553             =head2 C3 for TinyCLOS
554            
555             =over 4
556            
557             =item L<http://www.call-with-current-continuation.org/eggs/c3.html>
558            
559             =back
560            
561             =head1 ACKNOWLEGEMENTS
562            
563             =over 4
564            
565             =item Thanks to Matt S. Trout for using this module in his module L<DBIx::Class>
566             and finding many bugs and providing fixes.
567            
568             =item Thanks to Justin Guenther for making C<next::method> more robust by handling
569             calls inside C<eval> and anon-subs.
570            
571             =item Thanks to Robert Norris for adding support for C<next::can> and
572             C<maybe::next::method>.
573            
574             =back
575            
576             =head1 AUTHOR
577            
578             Stevan Little, <stevan@iinteractive.com>
579            
580             Brandon L. Black, <blblack@gmail.com>
581            
582             =head1 COPYRIGHT AND LICENSE
583            
584             Copyright 2005, 2006 by Infinity Interactive, Inc.
585            
586             L<http://www.iinteractive.com>
587            
588             This library is free software; you can redistribute it and/or modify
589             it under the same terms as Perl itself.
590            
591             =cut
592