use strict;
use warnings;
-our $VERSION = '0.15_01';
-
-# Class::C3 defines Class::C3::* in pure perl
-# if mro, it does nothing else
-# elsif Class::C3::XS, do nothing else
-# else load next.pm
-# Class::C3::XS defines the same routines as next.pm,
-# and also redefines (suppress warning) calculateMRO
-# (ditto for anything else in Class::C3::* we want to
-# XS-ize).
+our $VERSION = '0.15_05';
our $C3_IN_CORE;
+our $C3_XS;
BEGIN {
- eval "require mro"; # XXX in the future, this should be a version check
- if($@) {
- die $@ if $@ !~ /locate/;
+ if($^V < 5.009005) {
eval "require Class::C3::XS";
if($@) {
die $@ if $@ !~ /locate/;
eval "require Algorithm::C3; require Class::C3::next";
die $@ if $@;
}
+ else {
+ $C3_XS = 1;
+ }
}
else {
$C3_IN_CORE = 1;
no strict 'refs';
my @MRO = calculateMRO($class, $merge_cache);
$MRO{$class} = { MRO => \@MRO };
- my $has_overload_fallback = 0;
+ my $has_overload_fallback;
my %methods;
# NOTE:
# we do @MRO[1 .. $#MRO] here because it
# have use "fallback", then we want to
# grab that value
$has_overload_fallback = ${"${local}::()"}
- if defined ${"${local}::()"};
+ if !defined $has_overload_fallback && defined ${"${local}::()"};
foreach my $method (grep { defined &{"${local}::$_"} } keys %{"${local}::"}) {
# skip if already overriden in local class
next unless !defined *{"${class}::$method"}{CODE};
my $class = shift;
no strict 'refs';
${"${class}::()"} = $MRO{$class}->{has_overload_fallback}
- if $MRO{$class}->{has_overload_fallback};
+ if !defined &{"${class}::()"}
+ && defined $MRO{$class}->{has_overload_fallback};
foreach my $method (keys %{$MRO{$class}->{methods}}) {
+ if ( $method =~ /^\(/ ) {
+ my $orig = $MRO{$class}->{methods}->{$method}->{orig};
+ ${"${class}::$method"} = $$orig if defined $$orig;
+ }
*{"${class}::$method"} = $MRO{$class}->{methods}->{$method}->{code};
}
}
sub calculateMRO {
my ($class, $merge_cache) = @_;
- return @{mro::get_linear_isa($class)} if $C3_IN_CORE;
-
return Algorithm::C3::merge($class, sub {
no strict 'refs';
@{$_[0] . '::ISA'};
}, $merge_cache);
}
+sub _core_calculateMRO { @{mro::get_linear_isa($_[0])} }
+
+if($C3_IN_CORE) {
+ no warnings 'redefine';
+ *Class::C3::calculateMRO = \&_core_calculateMRO;
+}
+elsif($C3_XS) {
+ no warnings 'redefine';
+ *Class::C3::calculateMRO = \&Class::C3::XS::calculateMRO;
+}
+
1;
__END__
D->can('hello')->(); # can() also works correctly
UNIVERSAL::can('D', 'hello'); # as does UNIVERSAL::can()
+=head1 SPECIAL NOTE FOR 0.15_05
+
+To try this with the new perl core c3 support,
+download the most recent copy perl-current:
+
+http://mirrors.develooper.com/perl/APC/perl-current-snap/
+
+sh Configure -Dusedevel -Dprefix=/where/I/want/it -d -e && make && make test && make install
+
+then try your C3-using software against this perl + Class::C3 0.15_05.
+
=head1 DESCRIPTION
This is pragma to change Perl 5's standard method resolution order from depth-first left-to-right
=back
+=head1 COMPATIBILITY
+
+If your software requires Perl 5.9.5 or higher, you do not need L<Class::C3>, you can simple C<use mro 'c3'>, and not worry about C<initialize()>, avoid some of the above caveats, and get the best possible performance. See L<mro> for more details.
+
+If your software is meant to work on earlier Perls, use L<Class::C3> as documented here. L<Class::C3> will detect Perl 5.9.5+ and take advantage of the core support when available.
+
+=head1 Class::C3::XS
+
+This module will load L<Class::C3::XS> if it's installed and you are running on a Perl version older than 5.9.5. Installing this is recommended when possible, as it results in significant performance improvements (but unlike the 5.9.5+ core support, it still has all of the same caveats as L<Class::C3>).
+
=head1 CODE COVERAGE
I use B<Devel::Cover> to test the code coverage of my tests, below is the B<Devel::Cover> report on this