Method-Lexical
view release on metacpan or search on metacpan
lib/Method/Lexical.pm view on Meta::CPAN
# Note: the class-specific data is stored under "Method::Lexical($subclass)" rather than
# $subclass. The subclass might well have its own uses for $^H{$subclass}, so we keep
# our mitts off it
#
# Also, the unadorned class name can't be used as a key if $METHOD_LEXICAL is 'Method::Lexical' (which
# it is) as the two uses conflict with and clobber each other
my $subclass = "$METHOD_LEXICAL($class)";
my $class_data;
# never use $class as the identifier for new_scope() here - see above
if (new_scope($subclass)) {
my $temp = $hints->{$subclass};
$class_data = $hints->{$subclass} = $temp ? { %$temp } : {}; # clone/create
} else {
$class_data = $hints->{$subclass}; # augment
}
for my $name (keys %bindings) {
my $sub = $bindings{$name};
# normalize bindings
unless (_isa($sub, 'CODE')) {
my $_autoload = $sub =~ s{^\+}{}; # autoload this sub's package
my $subname = fqname($sub); # XXX watch out for fqname returning a list
if ($_autoload || $autoload) {
_load($subname);
}
$sub = do {
no strict 'refs';
*{$subname}{CODE}
} || confess "Can't find subroutine for target $name: '$subname'";
}
my $fqname = fqname($name, $caller);
if ($DEBUG) {
if (exists $installed->{$fqname}) {
$class->_debug('redefining', $fqname);
} else {
$class->_debug('creating', $fqname);
}
}
$installed->{$fqname} = $sub;
$class_data->{$fqname} = $sub;
}
}
# uninstall one or more lexical subs from the current scope
sub unimport {
my $class = shift;
my $hints = my_hints;
my $subclass = "$METHOD_LEXICAL($class)";
my $class_data;
return unless (($^H & 0x20000) && ($class_data = $hints->{$subclass}));
my $caller = ccstash();
my @subs = @_ ? (map { scalar(fqname($_, $caller)) } @_) : keys(%$class_data);
my $installed = $hints->{$METHOD_LEXICAL};
my $new_installed = { %$installed }; # clone
my $deleted = 0;
for my $fqname (@subs) {
my $sub = $class_data->{$fqname};
if ($sub) { # the coderef of the method this subclass installed
# if the current sub ($installed->{$fqname}) is the sub this module installed ($class_data->{$fqname})
if (Scalar::Util::refaddr($sub) == Scalar::Util::refaddr($installed->{$fqname})) {
$class->_debug('unimporting', $fqname) if ($DEBUG);
# what import adds, unimport taketh away
delete $new_installed->{$fqname};
delete $class_data->{$fqname};
++$deleted;
} else {
carp "$class: attempt to unimport a shadowed lexical method: $fqname";
}
} else {
carp "$class: attempt to unimport an undefined lexical method: $fqname";
}
}
if ($deleted) {
$hints->{$METHOD_LEXICAL} = $new_installed;
}
}
1;
__END__
=head1 NAME
Method::Lexical - private methods and lexical method overrides
=head1 SYNOPSIS
package MyPragma;
use base qw(Method::Lexical);
sub import {
shift->SUPER::import(
'private' => sub { ... },
'UNIVERSAL::dump' => '+Data::Dump::pp'
)
}
=cut
=pod
#!/usr/bin/env perl
( run in 0.794 second using v1.01-cache-2.11-cpan-97f6503c9c8 )