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