File Coverage

blib/lib/constant/lexical.pm
Criterion Covered Total %
statement 15 38 39.4
branch 8 22 36.3
condition 3 6 50.0
subroutine 4 6 66.6
pod n/a
total 30 72 41.6


line stmt bran cond sub pod time code
1 0     1   0 use 5.008;
  0         0  
  0         0  
2              
3             package constant::lexical;
4              
5             our $VERSION = '2.0001';
6              
7             my $old = '#line ' . (__LINE__+1) . " " . __FILE__ . "\n" . <<'__';
8              
9             no constant 1.03 ();
10             use constant hufh => eval 'require Hash::Util::FieldHash';
11             use Sub::Delete;
12             BEGIN {
13             0+$] eq 5.01
14             and VERSION Sub::Delete >= .03
15             and VERSION Sub::Delete 1.00001 # %^H scoping bug
16             }
17             hufh and eval '
18             Hash::Util::FieldHash::fieldhash %hh;
19             use Tie::Hash;
20             {
21             package constant::lexical::_hhfh;
22             @ISA = "Tie::StdHash";
23             sub DELETE { constant::lexical::DESTROY(SUPER::DELETE{@_}) }
24             }
25             tie %hh, constant::lexical::_hhfh::;;
26             ';
27              
28             sub import {
29             $^H |= 0x20000; # magic incantation to make %^H work before 5.10
30             shift;
31             return unless @ '_;
32             my @const = @_ == 1 && ref $_[0] eq 'HASH' ? keys %{$_[0]} : $_[0];
33             my $stashname = caller()."::"; my $stash = \%$stashname;
34             push @{hufh ? $hh{\%^H} ||= [] : ($^H{+__PACKAGE__} ||= bless[])},
35             map {
36             my $fqname = "$stashname$_"; my $ref;
37             if(exists $$stash{$_} && defined $$stash{$_}) {
38             $ref = ref $$stash{$_} eq 'SCALAR'
39             ? $$stash{$_}
40             : *$fqname{CODE};
41             delete_sub($fqname);
42             }
43             [$fqname, $stashname, $_, $ref]
44             } @const;
45             unshift @_, 'constant';
46             goto &{can constant 'import'}
47             }
48              
49             sub DESTROY { for(@{+shift}) {
50             delete_sub(my $fqname = $$_[0]);
51             next unless defined (my $ref = $$_[-1]);
52             ref $ref eq 'SCALAR' or *$fqname = $ref, next;
53             my $stash = \%{$$_[1]}; my $subname = $$_[2];
54             if(exists $$stash{$subname} &&defined $$stash{$subname}) {
55             my $val = $$ref;
56             *$fqname = sub(){$val}
57             } else { $$stash{$subname} = $ref }
58             }}
59              
60             1;
61             __
62              
63             my $new = '#line ' . (__LINE__+1) . " " . __FILE__ . "\n" . <<'__';
64              
65             require Lexical'Sub;
66              
67             sub import {
68 0     10   0 shift;
69 0 0       0 return unless @ '_;
70 0         0 my @args;
71 0 100 66     0 if(@_ == 1 && ref $_[0] eq 'HASH') {
    100          
72 0         0 _validate(keys %{$_[0]});
  0         0  
73 0         0 while(my($k,$v) = each %{$_[0]}) {
  0         0  
74 0     0   0 push @args, $k, sub(){ $v };
  0         0  
75             }
76             }
77             elsif(@_ == 2) {
78 0         0 _validate($_[0]);
79 0         0 my $v = pop;
80 0     0   0 @args = ($_[0], sub(){ $v });
  0         0  
81             }
82             else {
83 0         0 _validate($_[0]);
84 1     1   1758 @args = (shift, do { my @v = @'_; sub(){ @v } });
  0         0  
  0         0  
  0         0  
85             }
86 0         0 import Lexical'Sub @args;
87             _:
88 1         25636 }
89              
90             # Plagiarised from constant.pm
91              
92             # Some names are evil choices.
93             my %keywords
94             = map +($_, 1), qw{ BEGIN INIT CHECK END DESTROY AUTOLOAD UNITCHECK };
95              
96             my $normal_constant_name = qr/^_?[^\W_0-9]\w*\z/;
97             my $tolerable = qr/^[A-Za-z_]\w*\z/;
98             my $boolean = qr/^[01]?\z/;
99              
100             sub _validate {
101 1     9   4 for(@_) {
102 1 100       1529 defined or require Carp, Carp'croak("Can't use undef as constant name");
103             # Normal constant name
104 10 0 33     10708 if (/$normal_constant_name/ and !$keywords{$_}) {
    50          
    0          
    0          
105             # Everything is okay
106              
107             # Starts with double underscore. Fatal.
108             } elsif (/^__/) {
109 10         74 require Carp;
110 9         13 Carp::croak("Constant name '$_' begins with '__'");
111              
112             # Maybe the name is tolerable
113             } elsif (/$tolerable/) {
114             # Then we'll warn only if you've asked for warnings
115 9 0       47 if (warnings::enabled()) {
116 1 50       3 if ($keywords{$_}) {
117 1         6 warnings::warn("Constant name '$_' is a Perl keyword");
118             }
119             }
120              
121             # Looks like a boolean
122             # use constant FRED == fred;
123             } elsif (/$boolean/) {
124 1         2 require Carp;
125 3 0       16 if (@_) {
126 2         18 Carp::croak("Constant name '$_' is invalid");
127             } else {
128 0         0 Carp::croak("Constant name looks like boolean value");
129             }
130              
131             } else {
132             # Must have bad characters
133 7         21 require Carp;
134 7         14 Carp::croak("Constant name '$_' has invalid characters");
135             }
136             }
137             }
138              
139             1;
140             __
141              
142             eval($] < 5.011002 ? $old : $new) or die $@;
143              
144             __END__