File Coverage

blib/lib/KiokuDB/TypeMap/Entry/Closure.pm
Criterion Covered Total %
statement 558 558 100.0
branch 7 38 18.4
condition 0 9 0.0
subroutine 186 186 100.0
pod 0 3 0.0
total 751 794 94.5


line stmt bran cond sub pod time code
1             package KiokuDB::TypeMap::Entry::Closure;
2 13     13   7988 use Moose;
  13         22  
  13         109  
3              
4 13     13   59847 use Carp qw(croak);
  13         25  
  13         786  
5 13     13   62 use Scalar::Util qw(refaddr);
  13         17  
  13         547  
6              
7 13     13   56 no warnings 'recursion';
  13         20  
  13         550  
8              
9 13     13   60 use namespace::clean -except => 'meta';
  13         19  
  13         132  
10              
11             with qw(KiokuDB::TypeMap::Entry::Std);
12              
13             sub compile_collapse_body {
14 34     34 0 82 my $self = shift;
15              
16 34         290 require B;
17 34         177 require B::Deparse;
18 34         1288 require PadWalker;
19              
20             return sub {
21 67     67   355 my ( $collapser, %args ) = @_;
22              
23 67         166 my $sub = $args{object};
24              
25 67         395 my ( $pkg, $name ) = Class::MOP::get_code_info($sub);
26              
27 67         133 my %data;
28              
29             # FIXME make this customizable on a per sub and per typemap level
30 67 50       213 if ( $name eq '__ANON__' ) {
31 67         447 my $pad = PadWalker::closed_over($sub);
32              
33 67 50       360 if ( keys %$pad ) {
34 67         267 my $collapsed_pad = $collapser->visit($pad);
35              
36 67         502 $data{pad} = $collapsed_pad;
37              
38 67         1941 my $buffer = $collapser->_buffer;
39 67 50       1898 my $pad_entry_data = blessed $collapsed_pad ? $buffer->id_to_entry( $collapsed_pad->id )->data : $collapsed_pad;
40              
41 67         2067 $buffer->first_class->insert(map { $_->id } values %$pad_entry_data ); # maybe only if entry($_->id)->object's refcount is > 1 (only shared closure vars) ?
  67         1682  
42             }
43              
44             # FIXME find all GVs in the optree and insert refs to them?
45             # i suppose they should be handled like named...
46 67         288 $data{body} = $self->_deparse($sub);
47             } else {
48 1         1 ( my $pkg_file = "${pkg}.pm" ) =~ s{::}{/}g;
49              
50 1         28 my $file;
51              
52 1 0       5 if ( my $meta = Class::MOP::get_metaclass_by_name($pkg) ) {
53 1 0       1 if ( my $method = $meta->get_method($name) ) {
54 1 0 0     40 if ( refaddr($method->body) == refaddr($sub)
      0        
55             and
56             $method->isa("Class::MOP::Method::Generated")
57             and
58             $method->can("definition_context")
59             ) {
60 1         5 $file = $method->definition_context->{file};
61             }
62             }
63             }
64              
65 1 0       2 unless ( defined $file ) {
66 1         25 my $cv = B::svref_2object($sub);
67 1 0       4 $file = $cv->FILE unless $cv->XSUB; # Can't really tell who called newXS or even bootstrap, so we assume the package .pm did
68             }
69              
70 1         1 my $inc_key;
71              
72 1 0       32 if ( defined $file ) {
73 1         6 my %rev_inc = reverse %INC;
74 1         2 $inc_key = $rev_inc{$file};
75 1 0       26 $inc_key = $file unless defined $inc_key;
76             }
77              
78 1 0 0     5 if ( defined($inc_key) and $pkg_file ne $inc_key ) {
79 1         1 $data{file} = $inc_key;
80             }
81              
82 1         37 @data{qw(package name)} = ( $pkg, $name );
83             }
84              
85 67         1312 return $collapser->make_entry(
86             %args,
87             object => $sub,
88             data => \%data,
89             );
90 34         1866 };
91             }
92              
93             sub _deparse {
94 67     67   126 my ( $self, $cv ) = @_;
95              
96 67         49560 B::Deparse->new->coderef2text($cv);
97             }
98              
99             sub compile_expand {
100 34     34 0 70 my $self = shift;
101              
102 34         119 require PadWalker;
103              
104             return sub {
105 100     100   202 my ( $linker, $entry ) = @_;
106              
107 100         2288 my $data = $entry->data;
108              
109 100 50       355 if ( exists $data->{body} ) {
110 100         218 my ( $body, $pad ) = @{ $data }{qw(body pad)};
  100         310  
111              
112 100         155 my $inflated_pad;
113 100         391 $linker->inflate_data( $pad, \$inflated_pad );
114              
115 100         477 my $sub = $self->_eval_body( $linker, $body, $inflated_pad );
116              
117 100         386 $linker->register_object( $entry => $sub );
118              
119 100         381 return $sub;
120             } else {
121 1         2 my $fq = join("::", @{ $data }{qw(package name)});
  1         39  
122 13     13   9208 my $glob = do { no strict 'refs'; *$fq };
  13         25  
  13         4240  
  1         9  
  1         2  
123              
124 1 0       31 unless ( defined(*{$glob}{CODE}) ) {
  1         5  
125 1 0       2 if ( defined(my $file = $data->{file}) ) {
126 1 0       45 require $file unless exists $INC{$file};
127             } else {
128 1         7 Class::MOP::load_class($data->{package});
129             }
130              
131 1 0       2 unless ( defined(*{$glob}{CODE}) ) {
  1         28  
132 1         4 croak "The subroutine &$data->{name} is no longer defined, but is referred to in the database";
133             }
134             }
135              
136 1         2 my $sub = *{$glob}{CODE};
  1         42  
137              
138 1         7 $linker->register_object( $entry => $sub );
139              
140 1         2 return $sub;
141             }
142 34         369 };
143             }
144              
145             sub compile_refresh {
146 34     34 0 87 my $self = shift;
147              
148             return sub {
149 1     1   1 croak "refreshing of closures is not yet supported";
150 34         184 };
151             }
152              
153             sub _eval_body {
154 100     100   238 my ( $self, $linker, $body, $pad ) = @_;
155              
156 100         128 my ( $sub, $e ) = do {
157 100         121 local $@;
158              
159 100 50       496 if ( my @vars = keys %$pad ) {
160 100         265 my $vars = join ", ", @vars;
161              
162             # FIXME Parse::Perl
163 100     3   9254 my $sub = eval "
  3     3   20  
  3     3   6  
  3     3   86  
  3     3   13  
  3     3   6  
  3     1   119  
  3     1   35  
  3     1   6  
  3     1   100  
  3     1   15  
  3     1   7  
  3     1   144  
  3     1   32  
  3     1   8  
  3     1   116  
  3     1   16  
  3     1   12  
  3     1   148  
  1     1   7  
  1     1   2  
  1     1   27  
  1     1   4  
  1     1   0  
  1     1   36  
  1     1   7  
  1     1   1  
  1     1   28  
  1     1   4  
  1     1   1  
  1     1   39  
  1     1   6  
  1     1   1  
  1     1   23  
  1     1   4  
  1     1   1  
  1     1   31  
  1     1   8  
  1     1   1  
  1     1   27  
  1     1   4  
  1     1   2  
  1     1   43  
  1     1   8  
  1     1   1  
  1     1   30  
  1     1   4  
  1     1   2  
  1     1   40  
  1     1   5  
  1     1   2  
  1     1   27  
  1     1   5  
  1     1   1  
  1     1   61  
  1     1   6  
  1     1   1  
  1     1   27  
  1     1   4  
  1     1   1  
  1     1   36  
  1     1   9  
  1     1   2  
  1     1   33  
  1     1   6  
  1     1   1  
  1     1   46  
  1     1   8  
  1     1   2  
  1     1   31  
  1     1   4  
  1     1   2  
  1     1   39  
  1     1   8  
  1     1   1  
  1     1   31  
  1     1   4  
  1     1   2  
  1     1   36  
  1     1   6  
  1     1   2  
  1     1   29  
  1     1   4  
  1     1   2  
  1     1   47  
  1     1   6  
  1     1   1  
  1     1   26  
  1     1   5  
  1     1   1  
  1     1   35  
  1     1   8  
  1     1   2  
  1     1   29  
  1     1   5  
  1     1   2  
  1     1   38  
  1     1   7  
  1     1   2  
  1     1   32  
  1     1   4  
  1     1   1  
  1     1   43  
  1     1   5  
  1     1   1  
  1     1   22  
  1     1   3  
  1     1   2  
  1     1   36  
  1     1   6  
  1     1   2  
  1     1   24  
  1     1   4  
  1     1   2  
  1     1   39  
  1     1   6  
  1     1   2  
  1     1   27  
  1     1   5  
  1     1   1  
  1     1   40  
  1     1   5  
  1     1   1  
  1     1   23  
  1     1   4  
  1     1   2  
  1     1   28  
  1     1   13  
  1     1   2  
  1     1   26  
  1     1   3  
  1     1   1  
  1     1   37  
  1     1   9  
  1     1   1  
  1     1   34  
  1     1   4  
  1     1   1  
  1     1   39  
  1     1   9  
  1     1   2  
  1     1   52  
  1     1   4  
  1     1   2  
  1     1   37  
  1     1   7  
  1     1   1  
  1     1   30  
  1     1   4  
  1     1   1  
  1     1   42  
  1     1   8  
  1     1   2  
  1     1   30  
  1     1   5  
  1     1   1  
  1     1   58  
  1     1   5  
  1     1   2  
  1     1   34  
  1     1   7  
  1     1   2  
  1     1   48  
  1     1   7  
  1     1   1  
  1     1   39  
  1     1   4  
  1     1   3  
  1     1   33  
  1     1   7  
  1     1   2  
  1         28  
  1         4  
  1         2  
  1         38  
  1         7  
  1         2  
  1         53  
  1         8  
  1         2  
  1         50  
  1         7  
  1         2  
  1         29  
  1         5  
  1         1  
  1         37  
  1         11  
  1         3  
  1         50  
  1         7  
  1         2  
  1         68  
  1         12  
  1         3  
  1         47  
  1         8  
  1         2  
  1         66  
  1         11  
  1         2  
  1         49  
  1         9  
  1         2  
  1         76  
  1         7  
  1         2  
  1         30  
  1         4  
  1         1  
  1         49  
  1         5  
  1         2  
  1         22  
  1         4  
  1         1  
  1         35  
  1         7  
  1         2  
  1         34  
  1         6  
  1         2  
  1         44  
  1         11  
  1         2  
  1         29  
  1         4  
  1         1  
  1         42  
  1         6  
  1         1  
  1         22  
  1         4  
  1         1  
  1         44  
  1         6  
  1         1  
  1         34  
  1         5  
  1         1  
  1         40  
  1         7  
  1         2  
  1         30  
  1         4  
  1         2  
  1         41  
  1         7  
  1         2  
  1         27  
  1         4  
  1         3  
  1         43  
  1         7  
  1         2  
  1         36  
  1         4  
  1         2  
  1         40  
  1         11  
  1         2  
  1         46  
  1         7  
  1         1  
  1         40  
  1         7  
  1         3  
  1         28  
  1         4  
  1         1  
  1         62  
  1         7  
  1         2  
  1         34  
  1         5  
  1         1  
  1         39  
  1         8  
  1         1  
  1         28  
  1         5  
  1         2  
  1         40  
  1         6  
  1         2  
  1         57  
  1         6  
  1         1  
  1         35  
  1         6  
  1         2  
  1         36  
  1         4  
  1         2  
  1         37  
  1         7  
  1         2  
  1         28  
  1         4  
  1         2  
  1         41  
  1         7  
  1         2  
  1         31  
  1         4  
  1         2  
  1         35  
  1         9  
  1         2  
  1         43  
  1         4  
  1         2  
  1         41  
  1         8  
  1         1  
  1         30  
  1         5  
  1         2  
  1         56  
  1         5  
  1         2  
  1         24  
  1         4  
  1         1  
  1         37  
  1         7  
  1         1  
  1         31  
  1         5  
  1         1  
  1         41  
  1         7  
  1         2  
  1         28  
  1         5  
  1         1  
  1         41  
  1         6  
  1         1  
  1         24  
  1         4  
  1         2  
  1         30  
  1         6  
  1         2  
  1         33  
  1         5  
  1         1  
  1         37  
  1         6  
  1         2  
  1         29  
  1         7  
  1         2  
  1         41  
  1         6  
  1         2  
  1         22  
  1         3  
  1         2  
  1         30  
  1         7  
  1         2  
  1         54  
  1         5  
  1         2  
  1         38  
  1         7  
  1         1  
  1         28  
  1         4  
  1         2  
  1         44  
  1         5  
  1         2  
  1         27  
  1         4  
  1         2  
  1         30  
  1         7  
  1         2  
  1         27  
  1         4  
  1         1  
  1         43  
  1         7  
  1         3  
  1         27  
  1         4  
  1         1  
  1         39  
  1         5  
  1         1  
  1         32  
  1         4  
  1         1  
  1         32  
  1         6  
  1         6  
  1         28  
  1         4  
  1         1  
  1         36  
  1         7  
  1         2  
  1         29  
  1         5  
  1         2  
  1         44  
  1         7  
  1         2  
  1         29  
  1         4  
  1         2  
  1         40  
  1         10  
  1         4  
  1         50  
  1         6  
  1         1  
  1         42  
  1         8  
  1         2  
  1         31  
  1         4  
  1         1  
  1         41  
  1         7  
  1         2  
  1         26  
  1         3  
  1         2  
  1         33  
  1         7  
  1         3  
  1         34  
  1         5  
  1         2  
  1         39  
  1         7  
  1         2  
  1         28  
  1         4  
  1         2  
  1         45  
  1         7  
  1         2  
  1         25  
  1         5  
  1         2  
  1         38  
  1         9  
  1         1  
  1         30  
  1         4  
  1         1  
  1         43  
164             my ( $vars );
165             sub $body;
166             ";
167              
168 100         315 my $e = $@;
169              
170             $linker->queue_finalizer(sub {
171 100     100   649 PadWalker::set_closed_over($sub, $pad);
172 100 50       767 }) if $sub;
173              
174 100         457 ( $sub, $e );
175             } else {
176 1         4 eval "sub $body", $@;
177             }
178             };
179              
180 100 50       311 die $e unless $sub;
181              
182 100         304 return $sub;
183             }
184              
185              
186             __PACKAGE__->meta->make_immutable;
187              
188             __PACKAGE__
189              
190             __END__