File Coverage

blib/lib/Acme/RightSideOutObject.pm
Criterion Covered Total %
statement 60 62 96.7
branch 18 28 64.2
condition n/a
subroutine 12 12 100.0
pod n/a
total 90 102 88.2


line stmt bran cond sub pod time code
1             package Acme::RightSideOutObject;
2              
3 1     1   41120 use 5.008000;
  1         4  
  1         46  
4 1     1   5 use strict;
  1         2  
  1         32  
5 1     1   6 use warnings;
  1         7  
  1         57  
6              
7             our $VERSION = '0.01';
8              
9             # todo:
10             # o. recognize different inside-out object systems and handle them appropriately (eg, C::IO uses id($self) for a hash subscript)
11             # o. weaken?
12              
13 1     1   5 use strict; no strict 'refs';
  1     1   2  
  1         30  
  1         5  
  1         1  
  1         24  
14 1     1   4 use warnings;
  1         2  
  1         32  
15              
16 1     1   857 use Data::Alias;
  1         3479  
  1         117  
17 1     1   935 use PadWalker;
  1         1344  
  1         64  
18 1     1   7 use B;
  1         3  
  1         49  
19 1     1   6 use Scalar::Util;
  1         2  
  1         576  
20              
21             sub import {
22 1         18 *{caller().'::guts'} = sub {
23 1     1   860 my $their_self = shift;
24 1         3 my $weaken = grep $_ eq 'weaken', @_;
25 1         2 my $debug = grep $_ eq 'debug', @_;
26 1 50       8 my $id = Class::InsideOut::id($their_self) or die;
27 1         11 my $class = ref $their_self;
28 1         2 my %as_a_hash;
29 1         4 my $self = bless \%as_a_hash, $class;
30 1 50       6 my $our_id = Class::InsideOut::id($self) or die; # sooo bad
31 1         2 for my $sym (keys %{$class.'::'}) {
  1         8  
32 13 50       28 $debug and warn "$class\::$sym\n";
33 13 100       11 my $code = *{$class.'::'.$sym}{CODE} or next;
  13         49  
34 12 50       582 my $op = B::svref_2object($code) or next;
35 12 50       60 my $rootop = $op->ROOT or next;
36 12 100       23 $$rootop or next; # not XS
37 11 100       68 $op->STASH->NAME eq $class or next; # not imported
38 2 50       14 my $vars = PadWalker::peek_sub($code) or next; # don't know why this would fail but when it does, I think it dies
39 2         8 for my $var (keys %$vars) {
40 2 100       11 next unless $var =~ m/^\%/;
41 1 50       3 next unless exists $vars->{$var};
42 1 50       4 next unless exists $vars->{$var}->{$id};
43 1 50       3 $debug and warn " ... $var is $vars->{$var}->{$id}\n";
44 1         5 (my $var_without_sigil) = $var =~ m/^.(.*)/;
45 1         6 alias $as_a_hash{$var_without_sigil} = $vars->{$var}->{$id};
46 1         3 alias $vars->{$var}->{$our_id} = $vars->{$var}->{$id}; # so $self->func works as well as $their_self->func
47 1 50       4 if($weaken) {
48 0         0 Scalar::Util::weaken($as_a_hash{$var_without_sigil});
49 0         0 Scalar::Util::weaken($vars->{$var}->{$our_id});
50             }
51             }
52             }
53 1         5 $self;
54 1     1   20 };
55             }
56              
57             1;
58              
59             __END__