File Coverage

blib/lib/Object/InsideOut/Overload.pm
Criterion Covered Total %
statement 52 59 88.1
branch 3 6 50.0
condition 3 11 27.2
subroutine 7 7 100.0
pod n/a
total 65 83 78.3


line stmt bran cond sub pod time code
1             package Object::InsideOut; {
2              
3 13     13   478 use strict;
  13         27  
  13         458  
4 14     12   2297 use warnings;
  14         1887  
  14         559  
5 16     11   2085 no warnings 'redefine';
  15         2123  
  14         6791  
6              
7             sub generate_OVERLOAD :Sub(Private)
8             {
9 13         161 my ($GBL) = @_;
10              
11             # Overload specifiers
12 13         768 my %TYPE = (
13             'STRINGIFY' => q/""/,
14             'NUMERIFY' => q/0+/,
15             'BOOLIFY' => q/bool/,
16             'ARRAYIFY' => q/@{}/,
17             'HASHIFY' => q/%{}/,
18             'GLOBIFY' => q/*{}/,
19             'CODIFY' => q/&{}/,
20             );
21              
22 13         691 my (%code, $code, %meta);
23              
24             # Generate overload strings
25 13         693 while (my $info = shift(@{$$GBL{'sub'}{'ol'}})) {
  87         253  
26 76 50       983 if ($$info{'ify'} eq 'EQUATE') {
27 0         0 push(@{$code{$$info{'pkg'}}}, "\tq/==/ => sub { (ref(\$_[0]) eq ref(\$_[1])) && (\${\$_[0]} == \${\$_[1]}) },");
  0         0  
28             } else {
29 75   66     355 $$info{'name'} ||= sub_name($$info{'code'}, ":$$info{'ify'}", $$info{'loc'});
30 75         142 my $pkg = $$info{'pkg'};
31 75         106 my $name = $$info{'name'};
32              
33 75         141 push(@{$code{$pkg}}, "\tq/$TYPE{$$info{'ify'}}/ => sub { \$_[0]->$name() },");
  75         259  
34              
35 75         297 $meta{$pkg}{$name}{'kind'} = 'overload';
36             }
37             }
38 12         36 delete($$GBL{'sub'}{'ol'});
39              
40             # Generate entire code string
41 12         40 foreach my $pkg (keys(%code)) {
42             $code .= "package $pkg;\nuse overload (\n" .
43 14         39 join("\n", @{$code{$pkg}}) .
  14         83  
44             "\n\t'fallback' => 1);\n";
45             }
46              
47             # Eval the code string
48 12         25 my @errs;
49 12         87 local $SIG{'__WARN__'} = sub { push(@errs, @_); };
  0         0  
50 12     11   2332 eval $code;
  11     43   83  
  11         34  
  11         168  
  6         743  
  6         1478  
  2         142  
  12         945  
  41         20735  
  1         655  
  1         672  
51 12 50 33     1443 if ($@ || @errs) {
52 0   0     0 my ($err) = split(/ at /, $@ || join(" | ", @errs));
53 0         0 OIO::Internal->die(
54             'message' => "Failure creating overloads",
55             'Error' => $err,
56             'Code' => $code,
57             'self' => 1);
58             }
59              
60             # Add accumulated metadata
61 12         74 add_meta(\%meta);
62              
63 14     11   2142 no strict 'refs';
  12         346  
  12         2406  
64              
65 12         24 foreach my $pkg (keys(%{$$GBL{'tree'}{'td'}})) {
  12         57  
66             # Bless an object into every class
67             # This works around an obscure 'overload' bug reported against
68             # Class::Std (http://rt.cpan.org/Public/Bug/Display.html?id=14048)
69 61         91 bless(\do{ my $scalar; }, $pkg);
  61         130  
70              
71             # Verify that scalar dereferencing is not overloaded in any class
72 61 50       204 if (exists(${$pkg.'::'}{'(${}'})) {
  61         350  
73 0         0 (my $file = $pkg . '.pm') =~ s/::/\//g;
74             OIO::Code->die(
75 0   0     0 'location' => [ $pkg, $INC{$file} || '', '' ],
76             'message' => q/Overloading scalar dereferencing '${}' is not allowed/,
77             'Info' => q/The scalar of an object is its object ID, and can't be redefined/);
78             }
79             }
80 12     11   103 }
  12         710  
  12         416  
81              
82             } # End of package's lexical scope
83              
84              
85             # Ensure correct versioning
86             ($Object::InsideOut::VERSION eq '4.05')
87             or die("Version mismatch\n");
88              
89             # EOF