rename these for more consistency
[gitmo/Moose.git] / lib / Class / MOP / Mixin / HasMethods.pm
index 7de5e5f..5f6a4db 100644 (file)
@@ -4,13 +4,14 @@ use strict;
 use warnings;
 
 use Class::MOP::Method::Meta;
-
-our $AUTHORITY = 'cpan:STEVAN';
+use Class::MOP::Method::Overload;
 
 use Scalar::Util 'blessed';
 use Carp         'confess';
 use Sub::Name    'subname';
 
+use overload ();
+
 use base 'Class::MOP::Mixin';
 
 sub _meta_method_class { 'Class::MOP::Method::Meta' }
@@ -202,6 +203,84 @@ sub _full_method_map {
     return $self->_method_map;
 }
 
+# overloading
+
+my $overload_operators;
+sub overload_operators {
+    $overload_operators ||= [map { split /\s+/ } values %overload::ops];
+    return @$overload_operators;
+}
+
+sub is_overloaded {
+    my $self = shift;
+    return overload::Overloaded($self->name);
+}
+
+# XXX this could probably stand to be cached, but i figure it should be
+# uncommon enough to not particularly matter
+sub _overload_map {
+    my $self = shift;
+
+    return {} unless $self->is_overloaded;
+
+    my %map;
+    for my $op ($self->overload_operators) {
+        my $body = $self->_get_overloaded_operator_body($op);
+        next unless defined $body;
+        $map{$op} = $body;
+    }
+
+    return \%map;
+}
+
+sub get_overload_list {
+    my $self = shift;
+    return keys $self->_overload_map;
+}
+
+sub get_all_overloaded_operators {
+    my $self = shift;
+    my $map = $self->_overload_map;
+    return map { $self->_wrap_overload($_, $map->{$_}) } keys $map;
+}
+
+sub has_overloaded_operator {
+    my $self = shift;
+    my ($op) = @_;
+    return defined $self->_get_overloaded_operator_body($op);
+}
+
+sub get_overloaded_operator {
+    my $self = shift;
+    my ($op) = @_;
+    my $body = $self->_get_overloaded_operator_body($op);
+    return unless defined $body;
+    return $self->_wrap_overload($op, $body);
+}
+
+sub add_overloaded_operator {
+    my $self = shift;
+    my ($op, $body) = @_;
+    $self->name->overload::OVERLOAD($op => $body);
+}
+
+sub _get_overloaded_operator_body {
+    my $self = shift;
+    my ($op) = @_;
+    return overload::Method($self->name, $op);
+}
+
+sub _wrap_overload {
+    my $self = shift;
+    my ($op, $body) = @_;
+    return Class::MOP::Method::Overload->wrap(
+        operator             => $op,
+        package_name         => $self->name,
+        associated_metaclass => $self,
+        body                 => $body,
+    );
+}
+
 1;
 
 # ABSTRACT: Methods for metaclasses which have methods