File Coverage

blib/lib/autobox/Closure/Attributes.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             package autobox::Closure::Attributes;
2 10     10   311158 use strict;
  10         26  
  10         361  
3 10     10   5190 use warnings;
  10         23  
  10         297  
4 10     10   62 use base 'autobox';
  10         17  
  10         10312  
5 10     10   111433 use B;
  10         26  
  10         529  
6 10     10   17034 use Want;
  0            
  0            
7             our $VERSION = '0.05_1';
8              
9             our @leaves;
10              
11             sub import {
12             shift->SUPER::import(CODE => 'autobox::Closure::Attributes::Methods');
13             push @leaves, $^H{autobox_leave}; # keep them forever so their destructor never gets invoked?
14             }
15              
16             package autobox::Closure::Attributes::Methods;
17             use PadWalker;
18              
19             sub AUTOLOAD :lvalue {
20             my $code = shift;
21             (my $method = our $AUTOLOAD) =~ s/.*:://;
22             return if $method eq 'DESTROY';
23              
24             # we want the scalar unless the method name already a sigil
25             my $attr = $method =~ /^[\$\@\%\&\*]/ ? $method : '$' . $method;
26              
27             my $closed_over = PadWalker::closed_over($code);
28              
29             # is there a method of that name in the package the coderef was created in?
30             # if so, run it.
31             # give methods priority over the variables we close over.
32             # XXX this isn't lvalue friendly, but sdw can't figure out how to make it be and not piss off old perls.
33              
34             my $stash = B::svref_2object($code)->STASH->NAME;
35             if( $stash and $stash->can($method) ) {
36             return $stash->can($method)->( $code, @_ );
37             }
38              
39             exists $closed_over->{$attr} or Carp::croak "$code does not close over $attr";
40              
41             my $ref = ref $closed_over->{$attr};
42              
43             if (@_) {
44             return @{ $closed_over->{$attr} } = @_ if $ref eq 'ARRAY';
45             return %{ $closed_over->{$attr} } = @_ if $ref eq 'HASH';
46             return ${ $closed_over->{$attr} } = shift;
47             }
48              
49             $ref eq 'HASH' || $ref eq 'ARRAY' ? $closed_over->{$attr} : ${ $closed_over->{$attr} }; # lvalue friendly return
50              
51             }
52              
53             1;
54              
55             __END__