From: Brandon L Black Date: Tue, 3 Apr 2007 18:37:11 +0000 (+0000) Subject: updated for core support X-Git-Tag: 0.16~1^2~16 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=7f657ca33322c3bfcccf53d8061e69d3a2f84140;p=gitmo%2FClass-C3.git updated for core support --- diff --git a/lib/Class/C3.pm b/lib/Class/C3.pm index 5c62422..f4e2554 100644 --- a/lib/Class/C3.pm +++ b/lib/Class/C3.pm @@ -7,12 +7,10 @@ use warnings; our $VERSION = '0.15'; BEGIN { - eval { require Class::C3::XS }; + eval "require Class::C3::XS"; if($@) { - eval { require Class::C3::PurePerl }; - if($@) { - die 'Could not load Class::C3::XS or Class::C3::PurePerl!'; - } + eval "require Class::C3::PurePerl"; + die 'Could not load Class::C3::XS or Class::C3::PurePerl!' if $@; } } diff --git a/lib/Class/C3/PurePerl.pm b/lib/Class/C3/PurePerl.pm index c05f8f2..c9618ce 100644 --- a/lib/Class/C3/PurePerl.pm +++ b/lib/Class/C3/PurePerl.pm @@ -39,7 +39,20 @@ use strict; use warnings; use Scalar::Util 'blessed'; -use Algorithm::C3; + +our $VERSION = '0.15'; +our $C3_IN_CORE; + +BEGIN { + eval "require mro"; + if($@) { + eval "require Algorithm::C3"; + die "Could not load 'mro' or 'Algorithm::C3'!" if $@; + } + else { + $C3_IN_CORE = 1; + } +} # this is our global stash of both # MRO's and method dispatch tables @@ -69,7 +82,10 @@ sub import { # skip if the caller is main:: # since that is clearly not relevant return if $class eq 'main'; + return if $TURN_OFF_C3; + mro::set_mro_c3($class) if $C3_IN_CORE; + # make a note to calculate $class # during INIT phase $MRO{$class} = undef unless exists $MRO{$class}; @@ -78,24 +94,34 @@ sub import { ## initializers sub initialize { + %next::METHOD_CACHE = (); # why bother if we don't have anything ... return unless keys %MRO; - if($_initialized) { - uninitialize(); - $MRO{$_} = undef foreach keys %MRO; + if($C3_IN_CORE) { + mro::set_mro_c3($_) for keys %MRO; + } + else { + if($_initialized) { + uninitialize(); + $MRO{$_} = undef foreach keys %MRO; + } + _calculate_method_dispatch_tables(); + _apply_method_dispatch_tables(); + $_initialized = 1; } - _calculate_method_dispatch_tables(); - _apply_method_dispatch_tables(); - %next::METHOD_CACHE = (); - $_initialized = 1; } sub uninitialize { # why bother if we don't have anything ... - return unless keys %MRO; - _remove_method_dispatch_tables(); %next::METHOD_CACHE = (); - $_initialized = 0; + return unless keys %MRO; + if($C3_IN_CORE) { + mro::set_mro_dfs($_) for keys %MRO; + } + else { + _remove_method_dispatch_tables(); + $_initialized = 0; + } } sub reinitialize { goto &initialize } @@ -103,6 +129,7 @@ sub reinitialize { goto &initialize } ## functions for applying C3 to classes sub _calculate_method_dispatch_tables { + return if $C3_IN_CORE; my %merge_cache; foreach my $class (keys %MRO) { _calculate_method_dispatch_table($class, \%merge_cache); @@ -110,6 +137,7 @@ sub _calculate_method_dispatch_tables { } sub _calculate_method_dispatch_table { + return if $C3_IN_CORE; my ($class, $merge_cache) = @_; no strict 'refs'; my @MRO = calculateMRO($class, $merge_cache); @@ -141,12 +169,14 @@ sub _calculate_method_dispatch_table { } sub _apply_method_dispatch_tables { + return if $C3_IN_CORE; foreach my $class (keys %MRO) { _apply_method_dispatch_table($class); } } sub _apply_method_dispatch_table { + return if $C3_IN_CORE; my $class = shift; no strict 'refs'; ${"${class}::()"} = $MRO{$class}->{has_overload_fallback} @@ -157,12 +187,14 @@ sub _apply_method_dispatch_table { } sub _remove_method_dispatch_tables { + return if $C3_IN_CORE; foreach my $class (keys %MRO) { _remove_method_dispatch_table($class); } } sub _remove_method_dispatch_table { + return if $C3_IN_CORE; my $class = shift; no strict 'refs'; delete ${"${class}::"}{"()"} if $MRO{$class}->{has_overload_fallback}; @@ -177,6 +209,9 @@ sub _remove_method_dispatch_table { sub calculateMRO { my ($class, $merge_cache) = @_; + + return @{mro::get_mro_linear_c3($class)} if $C3_IN_CORE; + return Algorithm::C3::merge($class, sub { no strict 'refs'; @{$_[0] . '::ISA'}; @@ -189,13 +224,15 @@ package # hide me from PAUSE use strict; use warnings; -our $VERSION = 0.15; - use Scalar::Util 'blessed'; +our $VERSION = '0.06'; + our %METHOD_CACHE; sub method { + my $self = $_[0]; + my $class = blessed($self) || $self; my $indirect = caller() =~ /^(?:next|maybe::next)$/; my $level = $indirect ? 2 : 1; @@ -207,11 +244,12 @@ sub method { $label eq '(eval)' || $label eq '__ANON__'; } + + my $method; + my $caller = join '::' => @label; - my $self = $_[0]; - my $class = blessed($self) || $self; - my $method = $METHOD_CACHE{"$class|$caller|$label"} ||= do { + $method = $METHOD_CACHE{"$class|$caller|$label"} ||= do { my @MRO = Class::C3::calculateMRO($class); @@ -227,7 +265,7 @@ sub method { defined $Class::C3::MRO{$class}{methods}{$label}); last if (defined ($found = *{$class . '::' . $label}{CODE})); } - + $found; }; @@ -246,7 +284,7 @@ package # hide me from PAUSE use strict; use warnings; -our $VERSION = 0.15; +our $VERSION = '0.02'; sub method { (next::method($_[0]) || return)->(@_) } diff --git a/t/10_Inconsistent_hierarchy.t b/t/10_Inconsistent_hierarchy.t index 2378ea3..453d002 100644 --- a/t/10_Inconsistent_hierarchy.t +++ b/t/10_Inconsistent_hierarchy.t @@ -54,4 +54,4 @@ eval { Class::C3::calculateMRO('Z') }; #diag $@; -like($@, qr/^Inconsistent hierarchy/, '... got the right error with an inconsistent hierarchy'); +like($@, qr/^Inconsistent inheritance hierarchy/, '... got the right error with an inconsistent hierarchy'); diff --git a/t/20_reinitialize.t b/t/20_reinitialize.t index 7dce5d4..0912cb4 100644 --- a/t/20_reinitialize.t +++ b/t/20_reinitialize.t @@ -81,7 +81,13 @@ is_deeply( [ qw(Diamond_D Diamond_B Diamond_E Diamond_C Diamond_A) ], '... got the new MRO for Diamond_D'); -is(Diamond_D->hello, 'Diamond_C::hello', '... method still resolves with old MRO'); +# Doesn't work with core support, since reinit is not neccesary and the change +# takes effect immediately +SKIP: { + skip "This test does not work with a c3-patched perl interpreter", 1 + if $Class::C3::C3_IN_CORE; + is(Diamond_D->hello, 'Diamond_C::hello', '... method still resolves with old MRO'); +} Class::C3::reinitialize();