updated for core support
[gitmo/Class-C3.git] / lib / Class / C3 / PurePerl.pm
index c05f8f2..c9618ce 100644 (file)
@@ -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)->(@_) }