From 918097f3d406ac643ab6caf4387e4c0ab3d80718 Mon Sep 17 00:00:00 2001 From: Lorry Tar Creator Date: Wed, 26 Mar 2014 12:02:40 +0000 Subject: Devel-OverloadInfo-0.002 --- lib/Devel/OverloadInfo.pm | 192 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 lib/Devel/OverloadInfo.pm (limited to 'lib') diff --git a/lib/Devel/OverloadInfo.pm b/lib/Devel/OverloadInfo.pm new file mode 100644 index 0000000..2e06978 --- /dev/null +++ b/lib/Devel/OverloadInfo.pm @@ -0,0 +1,192 @@ +package Devel::OverloadInfo; +$Devel::OverloadInfo::VERSION = '0.002'; +# ABSTRACT: introspect overloaded operators + +# =head1 DESCRIPTION +# +# Devel::OverloadInfo returns information about L +# operators for a given class (or object), including where in the +# inheritance hierarchy the overloads are declared and where the code +# implementing it is. +# +# =cut + +use strict; +use warnings; +use overload (); +use Scalar::Util qw(blessed); +use Sub::Identify qw(sub_fullname); +use Package::Stash 0.14; +use MRO::Compat; + +use Exporter 5.57 qw(import); +our @EXPORT_OK = qw(overload_info); + +sub stash_with_symbol { + my ($class, $symbol) = @_; + + for my $package (@{mro::get_linear_isa($class)}) { + my $stash = Package::Stash->new($package); + my $value_ref = $stash->get_symbol($symbol); + return ($stash, $value_ref) if $value_ref; + } + return; +} + +# =func overload_info +# +# my $info = overload_info($class_or_object); +# +# Returns a hash reference with information about all the overloaded +# operators of the argument, which can be either a class name or a blessed +# object. The keys are the overloaded operators, as specified in +# C<%overload::ops> (see L). +# +# =over +# +# =item class +# +# The name of the class in which the operator overloading was declared. +# +# =item code +# +# A reference to the function implementing the overloaded operator. +# +# =item code_name +# +# The name of the function implementing the overloaded operator, as +# returned by C in L. +# +# =item method_name (optional) +# +# The name of the method implementing the overloaded operator, if the +# overloading was specified as a named method, e.g. C<< use overload $op +# => 'method'; >>. +# +# =item code_class (optional) +# +# The name of the class in which the method specified by C +# was found. +# +# =item value (optional) +# +# For the special C key, the value it was given in C. +# +# =back +# +# =cut + +sub overload_info { + my $class = blessed($_[0]) || $_[0]; + + return undef unless overload::Overloaded($class); + + my (%overloaded); + for my $op (map split(/\s+/), values %overload::ops) { + my $op_method = $op eq 'fallback' ? "()" : "($op"; + my ($stash, $func) = stash_with_symbol($class, "&$op_method") + or next; + my $info = $overloaded{$op} = { + class => $stash->name, + }; + if ($func == \&overload::nil) { + # Named method or fallback, stored in the scalar slot + if (my $value_ref = $stash->get_symbol("\$$op_method")) { + my $value = $$value_ref; + if ($op eq 'fallback') { + $info->{value} = $value; + } else { + $info->{method_name} = $value; + if (my ($impl_stash, $impl_func) = stash_with_symbol($class, "&$value")) { + $info->{code_class} = $impl_stash->name; + $info->{code} = $impl_func; + } + } + } + } else { + $info->{code} = $func; + } + $info->{code_name} = sub_fullname($info->{code}) + if exists $info->{code}; + } + return \%overloaded; +} + +1; + +__END__ + +=pod + +=encoding UTF-8 + +=head1 NAME + +Devel::OverloadInfo - introspect overloaded operators + +=head1 VERSION + +version 0.002 + +=head1 DESCRIPTION + +Devel::OverloadInfo returns information about L +operators for a given class (or object), including where in the +inheritance hierarchy the overloads are declared and where the code +implementing it is. + +=head1 FUNCTIONS + +=head2 overload_info + + my $info = overload_info($class_or_object); + +Returns a hash reference with information about all the overloaded +operators of the argument, which can be either a class name or a blessed +object. The keys are the overloaded operators, as specified in +C<%overload::ops> (see L). + +=over + +=item class + +The name of the class in which the operator overloading was declared. + +=item code + +A reference to the function implementing the overloaded operator. + +=item code_name + +The name of the function implementing the overloaded operator, as +returned by C in L. + +=item method_name (optional) + +The name of the method implementing the overloaded operator, if the +overloading was specified as a named method, e.g. C<< use overload $op +=> 'method'; >>. + +=item code_class (optional) + +The name of the class in which the method specified by C +was found. + +=item value (optional) + +For the special C key, the value it was given in C. + +=back + +=head1 AUTHOR + +Dagfinn Ilmari Mannsåker + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 2014 by Dagfinn Ilmari Mannsåker. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut -- cgit v1.2.1