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