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 # to fool Module::Install when generating META.yml
17 $INC{'mro.pm'} = 'Faked by MRO::Compat';
18 *mro::import = \&__import;
19 *mro::get_linear_isa = \&__get_linear_isa;
20 *mro::set_mro = \&__set_mro;
21 *mro::get_mro = \&__get_mro;
22 *mro::get_isarev = \&__get_isarev;
23 *mro::is_universal = \&__is_universal;
24 *mro::method_changed_in = \&__method_changed_in;
25 *mro::invalidate_all_method_caches
26 = \&__invalidate_all_method_caches;
28 if($Class::C3::XS::VERSION && $Class::C3::XS::VERSION > 0.03) {
29 *mro::get_pkg_gen = \&__get_pkg_gen_c3xs;
32 *mro::get_pkg_gen = \&__get_pkg_gen_pp;
36 # Load mro.pm and provide no-op Class::C3::.*initialize() funcs for 5.9.5+
39 no warnings 'redefine';
40 *Class::C3::initialize = sub { 1 };
41 *Class::C3::reinitialize = sub { 1 };
42 *Class::C3::uninitialize = sub { 1 };
48 MRO::Compat - mro::* interface compatibility for Perls < 5.9.5
52 package FooClass; use base qw/X Y Z/;
53 package X; use base qw/ZZZ/;
54 package Y; use base qw/ZZZ/;
55 package Z; use base qw/ZZZ/;
59 my $linear = mro::get_linear_isa('FooClass');
60 print join(q{, }, @$linear);
62 # Prints: "FooClass, X, ZZZ, Y, Z"
66 The "mro" namespace provides several utilities for dealing
67 with method resolution order and method caching in general
68 in Perl 5.9.5 and higher.
70 This module provides those interfaces for
71 earlier versions of Perl (back to 5.6.0 anyways).
73 It is a harmless no-op to use this module on 5.9.5+. If
74 you're writing a piece of software that would like to use
75 the parts of 5.9.5+'s mro:: interfaces that are supported
76 here, and you want compatibility with older Perls, this
77 is the module for you.
79 Some parts of this interface will work better with
80 L<Class::C3::XS> installed, but it's not a requirement.
82 This module never exports any functions. All calls must
83 be fully qualified with the C<mro::> prefix.
85 The interface documentation here serves only as a quick
86 reference of what the function basically does, and what
87 differences between L<MRO::Compat> and 5.9.5+ one should
88 look out for. The main docs in 5.9.5's L<mro> are the real
89 interface docs, and contain a lot of other useful information.
93 This is the first release of this new module, and on top of that,
94 the Perl 5.9.5 it seeks to provide compatibility with isn't even
97 If you're going to use/depend on this, please keep abreast of
98 possible interface changes in the next few versions. Once Perl
99 5.9.5 is out the door the interfaces should stabilize on whatever
100 5.9.5 has to offer. In the meantime, don't be surprised if
101 L<MRO::Compat> and 5.9.5's interfaces aren't perfectly in sync
106 =head2 mro::get_linear_isa($classname[, $type])
108 Returns an arrayref which is the linearized MRO of the given class.
109 Uses whichever MRO is currently in effect for that class by default,
110 or the given MRO (either C<c3> or C<dfs> if specified as C<$type>).
112 The linearized MRO of a class is a single ordered list of all of the
113 classes that would be visited in the process of resolving a method
114 on the given class, starting with itself. It does not include any
117 Note that C<UNIVERSAL> (and any members of C<UNIVERSAL>'s MRO) are not
118 part of the MRO of a class, even though all classes implicitly inherit
119 methods from C<UNIVERSAL> and its parents.
123 sub __get_linear_isa_dfs {
126 my $classname = shift;
128 my @lin = ($classname);
130 foreach my $parent (@{"$classname\::ISA"}) {
131 my $plin = __get_linear_isa_dfs($parent);
133 next if exists $stored{$_};
141 sub __get_linear_isa {
142 my ($classname, $type) = @_;
143 die "mro::get_mro requires a classname" if !$classname;
145 $type ||= __get_mro($classname);
147 return __get_linear_isa_dfs($classname);
149 elsif($type eq 'c3') {
150 return [Class::C3::calculateMRO($classname)];
152 die "type argument must be 'dfs' or 'c3'";
157 This allows the C<use mro 'dfs'> and
158 C<use mro 'c3'> syntaxes, providing you
159 L<use MRO::Compat> first. Please see the
160 L</USING C3> section for additional details.
166 goto &Class::C3::import if $_[1] eq 'c3';
167 __set_mro(scalar(caller), $_[1]);
171 =head2 mro::set_mro($classname, $type)
173 Sets the mro of C<$classname> to one of the types
174 C<dfs> or C<c3>. Please see the L</USING C3>
175 section for additional details.
180 my ($classname, $type) = @_;
181 if(!$classname || !$type) {
182 die q{Usage: mro::set_mro($classname, $type)};
185 eval "package $classname; use Class::C3";
189 die q{Invalid mro type "$type"};
192 # In the dfs case, check whether we need to undo C3
193 if(defined $Class::C3::MRO{$classname}) {
194 Class::C3::_remove_method_dispatch_table($classname);
196 delete $Class::C3::MRO{$classname};
201 =head2 mro::get_mro($classname)
203 Returns the MRO of the given class (either C<c3> or C<dfs>).
205 It considers any Class::C3-using class to have C3 MRO
206 even before L<Class::C3::initialize()> is called.
211 my $classname = shift;
212 die "mro::get_mro requires a classname" if !$classname;
213 return 'c3' if exists $Class::C3::MRO{$classname};
217 =head2 mro::get_isarev($classname)
219 Returns an arrayref of classes who are subclasses of the
220 given classname. In other words, classes who we exist,
221 however indirectly, in the @ISA inheritancy hierarchy of.
223 This is much slower on pre-5.9.5 Perls with MRO::Compat
224 than it is on 5.9.5+, as it has to search the entire
229 sub __get_all_pkgs_with_isas {
231 no warnings 'recursion';
239 $isa = \@{"$search\::ISA"};
248 push(@retval, $search) if scalar(@$isa);
250 foreach my $cand (keys %{"$search\::"}) {
253 next if $cand eq $search; # skip self-reference (main?)
254 push(@retval, @{__get_all_pkgs_with_isas($pfx . $cand)});
261 sub __get_isarev_recurse {
264 my ($class, $all_isas, $level) = @_;
266 die "Recursive inheritance detected" if $level > 100;
270 foreach my $cand (@$all_isas) {
272 foreach (@{"$cand\::ISA"}) {
280 map { $retval{$_} = 1 }
281 @{__get_isarev_recurse($cand, $all_isas, $level+1)};
284 return [keys %retval];
288 my $classname = shift;
289 die "mro::get_isarev requires a classname" if !$classname;
291 __get_isarev_recurse($classname, __get_all_pkgs_with_isas(), 0);
294 =head2 mro::is_universal($classname)
296 Returns a boolean status indicating whether or not
297 the given classname is either C<UNIVERSAL> itself,
298 or one of C<UNIVERSAL>'s parents by C<@ISA> inheritance.
300 Any class for which this function returns true is
301 "universal" in the sense that all classes potentially
302 inherit methods from it.
307 my $classname = shift;
308 die "mro::is_universal requires a classname" if !$classname;
310 my $lin = __get_linear_isa('UNIVERSAL');
312 return 1 if $classname eq $_;
318 =head2 mro::invalidate_all_method_caches
320 Increments C<PL_sub_generation>, which invalidates method
321 caching in all packages.
323 Please note that this is rarely necessary, unless you are
324 dealing with a situation which is known to confuse Perl's
329 sub __invalidate_all_method_caches {
330 # Super secret mystery code :)
331 @fedcba98::ISA = @fedcba98::ISA;
335 =head2 mro::method_changed_in($classname)
337 Invalidates the method cache of any classes dependent on the
338 given class. In L<MRO::Compat> on pre-5.9.5 Perls, this is
339 an alias for C<mro::invalidate_all_method_caches> above, as
340 pre-5.9.5 Perls have no other way to do this. It will still
341 enforce the requirement that you pass it a classname, for
344 Please note that this is rarely necessary, unless you are
345 dealing with a situation which is known to confuse Perl's
350 sub __method_changed_in {
351 my $classname = shift;
352 die "mro::method_changed_in requires a classname" if !$classname;
354 __invalidate_all_method_caches();
357 =head2 mro::get_pkg_gen($classname)
359 Returns an integer which is incremented every time a local
360 method of or the C<@ISA> of the given package changes on
361 Perl 5.9.5+. On earlier Perls with this L<MRO::Compat> module,
362 it will probably increment a lot more often than necessary.
367 sub __get_pkg_gen_pp {
368 my $classname = shift;
369 die "mro::get_pkg_gen requires a classname" if !$classname;
373 sub __get_pkg_gen_c3xs {
374 my $classname = shift;
375 die "mro::get_pkg_gen requires a classname" if !$classname;
377 return Class::C3::XS::_plsubgen();
382 While this module makes the 5.9.5+ syntaxes
383 C<use mro 'c3'> and C<mro::set_mro("Foo", 'c3')> available
384 on older Perls, it does so merely by passing off the work
387 It does not remove the need for you to call
388 L<Class::C3>'s C<initialize()>, C<reinitialize()>, and/or
389 C<uninitialize()> at the appropriate times
390 as documented in the L<Class::C3> docs.
392 Because L<MRO::Compat> has L<Class::C3> as a pre-requisite,
393 and requires it at C<use> time, you can blindly call
394 those functions in code that uses L<MRO::Compat>.
395 Under 5.9.5+ with L<MRO::Compat>, your calls to those
396 functions will become a no-op and everything will work fine.
406 Brandon L. Black, E<lt>blblack@gmail.comE<gt>
408 =head1 COPYRIGHT AND LICENSE
410 Copyright 2007 Brandon L. Black E<lt>blblack@gmail.comE<gt>
412 This library is free software; you can redistribute it and/or modify
413 it under the same terms as Perl itself.