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