← Index
NYTProf Performance Profile   « line view »
For ../prof.pl
  Run on Wed Dec 14 15:33:55 2022
Reported on Wed Dec 14 15:40:04 2022

Filename/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Types/Standard/Dict.pm
StatementsExecuted 851 statements in 4.52ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
24111.46ms43.6msTypes::Standard::Dict::::__ANON__[:161]Types::Standard::Dict::__ANON__[:161]
411455µs13.3msTypes::Standard::Dict::::__constraint_generatorTypes::Standard::Dict::__constraint_generator
411422µs9.67msTypes::Standard::Dict::::__inline_generatorTypes::Standard::Dict::__inline_generator
722171µs71µsTypes::Standard::Dict::::__ANON__[:40]Types::Standard::Dict::__ANON__[:40]
11162µs531µsTypes::Standard::Dict::::__coercion_generatorTypes::Standard::Dict::__coercion_generator
82155µs55µsTypes::Standard::Dict::::pair_iteratorTypes::Standard::Dict::pair_iterator
11131µs31µsTypes::Standard::Dict::::BEGIN@5Types::Standard::Dict::BEGIN@5
11113µs29µsTypes::Standard::Dict::::BEGIN@32Types::Standard::Dict::BEGIN@32
1119µs9µsTypes::Standard::Dict::::BEGIN@16Types::Standard::Dict::BEGIN@16
1117µs11µsTypes::Standard::Dict::::BEGIN@6Types::Standard::Dict::BEGIN@6
1116µs40µsTypes::Standard::Dict::::BEGIN@7Types::Standard::Dict::BEGIN@7
1112µs2µsTypes::Standard::Dict::::BEGIN@17Types::Standard::Dict::BEGIN@17
1112µs2µsTypes::Standard::Dict::::BEGIN@9Types::Standard::Dict::BEGIN@9
0000s0sTypes::Standard::Dict::::__ANON__[:339]Types::Standard::Dict::__ANON__[:339]
0000s0sTypes::Standard::Dict::::__ANON__[:386]Types::Standard::Dict::__ANON__[:386]
0000s0sTypes::Standard::Dict::::__ANON__[:399]Types::Standard::Dict::__ANON__[:399]
0000s0sTypes::Standard::Dict::::__ANON__[:415]Types::Standard::Dict::__ANON__[:415]
0000s0sTypes::Standard::Dict::::__ANON__[:450]Types::Standard::Dict::__ANON__[:450]
0000s0sTypes::Standard::Dict::::__ANON__[:82]Types::Standard::Dict::__ANON__[:82]
0000s0sTypes::Standard::Dict::::__deep_explanationTypes::Standard::Dict::__deep_explanation
0000s0sTypes::Standard::Dict::::__dict_is_slurpyTypes::Standard::Dict::__dict_is_slurpy
0000s0sTypes::Standard::Dict::::__hashref_allows_keyTypes::Standard::Dict::__hashref_allows_key
0000s0sTypes::Standard::Dict::::__hashref_allows_valueTypes::Standard::Dict::__hashref_allows_value
0000s0sTypes::Standard::Dict::::_croakTypes::Standard::Dict::_croak
0000s0sTypes::Standard::Dict::::my_dict_is_slurpyTypes::Standard::Dict::my_dict_is_slurpy
0000s0sTypes::Standard::Dict::::my_hashref_allows_keyTypes::Standard::Dict::my_hashref_allows_key
0000s0sTypes::Standard::Dict::::my_hashref_allows_valueTypes::Standard::Dict::my_hashref_allows_value
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1# INTERNAL MODULE: guts for Dict type from Types::Standard.
2
3package Types::Standard::Dict;
4
5249µs131µs
# spent 31µs within Types::Standard::Dict::BEGIN@5 which was called: # once (31µs+0s) by Types::Standard::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Types/Standard.pm:190] at line 5
use 5.008001;
# spent 31µs making 1 call to Types::Standard::Dict::BEGIN@5
6231µs215µs
# spent 11µs (7+4) within Types::Standard::Dict::BEGIN@6 which was called: # once (7µs+4µs) by Types::Standard::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Types/Standard.pm:190] at line 6
use strict;
# spent 11µs making 1 call to Types::Standard::Dict::BEGIN@6 # spent 4µs making 1 call to strict::import
7237µs274µs
# spent 40µs (6+34) within Types::Standard::Dict::BEGIN@7 which was called: # once (6µs+34µs) by Types::Standard::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Types/Standard.pm:190] at line 7
use warnings;
# spent 40µs making 1 call to Types::Standard::Dict::BEGIN@7 # spent 34µs making 1 call to warnings::import
8
9
# spent 2µs within Types::Standard::Dict::BEGIN@9 which was called: # once (2µs+0s) by Types::Standard::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Types/Standard.pm:190] at line 12
BEGIN {
1010s $Types::Standard::Dict::AUTHORITY = 'cpan:TOBYINK';
1117µs $Types::Standard::Dict::VERSION = '2.000001';
12139µs12µs}
# spent 2µs making 1 call to Types::Standard::Dict::BEGIN@9
13
1411µs$Types::Standard::Dict::VERSION =~ tr/_//d;
15
16215µs19µs
# spent 9µs within Types::Standard::Dict::BEGIN@16 which was called: # once (9µs+0s) by Types::Standard::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Types/Standard.pm:190] at line 16
use Types::Standard ();
# spent 9µs making 1 call to Types::Standard::Dict::BEGIN@16
17280µs12µs
# spent 2µs within Types::Standard::Dict::BEGIN@17 which was called: # once (2µs+0s) by Types::Standard::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Types/Standard.pm:190] at line 17
use Types::TypeTiny ();
# spent 2µs making 1 call to Types::Standard::Dict::BEGIN@17
18
19sub _croak ($;@) {
20 require Carp;
21 goto \&Carp::confess;
22 require Error::TypeTiny;
23 goto \&Error::TypeTiny::croak;
24}
25
2613µs19µsmy $_Slurpy = Types::Standard::Slurpy;
# spent 9µs making 1 call to Types::Standard::Slurpy
2711µs14µsmy $_optional = Types::Standard::Optional;
# spent 4µs making 1 call to Types::Standard::Optional
2811µs13µsmy $_hash = Types::Standard::HashRef;
# spent 3µs making 1 call to Types::Standard::HashRef
2911µs12µsmy $_map = Types::Standard::Map;
# spent 2µs making 1 call to Types::Standard::Map
3011µs12µsmy $_any = Types::Standard::Any;
# spent 2µs making 1 call to Types::Standard::Any
31
3222.15ms245µs
# spent 29µs (13+16) within Types::Standard::Dict::BEGIN@32 which was called: # once (13µs+16µs) by Types::Standard::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Types/Standard.pm:190] at line 32
no warnings;
# spent 29µs making 1 call to Types::Standard::Dict::BEGIN@32 # spent 16µs making 1 call to warnings::unimport
33
34
# spent 55µs within Types::Standard::Dict::pair_iterator which was called 8 times, avg 7µs/call: # 4 times (29µs+0s) by Types::Standard::Dict::__inline_generator at line 112, avg 7µs/call # 4 times (26µs+0s) by Types::Standard::Dict::__constraint_generator at line 50, avg 6µs/call
sub pair_iterator {
3588µs _croak( "Expected even-sized list" ) if @_ % 2;
36817µs my @array = @_;
37
# spent 71µs within Types::Standard::Dict::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Types/Standard/Dict.pm:40] which was called 72 times, avg 986ns/call: # 36 times (40µs+0s) by Types::Standard::Dict::__constraint_generator at line 55, avg 1µs/call # 36 times (31µs+0s) by Types::Standard::Dict::__inline_generator at line 116, avg 861ns/call
sub {
387219µs return unless @array;
3964150µs splice( @array, 0, 2 );
40833µs };
41}
42
43
# spent 13.3ms (455µs+12.9) within Types::Standard::Dict::__constraint_generator which was called 4 times, avg 3.33ms/call: # 4 times (455µs+12.9ms) by Type::Tiny::parameterize at line 1044 of Type/Tiny.pm, avg 3.33ms/call
sub __constraint_generator {
44430µs111.10ms my $slurpy =
# spent 713µs making 4 calls to Type::Tiny::is_strictly_a_type_of, avg 178µs/call # spent 328µs making 3 calls to Type::Tiny::AUTOLOAD, avg 109µs/call # spent 61µs making 4 calls to Types::TypeTiny::is_TypeTiny, avg 15µs/call
45 @_
46 && Types::TypeTiny::is_TypeTiny( $_[-1] )
47 && $_[-1]->is_strictly_a_type_of( $_Slurpy )
48 ? pop->my_unslurpy
49 : undef;
50410µs426µs my $iterator = pair_iterator @_;
# spent 26µs making 4 calls to Types::Standard::Dict::pair_iterator, avg 6µs/call
5142µs my %constraints;
52 my %is_optional;
53 my @keys;
54
55460µs3640µs while ( my ( $k, $v ) = $iterator->() ) {
# spent 40µs making 36 calls to Types::Standard::Dict::__ANON__[Types/Standard/Dict.pm:40], avg 1µs/call
563231µs $constraints{$k} = $v;
573232µs32501µs Types::TypeTiny::is_TypeTiny( $v )
# spent 501µs making 32 calls to Types::TypeTiny::is_TypeTiny, avg 16µs/call
58 or _croak(
59 "Parameter for Dict[...] with key '$k' expected to be a type constraint; got $v"
60 );
613228µs32407µs Types::TypeTiny::is_StringLike( $k )
# spent 407µs making 32 calls to Types::TypeTiny::is_StringLike, avg 13µs/call
62 or _croak( "Key for Dict[...] expected to be string; got $k" );
633217µs push @keys, $k;
643260µs327.64ms $is_optional{$k} = !!$constraints{$k}->is_strictly_a_type_of( $_optional );
# spent 7.64ms making 32 calls to Type::Tiny::is_strictly_a_type_of, avg 239µs/call
65 } #/ while ( my ( $k, $v ) = $iterator...)
66
67 return sub {
68 my $value = $_[0];
69 if ( $slurpy ) {
70 my %tmp = map +( exists( $constraints{$_} ) ? () : ( $_ => $value->{$_} ) ),
71 keys %$value;
72 return unless $slurpy->check( \%tmp );
73 }
74 else {
75 exists( $constraints{$_} ) || return for sort keys %$value;
76 }
77 for my $k ( @keys ) {
78 exists( $value->{$k} ) or ( $is_optional{$k} ? next : return );
79 $constraints{$k}->check( $value->{$k} ) or return;
80 }
81 return !!1;
82437µs };
83} #/ sub __constraint_generator
84
85
# spent 9.67ms (422µs+9.24) within Types::Standard::Dict::__inline_generator which was called 4 times, avg 2.42ms/call: # 4 times (422µs+9.24ms) by Type::Tiny::parameterize at line 1057 of Type/Tiny.pm, avg 2.42ms/call
sub __inline_generator {
86
87 # We can only inline a parameterized Dict if all the
88 # constraints inside can be inlined.
89
90426µs111.08ms my $slurpy =
# spent 880µs making 4 calls to Type::Tiny::is_strictly_a_type_of, avg 220µs/call # spent 132µs making 3 calls to Type::Tiny::AUTOLOAD, avg 44µs/call # spent 64µs making 4 calls to Types::TypeTiny::is_TypeTiny, avg 16µs/call
91 @_
92 && Types::TypeTiny::is_TypeTiny( $_[-1] )
93 && $_[-1]->is_strictly_a_type_of( $_Slurpy )
94 ? pop->my_unslurpy
95 : undef;
9648µs659µs return if $slurpy && !$slurpy->can_be_inlined;
# spent 57µs making 3 calls to Type::Tiny::can_be_inlined, avg 19µs/call # spent 2µs making 3 calls to Type::Tiny::__ANON__[Type/Tiny.pm:101], avg 667ns/call
97
98 # Is slurpy a very loose type constraint?
99 # i.e. Any, Item, Defined, Ref, or HashRef
100410µs67.46ms my $slurpy_is_any = $slurpy && $_hash->is_a_type_of( $slurpy );
# spent 7.46ms making 3 calls to Type::Tiny::is_a_type_of, avg 2.49ms/call # spent 1µs making 3 calls to Type::Tiny::__ANON__[Type/Tiny.pm:101], avg 333ns/call
101
102 # Is slurpy a parameterized Map, or expressable as a parameterized Map?
103437µs21217µs my $slurpy_is_map =
# spent 193µs making 6 calls to Type::Tiny::strictly_equals, avg 32µs/call # spent 15µs making 3 calls to Type::Tiny::is_parameterized, avg 5µs/call # spent 5µs making 3 calls to Type::Tiny::__ANON__[Type/Tiny.pm:101], avg 2µs/call # spent 2µs making 3 calls to Type::Tiny::parameters, avg 667ns/call # spent 2µs making 6 calls to Type::Tiny::parent, avg 333ns/call
104 $slurpy
105 && $slurpy->is_parameterized
106 && (
107 ( $slurpy->parent->strictly_equals( $_map ) && $slurpy->parameters )
108 || ( $slurpy->parent->strictly_equals( $_hash )
109 && [ $_any, $slurpy->parameters->[0] ] )
110 );
111
11247µs429µs my $iterator = pair_iterator @_;
# spent 29µs making 4 calls to Types::Standard::Dict::pair_iterator, avg 7µs/call
11342µs my %constraints;
114 my @keys;
115
116446µs3631µs while ( my ( $k, $c ) = $iterator->() ) {
# spent 31µs making 36 calls to Types::Standard::Dict::__ANON__[Types/Standard/Dict.pm:40], avg 861ns/call
1173228µs32369µs return unless $c->can_be_inlined;
# spent 366µs making 30 calls to Type::Tiny::can_be_inlined, avg 12µs/call # spent 3µs making 2 calls to Type::Tiny::Enum::can_be_inlined, avg 2µs/call
1183215µs $constraints{$k} = $c;
1193217µs push @keys, $k;
120 }
121
122425µs my $regexp = join "|", map quotemeta, @keys;
123
# spent 43.6ms (1.46+42.1) within Types::Standard::Dict::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Types/Standard/Dict.pm:161] which was called 24 times, avg 1.82ms/call: # 24 times (1.46ms+42.1ms) by Type::Tiny::inline_check at line 895 of Type/Tiny.pm, avg 1.82ms/call
return sub {
1242414µs require B;
125243µs my $h = $_[1];
126 join " and ",
127 Types::Standard::HashRef->inline_check( $h ),
128 (
129 $slurpy_is_any
130 ? ()
131 : $slurpy_is_map ? do {
132 '(not grep {' . "my \$v = ($h)->{\$_};" . sprintf(
133 'not((/\\A(?:%s)\\z/) or ((%s) and (%s)))',
134 $regexp,
135 $slurpy_is_map->[0]->inline_check( '$_' ),
136 $slurpy_is_map->[1]->inline_check( '$v' ),
137 ) . "} keys \%{$h})";
138 }
139 : $slurpy ? do {
140 'do {'
141 . "my \$slurpy_tmp = +{ map /\\A(?:$regexp)\\z/ ? () : (\$_ => ($h)->{\$_}), keys \%{$h} };"
142 . $slurpy->inline_check( '$slurpy_tmp' ) . '}';
143 }
144 : "not(grep !/\\A(?:$regexp)\\z/, keys \%{$h})"
145 ),
146 (
147 map {
148158725µs208191µs my $k = B::perlstring( $_ );
# spent 153µs making 134 calls to B::perlstring, avg 1µs/call # spent 44µs making 24 calls to Types::Standard::HashRef, avg 2µs/call, recursion: max depth 1, sum of overlapping time 6µs # spent 3.51ms making 50 calls to Type::Tiny::inline_check, avg 70µs/call, recursion: max depth 3, sum of overlapping time 3.51ms
149 $constraints{$_}->is_strictly_a_type_of( $_optional )
150 ? sprintf(
151 '(!exists %s->{%s} or %s)', $h, $k,
152 $constraints{$_}->inline_check( "$h\->{$k}" )
153 )
154 : (
155 "exists($h\->{$k})",
156134503µs26831.7ms $constraints{$_}->inline_check( "$h\->{$k}" )
# spent 31.4ms making 134 calls to Type::Tiny::is_strictly_a_type_of, avg 234µs/call # spent 306µs making 16 calls to Type::Tiny::Enum::inline_check, avg 19µs/call # spent 6.74ms making 118 calls to Type::Tiny::inline_check, avg 57µs/call, recursion: max depth 3, sum of overlapping time 6.74ms
157 )
158 } @keys
159 ),
160 ;
161 }
162449µs} #/ sub __inline_generator
163
164sub __deep_explanation {
165 require B;
166 my ( $type, $value, $varname ) = @_;
167 my @params = @{ $type->parameters };
168
169 my $slurpy =
170 @params
171 && Types::TypeTiny::is_TypeTiny( $params[-1] )
172 && $params[-1]->is_strictly_a_type_of( $_Slurpy )
173 ? pop( @params )->my_unslurpy
174 : undef;
175 my $iterator = pair_iterator @params;
176 my %constraints;
177 my @keys;
178
179 while ( my ( $k, $c ) = $iterator->() ) {
180 push @keys, $k;
181 $constraints{$k} = $c;
182 }
183
184 for my $k ( @keys ) {
185 next
186 if $constraints{$k}->has_parent
187 && ( $constraints{$k}->parent == Types::Standard::Optional )
188 && ( !exists $value->{$k} );
189 next if $constraints{$k}->check( $value->{$k} );
190
191 return [
192 sprintf( '"%s" requires key %s to appear in hash', $type, B::perlstring( $k ) )
193 ]
194 unless exists $value->{$k};
195
196 return [
197 sprintf(
198 '"%s" constrains value at key %s of hash with "%s"',
199 $type,
200 B::perlstring( $k ),
201 $constraints{$k},
202 ),
203 @{
204 $constraints{$k}->validate_explain(
205 $value->{$k},
206 sprintf( '%s->{%s}', $varname, B::perlstring( $k ) ),
207 )
208 },
209 ];
210 } #/ for my $k ( @keys )
211
212 if ( $slurpy ) {
213 my %tmp = map { exists( $constraints{$_} ) ? () : ( $_ => $value->{$_} ) }
214 keys %$value;
215
216 my $explain = $slurpy->validate_explain( \%tmp, '$slurpy' );
217 return [
218 sprintf(
219 '"%s" requires the hashref of additional key/value pairs to conform to "%s"',
220 $type, $slurpy
221 ),
222 @$explain,
223 ] if $explain;
224 } #/ if ( $slurpy )
225 else {
226 for my $k ( sort keys %$value ) {
227 return [
228 sprintf(
229 '"%s" does not allow key %s to appear in hash', $type, B::perlstring( $k )
230 )
231 ]
232 unless exists $constraints{$k};
233 }
234 } #/ else [ if ( $slurpy ) ]
235
236 # This should never happen...
237 return; # uncoverable statement
238} #/ sub __deep_explanation
239
24010smy $label_counter = 0;
24111µsour ( $keycheck_counter, @KEYCHECK ) = -1;
242
243
# spent 531µs (62+469) within Types::Standard::Dict::__coercion_generator which was called: # once (62µs+469µs) by Type::Tiny::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Type/Tiny.pm:1073] at line 1070 of Type/Tiny.pm
sub __coercion_generator {
24417µs2391µs my $slurpy =
# spent 370µs making 1 call to Type::Tiny::is_strictly_a_type_of # spent 21µs making 1 call to Types::TypeTiny::is_TypeTiny
245 @_
246 && Types::TypeTiny::is_TypeTiny( $_[-1] )
247 && $_[-1]->is_strictly_a_type_of( $_Slurpy )
248 ? pop->my_unslurpy
249 : undef;
25013µs my ( $parent, $child, %dict ) = @_;
25113µs124µs my $C = "Type::Coercion"->new( type_constraint => $child );
# spent 24µs making 1 call to Type::Coercion::new
252
25310s my $all_inlinable = 1;
25410s my $child_coercions_exist = 0;
25513µs for my $tc ( values %dict ) {
25623µs216µs $all_inlinable = 0 if !$tc->can_be_inlined;
# spent 15µs making 1 call to Type::Tiny::can_be_inlined # spent 1µs making 1 call to Type::Tiny::Enum::can_be_inlined
25726µs20s $all_inlinable = 0 if $tc->has_coercion && !$tc->coercion->can_be_inlined;
# spent 16µs making 2 calls to Type::Tiny::has_coercion, avg 8µs/call, recursion: max depth 2, sum of overlapping time 16µs
25823µs20s $child_coercions_exist++ if $tc->has_coercion;
# spent 9µs making 2 calls to Type::Tiny::has_coercion, avg 4µs/call, recursion: max depth 2, sum of overlapping time 9µs
259 }
26010s $all_inlinable = 0 if $slurpy && !$slurpy->can_be_inlined;
26111µs $all_inlinable = 0
262 if $slurpy
263 && $slurpy->has_coercion
264 && !$slurpy->coercion->can_be_inlined;
265
26610s $child_coercions_exist++ if $slurpy && $slurpy->has_coercion;
267112µs113µs return unless $child_coercions_exist;
# spent 13µs making 1 call to Type::Coercion::AUTOLOAD
268
269 if ( $all_inlinable ) {
270 $C->add_type_coercions(
271 $parent => Types::Standard::Stringable {
272 require B;
273
274 my $keycheck = join "|", map quotemeta,
275 sort { length( $b ) <=> length( $a ) or $a cmp $b } keys %dict;
276 $keycheck = $KEYCHECK[ ++$keycheck_counter ] = qr{^($keycheck)$}ms; # regexp for legal keys
277
278 my $label = sprintf( "DICTLABEL%d", ++$label_counter );
279 my @code;
280 push @code, 'do { my ($orig, $return_orig, $tmp, %new) = ($_, 0);';
281 push @code, "$label: {";
282 if ( $slurpy ) {
283 push @code,
284 sprintf(
285 'my $slurped = +{ map +($_=~$%s::KEYCHECK[%d])?():($_=>$orig->{$_}), keys %%$orig };',
286 __PACKAGE__, $keycheck_counter
287 );
288 if ( $slurpy->has_coercion ) {
289 push @code,
290 sprintf(
291 'my $coerced = %s;',
292 $slurpy->coercion->inline_coercion( '$slurped' )
293 );
294 push @code,
295 sprintf(
296 '((%s)&&(%s))?(%%new=%%$coerced):(($return_orig = 1), last %s);',
297 $_hash->inline_check( '$coerced' ), $slurpy->inline_check( '$coerced' ),
298 $label
299 );
300 } #/ if ( $slurpy->has_coercion)
301 else {
302 push @code,
303 sprintf(
304 '(%s)?(%%new=%%$slurped):(($return_orig = 1), last %s);',
305 $slurpy->inline_check( '$slurped' ), $label
306 );
307 }
308 } #/ if ( $slurpy )
309 else {
310 push @code,
311 sprintf(
312 '($_ =~ $%s::KEYCHECK[%d])||(($return_orig = 1), last %s) for sort keys %%$orig;',
313 __PACKAGE__, $keycheck_counter, $label
314 );
315 }
316 for my $k ( keys %dict ) {
317 my $ct = $dict{$k};
318 my $ct_coerce = $ct->has_coercion;
319 my $ct_optional = $ct->is_a_type_of( $_optional );
320 my $K = B::perlstring( $k );
321
322 push @code, sprintf(
323 'if (exists $orig->{%s}) { $tmp = %s; (%s) ? ($new{%s}=$tmp) : (($return_orig=1), last %s) }',
324 $K,
325 $ct_coerce
326 ? $ct->coercion->inline_coercion( "\$orig->{$K}" )
327 : "\$orig->{$K}",
328 $ct->inline_check( '$tmp' ),
329 $K,
330 $label,
331 );
332 } #/ for my $k ( keys %dict )
333 push @code, '}';
334 push @code, '$return_orig ? $orig : \\%new';
335 push @code, '}';
336
337 #warn "CODE:: @code";
338 "@code";
339 }
340 );
341 } #/ if ( $all_inlinable )
342
343 else {
344 my %is_optional = map {
345 ;
346 $_ => !!$dict{$_}->is_strictly_a_type_of( $_optional )
347 } sort keys %dict;
348 $C->add_type_coercions(
349 $parent => sub {
350 my $value = @_ ? $_[0] : $_;
351 my %new;
352
353 if ( $slurpy ) {
354 my %slurped = map exists( $dict{$_} ) ? () : ( $_ => $value->{$_} ),
355 keys %$value;
356
357 if ( $slurpy->check( \%slurped ) ) {
358 %new = %slurped;
359 }
360 elsif ( $slurpy->has_coercion ) {
361 my $coerced = $slurpy->coerce( \%slurped );
362 $slurpy->check( $coerced ) ? ( %new = %$coerced ) : ( return $value );
363 }
364 else {
365 return $value;
366 }
367 } #/ if ( $slurpy )
368 else {
369 for my $k ( keys %$value ) {
370 return $value unless exists $dict{$k};
371 }
372 }
373
374 for my $k ( keys %dict ) {
375 next if $is_optional{$k} and not exists $value->{$k};
376
377 my $ct = $dict{$k};
378 my $x = $ct->has_coercion ? $ct->coerce( $value->{$k} ) : $value->{$k};
379
380 return $value unless $ct->check( $x );
381
382 $new{$k} = $x;
383 } #/ for my $k ( keys %dict )
384
385 return \%new;
386 },
387 );
388 } #/ else [ if ( $all_inlinable ) ]
389
390 return $C;
391} #/ sub __coercion_generator
392
393sub __dict_is_slurpy {
394 my $self = shift;
395
396 return !!0 if $self == Types::Standard::Dict();
397
398 my $dict = $self->find_parent(
399 sub { $_->has_parent && $_->parent == Types::Standard::Dict() } );
400 my $slurpy =
401 @{ $dict->parameters }
402 && Types::TypeTiny::is_TypeTiny( $dict->parameters->[-1] )
403 && $dict->parameters->[-1]->is_strictly_a_type_of( $_Slurpy )
404 ? $dict->parameters->[-1]
405 : undef;
406} #/ sub __dict_is_slurpy
407
408sub __hashref_allows_key {
409 my $self = shift;
410 my ( $key ) = @_;
411
412 return Types::Standard::is_Str( $key ) if $self == Types::Standard::Dict();
413
414 my $dict = $self->find_parent(
415 sub { $_->has_parent && $_->parent == Types::Standard::Dict() } );
416 my %params;
417 my $slurpy = $dict->my_dict_is_slurpy;
418 if ( $slurpy ) {
419 my @args = @{ $dict->parameters };
420 pop @args;
421 %params = @args;
422 $slurpy = $slurpy->my_unslurpy;
423 }
424 else {
425 %params = @{ $dict->parameters };
426 }
427
428 return !!1
429 if exists( $params{$key} );
430 return !!0
431 if !$slurpy;
432 return Types::Standard::is_Str( $key )
433 if $slurpy == Types::Standard::Any()
434 || $slurpy == Types::Standard::Item()
435 || $slurpy == Types::Standard::Defined()
436 || $slurpy == Types::Standard::Ref();
437 return $slurpy->my_hashref_allows_key( $key )
438 if $slurpy->is_a_type_of( Types::Standard::HashRef() );
439 return !!0;
440} #/ sub __hashref_allows_key
441
442sub __hashref_allows_value {
443 my $self = shift;
444 my ( $key, $value ) = @_;
445
446 return !!0 unless $self->my_hashref_allows_key( $key );
447 return !!1 if $self == Types::Standard::Dict();
448
449 my $dict = $self->find_parent(
450 sub { $_->has_parent && $_->parent == Types::Standard::Dict() } );
451 my %params;
452 my $slurpy = $dict->my_dict_is_slurpy;
453 if ( $slurpy ) {
454 my @args = @{ $dict->parameters };
455 pop @args;
456 %params = @args;
457 $slurpy = $slurpy->my_unslurpy;
458 }
459 else {
460 %params = @{ $dict->parameters };
461 }
462
463 return !!1
464 if exists( $params{$key} ) && $params{$key}->check( $value );
465 return !!0
466 if !$slurpy;
467 return !!1
468 if $slurpy == Types::Standard::Any()
469 || $slurpy == Types::Standard::Item()
470 || $slurpy == Types::Standard::Defined()
471 || $slurpy == Types::Standard::Ref();
472 return $slurpy->my_hashref_allows_value( $key, $value )
473 if $slurpy->is_a_type_of( Types::Standard::HashRef() );
474 return !!0;
475} #/ sub __hashref_allows_value
476
47715µs1;