line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package autobox; |
2
|
|
|
|
|
|
|
|
3
|
19
|
|
|
19
|
|
948004
|
use 5.008; |
|
19
|
|
|
|
|
219
|
|
4
|
|
|
|
|
|
|
|
5
|
19
|
|
|
19
|
|
97
|
use strict; |
|
19
|
|
|
|
|
27
|
|
|
19
|
|
|
|
|
464
|
|
6
|
19
|
|
|
19
|
|
98
|
use warnings; |
|
19
|
|
|
|
|
48
|
|
|
19
|
|
|
|
|
592
|
|
7
|
|
|
|
|
|
|
|
8
|
19
|
|
|
19
|
|
106
|
use Carp; |
|
19
|
|
|
|
|
40
|
|
|
19
|
|
|
|
|
1151
|
|
9
|
19
|
|
|
19
|
|
123
|
use XSLoader; |
|
19
|
|
|
|
|
34
|
|
|
19
|
|
|
|
|
444
|
|
10
|
19
|
|
|
19
|
|
123
|
use Scalar::Util; |
|
19
|
|
|
|
|
48
|
|
|
19
|
|
|
|
|
747
|
|
11
|
19
|
|
|
19
|
|
8109
|
use Scope::Guard; |
|
19
|
|
|
|
|
8010
|
|
|
19
|
|
|
|
|
711
|
|
12
|
19
|
|
|
19
|
|
10434
|
use Storable; |
|
19
|
|
|
|
|
53882
|
|
|
19
|
|
|
|
|
1605
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
our $VERSION = '2.86'; |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
XSLoader::load 'autobox', $VERSION; |
17
|
|
|
|
|
|
|
|
18
|
19
|
|
|
19
|
|
6888
|
use autobox::universal (); # don't import |
|
19
|
|
|
|
|
40
|
|
|
19
|
|
|
|
|
5597
|
|
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
############################################# PRIVATE ############################################### |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
my $SEQ = 0; # unique identifier for synthetic classes |
23
|
|
|
|
|
|
|
my $BINDINGS_CACHE = {}; # hold a reference to the bindings hashes |
24
|
|
|
|
|
|
|
my $CLASS_CACHE = {}; # reuse the same synthetic class if the @isa has been seen before |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
# all supported types |
27
|
|
|
|
|
|
|
# the boolean indicates whether the type is a real internal type (as opposed to a virtual type) |
28
|
|
|
|
|
|
|
my %TYPES = ( |
29
|
|
|
|
|
|
|
UNDEF => 1, |
30
|
|
|
|
|
|
|
INTEGER => 1, |
31
|
|
|
|
|
|
|
FLOAT => 1, |
32
|
|
|
|
|
|
|
NUMBER => 0, |
33
|
|
|
|
|
|
|
STRING => 1, |
34
|
|
|
|
|
|
|
SCALAR => 0, |
35
|
|
|
|
|
|
|
ARRAY => 1, |
36
|
|
|
|
|
|
|
HASH => 1, |
37
|
|
|
|
|
|
|
CODE => 1, |
38
|
|
|
|
|
|
|
UNIVERSAL => 0 |
39
|
|
|
|
|
|
|
); |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
# type hierarchy: keys are parents, values are (depth, children) pairs |
42
|
|
|
|
|
|
|
my %ISA = ( |
43
|
|
|
|
|
|
|
UNIVERSAL => [ 0, [ qw(SCALAR ARRAY HASH CODE) ] ], |
44
|
|
|
|
|
|
|
SCALAR => [ 1, [ qw(STRING NUMBER) ] ], |
45
|
|
|
|
|
|
|
NUMBER => [ 2, [ qw(INTEGER FLOAT) ] ] |
46
|
|
|
|
|
|
|
); |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
# default bindings when no args are supplied |
49
|
|
|
|
|
|
|
my %DEFAULT = ( |
50
|
|
|
|
|
|
|
SCALAR => 'SCALAR', |
51
|
|
|
|
|
|
|
ARRAY => 'ARRAY', |
52
|
|
|
|
|
|
|
HASH => 'HASH', |
53
|
|
|
|
|
|
|
CODE => 'CODE' |
54
|
|
|
|
|
|
|
); |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
# reinvent List::MoreUtils::uniq to keep the dependencies light - return a reference |
57
|
|
|
|
|
|
|
# to an array containing (in order) the unique members of the supplied list |
58
|
|
|
|
|
|
|
sub _uniq($) { |
59
|
470
|
|
|
470
|
|
539
|
my $list = shift; |
60
|
470
|
|
|
|
|
569
|
my (%seen, @uniq); |
61
|
|
|
|
|
|
|
|
62
|
470
|
|
|
|
|
646
|
for my $element (@$list) { |
63
|
788
|
100
|
|
|
|
1285
|
next if ($seen{$element}); |
64
|
752
|
|
|
|
|
1024
|
push @uniq, $element; |
65
|
752
|
|
|
|
|
1128
|
$seen{$element} = 1; |
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
|
68
|
470
|
|
|
|
|
1049
|
return [ @uniq ]; |
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
# create a shim class - actual methods are implemented by the classes in its @ISA |
72
|
|
|
|
|
|
|
# |
73
|
|
|
|
|
|
|
# as an optimization, return the previously-generated class |
74
|
|
|
|
|
|
|
# if we've seen the same (canonicalized) @isa before |
75
|
|
|
|
|
|
|
sub _generate_class($) { |
76
|
470
|
|
|
470
|
|
651
|
my $isa = _uniq(shift); |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
# As an optimization, simply return the class if there's only one. |
79
|
|
|
|
|
|
|
# This speeds up method lookup as the method can (often) be found directly in the stash |
80
|
|
|
|
|
|
|
# rather than in the ISA hierarchy with its attendant AUTOLOAD-related overhead |
81
|
470
|
100
|
|
|
|
837
|
if (@$isa == 1) { |
82
|
340
|
|
|
|
|
398
|
my $class = $isa->[0]; |
83
|
340
|
|
|
|
|
576
|
_make_class_accessor($class); # NOP if it has already been added |
84
|
340
|
|
|
|
|
890
|
return $class; |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
130
|
|
|
|
|
303
|
my $key = Storable::freeze($isa); |
88
|
|
|
|
|
|
|
|
89
|
130
|
|
66
|
|
|
4827
|
return $CLASS_CACHE->{$key} ||= do { |
90
|
46
|
|
|
|
|
178
|
my $class = sprintf('autobox::_shim_%d_', ++$SEQ); |
91
|
46
|
|
|
|
|
122
|
my $synthetic_class_isa = _get_isa($class); # i.e. autovivify |
92
|
|
|
|
|
|
|
|
93
|
46
|
|
|
|
|
1057
|
@$synthetic_class_isa = @$isa; |
94
|
46
|
|
|
|
|
201
|
_make_class_accessor($class); |
95
|
46
|
|
|
|
|
235
|
$class; |
96
|
|
|
|
|
|
|
}; |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
# expose the autobox class (for can, isa &c.) |
100
|
|
|
|
|
|
|
# https://rt.cpan.org/Ticket/Display.html?id=55565 |
101
|
|
|
|
|
|
|
sub _make_class_accessor ($) { |
102
|
386
|
|
|
386
|
|
465
|
my $class = shift; |
103
|
386
|
50
|
|
|
|
573
|
return unless (defined $class); |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
{ |
106
|
19
|
|
|
19
|
|
137
|
no strict 'refs'; |
|
19
|
|
|
|
|
35
|
|
|
19
|
|
|
|
|
3784
|
|
|
386
|
|
|
|
|
417
|
|
107
|
386
|
100
|
|
136
|
|
393
|
*{"$class\::autobox_class"} = sub { $class } unless (*{"$class\::autobox_class"}{CODE}); |
|
115
|
|
|
|
|
384
|
|
|
136
|
|
|
|
|
99730
|
|
|
386
|
|
|
|
|
1710
|
|
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
# pretty-print the bindings hash by showing its values as the inherited classes rather than the synthetic class |
112
|
|
|
|
|
|
|
sub _pretty_print($) { |
113
|
44
|
|
|
44
|
|
57
|
my $hash = { %{ shift() } }; # clone the hash to isolate it from the original |
|
44
|
|
|
|
|
181
|
|
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
# reverse() turns a hash that maps an isa signature to a class name into a hash that maps |
116
|
|
|
|
|
|
|
# a class name into a boolean |
117
|
44
|
|
|
|
|
213
|
my %synthetic = reverse(%$CLASS_CACHE); |
118
|
|
|
|
|
|
|
|
119
|
44
|
|
|
|
|
131
|
for my $type (keys %$hash) { |
120
|
218
|
|
|
|
|
320
|
my $class = $hash->{$type}; |
121
|
218
|
100
|
|
|
|
441
|
$hash->{$type} = $synthetic{$class} ? [ _get_isa($class) ] : [ $class ]; |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
44
|
|
|
|
|
168
|
return $hash; |
125
|
|
|
|
|
|
|
} |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
# default sub called when the DEBUG option is supplied with a true value |
128
|
|
|
|
|
|
|
# prints the assigned bindings for the current scope |
129
|
|
|
|
|
|
|
sub _debug ($) { |
130
|
0
|
|
|
0
|
|
0
|
my $bindings = shift; |
131
|
0
|
|
|
|
|
0
|
require Data::Dumper; |
132
|
19
|
|
|
19
|
|
122
|
no warnings qw(once); |
|
19
|
|
|
|
|
37
|
|
|
19
|
|
|
|
|
3368
|
|
133
|
0
|
|
|
|
|
0
|
local ($|, $Data::Dumper::Indent, $Data::Dumper::Terse, $Data::Dumper::Sortkeys) = (1, 1, 1, 1); |
134
|
0
|
|
|
|
|
0
|
print STDERR Data::Dumper::Dumper($bindings), $/; |
135
|
|
|
|
|
|
|
} |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
# return true if $ref ISA $class - works with non-references, unblessed references and objects |
138
|
|
|
|
|
|
|
# we can't use UNIVERSAL::isa to test if a value is an array ref; |
139
|
|
|
|
|
|
|
# if the value is 'ARRAY', and that package exists, then UNIVERSAL::isa('ARRAY', 'ARRAY') is true! |
140
|
|
|
|
|
|
|
sub _isa($$) { |
141
|
1044
|
|
|
1044
|
|
1483
|
my ($ref, $class) = @_; |
142
|
1044
|
50
|
|
|
|
2901
|
return Scalar::Util::blessed($ref) ? $ref->isa($class) : ref($ref) eq $class; |
143
|
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
# get/autovivify the @ISA for the specified class |
146
|
|
|
|
|
|
|
sub _get_isa($) { |
147
|
237
|
|
|
237
|
|
318
|
my $class = shift; |
148
|
237
|
|
|
|
|
273
|
my $isa = do { |
149
|
19
|
|
|
19
|
|
148
|
no strict 'refs'; |
|
19
|
|
|
|
|
56
|
|
|
19
|
|
|
|
|
19898
|
|
150
|
237
|
|
|
|
|
263
|
*{"$class\::ISA"}{ARRAY}; |
|
237
|
|
|
|
|
825
|
|
151
|
|
|
|
|
|
|
}; |
152
|
237
|
100
|
|
|
|
810
|
return wantarray ? @$isa : $isa; |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
# install a new set of bindings for the current scope |
156
|
|
|
|
|
|
|
# |
157
|
|
|
|
|
|
|
# XXX this could be refined to reuse the same hashref if its contents have already been seen, |
158
|
|
|
|
|
|
|
# but that requires each (frozen) hash to be cached; at best, it may not be much of a win, and at |
159
|
|
|
|
|
|
|
# worst it will increase bloat |
160
|
|
|
|
|
|
|
sub _install ($) { |
161
|
108
|
|
|
108
|
|
151
|
my $bindings = shift; |
162
|
108
|
|
|
|
|
416
|
$^H{autobox} = $bindings; |
163
|
108
|
|
|
|
|
956
|
$BINDINGS_CACHE->{$bindings} = $bindings; # keep the $bindings hash alive |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
# return the supplied class name or a new class name made by appending the specified |
167
|
|
|
|
|
|
|
# type to the namespace prefix |
168
|
|
|
|
|
|
|
sub _expand_namespace($$) { |
169
|
967
|
|
|
967
|
|
1279
|
my ($class, $type) = @_; |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
# make sure we can weed out classes that are empty strings or undef by returning an empty list |
172
|
967
|
50
|
|
|
|
1487
|
Carp::confess("_expand_namespace not called in list context") unless (wantarray); |
173
|
|
|
|
|
|
|
|
174
|
967
|
100
|
66
|
|
|
2336
|
if ((defined $class) && ($class ne '')) { |
175
|
961
|
100
|
|
|
|
2927
|
($class =~ /::$/) ? "$class$type" : $class; |
176
|
|
|
|
|
|
|
} else { # return an empty list |
177
|
|
|
|
|
|
|
() |
178
|
6
|
|
|
|
|
9
|
} |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
############################################# PUBLIC (Methods) ############################################### |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
# enable some flavour of autoboxing in the current scope |
184
|
|
|
|
|
|
|
sub import { |
185
|
101
|
|
|
101
|
|
4079
|
my $class = shift; |
186
|
101
|
100
|
66
|
|
|
461
|
my %args = ((@_ == 1) && _isa($_[0], 'HASH')) ? %{shift()} : @_; # hash or hashref |
|
2
|
|
|
|
|
7
|
|
187
|
101
|
|
|
|
|
213
|
my $debug = delete $args{DEBUG}; |
188
|
|
|
|
|
|
|
|
189
|
101
|
100
|
|
|
|
328
|
%args = %DEFAULT unless (%args); # wait till DEBUG has been deleted |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
# normalize %args so that it has a (possibly empty) array ref for all types, both real and virtual |
192
|
101
|
|
|
|
|
347
|
for my $type (keys %TYPES) { |
193
|
1010
|
100
|
|
|
|
1603
|
if (exists $args{$type}) { # exists() as the value may be undef (or ''), meaning "don't default this type" |
194
|
160
|
100
|
|
|
|
290
|
if (_isa($args{$type}, 'ARRAY')) { |
195
|
8
|
|
|
|
|
14
|
$args{$type} = [ @{$args{$type}} ]; # clone the array ref to isolate changes |
|
8
|
|
|
|
|
53
|
|
196
|
|
|
|
|
|
|
} else { |
197
|
152
|
|
|
|
|
388
|
$args{$type} = [ $args{$type} ]; |
198
|
|
|
|
|
|
|
} |
199
|
|
|
|
|
|
|
} else { |
200
|
850
|
|
|
|
|
1399
|
$args{$type} = []; |
201
|
|
|
|
|
|
|
} |
202
|
|
|
|
|
|
|
} |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
# if supplied, fill in defaults for unspecified SCALAR, ARRAY, HASH and CODE bindings |
205
|
|
|
|
|
|
|
# must be done before the virtual type expansion below as one of the defaults, SCALAR, is a |
206
|
|
|
|
|
|
|
# virtual type |
207
|
|
|
|
|
|
|
|
208
|
101
|
|
|
|
|
312
|
my $default = delete $args{DEFAULT}; |
209
|
|
|
|
|
|
|
|
210
|
101
|
100
|
|
|
|
238
|
if ($default) { |
211
|
30
|
100
|
|
|
|
58
|
$default = [ $default ] unless (_isa($default, 'ARRAY')); # no need to clone as we flatten it each time |
212
|
|
|
|
|
|
|
|
213
|
30
|
|
|
|
|
78
|
for my $type (keys %DEFAULT) { |
214
|
|
|
|
|
|
|
# don't default if a binding has already been supplied; this may include an undef value meaning |
215
|
|
|
|
|
|
|
# "don't default this type" e.g. |
216
|
|
|
|
|
|
|
# |
217
|
|
|
|
|
|
|
# use autobox |
218
|
|
|
|
|
|
|
# DEFAULT => 'MyDefault', |
219
|
|
|
|
|
|
|
# HASH => undef; |
220
|
|
|
|
|
|
|
# |
221
|
|
|
|
|
|
|
# undefs are winnowed out by _expand_namespace |
222
|
|
|
|
|
|
|
|
223
|
120
|
100
|
|
|
|
140
|
next if (@{$args{$type}}); |
|
120
|
|
|
|
|
226
|
|
224
|
100
|
|
|
|
|
112
|
push @{$args{$type}}, map { _expand_namespace($_, $type) } @$default; |
|
100
|
|
|
|
|
151
|
|
|
108
|
|
|
|
|
154
|
|
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
} |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
# expand the virtual type "macros" from the root to the leaves |
229
|
101
|
|
|
|
|
374
|
for my $vtype (sort { $ISA{$a}->[0] <=> $ISA{$b}->[0] } keys %ISA) { |
|
258
|
|
|
|
|
550
|
|
230
|
303
|
50
|
|
|
|
542
|
next unless ($args{$vtype}); |
231
|
|
|
|
|
|
|
|
232
|
303
|
|
|
|
|
328
|
my @types = @{$ISA{$vtype}->[1]}; |
|
303
|
|
|
|
|
644
|
|
233
|
|
|
|
|
|
|
|
234
|
303
|
|
|
|
|
461
|
for my $type (@types) { |
235
|
808
|
50
|
|
|
|
1241
|
if (_isa($args{$vtype}, 'ARRAY')) { |
236
|
808
|
|
|
|
|
900
|
push @{$args{$type}}, map { _expand_namespace($_, $vtype) } @{$args{$vtype}}; |
|
808
|
|
|
|
|
1156
|
|
|
390
|
|
|
|
|
577
|
|
|
808
|
|
|
|
|
1362
|
|
237
|
|
|
|
|
|
|
} else { |
238
|
|
|
|
|
|
|
# _expand_namespace returns an empty list if $args{$vtype} is undef (or '') |
239
|
0
|
|
|
|
|
0
|
push @{$args{$type}}, _expand_namespace($args{$vtype}, $vtype); |
|
0
|
|
|
|
|
0
|
|
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
|
243
|
303
|
|
|
|
|
644
|
delete $args{$vtype}; |
244
|
|
|
|
|
|
|
} |
245
|
|
|
|
|
|
|
|
246
|
101
|
|
|
|
|
147
|
my $bindings; # custom typemap |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
# clone the bindings hash if available |
249
|
|
|
|
|
|
|
# |
250
|
|
|
|
|
|
|
# we may be assigning to it, and we don't want to contaminate outer/previous bindings |
251
|
|
|
|
|
|
|
# with nested/new bindings |
252
|
|
|
|
|
|
|
# |
253
|
|
|
|
|
|
|
# as of 5.10, references in %^H get stringified at runtime, but we don't need them then |
254
|
|
|
|
|
|
|
|
255
|
101
|
100
|
|
|
|
224
|
$bindings = $^H{autobox} ? { %{ $^H{autobox} } } : {}; |
|
31
|
|
|
|
|
143
|
|
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
# sanity check %args, expand the namespace prefixes into class names, |
258
|
|
|
|
|
|
|
# and copy values to the $bindings hash |
259
|
|
|
|
|
|
|
|
260
|
101
|
|
|
|
|
364
|
my %synthetic = reverse (%$CLASS_CACHE); # synthetic class name => bool - see _pretty_print |
261
|
|
|
|
|
|
|
|
262
|
101
|
|
|
|
|
259
|
for my $type (keys %args) { |
263
|
|
|
|
|
|
|
# we've handled the virtual types, so we only need to check that this is a valid (real) type |
264
|
707
|
0
|
|
|
|
1175
|
Carp::confess("unrecognized option: '", (defined $type ? $type : ''), "'") unless ($TYPES{$type}); |
|
|
50
|
|
|
|
|
|
265
|
|
|
|
|
|
|
|
266
|
707
|
|
|
|
|
849
|
my (@isa, $class); |
267
|
|
|
|
|
|
|
|
268
|
707
|
100
|
|
|
|
1147
|
if ($class = $bindings->{$type}) { |
269
|
142
|
100
|
|
|
|
326
|
@isa = $synthetic{$class} ? _get_isa($class) : ($class); |
270
|
|
|
|
|
|
|
} |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
# perform namespace expansion; dups are removed in _generate_class below |
273
|
707
|
|
|
|
|
784
|
push @isa, map { _expand_namespace($_, $type) } @{$args{$type}}; |
|
469
|
|
|
|
|
635
|
|
|
707
|
|
|
|
|
1002
|
|
274
|
|
|
|
|
|
|
|
275
|
707
|
|
|
|
|
1744
|
$bindings->{$type} = [ @isa ]; # assign the (possibly) new @isa for this type |
276
|
|
|
|
|
|
|
} |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
# replace each array ref of classes with the name of the generated class. |
279
|
|
|
|
|
|
|
# if there's only one class in the type's @ISA (e.g. SCALAR => 'MyScalar') then |
280
|
|
|
|
|
|
|
# that class is used; otherwise a shim class whose @ISA contains the two or more classes |
281
|
|
|
|
|
|
|
# is created |
282
|
|
|
|
|
|
|
|
283
|
101
|
|
|
|
|
333
|
for my $type (keys %$bindings) { |
284
|
707
|
|
|
|
|
980
|
my $isa = $bindings->{$type}; |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
# delete empty arrays e.g. use autobox SCALAR => [] |
287
|
707
|
100
|
|
|
|
1097
|
if (@$isa == 0) { |
288
|
237
|
|
|
|
|
402
|
delete $bindings->{$type}; |
289
|
|
|
|
|
|
|
} else { |
290
|
|
|
|
|
|
|
# associate the synthetic/single class with the specified type |
291
|
470
|
|
|
|
|
747
|
$bindings->{$type} = _generate_class($isa); |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
} |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
# This turns on autoboxing i.e. the method call checker sets a flag on the method call op |
296
|
|
|
|
|
|
|
# and replaces its default handler with the autobox implementation. |
297
|
|
|
|
|
|
|
# |
298
|
|
|
|
|
|
|
# It needs to be set unconditionally because it may have been unset in unimport |
299
|
|
|
|
|
|
|
|
300
|
101
|
|
|
|
|
300
|
$^H |= 0x80020000; # set HINT_LOCALIZE_HH + an unused bit to work around a %^H bug |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
# install the specified bindings in the current scope |
303
|
101
|
|
|
|
|
238
|
_install($bindings); |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
# this is %^H as an integer - it changes as scopes are entered/exited |
306
|
|
|
|
|
|
|
# we don't need to stack/unstack it in %^H as %^H itself takes care of that |
307
|
|
|
|
|
|
|
# note: we need to call this *after* %^H is referenced (and possibly created) above |
308
|
|
|
|
|
|
|
|
309
|
101
|
|
|
|
|
247
|
my $scope = _scope(); |
310
|
101
|
100
|
|
|
|
238
|
my $old_scope = exists($^H{autobox_scope})? $^H{autobox_scope} : 0; |
311
|
101
|
|
|
|
|
126
|
my $new_scope; # is this a new (top-level or nested) scope? |
312
|
|
|
|
|
|
|
|
313
|
101
|
100
|
|
|
|
168
|
if ($scope == $old_scope) { |
314
|
25
|
|
|
|
|
38
|
$new_scope = 0; |
315
|
|
|
|
|
|
|
} else { |
316
|
76
|
|
|
|
|
187
|
$^H{autobox_scope} = $scope; |
317
|
76
|
|
|
|
|
113
|
$new_scope = 1; |
318
|
|
|
|
|
|
|
} |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
# warn "OLD ($old_scope) => NEW ($scope): $new_scope ", join(':', (caller(1))[0 .. 2]), $/; |
321
|
|
|
|
|
|
|
|
322
|
101
|
100
|
|
|
|
223
|
if ($debug) { |
323
|
44
|
50
|
|
|
|
75
|
$debug = \&_debug unless (_isa($debug, 'CODE')); |
324
|
44
|
|
|
|
|
90
|
$debug->(_pretty_print($bindings)); |
325
|
|
|
|
|
|
|
} |
326
|
|
|
|
|
|
|
|
327
|
101
|
100
|
|
|
|
32587
|
return unless ($new_scope); |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
# This sub is called when this scope's $^H{autobox_leave} is deleted, usually when |
330
|
|
|
|
|
|
|
# %^H is destroyed at the end of the scope, but possibly directly in unimport() |
331
|
|
|
|
|
|
|
# |
332
|
|
|
|
|
|
|
# _enter splices in the autobox method call checker and method call op |
333
|
|
|
|
|
|
|
# if they're not already enabled |
334
|
|
|
|
|
|
|
# |
335
|
|
|
|
|
|
|
# _leave performs the necessary housekeeping to ensure that the default |
336
|
|
|
|
|
|
|
# checker and op are restored when autobox is no longer in scope |
337
|
|
|
|
|
|
|
|
338
|
76
|
|
|
76
|
|
512
|
my $guard = Scope::Guard->new(sub { _leave() }); |
|
76
|
|
|
|
|
90820
|
|
339
|
76
|
|
|
|
|
1067
|
$^H{autobox_leave} = $guard; |
340
|
|
|
|
|
|
|
|
341
|
76
|
|
|
|
|
9338
|
_enter(); |
342
|
|
|
|
|
|
|
} |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
# delete one or more bindings; if none remain, disable autobox in the current scope |
345
|
|
|
|
|
|
|
# |
346
|
|
|
|
|
|
|
# note: if bindings remain, we need to create a new hash (initially a clone of the current |
347
|
|
|
|
|
|
|
# hash) so that the previous hash (if any) is not contaminated by new deletion(s) |
348
|
|
|
|
|
|
|
# |
349
|
|
|
|
|
|
|
# use autobox; |
350
|
|
|
|
|
|
|
# |
351
|
|
|
|
|
|
|
# "foo"->bar; |
352
|
|
|
|
|
|
|
# |
353
|
|
|
|
|
|
|
# no autobox qw(SCALAR); # don't clobber the default bindings for "foo"->bar |
354
|
|
|
|
|
|
|
# |
355
|
|
|
|
|
|
|
# however, if there are no more bindings we can remove all traces of autobox from the |
356
|
|
|
|
|
|
|
# current scope. |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
sub unimport { |
359
|
34
|
|
|
34
|
|
7601
|
my ($class, @args) = @_; |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
# the only situation in which there is no bindings hash is if this is a "no autobox" |
362
|
|
|
|
|
|
|
# that precedes any "use autobox", in which case we don't need to turn autoboxing off as it's |
363
|
|
|
|
|
|
|
# not yet been turned on |
364
|
34
|
100
|
|
|
|
419
|
return unless ($^H{autobox}); |
365
|
|
|
|
|
|
|
|
366
|
20
|
|
|
|
|
36
|
my $bindings; |
367
|
|
|
|
|
|
|
|
368
|
20
|
100
|
|
|
|
51
|
if (@args) { |
369
|
9
|
|
|
|
|
14
|
$bindings = { %{$^H{autobox}} }; # clone the current bindings hash |
|
9
|
|
|
|
|
38
|
|
370
|
9
|
|
|
|
|
21
|
my %args = map { $_ => 1 } @args; |
|
10
|
|
|
|
|
33
|
|
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
# expand any virtual type "macros" |
373
|
9
|
|
|
|
|
33
|
for my $vtype (sort { $ISA{$a}->[0] <=> $ISA{$b}->[0] } keys %ISA) { |
|
26
|
|
|
|
|
55
|
|
374
|
27
|
100
|
|
|
|
53
|
next unless ($args{$vtype}); |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
# we could delete the types directly from $bindings here, but we may as well pipe them |
377
|
|
|
|
|
|
|
# through the option checker below to ensure correctness |
378
|
7
|
|
|
|
|
7
|
$args{$_} = 1 for (@{$ISA{$vtype}->[1]}); |
|
7
|
|
|
|
|
20
|
|
379
|
|
|
|
|
|
|
|
380
|
7
|
|
|
|
|
11
|
delete $args{$vtype}; |
381
|
|
|
|
|
|
|
} |
382
|
|
|
|
|
|
|
|
383
|
9
|
|
|
|
|
33
|
for my $type (keys %args) { |
384
|
|
|
|
|
|
|
# we've handled the virtual types, so we only need to check that this is a valid (real) type |
385
|
17
|
0
|
|
|
|
33
|
Carp::confess("unrecognized option: '", (defined $type ? $type : ''), "'") unless ($TYPES{$type}); |
|
|
50
|
|
|
|
|
|
386
|
17
|
|
|
|
|
34
|
delete $bindings->{$type}; |
387
|
|
|
|
|
|
|
} |
388
|
|
|
|
|
|
|
} else { # turn off autoboxing |
389
|
11
|
|
|
|
|
22
|
$bindings = {}; # empty hash to trigger full deletion below |
390
|
|
|
|
|
|
|
} |
391
|
|
|
|
|
|
|
|
392
|
20
|
100
|
|
|
|
52
|
if (%$bindings) { |
393
|
7
|
|
|
|
|
18
|
_install($bindings); |
394
|
|
|
|
|
|
|
} else { # remove all traces of autobox from the current scope |
395
|
13
|
|
|
|
|
43
|
$^H &= ~0x80020000; # unset HINT_LOCALIZE_HH + the additional bit |
396
|
13
|
|
|
|
|
42
|
delete $^H{autobox}; |
397
|
13
|
|
|
|
|
31
|
delete $^H{autobox_scope}; |
398
|
13
|
|
|
|
|
97
|
delete $^H{autobox_leave}; # triggers the leave handler |
399
|
|
|
|
|
|
|
} |
400
|
|
|
|
|
|
|
} |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
1; |