6 # Keep this < 1.00, so people can tell the fake
7 # mro.pm from the real one
11 # Alias our private functions over to
12 # the mro:: namespace and load
13 # Class::C3 if Perl < 5.9.5
15 $mro::VERSION = $VERSION;
16 $INC{'mro.pm'} = 'Faked by MRO::Compat';
17 *mro::import = \&__import;
18 *mro::get_linear_isa = \&__get_linear_isa;
19 *mro::set_mro = \&__set_mro;
20 *mro::get_mro = \&__get_mro;
21 *mro::get_isarev = \&__get_isarev;
22 *mro::is_universal = \&__is_universal;
23 *mro::method_changed_in = \&__method_changed_in;
24 *mro::invalidate_all_method_caches
25 = \&__invalidate_all_method_caches;
27 if($Class::C3::XS::VERSION && $Class::C3::XS::VERSION > 0.03) {
28 *mro::get_pkg_gen = \&__get_pkg_gen_c3xs;
31 *mro::get_pkg_gen = \&__get_pkg_gen_pp;
35 # Provide no-op Class::C3::.*initialize() funcs for 5.9.5+
37 no warnings 'redefine';
38 *Class::C3::initialize = sub { 1 };
39 *Class::C3::reinitialize = sub { 1 };
40 *Class::C3::uninitialize = sub { 1 };
46 MRO::Compat - mro::* interface compatibility for Perls < 5.9.5
50 package FooClass; use base qw/X Y Z/;
51 package X; use base qw/ZZZ/;
52 package Y; use base qw/ZZZ/;
53 package Z; use base qw/ZZZ/;
57 my $linear = mro::get_linear_isa('FooClass');
58 print join(q{, }, @$linear);
60 # Prints: "FooClass, X, ZZZ, Y, Z"
64 The "mro" namespace provides several utilities for dealing
65 with method resolution order and method caching in general
66 in Perl 5.9.5 and higher.
68 This module provides those interfaces for
69 earlier versions of Perl (back to 5.6.0 anyways).
71 It is a harmless no-op to use this module on 5.9.5+. If
72 you're writing a piece of software that would like to use
73 the parts of 5.9.5+'s mro:: interfaces that are supported
74 here, and you want compatibility with older Perls, this
75 is the module for you.
77 Some parts of this interface will work better with
78 L<Class::C3::XS> installed, but it's not a requirement.
80 This module never exports any functions. All calls must
81 be fully qualified with the C<mro::> prefix.
83 The interface documentation here serves only as a quick
84 reference of what the function basically does, and what
85 differences between L<MRO::Compat> and 5.9.5+ one should
86 look out for. The main docs in 5.9.5's L<mro> are the real
87 interface docs, and contain a lot of other useful information.
91 This is the first release of this new module, and on top of that,
92 the Perl 5.9.5 it seeks to provide compatibility with isn't even
95 If you're going to use/depend on this, please keep abreast of
96 possible interface changes in the next few versions. Once Perl
97 5.9.5 is out the door the interfaces should stabilize on whatever
98 5.9.5 has to offer. In the meantime, don't be surprised if
99 L<MRO::Compat> and 5.9.5's interfaces aren't perfectly in sync
104 =head2 mro::get_linear_isa($classname[, $type])
106 Returns an arrayref which is the linearized MRO of the given class.
107 Uses whichever MRO is currently in effect for that class by default,
108 or the given MRO (either C<c3> or C<dfs> if specified as C<$type>).
110 The linearized MRO of a class is a single ordered list of all of the
111 classes that would be visited in the process of resolving a method
112 on the given class, starting with itself. It does not include any
115 Note that C<UNIVERSAL> (and any members of C<UNIVERSAL>'s MRO) are not
116 part of the MRO of a class, even though all classes implicitly inherit
117 methods from C<UNIVERSAL> and its parents.
121 sub __get_linear_isa_dfs {
124 my $classname = shift;
126 my @lin = ($classname);
128 foreach my $parent (@{"$classname\::ISA"}) {
129 my $plin = __get_linear_isa_dfs($parent);
131 next if exists $stored{$_};
139 sub __get_linear_isa {
140 my ($classname, $type) = @_;
141 die "mro::get_mro requires a classname" if !$classname;
143 $type ||= __get_mro($classname);
145 return __get_linear_isa_dfs($classname);
147 elsif($type eq 'c3') {
148 return [Class::C3::calculateMRO($classname)];
150 die "type argument must be 'dfs' or 'c3'";
155 This allows the C<use mro 'dfs'> and
156 C<use mro 'c3'> syntaxes, providing you
157 L<use MRO::Compat> first. Please see the
158 L</USING C3> section for additional details.
164 goto &Class::C3::import if $_[1] eq 'c3';
165 __set_mro(scalar(caller), $_[1]);
169 =head2 mro::set_mro($classname, $type)
171 Sets the mro of C<$classname> to one of the types
172 C<dfs> or C<c3>. Please see the L</USING C3>
173 section for additional details.
178 my ($classname, $type) = @_;
179 if(!$classname || !$type) {
180 die q{Usage: mro::set_mro($classname, $type)};
183 eval "package $classname; use Class::C3";
187 die q{Invalid mro type "$type"};
190 # In the dfs case, check whether we need to undo C3
191 if(defined $Class::C3::MRO{$classname}) {
192 Class::C3::_remove_method_dispatch_table($classname);
194 delete $Class::C3::MRO{$classname};
199 =head2 mro::get_mro($classname)
201 Returns the MRO of the given class (either C<c3> or C<dfs>).
203 It considers any Class::C3-using class to have C3 MRO
204 even before L<Class::C3::initialize()> is called.
209 my $classname = shift;
210 die "mro::get_mro requires a classname" if !$classname;
211 return 'c3' if exists $Class::C3::MRO{$classname};
215 =head2 mro::get_isarev($classname)
217 Returns an arrayref of classes who are subclasses of the
218 given classname. In other words, classes who we exist,
219 however indirectly, in the @ISA inheritancy hierarchy of.
221 This is much slower on pre-5.9.5 Perls with MRO::Compat
222 than it is on 5.9.5+, as it has to search the entire
227 sub __get_all_pkgs_with_isas {
229 no warnings 'recursion';
237 $isa = \@{"$search\::ISA"};
246 push(@retval, $search) if scalar(@$isa);
248 foreach my $cand (keys %{"$search\::"}) {
251 next if $cand eq $search; # skip self-reference (main?)
252 push(@retval, @{__get_all_pkgs_with_isas($pfx . $cand)});
259 sub __get_isarev_recurse {
262 my ($class, $all_isas, $level) = @_;
264 die "Recursive inheritance detected" if $level > 100;
268 foreach my $cand (@$all_isas) {
270 foreach (@{"$cand\::ISA"}) {
278 map { $retval{$_} = 1 }
279 @{__get_isarev_recurse($cand, $all_isas, $level+1)};
282 return [keys %retval];
286 my $classname = shift;
287 die "mro::get_isarev requires a classname" if !$classname;
289 __get_isarev_recurse($classname, __get_all_pkgs_with_isas(), 0);
292 =head2 mro::is_universal($classname)
294 Returns a boolean status indicating whether or not
295 the given classname is either C<UNIVERSAL> itself,
296 or one of C<UNIVERSAL>'s parents by C<@ISA> inheritance.
298 Any class for which this function returns true is
299 "universal" in the sense that all classes potentially
300 inherit methods from it.
305 my $classname = shift;
306 die "mro::is_universal requires a classname" if !$classname;
308 my $lin = __get_linear_isa('UNIVERSAL');
310 return 1 if $classname eq $_;
316 =head2 mro::invalidate_all_method_caches
318 Increments C<PL_sub_generation>, which invalidates method
319 caching in all packages.
321 Please note that this is rarely necessary, unless you are
322 dealing with a situation which is known to confuse Perl's
327 sub __invalidate_all_method_caches {
328 # Super secret mystery code :)
329 @fedcba98::ISA = @fedcba98::ISA;
333 =head2 mro::method_changed_in($classname)
335 Invalidates the method cache of any classes dependent on the
336 given class. In L<MRO::Compat> on pre-5.9.5 Perls, this is
337 an alias for C<mro::invalidate_all_method_caches> above, as
338 pre-5.9.5 Perls have no other way to do this. It will still
339 enforce the requirement that you pass it a classname, for
342 Please note that this is rarely necessary, unless you are
343 dealing with a situation which is known to confuse Perl's
348 sub __method_changed_in {
349 my $classname = shift;
350 die "mro::method_changed_in requires a classname" if !$classname;
352 __invalidate_all_method_caches();
355 =head2 mro::get_pkg_gen($classname)
357 Returns an integer which is incremented every time a local
358 method of or the C<@ISA> of the given package changes on
359 Perl 5.9.5+. On earlier Perls with this L<MRO::Compat> module,
360 it will probably increment a lot more often than necessary.
365 sub __get_pkg_gen_pp {
366 my $classname = shift;
367 die "mro::get_pkg_gen requires a classname" if !$classname;
371 sub __get_pkg_gen_c3xs {
372 my $classname = shift;
373 die "mro::get_pkg_gen requires a classname" if !$classname;
375 return Class::C3::XS::_plsubgen();
380 While this module makes the 5.9.5+ syntaxes
381 C<use mro 'c3'> and C<mro::set_mro("Foo", 'c3')> available
382 on older Perls, it does so merely by passing off the work
385 It does not remove the need for you to call
386 L<Class::C3>'s C<initialize()>, C<reinitialize()>, and/or
387 C<uninitialize()> at the appropriate times
388 as documented in the L<Class::C3> docs.
390 Because L<MRO::Compat> has L<Class::C3> as a pre-requisite,
391 and requires it at C<use> time, you can blindly call
392 those functions in code that uses L<MRO::Compat>.
393 Under 5.9.5+ with L<MRO::Compat>, your calls to those
394 functions will become a no-op and everything will work fine.
404 Brandon L. Black, E<lt>blblack@gmail.comE<gt>
406 =head1 COPYRIGHT AND LICENSE
408 Copyright 2007 Brandon L. Black E<lt>blblack@gmail.comE<gt>
410 This library is free software; you can redistribute it and/or modify
411 it under the same terms as Perl itself.