line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
92
|
|
|
92
|
|
106283
|
use 5.008; |
|
92
|
|
|
|
|
429
|
|
2
|
92
|
|
|
92
|
|
701
|
use strict; |
|
92
|
|
|
|
|
232
|
|
|
92
|
|
|
|
|
2375
|
|
3
|
92
|
|
|
92
|
|
536
|
use warnings; |
|
92
|
|
|
|
|
243
|
|
|
92
|
|
|
|
|
7259
|
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $AUTHORITY = 'cpan:TOBYINK'; |
7
|
|
|
|
|
|
|
our $VERSION = '0.045'; |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
use Sub::HandlesVia::Mite -all; |
10
|
92
|
|
|
92
|
|
1254
|
|
|
92
|
|
|
|
|
274
|
|
|
92
|
|
|
|
|
1168
|
|
11
|
|
|
|
|
|
|
has toolkit => ( |
12
|
|
|
|
|
|
|
is => ro, |
13
|
|
|
|
|
|
|
); |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
has target => ( |
16
|
|
|
|
|
|
|
is => ro, |
17
|
|
|
|
|
|
|
); |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
has attribute => ( |
20
|
|
|
|
|
|
|
is => ro, |
21
|
|
|
|
|
|
|
); |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
has attribute_spec => ( |
24
|
|
|
|
|
|
|
is => ro, |
25
|
|
|
|
|
|
|
isa => 'HashRef', |
26
|
|
|
|
|
|
|
); |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
has isa => ( |
29
|
|
|
|
|
|
|
is => ro, |
30
|
|
|
|
|
|
|
); |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
has coerce => ( |
33
|
|
|
|
|
|
|
is => ro, |
34
|
|
|
|
|
|
|
isa => 'Bool', |
35
|
|
|
|
|
|
|
); |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
has env => ( |
38
|
|
|
|
|
|
|
is => ro, |
39
|
|
|
|
|
|
|
isa => 'HashRef', |
40
|
|
|
|
|
|
|
default => \ '{}', |
41
|
|
|
|
|
|
|
default_is_trusted => true, |
42
|
|
|
|
|
|
|
); |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
has sandboxing_package => ( |
45
|
|
|
|
|
|
|
is => ro, |
46
|
|
|
|
|
|
|
isa => 'Str|Undef', |
47
|
|
|
|
|
|
|
default => sprintf( '%s::__SANDBOX__', __PACKAGE__ ), |
48
|
|
|
|
|
|
|
default_is_trusted => true, |
49
|
|
|
|
|
|
|
); |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
has [ 'generator_for_slot', 'generator_for_get', 'generator_for_set', 'generator_for_default' ] => ( |
52
|
|
|
|
|
|
|
is => ro, |
53
|
|
|
|
|
|
|
isa => 'CodeRef', |
54
|
|
|
|
|
|
|
); |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
has generator_for_args => ( |
57
|
|
|
|
|
|
|
is => ro, |
58
|
|
|
|
|
|
|
isa => 'CodeRef', |
59
|
|
|
|
|
|
|
builder => sub { |
60
|
|
|
|
|
|
|
return sub { |
61
|
|
|
|
|
|
|
'@_[1..$#_]'; |
62
|
134
|
|
|
134
|
|
738
|
}; |
63
|
342
|
|
|
342
|
|
1959
|
}, |
64
|
|
|
|
|
|
|
default_is_trusted => true, |
65
|
|
|
|
|
|
|
); |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
has generator_for_arg => ( |
68
|
|
|
|
|
|
|
is => ro, |
69
|
|
|
|
|
|
|
isa => 'CodeRef', |
70
|
|
|
|
|
|
|
builder => sub { |
71
|
|
|
|
|
|
|
return sub { |
72
|
|
|
|
|
|
|
@_==2 or die; |
73
|
4571
|
50
|
|
4571
|
|
10411
|
my $n = pop; |
74
|
4571
|
|
|
|
|
8269
|
"\$_[$n]"; |
75
|
4571
|
|
|
|
|
20022
|
}; |
76
|
342
|
|
|
342
|
|
1989
|
}, |
77
|
|
|
|
|
|
|
default_is_trusted => true, |
78
|
|
|
|
|
|
|
); |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
has generator_for_argc => ( |
81
|
|
|
|
|
|
|
is => ro, |
82
|
|
|
|
|
|
|
isa => 'CodeRef', |
83
|
|
|
|
|
|
|
builder => sub { |
84
|
|
|
|
|
|
|
return sub { |
85
|
|
|
|
|
|
|
'(@_-1)'; |
86
|
472
|
|
|
472
|
|
1980
|
}; |
87
|
342
|
|
|
342
|
|
1614
|
}, |
88
|
|
|
|
|
|
|
default_is_trusted => true, |
89
|
|
|
|
|
|
|
); |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
has generator_for_currying => ( |
92
|
|
|
|
|
|
|
is => ro, |
93
|
|
|
|
|
|
|
isa => 'CodeRef', |
94
|
|
|
|
|
|
|
builder => sub { |
95
|
|
|
|
|
|
|
return sub { |
96
|
|
|
|
|
|
|
@_==2 or die; |
97
|
0
|
0
|
|
0
|
|
0
|
my $arr = pop; |
98
|
0
|
|
|
|
|
0
|
"splice(\@_,1,0,$arr);"; |
99
|
0
|
|
|
|
|
0
|
}; |
100
|
342
|
|
|
342
|
|
1814
|
}, |
101
|
|
|
|
|
|
|
default_is_trusted => true, |
102
|
|
|
|
|
|
|
); |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
has generator_for_usage_string => ( |
105
|
|
|
|
|
|
|
is => ro, |
106
|
|
|
|
|
|
|
isa => 'CodeRef', |
107
|
|
|
|
|
|
|
builder => sub { |
108
|
|
|
|
|
|
|
return sub { |
109
|
|
|
|
|
|
|
@_==3 or die; |
110
|
2638
|
50
|
|
2638
|
|
6208
|
shift; |
111
|
2638
|
|
|
|
|
4195
|
my $method_name = shift; |
112
|
2638
|
|
|
|
|
4221
|
my $guts = shift; |
113
|
2638
|
|
|
|
|
4093
|
"\$instance->$method_name($guts)"; |
114
|
2638
|
|
|
|
|
21558
|
}; |
115
|
342
|
|
|
342
|
|
1852
|
}, |
116
|
|
|
|
|
|
|
default_is_trusted => true, |
117
|
|
|
|
|
|
|
); |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
has generator_for_self => ( |
120
|
|
|
|
|
|
|
is => ro, |
121
|
|
|
|
|
|
|
isa => 'CodeRef', |
122
|
|
|
|
|
|
|
builder => sub { |
123
|
|
|
|
|
|
|
return sub { |
124
|
|
|
|
|
|
|
'$_[0]'; |
125
|
5372
|
|
|
5372
|
|
18132
|
}; |
126
|
342
|
|
|
342
|
|
1536
|
}, |
127
|
|
|
|
|
|
|
default_is_trusted => true, |
128
|
|
|
|
|
|
|
); |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
has generator_for_type_assertion => ( |
131
|
|
|
|
|
|
|
is => ro, |
132
|
|
|
|
|
|
|
isa => 'CodeRef', |
133
|
|
|
|
|
|
|
builder => sub { |
134
|
|
|
|
|
|
|
return sub { |
135
|
|
|
|
|
|
|
my ( $gen, $env, $type, $varname ) = @_; |
136
|
790
|
|
|
790
|
|
1916
|
my $i = 0; |
137
|
790
|
|
|
|
|
1291
|
my $type_varname = sprintf '$shv_type_constraint_%d', $type->{uniq}; |
138
|
790
|
|
|
|
|
3163
|
$env->{$type_varname} = \$type; |
139
|
790
|
|
|
|
|
2092
|
if ( $gen->coerce and $type->has_coercion ) { |
140
|
790
|
100
|
100
|
|
|
2765
|
if ( $type->coercion->can_be_inlined ) { |
141
|
8
|
50
|
|
|
|
110
|
return sprintf '%s=%s;%s;', |
142
|
8
|
|
|
|
|
728
|
$varname, |
143
|
|
|
|
|
|
|
$type->coercion->inline_coercion($varname), |
144
|
|
|
|
|
|
|
$type->inline_assert( $varname, $type_varname ); |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
else { |
147
|
|
|
|
|
|
|
return sprintf '%s=%s->assert_coerce(%s);', |
148
|
0
|
|
|
|
|
0
|
$varname, $type_varname, $varname; |
149
|
|
|
|
|
|
|
} |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
return $type->inline_assert( $varname, $type_varname ); |
152
|
782
|
|
|
|
|
3558
|
}; |
153
|
342
|
|
|
342
|
|
2115
|
}, |
154
|
|
|
|
|
|
|
default_is_trusted => true, |
155
|
|
|
|
|
|
|
); |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
has generator_for_error => ( |
158
|
|
|
|
|
|
|
is => ro, |
159
|
|
|
|
|
|
|
isa => 'CodeRef', |
160
|
|
|
|
|
|
|
builder => sub { |
161
|
|
|
|
|
|
|
return sub { |
162
|
|
|
|
|
|
|
my ( $gen, $error ) = @_; |
163
|
2723
|
|
|
2723
|
|
5984
|
sprintf 'do { require Carp; Carp::croak(%s) }', $error; |
164
|
2723
|
|
|
|
|
9359
|
}; |
165
|
342
|
|
|
342
|
|
1816
|
}, |
166
|
|
|
|
|
|
|
default_is_trusted => true, |
167
|
|
|
|
|
|
|
); |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
has generator_for_prelude => ( |
170
|
|
|
|
|
|
|
is => ro, |
171
|
|
|
|
|
|
|
isa => 'CodeRef', |
172
|
|
|
|
|
|
|
builder => sub { |
173
|
|
|
|
|
|
|
return sub { '' }; |
174
|
2172
|
|
|
2172
|
|
5639
|
}, |
|
2388
|
|
|
|
|
6264
|
|
175
|
|
|
|
|
|
|
default_is_trusted => true, |
176
|
|
|
|
|
|
|
); |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
has method_installer => ( |
179
|
|
|
|
|
|
|
is => rw, |
180
|
|
|
|
|
|
|
isa => 'CodeRef', |
181
|
|
|
|
|
|
|
); |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
has _override => ( |
184
|
|
|
|
|
|
|
is => rw, |
185
|
|
|
|
|
|
|
init_arg => undef, |
186
|
|
|
|
|
|
|
); |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
has is_method => ( |
189
|
|
|
|
|
|
|
is => ro, |
190
|
|
|
|
|
|
|
default => true, |
191
|
|
|
|
|
|
|
); |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
has get_is_lvalue => ( |
194
|
|
|
|
|
|
|
is => ro, |
195
|
|
|
|
|
|
|
default => false, |
196
|
|
|
|
|
|
|
); |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
has set_checks_isa => ( |
199
|
|
|
|
|
|
|
is => ro, |
200
|
|
|
|
|
|
|
default => false, |
201
|
|
|
|
|
|
|
); |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
has set_strictly => ( |
204
|
|
|
|
|
|
|
is => ro, |
205
|
|
|
|
|
|
|
default => true, |
206
|
|
|
|
|
|
|
); |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
my $REASONABLE_SCALAR = qr/^ |
209
|
|
|
|
|
|
|
\$ # scalar access |
210
|
|
|
|
|
|
|
[^\W0-9]\w* # normal-looking variable name (including $_) |
211
|
|
|
|
|
|
|
(?: # then... |
212
|
|
|
|
|
|
|
(?:\-\>)? # dereference maybe |
213
|
|
|
|
|
|
|
[\[\{] # opening [ or { |
214
|
|
|
|
|
|
|
[\'\"]? # quote maybe |
215
|
|
|
|
|
|
|
\w+ # word characters (includes digits) |
216
|
|
|
|
|
|
|
[\'\"]? # quote maybe |
217
|
|
|
|
|
|
|
[\]\}] # closing ] or } |
218
|
|
|
|
|
|
|
){0,3} # ... up to thrice |
219
|
|
|
|
|
|
|
$/x; |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
my @generatable_things = qw( |
222
|
|
|
|
|
|
|
slot get set default arg args argc currying usage_string self |
223
|
|
|
|
|
|
|
type_assertion error prelude |
224
|
|
|
|
|
|
|
); |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
for my $thing ( @generatable_things ) { |
227
|
|
|
|
|
|
|
my $generator = "generator_for_$thing"; |
228
|
|
|
|
|
|
|
my $method_name = "generate_$thing"; |
229
|
|
|
|
|
|
|
my $method = sub { |
230
|
|
|
|
|
|
|
my $gen = shift; |
231
|
37396
|
|
|
37396
|
|
95962
|
local ${^GENERATOR} = $gen; |
232
|
37396
|
|
|
|
|
55386
|
|
233
|
|
|
|
|
|
|
if ( @{ $gen->_override->{$thing} || [] } ) { |
234
|
37396
|
100
|
|
|
|
49391
|
my $coderef = pop @{ $gen->_override->{$thing} }; |
|
37396
|
100
|
|
|
|
138090
|
|
235
|
8523
|
|
|
|
|
12772
|
my $guard = guard { |
|
8523
|
|
|
|
|
18128
|
|
236
|
|
|
|
|
|
|
push @{ $gen->_override->{$thing} ||= [] }, $coderef; |
237
|
8523
|
|
50
|
8523
|
|
12385
|
}; |
|
8523
|
|
|
|
|
58755
|
|
238
|
8523
|
|
|
|
|
40375
|
return $gen->$coderef( @_ ); |
239
|
8523
|
|
|
|
|
20304
|
} |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
return $gen->$generator->( $gen, @_ ); |
242
|
28873
|
|
|
|
|
100249
|
}; |
243
|
|
|
|
|
|
|
no strict 'refs'; |
244
|
92
|
|
|
92
|
|
108761
|
*$method_name = $method; |
|
92
|
|
|
|
|
276
|
|
|
92
|
|
|
|
|
49629
|
|
245
|
|
|
|
|
|
|
} |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
my $self = shift; |
248
|
|
|
|
|
|
|
my $attr = $self->attribute; |
249
|
3
|
|
|
3
|
0
|
8
|
|
250
|
3
|
|
|
|
|
9
|
return $attr |
251
|
|
|
|
|
|
|
if !ref $attr; |
252
|
3
|
50
|
|
|
|
15
|
|
253
|
|
|
|
|
|
|
return sprintf '$instance->%s', $attr->[0] |
254
|
|
|
|
|
|
|
if ref($attr) eq 'ARRAY'; |
255
|
0
|
0
|
|
|
|
0
|
|
256
|
|
|
|
|
|
|
return '$attribute_value'; |
257
|
|
|
|
|
|
|
} |
258
|
0
|
|
|
|
|
0
|
|
259
|
|
|
|
|
|
|
my $self = shift; |
260
|
|
|
|
|
|
|
$self->_override( {} ); |
261
|
|
|
|
|
|
|
return guard { |
262
|
4221
|
|
|
4221
|
|
6898
|
$self->_override( {} ); |
263
|
4221
|
|
|
|
|
13811
|
}; |
264
|
|
|
|
|
|
|
} |
265
|
4221
|
|
|
4221
|
|
31748
|
|
266
|
4221
|
|
|
|
|
22936
|
{ |
267
|
|
|
|
|
|
|
my %generatable_thing = map +( $_ => 1 ), @generatable_things; |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
my ( $self, %overrides ) = @_; |
270
|
|
|
|
|
|
|
while ( my ( $key, $value ) = each %overrides ) { |
271
|
|
|
|
|
|
|
next if !defined $value; |
272
|
|
|
|
|
|
|
next if !$generatable_thing{$key}; |
273
|
3069
|
|
|
3069
|
|
11161
|
push @{ $self->_override->{$key} ||= [] }, $value; |
274
|
3069
|
|
|
|
|
11644
|
} |
275
|
11112
|
100
|
|
|
|
22249
|
return $self; |
276
|
10840
|
100
|
|
|
|
24466
|
} |
277
|
8836
|
|
100
|
|
|
13596
|
} |
|
8836
|
|
|
|
|
46118
|
|
278
|
|
|
|
|
|
|
|
279
|
3069
|
|
|
|
|
7614
|
my ( $self, $method_name, $handler ) = @_; |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
$self->install_method( |
282
|
|
|
|
|
|
|
$method_name, |
283
|
|
|
|
|
|
|
$self->generate_coderef_for_handler( $method_name, $handler ), |
284
|
4219
|
|
|
4219
|
1
|
8863
|
); |
285
|
|
|
|
|
|
|
} |
286
|
4219
|
|
|
|
|
10620
|
|
287
|
|
|
|
|
|
|
{ |
288
|
|
|
|
|
|
|
my $sub_rename; |
289
|
|
|
|
|
|
|
if ( eval { require Sub::Util } ) { |
290
|
|
|
|
|
|
|
$sub_rename = Sub::Util->can('set_subname'); |
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
elsif ( eval { require Sub::Name } ) { |
293
|
|
|
|
|
|
|
$sub_rename = Sub::Name->can('subname'); |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
my ( $self, $method_name, $coderef ) = @_; |
297
|
|
|
|
|
|
|
my $target = $self->target; |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
eval { |
300
|
|
|
|
|
|
|
$coderef = $sub_rename->( "$target\::$method_name", $coderef ) |
301
|
|
|
|
|
|
|
} if ref $sub_rename; |
302
|
4219
|
|
|
4219
|
1
|
1791530
|
|
303
|
4219
|
|
|
|
|
13515
|
if ( $self->method_installer ) { |
304
|
|
|
|
|
|
|
$self->method_installer->( $method_name, $coderef ); |
305
|
4219
|
50
|
|
|
|
13758
|
} |
306
|
4219
|
|
|
|
|
33256
|
else { |
307
|
|
|
|
|
|
|
no strict 'refs'; |
308
|
|
|
|
|
|
|
*{"$target\::$method_name"} = $coderef; |
309
|
4219
|
100
|
|
|
|
16691
|
} |
310
|
2593
|
|
|
|
|
7235
|
} |
311
|
|
|
|
|
|
|
} |
312
|
|
|
|
|
|
|
|
313
|
92
|
|
|
92
|
|
868
|
my ( $self, $method_name, $handler ) = @_; |
|
92
|
|
|
|
|
272
|
|
|
92
|
|
|
|
|
220263
|
|
314
|
1626
|
|
|
|
|
2681
|
|
|
1626
|
|
|
|
|
11241
|
|
315
|
|
|
|
|
|
|
my $ec_args = $self->_generate_ec_args_for_handler( $method_name, $handler ); |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
# warn "#### $method_name"; |
318
|
|
|
|
|
|
|
# warn join("\n", @{$ec_args->{source}}); |
319
|
|
|
|
|
|
|
# for my $key (sort keys %{$ec_args->{environment}}) { |
320
|
4220
|
|
|
4220
|
1
|
7924
|
# warn ">> $key : ".ref($ec_args->{environment}{$key}); |
321
|
|
|
|
|
|
|
# if ( ref($ec_args->{environment}{$key}) eq 'REF' and ref(${$ec_args->{environment}{$key}}) eq 'CODE' ) { |
322
|
4220
|
|
|
|
|
9166
|
# require B::Deparse; |
323
|
|
|
|
|
|
|
# warn B::Deparse->new->coderef2text(${$ec_args->{environment}{$key}}); |
324
|
|
|
|
|
|
|
# } |
325
|
|
|
|
|
|
|
# } |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
require Eval::TypeTiny; |
328
|
|
|
|
|
|
|
Eval::TypeTiny::eval_closure( %$ec_args ); |
329
|
|
|
|
|
|
|
} |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
my ( $self, $method_name, $handler ) = @_; |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
# Later on, we might need to override the generators for |
334
|
4220
|
|
|
|
|
24069
|
# arg, argc, args, set, etc. |
335
|
4220
|
|
|
|
|
19006
|
# |
336
|
|
|
|
|
|
|
my $guard = $self->_start_overriding_generators; |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
# Make a COPY of $self->env! |
339
|
4221
|
|
|
4221
|
|
7271
|
# |
340
|
|
|
|
|
|
|
my $env = { %{$self->env} }; |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
# Preamble code. |
343
|
|
|
|
|
|
|
# |
344
|
4221
|
|
|
|
|
8887
|
my $code = [ |
345
|
|
|
|
|
|
|
'sub {', |
346
|
|
|
|
|
|
|
]; |
347
|
|
|
|
|
|
|
|
348
|
4221
|
|
|
|
|
7737
|
push @$code, sprintf( 'package %s;', $self->sandboxing_package ) |
|
4221
|
|
|
|
|
13755
|
|
349
|
|
|
|
|
|
|
if $self->sandboxing_package; |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
# Need to maintain state between following method calls. A proper |
352
|
4221
|
|
|
|
|
9731
|
# object might be nice, but a hashref will do for now. |
353
|
|
|
|
|
|
|
# |
354
|
|
|
|
|
|
|
my $state = { |
355
|
|
|
|
|
|
|
signature_check_needed => true, # hasn't been done yet |
356
|
4221
|
50
|
|
|
|
24393
|
final_type_check_needed => $handler->is_mutator, |
357
|
|
|
|
|
|
|
getter => scalar($self->generate_get), |
358
|
|
|
|
|
|
|
getter_is_lvalue => $self->get_is_lvalue, |
359
|
|
|
|
|
|
|
template_wrapper => undef, # nothing yet |
360
|
|
|
|
|
|
|
add_later => undef, # nothing yet |
361
|
|
|
|
|
|
|
shifted_self => false, |
362
|
4221
|
|
|
|
|
14166
|
}; |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
# use Hash::Util qw( lock_ref_keys ); |
365
|
|
|
|
|
|
|
# lock_ref_keys( $state ); |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
my @args = ( |
368
|
|
|
|
|
|
|
$method_name, # Intended name for the coderef being generated |
369
|
|
|
|
|
|
|
$handler, # Info about the functionality being delegated |
370
|
|
|
|
|
|
|
$env, # Variables which need to be closed over |
371
|
|
|
|
|
|
|
$code, # Lines of code in the method |
372
|
|
|
|
|
|
|
$state, # Shared state while building method. (Minimal!) |
373
|
|
|
|
|
|
|
); |
374
|
|
|
|
|
|
|
$self |
375
|
4221
|
|
|
|
|
24243
|
->_handle_sigcheck( @args ) # check method sigs |
376
|
|
|
|
|
|
|
->_handle_prelude( @args ) # insert any prelude |
377
|
|
|
|
|
|
|
->_handle_shiftself( @args ) # $self = shift |
378
|
|
|
|
|
|
|
->_handle_currying( @args ) # push curried values to @_ |
379
|
|
|
|
|
|
|
->_handle_additional_validation( @args ) # additional type checks |
380
|
|
|
|
|
|
|
->_handle_getter_code( @args ) # optimize calling getter |
381
|
|
|
|
|
|
|
->_handle_setter_code( @args ) # make calling setter safer |
382
|
4221
|
|
|
|
|
10565
|
->_handle_template( @args ) # perform code substitutes |
383
|
|
|
|
|
|
|
->_handle_chaining( @args ); # return $self if requested |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
# Postamble code. Can't really do much here because the template |
386
|
|
|
|
|
|
|
# might want to be able to return something. |
387
|
|
|
|
|
|
|
# |
388
|
|
|
|
|
|
|
push @$code, "}"; |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
# Allow the handler to inject variables into the environment. |
391
|
|
|
|
|
|
|
# Rarely needed. |
392
|
|
|
|
|
|
|
# |
393
|
|
|
|
|
|
|
$handler->_tweak_env( $env ); |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
return { |
396
|
4221
|
|
|
|
|
9622
|
source => $code, |
397
|
|
|
|
|
|
|
environment => $env, |
398
|
|
|
|
|
|
|
description => sprintf( |
399
|
|
|
|
|
|
|
"%s=%s", |
400
|
|
|
|
|
|
|
$method_name || '__ANON__', |
401
|
4221
|
|
|
|
|
14517
|
$handler->name, |
402
|
|
|
|
|
|
|
), |
403
|
|
|
|
|
|
|
}; |
404
|
4221
|
|
50
|
|
|
43879
|
} |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
my ( $self, $method_name, $handler, $env, $code, $state ) = @_; |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
# If there's a proper signature for the method... |
409
|
|
|
|
|
|
|
# |
410
|
|
|
|
|
|
|
if ( @{ $handler->signature || [] } ) { |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
# Generate code using Type::Params to check the signature. |
413
|
|
|
|
|
|
|
# We also need to close over the signature. |
414
|
|
|
|
|
|
|
# |
415
|
4221
|
|
|
4221
|
|
9102
|
require Type::Params; |
416
|
|
|
|
|
|
|
unshift @$code, 'my $__sigcheck;'; |
417
|
|
|
|
|
|
|
$env->{'@__sig'} = $handler->signature; |
418
|
|
|
|
|
|
|
if ( $state->{shifted_self} ) { |
419
|
4221
|
100
|
|
|
|
6013
|
push @$code, '$__sigcheck||=Type::Params::compile(@__sig);@_=&$__sigcheck;'; |
|
4221
|
100
|
|
|
|
17536
|
|
420
|
|
|
|
|
|
|
} |
421
|
|
|
|
|
|
|
else { |
422
|
|
|
|
|
|
|
push @$code, '$__sigcheck||=Type::Params::compile(1, @__sig);@_=&$__sigcheck;'; |
423
|
|
|
|
|
|
|
} |
424
|
1583
|
|
|
|
|
9017
|
|
425
|
1583
|
|
|
|
|
4664
|
# As we've now inserted a signature check, we can stop worrying |
426
|
1583
|
|
|
|
|
3869
|
# about signature checks. |
427
|
1583
|
50
|
|
|
|
3379
|
# |
428
|
0
|
|
|
|
|
0
|
$state->{signature_check_needed} = 0; |
429
|
|
|
|
|
|
|
} |
430
|
|
|
|
|
|
|
# There is no proper signature, but there's still check the |
431
|
1583
|
|
|
|
|
3696
|
# arity of the method. |
432
|
|
|
|
|
|
|
# |
433
|
|
|
|
|
|
|
else { |
434
|
|
|
|
|
|
|
# What is the arity? |
435
|
|
|
|
|
|
|
# |
436
|
|
|
|
|
|
|
my $min_args = $handler->min_args || 0; |
437
|
1583
|
|
|
|
|
2952
|
my $max_args = $handler->max_args; |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
my $plus = 1; |
440
|
|
|
|
|
|
|
if ( $state->{shifted_self} ) { |
441
|
|
|
|
|
|
|
$plus = 0; |
442
|
|
|
|
|
|
|
} |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
# What usage message do we want to print if wrong arity? |
445
|
2638
|
|
100
|
|
|
7587
|
# |
446
|
2638
|
|
|
|
|
7286
|
my $usg = $self->generate_error( sprintf( |
447
|
|
|
|
|
|
|
' "Wrong number of parameters; usage: " . %s ', |
448
|
2638
|
|
|
|
|
4653
|
B::perlstring( $self->generate_usage_string( $method_name, $handler->usage ) ), |
449
|
2638
|
50
|
|
|
|
6304
|
) ); |
450
|
0
|
|
|
|
|
0
|
|
451
|
|
|
|
|
|
|
# Insert the check into the code. |
452
|
|
|
|
|
|
|
# |
453
|
|
|
|
|
|
|
if (defined $min_args and defined $max_args and $min_args==$max_args) { |
454
|
|
|
|
|
|
|
push @$code, sprintf('@_==%d or %s;', $min_args + $plus, $usg); |
455
|
2638
|
|
|
|
|
8132
|
} |
456
|
|
|
|
|
|
|
elsif (defined $min_args and defined $max_args) { |
457
|
|
|
|
|
|
|
push @$code, sprintf('(@_ >= %d and @_ <= %d) or %s;', $min_args + $plus, $max_args + $plus, $usg); |
458
|
|
|
|
|
|
|
} |
459
|
|
|
|
|
|
|
elsif (defined $min_args and $min_args > 0) { |
460
|
|
|
|
|
|
|
push @$code, sprintf('@_ >= %d or %s;', $min_args + $plus, $usg); |
461
|
|
|
|
|
|
|
} |
462
|
2638
|
100
|
66
|
|
|
17685
|
|
|
|
100
|
100
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
463
|
1789
|
|
|
|
|
6750
|
# We are still lacking a proper signature check though, so note |
464
|
|
|
|
|
|
|
# that in the state. The information can be used by |
465
|
|
|
|
|
|
|
# additional_validation coderefs. |
466
|
264
|
|
|
|
|
1237
|
# |
467
|
|
|
|
|
|
|
$state->{signature_check_needed} = true; |
468
|
|
|
|
|
|
|
} |
469
|
187
|
|
|
|
|
898
|
|
470
|
|
|
|
|
|
|
return $self; |
471
|
|
|
|
|
|
|
} |
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
my ( $self, $method_name, $handler, $env, $code, $state ) = @_; |
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
push @$code, $self->generate_prelude(); |
476
|
2638
|
|
|
|
|
6509
|
|
477
|
|
|
|
|
|
|
return $self; |
478
|
|
|
|
|
|
|
} |
479
|
4221
|
|
|
|
|
12498
|
|
480
|
|
|
|
|
|
|
my ( $self, $method_name, $handler, $env, $code, $state ) = @_; |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
# Handlers which use @ARG will benefit from shifting $self |
483
|
4221
|
|
|
4221
|
|
9241
|
# off @_, but for other handlers, this will just slow compilation |
484
|
|
|
|
|
|
|
# down (but not much). |
485
|
4221
|
|
|
|
|
9242
|
# |
486
|
|
|
|
|
|
|
return $self |
487
|
4221
|
|
|
|
|
10925
|
unless $handler->curried || $handler->prefer_shift_self; |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
# Shift off the invocant. |
490
|
|
|
|
|
|
|
# |
491
|
4221
|
|
|
4221
|
|
8730
|
push @$code, 'my $shv_self=shift;'; |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
$self->_add_generator_override( |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
# Override $ARG[$n] because the array has been reindexed. |
496
|
|
|
|
|
|
|
# |
497
|
4221
|
100
|
100
|
|
|
20065
|
arg => sub { my ($gen, $n) = @_; $gen->generate_arg( $n - 1 ) }, |
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
# Overrride @ARG to point to the whole array. This is the |
500
|
|
|
|
|
|
|
# real speed-up! |
501
|
|
|
|
|
|
|
# |
502
|
1692
|
|
|
|
|
3581
|
args => sub { '@_' }, |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
# Override #ARG to no longer subtract 1. |
505
|
|
|
|
|
|
|
# |
506
|
|
|
|
|
|
|
argc => sub { 'scalar(@_)' }, |
507
|
|
|
|
|
|
|
|
508
|
2458
|
|
|
2458
|
|
6484
|
# $SELF is now '$shv_self'. |
|
2458
|
|
|
|
|
6857
|
|
509
|
|
|
|
|
|
|
# |
510
|
|
|
|
|
|
|
self => sub { '$shv_self' }, |
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
# The default currying callback will splice the list into |
513
|
681
|
|
|
681
|
|
2606
|
# @_ at index 1. Instead unshift the list at the start of @_. |
514
|
|
|
|
|
|
|
# |
515
|
|
|
|
|
|
|
currying => sub { |
516
|
|
|
|
|
|
|
my ($gen, $list) = @_; |
517
|
875
|
|
|
875
|
|
2783
|
"CORE::unshift(\@_, $list);"; |
518
|
|
|
|
|
|
|
}, |
519
|
|
|
|
|
|
|
); |
520
|
|
|
|
|
|
|
|
521
|
2612
|
|
|
2612
|
|
9136
|
# Getter was cached in $state and needs update. |
522
|
|
|
|
|
|
|
# |
523
|
|
|
|
|
|
|
$state->{getter} = $self->generate_get; |
524
|
|
|
|
|
|
|
$state->{shifted_self} = true; |
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
return $self; |
527
|
1389
|
|
|
1389
|
|
3665
|
} |
528
|
1389
|
|
|
|
|
6220
|
|
529
|
|
|
|
|
|
|
# Insert code into method for currying. |
530
|
1692
|
|
|
|
|
19013
|
# |
531
|
|
|
|
|
|
|
my ( $self, $method_name, $handler, $env, $code, $state ) = @_; |
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
if ( my $curried = $handler->curried ) { |
534
|
1692
|
|
|
|
|
4323
|
|
535
|
1692
|
|
|
|
|
7047
|
# If the curried values are non-simple, we close over an array |
536
|
|
|
|
|
|
|
# called @curry. |
537
|
1692
|
|
|
|
|
4556
|
# |
538
|
|
|
|
|
|
|
if ( grep ref, @$curried ) { |
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
# Note that generate_currying will generate code that unshifts whatever |
541
|
|
|
|
|
|
|
# parameters it is given onto @_. |
542
|
|
|
|
|
|
|
push @$code, $self->generate_currying('@curry'); |
543
|
4221
|
|
|
4221
|
|
9090
|
$env->{'@curry'} = $curried; |
544
|
|
|
|
|
|
|
} |
545
|
4221
|
100
|
|
|
|
11179
|
# If it's just strings, numbers, and undef, it should be pretty |
546
|
|
|
|
|
|
|
# trivial to hard-code the values into the generated Perl string. |
547
|
|
|
|
|
|
|
# |
548
|
|
|
|
|
|
|
else { |
549
|
|
|
|
|
|
|
require B; |
550
|
1389
|
100
|
|
|
|
5299
|
my $values = join( |
551
|
|
|
|
|
|
|
',', |
552
|
|
|
|
|
|
|
map { defined($_) ? B::perlstring($_) : 'undef' } @$curried, |
553
|
|
|
|
|
|
|
); |
554
|
360
|
|
|
|
|
1082
|
push @$code, $self->generate_currying( "($values)" ); |
555
|
360
|
|
|
|
|
1115
|
} |
556
|
|
|
|
|
|
|
} |
557
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
return $self; |
559
|
|
|
|
|
|
|
} |
560
|
|
|
|
|
|
|
|
561
|
1029
|
|
|
|
|
5663
|
my ( $self, $method_name, $handler, $env, $code, $state ) = @_; |
562
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
# If the handler specifies no validation needed, or the attribute |
564
|
1029
|
50
|
|
|
|
2266
|
# simply has no type check, we don't need to check the type of the |
|
1545
|
|
|
|
|
7034
|
|
565
|
|
|
|
|
|
|
# final attribute value. |
566
|
1029
|
|
|
|
|
4406
|
# |
567
|
|
|
|
|
|
|
if ( $handler->no_validation_needed or not $self->isa ) { |
568
|
|
|
|
|
|
|
$state->{final_type_check_needed} = false; |
569
|
|
|
|
|
|
|
} |
570
|
4221
|
|
|
|
|
11136
|
|
571
|
|
|
|
|
|
|
# The handler can define some additional validation to be performed |
572
|
|
|
|
|
|
|
# on arguments either now or later, such that if this additional |
573
|
|
|
|
|
|
|
# validation is performed, the type check we were planning later |
574
|
4221
|
|
|
4221
|
|
8439
|
# will be known to be unnecessary. |
575
|
|
|
|
|
|
|
# |
576
|
|
|
|
|
|
|
# An example for this is that is the attribute value is already an |
577
|
|
|
|
|
|
|
# arrayref of numbers, and we're pushing a new value onto it, by checking |
578
|
|
|
|
|
|
|
# up front that the INCOMING value is a number, it becomes unnecessary |
579
|
|
|
|
|
|
|
# to check the whole arrayref contains numbers after the push. |
580
|
4221
|
100
|
66
|
|
|
33137
|
# |
581
|
177
|
|
|
|
|
348
|
# Not all handlers define an additional_validation coderef to do |
582
|
|
|
|
|
|
|
# this, because in many cases it doesn't make sense to. |
583
|
|
|
|
|
|
|
# |
584
|
|
|
|
|
|
|
# Also if we've already decided a final type check isn't needed, we |
585
|
|
|
|
|
|
|
# can skip this step. |
586
|
|
|
|
|
|
|
# |
587
|
|
|
|
|
|
|
if ( $state->{final_type_check_needed} |
588
|
|
|
|
|
|
|
and defined $handler->additional_validation ) { |
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
my $real_av_method = $handler->_real_additional_validation; |
591
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
# The additional_validation coderef is called as a method and takes |
593
|
|
|
|
|
|
|
# two additional parameters: |
594
|
|
|
|
|
|
|
# |
595
|
|
|
|
|
|
|
my $opt = $handler->$real_av_method( |
596
|
|
|
|
|
|
|
!$state->{signature_check_needed}, # $sig_was_checked |
597
|
|
|
|
|
|
|
$self, # $gen |
598
|
|
|
|
|
|
|
); |
599
|
|
|
|
|
|
|
$opt ||= {}; # can return undef |
600
|
4221
|
100
|
100
|
|
|
31213
|
|
601
|
|
|
|
|
|
|
# The additional_validation coderef will often generate code which |
602
|
|
|
|
|
|
|
# coerces incoming data, thus moving it from @_ to some other array. |
603
|
1377
|
|
|
|
|
4817
|
# This means that the generators for @ARG, $ARG, etc will need to |
604
|
|
|
|
|
|
|
# need to be overridden to point to the new array. |
605
|
|
|
|
|
|
|
# |
606
|
|
|
|
|
|
|
$self->_add_generator_override( %$opt ); |
607
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
# The additional_validation coderef may supply extra variables |
609
|
|
|
|
|
|
|
# to close over. |
610
|
1377
|
|
|
|
|
5331
|
# |
611
|
|
|
|
|
|
|
$env->{$_} = $opt->{env}{$_} |
612
|
1377
|
|
100
|
|
|
6704
|
for keys %{ $opt->{env} || {} }; |
613
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
# The additional_validation coderef will normally generate |
615
|
|
|
|
|
|
|
# new code. |
616
|
|
|
|
|
|
|
# |
617
|
|
|
|
|
|
|
if ( defined $opt->{code} ) { |
618
|
|
|
|
|
|
|
|
619
|
1377
|
|
|
|
|
6144
|
# Code can be inserted into the generated method straight away, |
620
|
|
|
|
|
|
|
# or may need to be inserted in a special placeholder position |
621
|
|
|
|
|
|
|
# later. |
622
|
|
|
|
|
|
|
# |
623
|
|
|
|
|
|
|
$opt->{add_later} |
624
|
|
|
|
|
|
|
? ( $state->{add_later} = $opt->{code} ) |
625
|
1377
|
100
|
|
|
|
2352
|
: push( @$code, $opt->{code} ); |
|
1377
|
|
|
|
|
6441
|
|
626
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
# Final type check is often no longer needed. |
628
|
|
|
|
|
|
|
# |
629
|
|
|
|
|
|
|
$state->{final_type_check_needed} = $opt->{final_type_check_needed} || false; |
630
|
1377
|
100
|
|
|
|
5539
|
} |
631
|
|
|
|
|
|
|
} |
632
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
return $self; |
634
|
|
|
|
|
|
|
} |
635
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
my ( $self, $method_name, $handler, $env, $code, $state ) = @_; |
637
|
|
|
|
|
|
|
|
638
|
885
|
100
|
|
|
|
2709
|
# If there's a complicated way to fetch the attribute value (perhaps |
639
|
|
|
|
|
|
|
# involving a lazy builder)... |
640
|
|
|
|
|
|
|
# |
641
|
|
|
|
|
|
|
if ( $state->{getter} !~ $REASONABLE_SCALAR ) { |
642
|
885
|
|
100
|
|
|
5827
|
|
643
|
|
|
|
|
|
|
# And if it's definitely a reference anyway, then get it straight away, |
644
|
|
|
|
|
|
|
# and store it in $shv_ref_invocant so we don't have to keep doing the |
645
|
|
|
|
|
|
|
# complicated thing. |
646
|
4221
|
|
|
|
|
11358
|
# |
647
|
|
|
|
|
|
|
if ( $handler->name =~ /^(Array|Hash):/ ) { |
648
|
|
|
|
|
|
|
push @$code, "my \$shv_ref_invocant = do { $state->{getter} };"; |
649
|
|
|
|
|
|
|
$state->{getter} = '$shv_ref_invocant'; |
650
|
4221
|
|
|
4221
|
|
9319
|
$state->{getter_is_lvalue} = true; |
651
|
|
|
|
|
|
|
} |
652
|
|
|
|
|
|
|
|
653
|
|
|
|
|
|
|
# Alternatively, unless the handler doesn't want us to, or the template |
654
|
|
|
|
|
|
|
# doesn't want to get the attribute value anyway, then we'll do something |
655
|
4221
|
100
|
|
|
|
38196
|
# similar. Here it can't be used as an lvalue though. |
656
|
|
|
|
|
|
|
# |
657
|
|
|
|
|
|
|
elsif ( $handler->allow_getter_shortcuts |
658
|
|
|
|
|
|
|
and $handler->template.($handler->lvalue_template||'') =~ /\$GET/ ) { |
659
|
|
|
|
|
|
|
( my $g = $state->{getter} ) =~ s/%/%%/g; |
660
|
|
|
|
|
|
|
$state->{template_wrapper} = "do { my \$shv_real_invocant = $g; %s }"; |
661
|
822
|
100
|
100
|
|
|
6300
|
$state->{getter} = '$shv_real_invocant'; |
|
|
100
|
66
|
|
|
|
|
662
|
490
|
|
|
|
|
1729
|
} |
663
|
490
|
|
|
|
|
919
|
} |
664
|
490
|
|
|
|
|
952
|
|
665
|
|
|
|
|
|
|
return $self; |
666
|
|
|
|
|
|
|
} |
667
|
|
|
|
|
|
|
|
668
|
|
|
|
|
|
|
my ( $self, $method_name, $handler, $env, $code, $state ) = @_; |
669
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
# If a type check is needed, but the setter doesn't do type checks, |
671
|
|
|
|
|
|
|
# then override the setter. Now the setter does the type check, so |
672
|
|
|
|
|
|
|
# we no longer need to worry about it. |
673
|
329
|
|
|
|
|
1175
|
# |
674
|
329
|
|
|
|
|
938
|
# XXX: I don't think any of the tests currently exercise this. |
675
|
329
|
|
|
|
|
680
|
# |
676
|
|
|
|
|
|
|
if ( $state->{final_type_check_needed} and not $self->set_checks_isa ) { |
677
|
|
|
|
|
|
|
$self->_add_generator_override( set => sub { |
678
|
|
|
|
|
|
|
my ( $me, $value_code ) = @_; |
679
|
4221
|
|
|
|
|
11921
|
$me->generate_set( sprintf( |
680
|
|
|
|
|
|
|
'do { my $shv_final_unchecked = %s; %s }', |
681
|
|
|
|
|
|
|
$value_code, |
682
|
|
|
|
|
|
|
$me->generate_type_assertion( $env, $me->isa, '$shv_final_unchecked' ), |
683
|
4221
|
|
|
4221
|
|
9240
|
) ); |
684
|
|
|
|
|
|
|
} ); |
685
|
|
|
|
|
|
|
|
686
|
|
|
|
|
|
|
# In this case we can no longer use the getter as an lvalue, if we |
687
|
|
|
|
|
|
|
# ever could. |
688
|
|
|
|
|
|
|
# |
689
|
|
|
|
|
|
|
$state->{getter_is_lvalue} = false; |
690
|
|
|
|
|
|
|
|
691
|
4221
|
50
|
66
|
|
|
13848
|
# Stop worrying about the final type check. The setter does that now. |
692
|
|
|
|
|
|
|
# |
693
|
0
|
|
|
0
|
|
0
|
$state->{final_type_check_needed} = false; |
694
|
0
|
|
|
|
|
0
|
} |
695
|
|
|
|
|
|
|
|
696
|
|
|
|
|
|
|
return $self; |
697
|
|
|
|
|
|
|
} |
698
|
|
|
|
|
|
|
|
699
|
0
|
|
|
|
|
0
|
my ( $self, $method_name, $handler, $env, $code, $state ) = @_; |
700
|
|
|
|
|
|
|
|
701
|
|
|
|
|
|
|
my $template; |
702
|
|
|
|
|
|
|
|
703
|
|
|
|
|
|
|
# If the getter is an lvalue, the handler has a special template |
704
|
0
|
|
|
|
|
0
|
# for lvalues, we haven't been told to set strictly, and we have taken |
705
|
|
|
|
|
|
|
# care of any type checks, then use the special lvalue template. |
706
|
|
|
|
|
|
|
# |
707
|
|
|
|
|
|
|
if ( $state->{getter_is_lvalue} |
708
|
0
|
|
|
|
|
0
|
and $handler->lvalue_template |
709
|
|
|
|
|
|
|
and !$self->set_strictly |
710
|
|
|
|
|
|
|
and !$state->{final_type_check_needed} ) { |
711
|
4221
|
|
|
|
|
10079
|
$template = $handler->lvalue_template; |
712
|
|
|
|
|
|
|
} |
713
|
|
|
|
|
|
|
else { |
714
|
|
|
|
|
|
|
$template = $handler->template; |
715
|
4221
|
|
|
4221
|
|
8347
|
} |
716
|
|
|
|
|
|
|
|
717
|
4221
|
|
|
|
|
6767
|
# Perform substitutions of special codes in the template string. |
718
|
|
|
|
|
|
|
# |
719
|
|
|
|
|
|
|
$template =~ s/\$SLOT/$self->generate_slot()/eg; |
720
|
|
|
|
|
|
|
$template =~ s/\$GET/$state->{getter}/g; |
721
|
|
|
|
|
|
|
$template =~ s/\$ATTRNAME/$self->attribute_name()/eg; |
722
|
|
|
|
|
|
|
$template =~ s/\$ARG\[([0-9]+)\]/$self->generate_arg($1)/eg; |
723
|
4221
|
100
|
100
|
|
|
25186
|
$template =~ s/\$ARG/$self->generate_arg(1)/eg; |
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
724
|
|
|
|
|
|
|
$template =~ s/\#ARG/$self->generate_argc()/eg; |
725
|
|
|
|
|
|
|
$template =~ s/\@ARG/$self->generate_args()/eg; |
726
|
|
|
|
|
|
|
$template =~ s/⸨(.+?)⸩/$self->generate_error($1)/eg; |
727
|
461
|
|
|
|
|
981
|
$template =~ s/«(.+?)»/$self->generate_set($1)/eg; |
728
|
|
|
|
|
|
|
$template =~ s/\$DEFAULT/$self->generate_default($handler)/eg; |
729
|
|
|
|
|
|
|
$template =~ s/\$SELF/$self->generate_self()/eg; |
730
|
3760
|
|
|
|
|
8890
|
|
731
|
|
|
|
|
|
|
# Apply wrapper (if any). This wrapper is given |
732
|
|
|
|
|
|
|
# by _handle_getter_code (sometimes). |
733
|
|
|
|
|
|
|
# |
734
|
|
|
|
|
|
|
$template = sprintf( $state->{template_wrapper}, $template ) |
735
|
4221
|
|
|
|
|
9599
|
if $state->{template_wrapper}; |
|
2
|
|
|
|
|
6
|
|
736
|
4221
|
|
|
|
|
24346
|
|
737
|
4221
|
|
|
|
|
10198
|
# If validation needs to be added late... |
|
3
|
|
|
|
|
9
|
|
738
|
4221
|
|
|
|
|
9535
|
# |
|
2586
|
|
|
|
|
6214
|
|
739
|
4221
|
|
|
|
|
9905
|
$template =~ s/\"?____VALIDATION_HERE____\"?/$state->{add_later}/ |
|
2051
|
|
|
|
|
5575
|
|
740
|
4221
|
|
|
|
|
9066
|
if defined $state->{add_later}; |
|
865
|
|
|
|
|
2180
|
|
741
|
4221
|
|
|
|
|
8135
|
|
|
585
|
|
|
|
|
1681
|
|
742
|
4221
|
|
|
|
|
7370
|
push @$code, $template; |
|
85
|
|
|
|
|
263
|
|
743
|
4221
|
|
|
|
|
14199
|
|
|
1982
|
|
|
|
|
5358
|
|
744
|
4221
|
|
|
|
|
8788
|
return $self; |
|
55
|
|
|
|
|
229
|
|
745
|
4221
|
|
|
|
|
7078
|
} |
|
47
|
|
|
|
|
126
|
|
746
|
|
|
|
|
|
|
|
747
|
|
|
|
|
|
|
my ( $self, $method_name, $handler, $env, $code, $state ) = @_; |
748
|
|
|
|
|
|
|
|
749
|
|
|
|
|
|
|
# Will just insert a string like ';$_[0]' at the end |
750
|
|
|
|
|
|
|
# |
751
|
4221
|
100
|
|
|
|
11047
|
push @$code, ';' . $self->generate_self, |
752
|
|
|
|
|
|
|
if $handler->is_chainable; |
753
|
|
|
|
|
|
|
|
754
|
|
|
|
|
|
|
return $self; |
755
|
|
|
|
|
|
|
} |
756
|
4221
|
100
|
|
|
|
9792
|
|
757
|
|
|
|
|
|
|
1; |
758
|
4221
|
|
|
|
|
9571
|
|
759
|
|
|
|
|
|
|
|
760
|
4221
|
|
|
|
|
15237
|
=pod |
761
|
|
|
|
|
|
|
|
762
|
|
|
|
|
|
|
=encoding utf-8 |
763
|
|
|
|
|
|
|
|
764
|
4221
|
|
|
4221
|
|
8836
|
=head1 NAME |
765
|
|
|
|
|
|
|
|
766
|
|
|
|
|
|
|
Sub::HandlesVia::CodeGenerator - looks at a Handler and generates a string of Perl code for it |
767
|
|
|
|
|
|
|
|
768
|
4221
|
100
|
|
|
|
12061
|
=head1 DESCRIPTION |
769
|
|
|
|
|
|
|
|
770
|
|
|
|
|
|
|
B<< This module is part of Sub::HandlesVia's internal API. >> |
771
|
4221
|
|
|
|
|
7318
|
It is mostly of interest to people extending Sub::HandlesVia. |
772
|
|
|
|
|
|
|
|
773
|
|
|
|
|
|
|
Sub::HandlesVia toolkits create a code generator for each attribute they're |
774
|
|
|
|
|
|
|
dealing with, and use the code generator to generate Perl code for one or |
775
|
|
|
|
|
|
|
more delegated methods. |
776
|
|
|
|
|
|
|
|
777
|
|
|
|
|
|
|
=head1 CONSTRUCTORS |
778
|
|
|
|
|
|
|
|
779
|
|
|
|
|
|
|
=head2 C<< new( %attributes ) >> |
780
|
|
|
|
|
|
|
|
781
|
|
|
|
|
|
|
Standard Moose-like constructor. |
782
|
|
|
|
|
|
|
|
783
|
|
|
|
|
|
|
=head1 ATTRIBUTES |
784
|
|
|
|
|
|
|
|
785
|
|
|
|
|
|
|
=head2 C<toolkit> B<Object> |
786
|
|
|
|
|
|
|
|
787
|
|
|
|
|
|
|
The toolkit which made this code generator. |
788
|
|
|
|
|
|
|
|
789
|
|
|
|
|
|
|
=head2 C<target> B<< ClassName|RoleName >> |
790
|
|
|
|
|
|
|
|
791
|
|
|
|
|
|
|
The target package for generated methods. |
792
|
|
|
|
|
|
|
|
793
|
|
|
|
|
|
|
=head2 C<sandboxing_package> B<< ClassName|RoleName|Undef >> |
794
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
Package name to use as a sandbox; the default is usually fine. |
796
|
|
|
|
|
|
|
|
797
|
|
|
|
|
|
|
=head2 C<attribute> B<< Str|ArrayRef >> |
798
|
|
|
|
|
|
|
|
799
|
|
|
|
|
|
|
The attribute delegated to. |
800
|
|
|
|
|
|
|
|
801
|
|
|
|
|
|
|
=head2 C<attribute_spec> B<< HashRef >> |
802
|
|
|
|
|
|
|
|
803
|
|
|
|
|
|
|
Informational only. |
804
|
|
|
|
|
|
|
|
805
|
|
|
|
|
|
|
=head2 C<is_method> B<< Bool >> |
806
|
|
|
|
|
|
|
|
807
|
|
|
|
|
|
|
Indicates whether the generated code should be methods rather than functions. |
808
|
|
|
|
|
|
|
This defaults to true, and false isn't really tested or well-defined. |
809
|
|
|
|
|
|
|
|
810
|
|
|
|
|
|
|
=head2 C<env> B<< HashRef >> |
811
|
|
|
|
|
|
|
|
812
|
|
|
|
|
|
|
Variables which need to be closed over when compiling coderefs. |
813
|
|
|
|
|
|
|
|
814
|
|
|
|
|
|
|
=head2 C<isa> B<< Maybe[TypeTiny] >> |
815
|
|
|
|
|
|
|
|
816
|
|
|
|
|
|
|
The type constraint for the attribute. |
817
|
|
|
|
|
|
|
|
818
|
|
|
|
|
|
|
=head2 C<coerce> B<< Bool >> |
819
|
|
|
|
|
|
|
|
820
|
|
|
|
|
|
|
Should the attribute coerce? |
821
|
|
|
|
|
|
|
|
822
|
|
|
|
|
|
|
=head2 C<method_installer> B<CodeRef> |
823
|
|
|
|
|
|
|
|
824
|
|
|
|
|
|
|
A coderef which can be called with C<< $method_name >> and C<< $coderef >>, |
825
|
|
|
|
|
|
|
will install the method. Note that it isn't passed the package to install |
826
|
|
|
|
|
|
|
into (which can be found in C<target>), so that would need to be closed |
827
|
|
|
|
|
|
|
over. |
828
|
|
|
|
|
|
|
|
829
|
|
|
|
|
|
|
=head2 C<generator_for_self> B<< CodeRef >> |
830
|
|
|
|
|
|
|
|
831
|
|
|
|
|
|
|
A coderef which if called, generates a string like C<< '$_[0]' >>. |
832
|
|
|
|
|
|
|
|
833
|
|
|
|
|
|
|
Has a sensible default. |
834
|
|
|
|
|
|
|
|
835
|
|
|
|
|
|
|
All the C<generator_for_XXX> methods are called as methods, so have |
836
|
|
|
|
|
|
|
the code generator object as an invocant. |
837
|
|
|
|
|
|
|
|
838
|
|
|
|
|
|
|
=head2 C<generator_for_slot> B<< CodeRef >> |
839
|
|
|
|
|
|
|
|
840
|
|
|
|
|
|
|
A coderef which if called, generates a string like C<< '$_[0]{attrname}' >>. |
841
|
|
|
|
|
|
|
|
842
|
|
|
|
|
|
|
=head2 C<generator_for_get> B<< CodeRef >> |
843
|
|
|
|
|
|
|
|
844
|
|
|
|
|
|
|
A coderef which if called, generates a string like C<< '$_[0]->attrname' >>. |
845
|
|
|
|
|
|
|
|
846
|
|
|
|
|
|
|
=head2 C<generator_for_set> B<< CodeRef >> |
847
|
|
|
|
|
|
|
|
848
|
|
|
|
|
|
|
A coderef which if called with a parameter, generates a string like |
849
|
|
|
|
|
|
|
C<< "\$_[0]->_set_attrname( $parameter )" >>. |
850
|
|
|
|
|
|
|
|
851
|
|
|
|
|
|
|
=head2 C<generator_for_simple_default> B<< CodeRef >> |
852
|
|
|
|
|
|
|
|
853
|
|
|
|
|
|
|
A coderef which if called with a parameter, generates a string like |
854
|
|
|
|
|
|
|
C<< 'undef' >> or C<< 'q[]' >> or C<< '{}' >>. |
855
|
|
|
|
|
|
|
|
856
|
|
|
|
|
|
|
The parameter is a handler object, which offers a C<default_for_reset> |
857
|
|
|
|
|
|
|
attribute which might be able to provide a useful fallback. |
858
|
|
|
|
|
|
|
|
859
|
|
|
|
|
|
|
=head2 C<generator_for_args> B<< CodeRef >> |
860
|
|
|
|
|
|
|
|
861
|
|
|
|
|
|
|
A coderef which if called, generates a string like C<< '@_[1..$#_]' >>. |
862
|
|
|
|
|
|
|
|
863
|
|
|
|
|
|
|
Has a sensible default. |
864
|
|
|
|
|
|
|
|
865
|
|
|
|
|
|
|
=head2 C<generator_for_argc> B<< CodeRef >> |
866
|
|
|
|
|
|
|
|
867
|
|
|
|
|
|
|
A coderef which if called, generates a string like C<< '$#_' >>. |
868
|
|
|
|
|
|
|
|
869
|
|
|
|
|
|
|
Has a sensible default. |
870
|
|
|
|
|
|
|
|
871
|
|
|
|
|
|
|
=head2 C<generator_for_argc> B<< CodeRef >> |
872
|
|
|
|
|
|
|
|
873
|
|
|
|
|
|
|
A coderef which if called with a parameter, generates a string like |
874
|
|
|
|
|
|
|
C<< "\$_[$parameter + 1]" >>. |
875
|
|
|
|
|
|
|
|
876
|
|
|
|
|
|
|
Has a sensible default. |
877
|
|
|
|
|
|
|
|
878
|
|
|
|
|
|
|
=head2 C<generator_for_currying> B<< CodeRef >> |
879
|
|
|
|
|
|
|
|
880
|
|
|
|
|
|
|
A coderef which if called with a parameter, generates a string like |
881
|
|
|
|
|
|
|
C<< "splice(\@_,1,0,$parameter);" >>. |
882
|
|
|
|
|
|
|
|
883
|
|
|
|
|
|
|
Has a sensible default. |
884
|
|
|
|
|
|
|
|
885
|
|
|
|
|
|
|
=head2 C<generator_for_usage_string> B<< CodeRef >> |
886
|
|
|
|
|
|
|
|
887
|
|
|
|
|
|
|
The default is this coderef: |
888
|
|
|
|
|
|
|
|
889
|
|
|
|
|
|
|
sub { |
890
|
|
|
|
|
|
|
@_==3 or die; |
891
|
|
|
|
|
|
|
shift; |
892
|
|
|
|
|
|
|
my $method_name = shift; |
893
|
|
|
|
|
|
|
my $guts = shift; |
894
|
|
|
|
|
|
|
return "\$instance->$method_name($guts)"; |
895
|
|
|
|
|
|
|
} |
896
|
|
|
|
|
|
|
|
897
|
|
|
|
|
|
|
=head2 C<generator_for_type_assertion> B<< CodeRef >> |
898
|
|
|
|
|
|
|
|
899
|
|
|
|
|
|
|
Called as a method and passed a hashref compilation environment, a type |
900
|
|
|
|
|
|
|
constraint, and a variable name. Generates code to assert that the variable |
901
|
|
|
|
|
|
|
value meets the type constraint, with coercion if appropriate. |
902
|
|
|
|
|
|
|
|
903
|
|
|
|
|
|
|
=head2 C<generator_for_error> B<< CodeRef >> |
904
|
|
|
|
|
|
|
|
905
|
|
|
|
|
|
|
Called as a method and passed a Perl string which is an expression evaluating |
906
|
|
|
|
|
|
|
to an error message. Generates code to throw the error. |
907
|
|
|
|
|
|
|
|
908
|
|
|
|
|
|
|
=head2 C<generator_for_prelude> B<< CodeRef >> |
909
|
|
|
|
|
|
|
|
910
|
|
|
|
|
|
|
By default is a coderef returning the empty string. Can be used to generate |
911
|
|
|
|
|
|
|
some additional statements which will be inserted near the top of the |
912
|
|
|
|
|
|
|
method being generated. (Typically after parameter checks but before |
913
|
|
|
|
|
|
|
doing anything serious.) This can be used to unlock a read-only attribute, |
914
|
|
|
|
|
|
|
for example. |
915
|
|
|
|
|
|
|
|
916
|
|
|
|
|
|
|
=head2 C<get_is_lvalue> B<Bool> |
917
|
|
|
|
|
|
|
|
918
|
|
|
|
|
|
|
Indicates wheter the code generated by C<generator_for_get> |
919
|
|
|
|
|
|
|
will be suitable for used as an lvalue. |
920
|
|
|
|
|
|
|
|
921
|
|
|
|
|
|
|
=head2 C<set_checks_isa> B<Bool> |
922
|
|
|
|
|
|
|
|
923
|
|
|
|
|
|
|
Indicates wheter the code generated by C<generator_for_set> |
924
|
|
|
|
|
|
|
will do type checks. |
925
|
|
|
|
|
|
|
|
926
|
|
|
|
|
|
|
=head2 C<set_strictly> B<Bool> |
927
|
|
|
|
|
|
|
|
928
|
|
|
|
|
|
|
Indicates wheter we want to ensure that the setter is always called, |
929
|
|
|
|
|
|
|
and we should not try to bypass it, even if we have an lvalue getter. |
930
|
|
|
|
|
|
|
|
931
|
|
|
|
|
|
|
=head1 METHODS |
932
|
|
|
|
|
|
|
|
933
|
|
|
|
|
|
|
For each C<generator_for_XXX> attribute, there's a corresponding |
934
|
|
|
|
|
|
|
C<generate_XXX> method to actually call the coderef, possibly including |
935
|
|
|
|
|
|
|
additional processing. |
936
|
|
|
|
|
|
|
|
937
|
|
|
|
|
|
|
=head2 C<< generate_and_install_method( $method_name, $handler ) >> |
938
|
|
|
|
|
|
|
|
939
|
|
|
|
|
|
|
Given a handler and a method name, will generate a coderef for the handler |
940
|
|
|
|
|
|
|
and install it into the target package. |
941
|
|
|
|
|
|
|
|
942
|
|
|
|
|
|
|
=head2 C<< generate_coderef_for_handler( $method_name, $handler ) >> |
943
|
|
|
|
|
|
|
|
944
|
|
|
|
|
|
|
As above, but just returns the coderef rather than installs it. |
945
|
|
|
|
|
|
|
|
946
|
|
|
|
|
|
|
=head2 C<< install_method( $method_name, $coderef ) >> |
947
|
|
|
|
|
|
|
|
948
|
|
|
|
|
|
|
Installs a coderef into the target package with the given name. |
949
|
|
|
|
|
|
|
|
950
|
|
|
|
|
|
|
=head1 BUGS |
951
|
|
|
|
|
|
|
|
952
|
|
|
|
|
|
|
Please report any bugs to |
953
|
|
|
|
|
|
|
L<https://github.com/tobyink/p5-sub-handlesvia/issues>. |
954
|
|
|
|
|
|
|
|
955
|
|
|
|
|
|
|
=head1 SEE ALSO |
956
|
|
|
|
|
|
|
|
957
|
|
|
|
|
|
|
L<Sub::HandlesVia>. |
958
|
|
|
|
|
|
|
|
959
|
|
|
|
|
|
|
=head1 AUTHOR |
960
|
|
|
|
|
|
|
|
961
|
|
|
|
|
|
|
Toby Inkster E<lt>tobyink@cpan.orgE<gt>. |
962
|
|
|
|
|
|
|
|
963
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENCE |
964
|
|
|
|
|
|
|
|
965
|
|
|
|
|
|
|
This software is copyright (c) 2020, 2022 by Toby Inkster. |
966
|
|
|
|
|
|
|
|
967
|
|
|
|
|
|
|
This is free software; you can redistribute it and/or modify it under |
968
|
|
|
|
|
|
|
the same terms as the Perl 5 programming language system itself. |
969
|
|
|
|
|
|
|
|
970
|
|
|
|
|
|
|
=head1 DISCLAIMER OF WARRANTIES |
971
|
|
|
|
|
|
|
|
972
|
|
|
|
|
|
|
THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED |
973
|
|
|
|
|
|
|
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
974
|
|
|
|
|
|
|
MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. |