use Scalar::Util 'blessed';
-our $VERSION = '0.06';
+our $VERSION = '0.08';
# this is our global stash of both
# MRO's and method dispatch tables
# methods => {
# orig => <original location of method>,
# code => \&<ref to original method>
-# }
+# },
+# has_overload_fallback => (1 | 0)
# }
#
-my %MRO;
+our %MRO;
# use these for debugging ...
sub _dump_MRO_table { %MRO }
return if $TURN_OFF_C3;
# make a note to calculate $class
# during INIT phase
- $MRO{$class} = undef;
+ $MRO{$class} = undef unless exists $MRO{$class};
}
## initializers
no strict 'refs';
my @MRO = calculateMRO($class);
$MRO{$class} = { MRO => \@MRO };
+ my $has_overload_fallback = 0;
my %methods;
# NOTE:
# we do @MRO[1 .. $#MRO] here because it
# makes no sense to interogate the class
# which you are calculating for.
foreach my $local (@MRO[1 .. $#MRO]) {
+ # if overload has tagged this module to
+ # have use "fallback", then we want to
+ # grab that value
+ $has_overload_fallback = ${"${local}::()"}
+ if defined ${"${local}::()"};
foreach my $method (grep { defined &{"${local}::$_"} } keys %{"${local}::"}) {
# skip if already overriden in local class
next unless !defined *{"${class}::$method"}{CODE};
}
}
# now stash them in our %MRO table
- $MRO{$class}->{methods} = \%methods;
+ $MRO{$class}->{methods} = \%methods;
+ $MRO{$class}->{has_overload_fallback} = $has_overload_fallback;
}
sub _apply_method_dispatch_tables {
sub _apply_method_dispatch_table {
my $class = shift;
no strict 'refs';
+ ${"${class}::()"} = $MRO{$class}->{has_overload_fallback}
+ if $MRO{$class}->{has_overload_fallback};
foreach my $method (keys %{$MRO{$class}->{methods}}) {
*{"${class}::$method"} = $MRO{$class}->{methods}->{$method}->{code};
}
sub _remove_method_dispatch_table {
my $class = shift;
no strict 'refs';
+ delete ${"${class}::"}{"()"} if $MRO{$class}->{has_overload_fallback};
foreach my $method (keys %{$MRO{$class}->{methods}}) {
- delete ${"${class}::"}{$method};
+ delete ${"${class}::"}{$method}
+ if defined *{"${class}::${method}"}{CODE} &&
+ (*{"${class}::${method}"}{CODE} eq $MRO{$class}->{methods}->{$method}->{code});
}
}
# jump out as soon as we find one matching
# there is no reason not too. However, if
# we find one, then just remove the '&& last'
- $nothead++ && last if exists $in_tail{$cand};
+ ++$nothead && last if exists $in_tail{$cand};
}
last unless $nothead; # leave the loop with our canidate ...
$reject = $cand;
use Scalar::Util 'blessed';
-our $VERSION = '0.03';
+our $VERSION = '0.05';
our %METHOD_CACHE;
sub method {
- my @label = (split '::', (caller(1))[3]);
+ my $level = 1;
+ my $method_caller;
+ while ($method_caller = (caller($level++))[3]) {
+ last unless $method_caller eq '(eval)';
+ }
+ my @label = (split '::', $method_caller);
my $label = pop @label;
my $caller = join '::' => @label;
my $self = $_[0];
no strict 'refs';
my $found;
foreach my $class (@MRO) {
+ next if (defined $Class::C3::MRO{$class} &&
+ defined $Class::C3::MRO{$class}{methods}{$label});
last if (defined ($found = *{$class . '::' . $label}{CODE}));
}
=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 module's test suite.
+I use B<Devel::Cover> to test the code coverage of my tests, below is the B<Devel::Cover> report on this
+module's test suite.
---------------------------- ------ ------ ------ ------ ------ ------ ------
File stmt bran cond sub pod time total
---------------------------- ------ ------ ------ ------ ------ ------ ------
- Class/C3.pm 99.2 93.3 66.7 96.0 100.0 92.8 96.3
+ Class/C3.pm 98.6 90.9 73.3 96.0 100.0 96.8 95.3
---------------------------- ------ ------ ------ ------ ------ ------ ------
- Total 99.2 93.3 66.7 96.0 100.0 92.8 96.3
+ Total 98.6 90.9 73.3 96.0 100.0 96.8 95.3
---------------------------- ------ ------ ------ ------ ------ ------ ------
=head1 SEE ALSO