Filename | /opt/perl-5.18.1/lib/site_perl/5.18.1/Type/Coercion.pm |
Statements | Executed 140 statements in 3.93ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 71µs | 850µs | add_type_coercions | Type::Coercion::
3 | 1 | 1 | 67µs | 950µs | new | Type::Coercion::
1 | 1 | 1 | 26µs | 26µs | frozen | Type::Coercion::
1 | 1 | 1 | 24µs | 24µs | BEGIN@3 | Type::Coercion::
18 | 5 | 2 | 22µs | 22µs | name | Type::Coercion::
6 | 2 | 2 | 22µs | 29µs | is_anon | Type::Coercion::
3 | 1 | 1 | 21µs | 28µs | qualified_name | Type::Coercion::
3 | 1 | 1 | 20µs | 54µs | __ANON__[:19] | Type::Coercion::
1 | 1 | 1 | 18µs | 74µs | BEGIN@19 | Type::Coercion::
3 | 1 | 1 | 18µs | 31µs | display_name | Type::Coercion::
6 | 2 | 1 | 12µs | 12µs | CORE:match (opcode) | Type::Coercion::
3 | 1 | 1 | 10µs | 15µs | is_parameterizable | Type::Coercion::
3 | 1 | 1 | 10µs | 13µs | _build_display_name | Type::Coercion::
1 | 1 | 1 | 9µs | 16µs | BEGIN@5 | Type::Coercion::
1 | 1 | 1 | 9µs | 47µs | BEGIN@13 | Type::Coercion::
1 | 1 | 1 | 9µs | 27µs | BEGIN@4 | Type::Coercion::
1 | 1 | 1 | 4µs | 4µs | BEGIN@26 | Type::Coercion::
3 | 1 | 1 | 4µs | 4µs | has_coercion_generator | Type::Coercion::
3 | 1 | 1 | 4µs | 4µs | type_coercion_map | Type::Coercion::
1 | 1 | 1 | 4µs | 4µs | BEGIN@7 | Type::Coercion::
1 | 1 | 1 | 4µs | 4µs | BEGIN@14 | Type::Coercion::
3 | 1 | 1 | 4µs | 4µs | has_library | Type::Coercion::
1 | 1 | 1 | 4µs | 4µs | BEGIN@12 | Type::Coercion::
1 | 1 | 1 | 2µs | 2µs | _clear_compiled_coercion | Type::Coercion::
0 | 0 | 0 | 0s | 0s | AUTOLOAD | Type::Coercion::
0 | 0 | 0 | 0s | 0s | __ANON__[:20] | Type::Coercion::
0 | 0 | 0 | 0s | 0s | __ANON__[:22] | Type::Coercion::
0 | 0 | 0 | 0s | 0s | __ANON__[:230] | Type::Coercion::
0 | 0 | 0 | 0s | 0s | __ANON__[:28] | Type::Coercion::
0 | 0 | 0 | 0s | 0s | __ANON__[:43] | Type::Coercion::
0 | 0 | 0 | 0s | 0s | __ANON__[:452] | Type::Coercion::
0 | 0 | 0 | 0s | 0s | _build_compiled_coercion | Type::Coercion::
0 | 0 | 0 | 0s | 0s | _build_moose_coercion | Type::Coercion::
0 | 0 | 0 | 0s | 0s | _codelike_type_coercion_map | Type::Coercion::
0 | 0 | 0 | 0s | 0s | _compiled_type_coercion | Type::Coercion::
0 | 0 | 0 | 0s | 0s | _croak | Type::Coercion::
0 | 0 | 0 | 0s | 0s | _overload_coderef | Type::Coercion::
0 | 0 | 0 | 0s | 0s | _source_type_union | Type::Coercion::
0 | 0 | 0 | 0s | 0s | add | Type::Coercion::
0 | 0 | 0 | 0s | 0s | assert_coerce | Type::Coercion::
0 | 0 | 0 | 0s | 0s | can | Type::Coercion::
0 | 0 | 0 | 0s | 0s | can_be_inlined | Type::Coercion::
0 | 0 | 0 | 0s | 0s | coerce | Type::Coercion::
0 | 0 | 0 | 0s | 0s | coercion_generator | Type::Coercion::
0 | 0 | 0 | 0s | 0s | compiled_coercion | Type::Coercion::
0 | 0 | 0 | 0s | 0s | freeze | Type::Coercion::
0 | 0 | 0 | 0s | 0s | has_coercion_for_type | Type::Coercion::
0 | 0 | 0 | 0s | 0s | has_coercion_for_value | Type::Coercion::
0 | 0 | 0 | 0s | 0s | has_parameters | Type::Coercion::
0 | 0 | 0 | 0s | 0s | has_type_constraint | Type::Coercion::
0 | 0 | 0 | 0s | 0s | inline_coercion | Type::Coercion::
0 | 0 | 0 | 0s | 0s | is_parameterized | Type::Coercion::
0 | 0 | 0 | 0s | 0s | isa | Type::Coercion::
0 | 0 | 0 | 0s | 0s | library | Type::Coercion::
0 | 0 | 0 | 0s | 0s | meta | Type::Coercion::
0 | 0 | 0 | 0s | 0s | moose_coercion | Type::Coercion::
0 | 0 | 0 | 0s | 0s | parameterize | Type::Coercion::
0 | 0 | 0 | 0s | 0s | parameters | Type::Coercion::
0 | 0 | 0 | 0s | 0s | type_constraint | Type::Coercion::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package Type::Coercion; | ||||
2 | |||||
3 | 2 | 61µs | 1 | 24µs | # spent 24µs within Type::Coercion::BEGIN@3 which was called:
# once (24µs+0s) by Type::Library::add_coercion at line 3 # spent 24µs making 1 call to Type::Coercion::BEGIN@3 |
4 | 2 | 30µs | 2 | 45µs | # spent 27µs (9+18) within Type::Coercion::BEGIN@4 which was called:
# once (9µs+18µs) by Type::Library::add_coercion at line 4 # spent 27µs making 1 call to Type::Coercion::BEGIN@4
# spent 18µs making 1 call to strict::import |
5 | 2 | 55µs | 2 | 22µs | # spent 16µs (9+7) within Type::Coercion::BEGIN@5 which was called:
# once (9µs+7µs) by Type::Library::add_coercion at line 5 # spent 16µs making 1 call to Type::Coercion::BEGIN@5
# spent 7µs making 1 call to warnings::import |
6 | |||||
7 | # spent 4µs within Type::Coercion::BEGIN@7 which was called:
# once (4µs+0s) by Type::Library::add_coercion at line 10 | ||||
8 | 1 | 500ns | $Type::Coercion::AUTHORITY = 'cpan:TOBYINK'; | ||
9 | 1 | 10µs | $Type::Coercion::VERSION = '0.038'; | ||
10 | 1 | 26µs | 1 | 4µs | } # spent 4µs making 1 call to Type::Coercion::BEGIN@7 |
11 | |||||
12 | 2 | 29µs | 1 | 4µs | # spent 4µs within Type::Coercion::BEGIN@12 which was called:
# once (4µs+0s) by Type::Library::add_coercion at line 12 # spent 4µs making 1 call to Type::Coercion::BEGIN@12 |
13 | 2 | 37µs | 2 | 85µs | # spent 47µs (9+38) within Type::Coercion::BEGIN@13 which was called:
# once (9µs+38µs) by Type::Library::add_coercion at line 13 # spent 47µs making 1 call to Type::Coercion::BEGIN@13
# spent 38µs making 1 call to Exporter::import |
14 | 2 | 222µs | 1 | 4µs | # spent 4µs within Type::Coercion::BEGIN@14 which was called:
# once (4µs+0s) by Type::Library::add_coercion at line 14 # spent 4µs making 1 call to Type::Coercion::BEGIN@14 |
15 | |||||
16 | sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak } | ||||
17 | |||||
18 | use overload | ||||
19 | 3 | 21µs | 6 | 34µs | # spent 74µs (18+55) within Type::Coercion::BEGIN@19 which was called:
# once (18µs+55µs) by Type::Library::add_coercion at line 24
# spent 54µs (20+34) within Type::Coercion::__ANON__[/opt/perl-5.18.1/lib/site_perl/5.18.1/Type/Coercion.pm:19] which was called 3 times, avg 18µs/call:
# 3 times (20µs+34µs) by Type::Library::_mksub at line 100 of Type/Library.pm, avg 18µs/call # spent 31µs making 3 calls to Type::Coercion::display_name, avg 10µs/call
# spent 3µs making 3 calls to Type::Coercion::CORE:match, avg 1µs/call |
20 | q(bool) => sub { 1 }, | ||||
21 | q(&{}) => "_overload_coderef", | ||||
22 | q(+) => sub { __PACKAGE__->add(@_) }, | ||||
23 | 1 | 500ns | fallback => 1, | ||
24 | 1 | 97µs | 2 | 130µs | ; # spent 74µs making 1 call to Type::Coercion::BEGIN@19
# spent 56µs making 1 call to overload::import |
25 | |||||
26 | # spent 4µs within Type::Coercion::BEGIN@26 which was called:
# once (4µs+0s) by Type::Library::add_coercion at line 30 | ||||
27 | 1 | 500ns | require Type::Tiny; | ||
28 | overload->import(q(~~) => sub { $_[0]->has_coercion_for_value($_[1]) }) | ||||
29 | 1 | 6µs | if Type::Tiny::SUPPORT_SMARTMATCH(); | ||
30 | 1 | 3.05ms | 1 | 4µs | } # spent 4µs making 1 call to Type::Coercion::BEGIN@26 |
31 | |||||
32 | sub _overload_coderef | ||||
33 | { | ||||
34 | my $self = shift; | ||||
35 | |||||
36 | if ("Sub::Quote"->can("quote_sub") && $self->can_be_inlined) | ||||
37 | { | ||||
38 | $self->{_overload_coderef} = Sub::Quote::quote_sub($self->inline_coercion('$_[0]')) | ||||
39 | if !$self->{_overload_coderef} || !$self->{_sub_quoted}++; | ||||
40 | } | ||||
41 | else | ||||
42 | { | ||||
43 | $self->{_overload_coderef} ||= sub { $self->coerce(@_) }; | ||||
44 | } | ||||
45 | |||||
46 | $self->{_overload_coderef}; | ||||
47 | } | ||||
48 | |||||
49 | sub new | ||||
50 | # spent 950µs (67+882) within Type::Coercion::new which was called 3 times, avg 317µs/call:
# 3 times (67µs+882µs) by Type::Library::add_coercion at line 271 of Type/Library.pm, avg 317µs/call | ||||
51 | 3 | 1µs | my $class = shift; | ||
52 | 3 | 10µs | my %params = (@_==1) ? %{$_[0]} : @_; | ||
53 | |||||
54 | 3 | 1µs | $params{name} = '__ANON__' unless exists($params{name}); | ||
55 | 3 | 3µs | my $C = delete($params{type_coercion_map}) || []; | ||
56 | 3 | 600ns | my $F = delete($params{frozen}); | ||
57 | |||||
58 | 3 | 3µs | my $self = bless \%params, $class; | ||
59 | 3 | 2µs | 1 | 850µs | $self->add_type_coercions(@$C) if @$C; # spent 850µs making 1 call to Type::Coercion::add_type_coercions |
60 | 3 | 13µs | 3 | 4µs | Scalar::Util::weaken($self->{type_constraint}); # break ref cycle # spent 4µs making 3 calls to Scalar::Util::weaken, avg 1µs/call |
61 | 3 | 300ns | $self->{frozen} = $F if $F; | ||
62 | |||||
63 | 3 | 6µs | 3 | 16µs | unless ($self->is_anon) # spent 16µs making 3 calls to Type::Coercion::is_anon, avg 5µs/call |
64 | { | ||||
65 | # First try a fast ASCII-only expression, but fall back to Unicode | ||||
66 | 3 | 21µs | 6 | 12µs | $self->name =~ /^_{0,2}[A-Z][A-Za-z0-9_]+$/sm # spent 9µs making 3 calls to Type::Coercion::CORE:match, avg 3µs/call
# spent 3µs making 3 calls to Type::Coercion::name, avg 1µs/call |
67 | or eval q( use 5.008; $self->name =~ /^_{0,2}\p{Lu}[\p{L}0-9_]+$/sm ) | ||||
68 | or _croak '"%s" is not a valid coercion name', $self->name; | ||||
69 | } | ||||
70 | |||||
71 | 3 | 9µs | return $self; | ||
72 | } | ||||
73 | |||||
74 | 18 | 46µs | # spent 22µs within Type::Coercion::name which was called 18 times, avg 1µs/call:
# 6 times (8µs+0s) by Type::Coercion::is_anon at line 144, avg 1µs/call
# 3 times (4µs+0s) by Type::Library::add_coercion at line 272 of Type/Library.pm, avg 1µs/call
# 3 times (4µs+0s) by Type::Coercion::qualified_name at line 138, avg 1µs/call
# 3 times (3µs+0s) by Type::Coercion::new at line 66, avg 1µs/call
# 3 times (3µs+0s) by Type::Coercion::_build_display_name at line 126, avg 1µs/call | ||
75 | 3 | 12µs | 3 | 13µs | # spent 31µs (18+13) within Type::Coercion::display_name which was called 3 times, avg 10µs/call:
# 3 times (18µs+13µs) by Type::Coercion::__ANON__[/opt/perl-5.18.1/lib/site_perl/5.18.1/Type/Coercion.pm:19] at line 19, avg 10µs/call # spent 13µs making 3 calls to Type::Coercion::_build_display_name, avg 4µs/call |
76 | sub library { $_[0]{library} } | ||||
77 | sub type_constraint { $_[0]{type_constraint} } | ||||
78 | 3 | 9µs | # spent 4µs within Type::Coercion::type_coercion_map which was called 3 times, avg 2µs/call:
# 3 times (4µs+0s) by Type::Coercion::add_type_coercions at line 218, avg 2µs/call | ||
79 | sub moose_coercion { $_[0]{moose_coercion} ||= $_[0]->_build_moose_coercion } | ||||
80 | sub compiled_coercion { $_[0]{compiled_coercion} ||= $_[0]->_build_compiled_coercion } | ||||
81 | 1 | 29µs | # spent 26µs within Type::Coercion::frozen which was called:
# once (26µs+0s) by Type::Coercion::add_type_coercions at line 206 | ||
82 | sub coercion_generator { $_[0]{coercion_generator} } | ||||
83 | sub parameters { $_[0]{parameters} } | ||||
84 | |||||
85 | 3 | 9µs | # spent 4µs within Type::Coercion::has_library which was called 3 times, avg 1µs/call:
# 3 times (4µs+0s) by Type::Coercion::qualified_name at line 133, avg 1µs/call | ||
86 | sub has_type_constraint { defined $_[0]{type_constraint} } # sic | ||||
87 | 3 | 9µs | # spent 4µs within Type::Coercion::has_coercion_generator which was called 3 times, avg 2µs/call:
# 3 times (4µs+0s) by Type::Coercion::is_parameterizable at line 401, avg 2µs/call | ||
88 | sub has_parameters { exists $_[0]{parameters} } | ||||
89 | |||||
90 | sub add | ||||
91 | { | ||||
92 | my $class = shift; | ||||
93 | my ($x, $y, $swap) = @_; | ||||
94 | |||||
95 | Types::TypeTiny::TypeTiny->check($x) and return $x->plus_fallback_coercions($y); | ||||
96 | Types::TypeTiny::TypeTiny->check($y) and return $y->plus_coercions($x); | ||||
97 | |||||
98 | _croak "Attempt to add $class to something that is not a $class" | ||||
99 | unless blessed($x) && blessed($y) && $x->isa($class) && $y->isa($class); | ||||
100 | |||||
101 | ($y, $x) = ($x, $y) if $swap; | ||||
102 | |||||
103 | my %opts; | ||||
104 | if ($x->has_type_constraint and $y->has_type_constraint and $x->type_constraint == $y->type_constraint) | ||||
105 | { | ||||
106 | $opts{type_constraint} = $x->type_constraint; | ||||
107 | } | ||||
108 | elsif ($x->has_type_constraint and $y->has_type_constraint) | ||||
109 | { | ||||
110 | # require Type::Tiny::Union; | ||||
111 | # $opts{type_constraint} = "Type::Tiny::Union"->new( | ||||
112 | # type_constraints => [ $x->type_constraint, $y->type_constraint ], | ||||
113 | # ); | ||||
114 | } | ||||
115 | $opts{display_name} ||= "$x+$y"; | ||||
116 | delete $opts{display_name} if $opts{display_name} eq '__ANON__+__ANON__'; | ||||
117 | |||||
118 | my $new = $class->new(%opts); | ||||
119 | $new->add_type_coercions( @{$x->type_coercion_map} ); | ||||
120 | $new->add_type_coercions( @{$y->type_coercion_map} ); | ||||
121 | return $new; | ||||
122 | } | ||||
123 | |||||
124 | sub _build_display_name | ||||
125 | # spent 13µs (10+3) within Type::Coercion::_build_display_name which was called 3 times, avg 4µs/call:
# 3 times (10µs+3µs) by Type::Coercion::display_name at line 75, avg 4µs/call | ||||
126 | 3 | 13µs | 3 | 3µs | shift->name; # spent 3µs making 3 calls to Type::Coercion::name, avg 1µs/call |
127 | } | ||||
128 | |||||
129 | sub qualified_name | ||||
130 | # spent 28µs (21+8) within Type::Coercion::qualified_name which was called 3 times, avg 9µs/call:
# 3 times (21µs+8µs) by Type::Library::_mksub at line 100 of Type/Library.pm, avg 9µs/call | ||||
131 | 3 | 600ns | my $self = shift; | ||
132 | |||||
133 | 3 | 4µs | 3 | 4µs | if ($self->has_library and not $self->is_anon) # spent 4µs making 3 calls to Type::Coercion::has_library, avg 1µs/call |
134 | { | ||||
135 | return sprintf("%s::%s", $self->library, $self->name); | ||||
136 | } | ||||
137 | |||||
138 | 3 | 10µs | 3 | 4µs | return $self->name; # spent 4µs making 3 calls to Type::Coercion::name, avg 1µs/call |
139 | } | ||||
140 | |||||
141 | sub is_anon | ||||
142 | # spent 29µs (22+8) within Type::Coercion::is_anon which was called 6 times, avg 5µs/call:
# 3 times (12µs+4µs) by Type::Coercion::new at line 63, avg 5µs/call
# 3 times (10µs+3µs) by Type::Library::add_coercion at line 277 of Type/Library.pm, avg 4µs/call | ||||
143 | 6 | 1µs | my $self = shift; | ||
144 | 6 | 19µs | 6 | 8µs | $self->name eq "__ANON__"; # spent 8µs making 6 calls to Type::Coercion::name, avg 1µs/call |
145 | } | ||||
146 | |||||
147 | # spent 2µs within Type::Coercion::_clear_compiled_coercion which was called:
# once (2µs+0s) by Type::Coercion::add_type_coercions at line 221 | ||||
148 | 1 | 700ns | delete $_[0]{_overload_coderef}; | ||
149 | 1 | 4µs | delete $_[0]{compiled_coercion}; | ||
150 | } | ||||
151 | |||||
152 | sub freeze { $_[0]{frozen} = 1; $_[0] } | ||||
153 | |||||
154 | sub coerce | ||||
155 | { | ||||
156 | my $self = shift; | ||||
157 | return $self->compiled_coercion->(@_); | ||||
158 | } | ||||
159 | |||||
160 | sub assert_coerce | ||||
161 | { | ||||
162 | my $self = shift; | ||||
163 | my $r = $self->coerce(@_); | ||||
164 | $self->type_constraint->assert_valid($r) | ||||
165 | if $self->has_type_constraint; | ||||
166 | return $r; | ||||
167 | } | ||||
168 | |||||
169 | sub has_coercion_for_type | ||||
170 | { | ||||
171 | my $self = shift; | ||||
172 | my $type = Types::TypeTiny::to_TypeTiny($_[0]); | ||||
173 | |||||
174 | return "0 but true" | ||||
175 | if $self->has_type_constraint && $type->is_a_type_of($self->type_constraint); | ||||
176 | |||||
177 | my $c = $self->type_coercion_map; | ||||
178 | for (my $i = 0; $i <= $#$c; $i += 2) | ||||
179 | { | ||||
180 | return !!1 if $type->is_a_type_of($c->[$i]); | ||||
181 | } | ||||
182 | return; | ||||
183 | } | ||||
184 | |||||
185 | sub has_coercion_for_value | ||||
186 | { | ||||
187 | my $self = shift; | ||||
188 | local $_ = $_[0]; | ||||
189 | |||||
190 | return "0 but true" | ||||
191 | if $self->has_type_constraint && $self->type_constraint->check(@_); | ||||
192 | |||||
193 | my $c = $self->type_coercion_map; | ||||
194 | for (my $i = 0; $i <= $#$c; $i += 2) | ||||
195 | { | ||||
196 | return !!1 if $c->[$i]->check(@_); | ||||
197 | } | ||||
198 | return; | ||||
199 | } | ||||
200 | |||||
201 | sub add_type_coercions | ||||
202 | # spent 850µs (71+780) within Type::Coercion::add_type_coercions which was called:
# once (71µs+780µs) by Type::Coercion::new at line 59 | ||||
203 | 1 | 100ns | my $self = shift; | ||
204 | 1 | 2µs | my @args = @_; | ||
205 | |||||
206 | 1 | 1µs | 1 | 26µs | _croak "Attempt to add coercion code to a Type::Coercion which has been frozen" if $self->frozen; # spent 26µs making 1 call to Type::Coercion::frozen |
207 | |||||
208 | 1 | 700ns | while (@args) | ||
209 | { | ||||
210 | 3 | 4µs | 3 | 22µs | my $type = Types::TypeTiny::to_TypeTiny(shift @args); # spent 22µs making 3 calls to Types::TypeTiny::to_TypeTiny, avg 7µs/call |
211 | 3 | 1µs | my $coercion = shift @args; | ||
212 | |||||
213 | 3 | 9µs | 6 | 391µs | _croak "Types must be blessed Type::Tiny objects" # spent 326µs making 3 calls to Type::Tiny::check, avg 109µs/call
# spent 65µs making 3 calls to Types::TypeTiny::TypeTiny, avg 22µs/call |
214 | unless Types::TypeTiny::TypeTiny->check($type); | ||||
215 | 3 | 8µs | 6 | 335µs | _croak "Coercions must be code references or strings" # spent 274µs making 3 calls to Type::Tiny::check, avg 91µs/call
# spent 61µs making 3 calls to Types::TypeTiny::StringLike, avg 20µs/call |
216 | unless Types::TypeTiny::StringLike->check($coercion) || Types::TypeTiny::CodeLike->check($coercion); | ||||
217 | |||||
218 | 3 | 8µs | 3 | 4µs | push @{$self->type_coercion_map}, $type, $coercion; # spent 4µs making 3 calls to Type::Coercion::type_coercion_map, avg 2µs/call |
219 | } | ||||
220 | |||||
221 | 1 | 1µs | 1 | 2µs | $self->_clear_compiled_coercion; # spent 2µs making 1 call to Type::Coercion::_clear_compiled_coercion |
222 | 1 | 4µs | return $self; | ||
223 | } | ||||
224 | |||||
225 | sub _build_compiled_coercion | ||||
226 | { | ||||
227 | my $self = shift; | ||||
228 | |||||
229 | my @mishmash = @{$self->type_coercion_map}; | ||||
230 | return sub { $_[0] } unless @mishmash; | ||||
231 | |||||
232 | if ($self->can_be_inlined) | ||||
233 | { | ||||
234 | return Eval::TypeTiny::eval_closure( | ||||
235 | source => sprintf('sub ($) { %s }', $self->inline_coercion('$_[0]')), | ||||
236 | description => sprintf("compiled coercion '%s'", $self), | ||||
237 | ); | ||||
238 | } | ||||
239 | |||||
240 | # These arrays will be closed over. | ||||
241 | my (@types, @codes); | ||||
242 | while (@mishmash) | ||||
243 | { | ||||
244 | push @types, shift @mishmash; | ||||
245 | push @codes, shift @mishmash; | ||||
246 | } | ||||
247 | if ($self->has_type_constraint) | ||||
248 | { | ||||
249 | unshift @types, $self->type_constraint; | ||||
250 | unshift @codes, undef; | ||||
251 | } | ||||
252 | |||||
253 | my @sub; | ||||
254 | |||||
255 | for my $i (0..$#types) | ||||
256 | { | ||||
257 | push @sub, | ||||
258 | $types[$i]->can_be_inlined ? sprintf('if (%s)', $types[$i]->inline_check('$_[0]')) : | ||||
259 | sprintf('if ($checks[%d]->(@_))', $i); | ||||
260 | push @sub, | ||||
261 | !defined($codes[$i]) | ||||
262 | ? sprintf(' { return $_[0] }') : | ||||
263 | Types::TypeTiny::StringLike->check($codes[$i]) | ||||
264 | ? sprintf(' { local $_ = $_[0]; return( %s ) }', $codes[$i]) : | ||||
265 | sprintf(' { local $_ = $_[0]; return $codes[%d]->(@_) }', $i); | ||||
266 | } | ||||
267 | |||||
268 | push @sub, 'return $_[0];'; | ||||
269 | |||||
270 | return Eval::TypeTiny::eval_closure( | ||||
271 | source => sprintf('sub ($) { %s }', join qq[\n], @sub), | ||||
272 | description => sprintf("compiled coercion '%s'", $self), | ||||
273 | environment => { | ||||
274 | '@checks' => [ map $_->compiled_check, @types ], | ||||
275 | '@codes' => \@codes, | ||||
276 | }, | ||||
277 | ); | ||||
278 | } | ||||
279 | |||||
280 | sub can_be_inlined | ||||
281 | { | ||||
282 | my $self = shift; | ||||
283 | return | ||||
284 | if $self->has_type_constraint | ||||
285 | && !$self->type_constraint->can_be_inlined; | ||||
286 | |||||
287 | my @mishmash = @{$self->type_coercion_map}; | ||||
288 | while (@mishmash) | ||||
289 | { | ||||
290 | my ($type, $converter) = splice(@mishmash, 0, 2); | ||||
291 | return unless $type->can_be_inlined; | ||||
292 | return unless Types::TypeTiny::StringLike->check($converter); | ||||
293 | } | ||||
294 | return !!1; | ||||
295 | } | ||||
296 | |||||
297 | sub _source_type_union | ||||
298 | { | ||||
299 | my $self = shift; | ||||
300 | |||||
301 | my @r; | ||||
302 | push @r, $self->type_constraint if $self->has_type_constraint; | ||||
303 | |||||
304 | my @mishmash = @{$self->type_coercion_map}; | ||||
305 | while (@mishmash) | ||||
306 | { | ||||
307 | my ($type) = splice(@mishmash, 0, 2); | ||||
308 | push @r, $type; | ||||
309 | } | ||||
310 | |||||
311 | require Type::Tiny::Union; | ||||
312 | return "Type::Tiny::Union"->new(type_constraints => \@r, tmp => 1); | ||||
313 | } | ||||
314 | |||||
315 | sub inline_coercion | ||||
316 | { | ||||
317 | my $self = shift; | ||||
318 | my $varname = $_[0]; | ||||
319 | |||||
320 | _croak "This coercion cannot be inlined" unless $self->can_be_inlined; | ||||
321 | |||||
322 | my @mishmash = @{$self->type_coercion_map}; | ||||
323 | return "($varname)" unless @mishmash; | ||||
324 | |||||
325 | my (@types, @codes); | ||||
326 | while (@mishmash) | ||||
327 | { | ||||
328 | push @types, shift @mishmash; | ||||
329 | push @codes, shift @mishmash; | ||||
330 | } | ||||
331 | if ($self->has_type_constraint) | ||||
332 | { | ||||
333 | unshift @types, $self->type_constraint; | ||||
334 | unshift @codes, undef; | ||||
335 | } | ||||
336 | |||||
337 | my @sub; | ||||
338 | |||||
339 | for my $i (0..$#types) | ||||
340 | { | ||||
341 | push @sub, sprintf('(%s) ?', $types[$i]->inline_check($varname)); | ||||
342 | push @sub, | ||||
343 | (defined($codes[$i]) && ($varname eq '$_')) | ||||
344 | ? sprintf('scalar(%s) :', $codes[$i]) : | ||||
345 | defined($codes[$i]) | ||||
346 | ? sprintf('do { local $_ = %s; scalar(%s) } :', $varname, $codes[$i]) : | ||||
347 | sprintf('%s :', $varname); | ||||
348 | } | ||||
349 | |||||
350 | push @sub, "$varname"; | ||||
351 | |||||
352 | "@sub"; | ||||
353 | } | ||||
354 | |||||
355 | sub _build_moose_coercion | ||||
356 | { | ||||
357 | my $self = shift; | ||||
358 | |||||
359 | my %options = (); | ||||
360 | $options{type_coercion_map} = [ $self->freeze->_codelike_type_coercion_map('moose_type') ]; | ||||
361 | $options{type_constraint} = $self->type_constraint if $self->has_type_constraint; | ||||
362 | |||||
363 | require Moose::Meta::TypeCoercion; | ||||
364 | my $r = "Moose::Meta::TypeCoercion"->new(%options); | ||||
365 | |||||
366 | return $r; | ||||
367 | } | ||||
368 | |||||
369 | sub _codelike_type_coercion_map | ||||
370 | { | ||||
371 | my $self = shift; | ||||
372 | my $modifier = $_[0]; | ||||
373 | |||||
374 | my @orig = @{ $self->type_coercion_map }; | ||||
375 | my @new; | ||||
376 | |||||
377 | while (@orig) | ||||
378 | { | ||||
379 | my ($type, $converter) = splice(@orig, 0, 2); | ||||
380 | |||||
381 | push @new, $modifier ? $type->$modifier : $type; | ||||
382 | |||||
383 | if (Types::TypeTiny::CodeLike->check($converter)) | ||||
384 | { | ||||
385 | push @new, $converter; | ||||
386 | } | ||||
387 | else | ||||
388 | { | ||||
389 | Eval::TypeTiny::eval_closure( | ||||
390 | source => sprintf('sub { local $_ = $_[0]; %s }', $converter), | ||||
391 | description => sprintf("temporary compiled converter from '%s'", $type), | ||||
392 | ); | ||||
393 | } | ||||
394 | } | ||||
395 | |||||
396 | return @new; | ||||
397 | } | ||||
398 | |||||
399 | sub is_parameterizable | ||||
400 | # spent 15µs (10+5) within Type::Coercion::is_parameterizable which was called 3 times, avg 5µs/call:
# 3 times (10µs+5µs) by Type::Library::_mksub at line 82 of Type/Library.pm, avg 5µs/call | ||||
401 | 3 | 9µs | 3 | 4µs | shift->has_coercion_generator; # spent 4µs making 3 calls to Type::Coercion::has_coercion_generator, avg 2µs/call |
402 | } | ||||
403 | |||||
404 | sub is_parameterized | ||||
405 | { | ||||
406 | shift->has_parameters; | ||||
407 | } | ||||
408 | |||||
409 | sub parameterize | ||||
410 | { | ||||
411 | my $self = shift; | ||||
412 | return $self unless @_; | ||||
413 | $self->is_parameterizable | ||||
414 | or _croak "Constraint '%s' does not accept parameters", "$self"; | ||||
415 | |||||
416 | @_ = map Types::TypeTiny::to_TypeTiny($_), @_; | ||||
417 | |||||
418 | return ref($self)->new( | ||||
419 | type_constraint => $self->type_constraint, | ||||
420 | type_coercion_map => [ $self->coercion_generator->($self, $self->type_constraint, @_) ], | ||||
421 | parameters => \@_, | ||||
422 | frozen => 1, | ||||
423 | ); | ||||
424 | } | ||||
425 | |||||
426 | sub isa | ||||
427 | { | ||||
428 | my $self = shift; | ||||
429 | |||||
430 | if ($INC{"Moose.pm"} and blessed($self) and $_[0] eq 'Moose::Meta::TypeCoercion') | ||||
431 | { | ||||
432 | return !!1; | ||||
433 | } | ||||
434 | |||||
435 | if ($INC{"Moose.pm"} and blessed($self) and $_[0] =~ /^Moose/ and my $r = $self->moose_coercion->isa(@_)) | ||||
436 | { | ||||
437 | return $r; | ||||
438 | } | ||||
439 | |||||
440 | $self->SUPER::isa(@_); | ||||
441 | } | ||||
442 | |||||
443 | sub can | ||||
444 | { | ||||
445 | my $self = shift; | ||||
446 | |||||
447 | my $can = $self->SUPER::can(@_); | ||||
448 | return $can if $can; | ||||
449 | |||||
450 | if ($INC{"Moose.pm"} and blessed($self) and my $method = $self->moose_coercion->can(@_)) | ||||
451 | { | ||||
452 | return sub { $method->(shift->moose_coercion, @_) }; | ||||
453 | } | ||||
454 | |||||
455 | return; | ||||
456 | } | ||||
457 | |||||
458 | sub AUTOLOAD | ||||
459 | { | ||||
460 | my $self = shift; | ||||
461 | my ($m) = (our $AUTOLOAD =~ /::(\w+)$/); | ||||
462 | return if $m eq 'DESTROY'; | ||||
463 | |||||
464 | if ($INC{"Moose.pm"} and blessed($self) and my $method = $self->moose_coercion->can($m)) | ||||
465 | { | ||||
466 | return $method->($self->moose_coercion, @_); | ||||
467 | } | ||||
468 | |||||
469 | _croak q[Can't locate object method "%s" via package "%s"], $m, ref($self)||$self; | ||||
470 | } | ||||
471 | |||||
472 | # Private Moose method, but Moo uses this... | ||||
473 | sub _compiled_type_coercion | ||||
474 | { | ||||
475 | my $self = shift; | ||||
476 | if (@_) | ||||
477 | { | ||||
478 | my $thing = $_[0]; | ||||
479 | if (blessed($thing) and $thing->isa("Type::Coercion")) | ||||
480 | { | ||||
481 | $self->add_type_coercions(@{$thing->type_coercion_map}); | ||||
482 | } | ||||
483 | elsif (Types::TypeTiny::CodeLike->check($thing)) | ||||
484 | { | ||||
485 | require Types::Standard; | ||||
486 | $self->add_type_coercions(Types::Standard::Any(), $thing); | ||||
487 | } | ||||
488 | } | ||||
489 | $self->compiled_coercion; | ||||
490 | } | ||||
491 | |||||
492 | 1 | 2µs | *compile_type_coercion = \&compiled_coercion; | ||
493 | sub meta { _croak("Not really a Moose::Meta::TypeCoercion. Sorry!") } | ||||
494 | |||||
495 | 1 | 4µs | 1; | ||
496 | |||||
497 | __END__ | ||||
sub Type::Coercion::CORE:match; # opcode |