Beta Shell
v2.0 ยท web2.us.cloudlogin.co
[FM]
[CMD]
[PHP]
[DB]
[INFO]
[SEC]
File Manager
~
/
usr
/
lib64
/
perl5
/
vendor_perl
/
UNIVERSAL
Upload
3 items
Name
Size
Perms
Modified
Actions
[ .. / .. ]
ref.pm
4 KB
-rw-r--r--
2011-01-23 19:17:15
Edit
Del
Editing: ref.pm
(4 KB)
Path: /usr/lib64/perl5/vendor_perl/UNIVERSAL/ref.pm
Back
package UNIVERSAL::ref; BEGIN { $UNIVERSAL::ref::VERSION = '0.14'; } use strict; use warnings; use B::Utils; our @hooked; our @needs_truth = qw(overload); sub import { my $class = caller; my %unique; @hooked = grep { !$unique{$_}++ } ( @hooked, $class ); } sub unimport { my $class = caller; @hooked = grep $_ ne $class, @hooked; } my $DOES; BEGIN { $DOES = UNIVERSAL->can('DOES') ? 'DOES' : 'isa' } sub _hook { # Below, you'll see that there is special dispensation for never # hooking the function named UNIVERSAL::ref::_hook. That's why this # ref() is safe from predation by this module. # Is this object asserting that it is an ancestor of any hooked class? my $is_hooked; my $obj_class = CORE::ref $_[0]; my $caller_class = caller; # For any special classes needing truth, just return if we've got # any of those. for my $class (@needs_truth) { if ( $caller_class->$DOES($class) ) { # CORE::ref return $obj_class; } } # for my $hooked_class (@hooked) { # Find only hooked ancestries that pertain this object. next unless $obj_class->$DOES($hooked_class); # Check that the call wasn't made from within this object's # ancestry. It has to be possible for an object to ask # questions about itself without getting lies. next if $obj_class->$DOES($caller_class); return $_[0]->ref; } # CORE::ref return $obj_class; } use XSLoader; $| = 1; XSLoader::load( 'UNIVERSAL::ref', $UNIVERSAL::ref::VERSION ); use B 'svref_2object'; use B::Utils 'all_roots'; my %roots = all_roots(); for my $nm ( sort keys %roots ) { my $op = $roots{$nm}; next unless $$op; next if $nm eq 'UNIVERSAL::ref::_hook'; if ( defined &$nm ) { my $cv = svref_2object( \&$nm ); next unless ${ $cv->ROOT }; next unless ${ $cv->START }; } _fixupop($op); } no warnings; q[Let's Make Love and Listen to Death From Above]; __END__ =head1 NAME UNIVERSAL::ref - Turns ref() into a multimethod =head1 SYNOPSIS # True! Wrapper pretends to be Thing. ref( Wrapper->new( Thing->new ) ) eq ref( Thing->new ); package Thing; sub new { bless [], shift } package Wrapper; sub new { my ($class,$proxy) = @_; bless \ $proxy, $class; } sub ref { my $self = shift @_; return $$self; } =head1 DESCRIPTION This module changes the behavior of the builtin function ref(). If ref() is called on an object that has requested an overloaded ref, the object's C<< ->ref >> method will be called and its return value used instead. =head1 USING To enable this feature for a class, C<use UNIVERSAL::ref> in your class. Here is a sample proxy module. package Pirate; # Pirate pretends to be a Privateer use UNIVERSAL::ref; sub new { bless {}, shift } sub ref { return 'Privateer' } Anywhere you call C<ref($obj)> on a C<Pirate> object, it will allow C<Pirate> to lie and pretend to be something else. =head1 METHODS =over =item import A pragma for ref()-enabling your class. This adds the calling class name to a global list of ref()-enabled classes. package YourClass; use UNIVERSAL::ref; sub ref { ... } =item unimport A pragma for ref()-disabling your class. This removes the calling class name from a global list of ref()-enabled classes. =back =head1 TODO Currently UNIVERSAL::ref must be installed before any ref() calls that are to be affected. I think ref() always occurs in an implicit scalar context. There is no accomodation for list context. UNIVERSAL::ref probably shouldn't allow a module to lie to itself. Or should it? =head1 ACKNOWLEDGEMENTS ambrus for the excellent idea to overload defined() to allow Perl 5 to have Perl 6's "interesting values of undef." chromatic for pointing out how utterly broken ref() is. This fix covers its biggest hole. =head1 AUTHOR Joshua ben Jore - jjore@cpan.org =head1 LICENSE The standard Artistic / GPL license most other perl code is typically using.