package MRO::Compat;
use strict;
use warnings;
require 5.006_000;
# Keep this < 1.00, so people can tell the fake
# mro.pm from the real one
our $VERSION = '0.13';
BEGIN {
# Alias our private functions over to
# the mro:: namespace and load
# Class::C3 if Perl < 5.9.5
if($] < 5.009_005) {
$mro::VERSION # to fool Module::Install when generating META.yml
= $VERSION;
$INC{'mro.pm'} = __FILE__;
*mro::import = \&__import;
*mro::get_linear_isa = \&__get_linear_isa;
*mro::set_mro = \&__set_mro;
*mro::get_mro = \&__get_mro;
*mro::get_isarev = \&__get_isarev;
*mro::is_universal = \&__is_universal;
*mro::method_changed_in = \&__method_changed_in;
*mro::invalidate_all_method_caches
= \&__invalidate_all_method_caches;
require Class::C3;
if($Class::C3::XS::VERSION && $Class::C3::XS::VERSION > 0.03) {
*mro::get_pkg_gen = \&__get_pkg_gen_c3xs;
}
else {
*mro::get_pkg_gen = \&__get_pkg_gen_pp;
}
}
# Load mro.pm and provide no-op Class::C3::.*initialize() funcs for 5.9.5+
else {
require mro;
no warnings 'redefine';
*Class::C3::initialize = sub { 1 };
*Class::C3::reinitialize = sub { 1 };
*Class::C3::uninitialize = sub { 1 };
}
}
=head1 NAME
MRO::Compat - mro::* interface compatibility for Perls < 5.9.5
=head1 SYNOPSIS
package PPP; use base qw/Exporter/;
package X; use base qw/PPP/;
package Y; use base qw/PPP/;
package Z; use base qw/PPP/;
package FooClass; use base qw/X Y Z/;
package main;
use MRO::Compat;
my $linear = mro::get_linear_isa('FooClass');
print join(q{, }, @$linear);
# Prints: FooClass, X, PPP, Exporter, Y, Z
=head1 DESCRIPTION
The "mro" namespace provides several utilities for dealing
with method resolution order and method caching in general
in Perl 5.9.5 and higher.
This module provides those interfaces for
earlier versions of Perl (back to 5.6.0 anyways).
It is a harmless no-op to use this module on 5.9.5+. That
is to say, code which properly uses L will work
unmodified on both older Perls and 5.9.5+.
If you're writing a piece of software that would like to use
the parts of 5.9.5+'s mro:: interfaces that are supported
here, and you want compatibility with older Perls, this
is the module for you.
Some parts of this code will work better and/or faster with
L installed (which is an optional prereq
of L, which is in turn a prereq of this
package), but it's not a requirement.
This module never exports any functions. All calls must
be fully qualified with the C prefix.
The interface documentation here serves only as a quick
reference of what the function basically does, and what
differences between L and 5.9.5+ one should
look out for. The main docs in 5.9.5's L are the real
interface docs, and contain a lot of other useful information.
=head1 Functions
=head2 mro::get_linear_isa($classname[, $type])
Returns an arrayref which is the linearized "ISA" of the given class.
Uses whichever MRO is currently in effect for that class by default,
or the given MRO (either C or C if specified as C<$type>).
The linearized ISA of a class is a single ordered list of all of the
classes that would be visited in the process of resolving a method
on the given class, starting with itself. It does not include any
duplicate entries.
Note that C (and any members of C's MRO) are not
part of the MRO of a class, even though all classes implicitly inherit
methods from C and its parents.
=cut
sub __get_linear_isa_dfs {
no strict 'refs';
my $classname = shift;
my @lin = ($classname);
my %stored;
foreach my $parent (@{"$classname\::ISA"}) {
my $plin = __get_linear_isa_dfs($parent);
foreach (@$plin) {
next if exists $stored{$_};
push(@lin, $_);
$stored{$_} = 1;
}
}
return \@lin;
}
sub __get_linear_isa {
my ($classname, $type) = @_;
die "mro::get_mro requires a classname" if !defined $classname;
$type ||= __get_mro($classname);
if($type eq 'dfs') {
return __get_linear_isa_dfs($classname);
}
elsif($type eq 'c3') {
return [Class::C3::calculateMRO($classname)];
}
die "type argument must be 'dfs' or 'c3'";
}
=head2 mro::import
This allows the C