line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Mouse::Util::TypeConstraints; |
2
|
283
|
|
|
283
|
|
147901
|
use Mouse::Util; # enables strict and warnings |
|
283
|
|
|
|
|
333
|
|
|
283
|
|
|
|
|
1253
|
|
3
|
|
|
|
|
|
|
|
4
|
283
|
|
|
283
|
|
4259
|
use Mouse::Meta::TypeConstraint; |
|
283
|
|
|
|
|
328
|
|
|
283
|
|
|
|
|
4516
|
|
5
|
283
|
|
|
283
|
|
891
|
use Mouse::Exporter; |
|
283
|
|
|
|
|
278
|
|
|
283
|
|
|
|
|
1174
|
|
6
|
|
|
|
|
|
|
|
7
|
283
|
|
|
283
|
|
958
|
use Carp (); |
|
283
|
|
|
|
|
310
|
|
|
283
|
|
|
|
|
3237
|
|
8
|
283
|
|
|
283
|
|
819
|
use Scalar::Util (); |
|
283
|
|
|
|
|
309
|
|
|
283
|
|
|
|
|
667132
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
Mouse::Exporter->setup_import_methods( |
11
|
|
|
|
|
|
|
as_is => [qw( |
12
|
|
|
|
|
|
|
as where message optimize_as |
13
|
|
|
|
|
|
|
from via |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
type subtype class_type role_type maybe_type duck_type |
16
|
|
|
|
|
|
|
enum |
17
|
|
|
|
|
|
|
coerce |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
find_type_constraint |
20
|
|
|
|
|
|
|
register_type_constraint |
21
|
|
|
|
|
|
|
)], |
22
|
|
|
|
|
|
|
); |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
our @CARP_NOT = qw(Mouse::Meta::Attribute); |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
my %TYPE; |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
# The root type |
29
|
|
|
|
|
|
|
$TYPE{Any} = Mouse::Meta::TypeConstraint->new( |
30
|
|
|
|
|
|
|
name => 'Any', |
31
|
|
|
|
|
|
|
); |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
my @builtins = ( |
34
|
|
|
|
|
|
|
# $name => $parent, $code, |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
# the base type |
37
|
|
|
|
|
|
|
Item => 'Any', undef, |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
# the maybe[] type |
40
|
|
|
|
|
|
|
Maybe => 'Item', undef, |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
# value types |
43
|
|
|
|
|
|
|
Undef => 'Item', \&Undef, |
44
|
|
|
|
|
|
|
Defined => 'Item', \&Defined, |
45
|
|
|
|
|
|
|
Bool => 'Item', \&Bool, |
46
|
|
|
|
|
|
|
Value => 'Defined', \&Value, |
47
|
|
|
|
|
|
|
Str => 'Value', \&Str, |
48
|
|
|
|
|
|
|
Num => 'Str', \&Num, |
49
|
|
|
|
|
|
|
Int => 'Num', \&Int, |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
# ref types |
52
|
|
|
|
|
|
|
Ref => 'Defined', \&Ref, |
53
|
|
|
|
|
|
|
ScalarRef => 'Ref', \&ScalarRef, |
54
|
|
|
|
|
|
|
ArrayRef => 'Ref', \&ArrayRef, |
55
|
|
|
|
|
|
|
HashRef => 'Ref', \&HashRef, |
56
|
|
|
|
|
|
|
CodeRef => 'Ref', \&CodeRef, |
57
|
|
|
|
|
|
|
RegexpRef => 'Ref', \&RegexpRef, |
58
|
|
|
|
|
|
|
GlobRef => 'Ref', \&GlobRef, |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
# object types |
61
|
|
|
|
|
|
|
FileHandle => 'GlobRef', \&FileHandle, |
62
|
|
|
|
|
|
|
Object => 'Ref', \&Object, |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
# special string types |
65
|
|
|
|
|
|
|
ClassName => 'Str', \&ClassName, |
66
|
|
|
|
|
|
|
RoleName => 'ClassName', \&RoleName, |
67
|
|
|
|
|
|
|
); |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
while (my ($name, $parent, $code) = splice @builtins, 0, 3) { |
70
|
|
|
|
|
|
|
$TYPE{$name} = Mouse::Meta::TypeConstraint->new( |
71
|
|
|
|
|
|
|
name => $name, |
72
|
|
|
|
|
|
|
parent => $TYPE{$parent}, |
73
|
|
|
|
|
|
|
optimized => $code, |
74
|
|
|
|
|
|
|
); |
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
# parametarizable types |
78
|
|
|
|
|
|
|
$TYPE{Maybe} {constraint_generator} = \&_parameterize_Maybe_for; |
79
|
|
|
|
|
|
|
$TYPE{ArrayRef}{constraint_generator} = \&_parameterize_ArrayRef_for; |
80
|
|
|
|
|
|
|
$TYPE{HashRef} {constraint_generator} = \&_parameterize_HashRef_for; |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
# sugars |
83
|
59
|
|
|
59
|
1
|
12806
|
sub as ($) { (as => $_[0]) } ## no critic |
84
|
58
|
|
|
58
|
1
|
3014
|
sub where (&) { (where => $_[0]) } ## no critic |
85
|
7
|
|
|
7
|
0
|
25
|
sub message (&) { (message => $_[0]) } ## no critic |
86
|
0
|
|
|
0
|
0
|
0
|
sub optimize_as (&) { (optimize_as => $_[0]) } ## no critic |
87
|
|
|
|
|
|
|
|
88
|
37
|
|
|
37
|
1
|
111
|
sub from { @_ } |
89
|
37
|
|
|
37
|
1
|
3164
|
sub via (&) { $_[0] } ## no critic |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
# type utilities |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
sub optimized_constraints { # DEPRECATED |
94
|
0
|
|
|
0
|
0
|
0
|
Carp::cluck('optimized_constraints() has been deprecated'); |
95
|
0
|
|
|
|
|
0
|
return \%TYPE; |
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
undef @builtins; # free the allocated memory |
99
|
|
|
|
|
|
|
@builtins = keys %TYPE; # reuse it |
100
|
1
|
|
|
1
|
1
|
6
|
sub list_all_builtin_type_constraints { @builtins } |
101
|
5
|
|
|
5
|
1
|
563
|
sub list_all_type_constraints { keys %TYPE } |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
sub _define_type { |
104
|
853
|
|
|
853
|
|
884
|
my $is_subtype = shift; |
105
|
853
|
|
|
|
|
709
|
my $name; |
106
|
|
|
|
|
|
|
my %args; |
107
|
|
|
|
|
|
|
|
108
|
853
|
50
|
33
|
|
|
4748
|
if(@_ == 1 && ref $_[0] ){ # @_ : { name => $name, where => ... } |
|
|
50
|
66
|
|
|
|
|
|
|
100
|
|
|
|
|
|
109
|
0
|
|
|
|
|
0
|
%args = %{$_[0]}; |
|
0
|
|
|
|
|
0
|
|
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
elsif(@_ == 2 && ref $_[1]) { # @_ : $name => { where => ... } |
112
|
0
|
|
|
|
|
0
|
$name = $_[0]; |
113
|
0
|
|
|
|
|
0
|
%args = %{$_[1]}; |
|
0
|
|
|
|
|
0
|
|
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
elsif(@_ % 2) { # @_ : $name => ( where => ... ) |
116
|
850
|
|
|
|
|
2664
|
($name, %args) = @_; |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
else{ # @_ : (name => $name, where => ...) |
119
|
3
|
|
|
|
|
9
|
%args = @_; |
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
|
122
|
853
|
100
|
|
|
|
1868
|
if(!defined $name){ |
123
|
7
|
|
|
|
|
15
|
$name = $args{name}; |
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
|
126
|
853
|
|
|
|
|
1141
|
$args{name} = $name; |
127
|
|
|
|
|
|
|
|
128
|
853
|
|
|
|
|
1138
|
my $parent = delete $args{as}; |
129
|
853
|
100
|
100
|
|
|
3423
|
if($is_subtype && !$parent){ |
130
|
3
|
|
|
|
|
8
|
$parent = delete $args{name}; |
131
|
3
|
|
|
|
|
5
|
$name = undef; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
853
|
100
|
|
|
|
1488
|
if(defined $parent) { |
135
|
838
|
|
|
|
|
1398
|
$args{parent} = find_or_create_isa_type_constraint($parent); |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
852
|
100
|
|
|
|
1422
|
if(defined $name){ |
139
|
|
|
|
|
|
|
# set 'package_defined_in' only if it is not a core package |
140
|
842
|
|
|
|
|
872
|
my $this = $args{package_defined_in}; |
141
|
842
|
50
|
|
|
|
1342
|
if(!$this){ |
142
|
842
|
|
|
|
|
1350
|
$this = caller(1); |
143
|
842
|
100
|
|
|
|
6204
|
if($this !~ /\A Mouse \b/xms){ |
144
|
79
|
|
|
|
|
138
|
$args{package_defined_in} = $this; |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
|
148
|
842
|
100
|
|
|
|
1701
|
if(defined $TYPE{$name}){ |
149
|
10
|
|
100
|
|
|
97
|
my $that = $TYPE{$name}->{package_defined_in} || __PACKAGE__; |
150
|
10
|
100
|
|
|
|
30
|
if($this ne $that) { |
151
|
3
|
|
|
|
|
6
|
my $note = ''; |
152
|
3
|
100
|
|
|
|
8
|
if($that eq __PACKAGE__) { |
153
|
|
|
|
|
|
|
$note = sprintf " ('%s' is %s type constraint)", |
154
|
|
|
|
|
|
|
$name, |
155
|
1
|
50
|
|
|
|
4
|
scalar(grep { $name eq $_ } list_all_builtin_type_constraints()) |
|
21
|
|
|
|
|
25
|
|
156
|
|
|
|
|
|
|
? 'a builtin' |
157
|
|
|
|
|
|
|
: 'an implicitly created'; |
158
|
|
|
|
|
|
|
} |
159
|
3
|
|
|
|
|
505
|
Carp::croak("The type constraint '$name' has already been created in $that" |
160
|
|
|
|
|
|
|
. " and cannot be created again in $this" . $note); |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
} |
164
|
|
|
|
|
|
|
|
165
|
849
|
100
|
|
|
|
1494
|
$args{constraint} = delete $args{where} if exists $args{where}; |
166
|
849
|
100
|
|
|
|
1921
|
$args{optimized} = delete $args{optimized_as} if exists $args{optimized_as}; |
167
|
|
|
|
|
|
|
|
168
|
849
|
|
|
|
|
3670
|
my $constraint = Mouse::Meta::TypeConstraint->new(%args); |
169
|
|
|
|
|
|
|
|
170
|
849
|
100
|
|
|
|
1618
|
if(defined $name){ |
171
|
839
|
|
|
|
|
2734
|
return $TYPE{$name} = $constraint; |
172
|
|
|
|
|
|
|
} |
173
|
|
|
|
|
|
|
else{ |
174
|
10
|
|
|
|
|
41
|
return $constraint; |
175
|
|
|
|
|
|
|
} |
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
sub type { |
179
|
15
|
|
|
15
|
1
|
39
|
return _define_type 0, @_; |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
sub subtype { |
183
|
825
|
|
|
825
|
1
|
1495
|
return _define_type 1, @_; |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
sub coerce { # coerce $type, from $from, via { ... }, ... |
187
|
31
|
|
|
31
|
1
|
44
|
my $type_name = shift; |
188
|
31
|
100
|
|
|
|
78
|
my $type = find_type_constraint($type_name) |
189
|
|
|
|
|
|
|
or Carp::croak("Cannot find type '$type_name', perhaps you forgot to load it"); |
190
|
|
|
|
|
|
|
|
191
|
30
|
|
|
|
|
118
|
$type->_add_type_coercions(@_); |
192
|
28
|
|
|
|
|
46
|
return; |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
sub class_type { |
196
|
570
|
|
|
570
|
1
|
704
|
my($name, $options) = @_; |
197
|
570
|
|
33
|
|
|
2091
|
my $class = $options->{class} || $name; |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
# ClassType |
200
|
570
|
|
|
|
|
3595
|
return subtype $name => ( |
201
|
|
|
|
|
|
|
as => 'Object', |
202
|
|
|
|
|
|
|
optimized_as => Mouse::Util::generate_isa_predicate_for($class), |
203
|
|
|
|
|
|
|
class => $class, |
204
|
|
|
|
|
|
|
); |
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
sub role_type { |
208
|
193
|
|
|
193
|
1
|
282
|
my($name, $options) = @_; |
209
|
193
|
|
66
|
|
|
939
|
my $role = $options->{role} || $name; |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
# RoleType |
212
|
|
|
|
|
|
|
return subtype $name => ( |
213
|
|
|
|
|
|
|
as => 'Object', |
214
|
|
|
|
|
|
|
optimized_as => sub { |
215
|
23
|
|
100
|
23
|
|
3919
|
return Scalar::Util::blessed($_[0]) |
216
|
|
|
|
|
|
|
&& Mouse::Util::does_role($_[0], $role); |
217
|
|
|
|
|
|
|
}, |
218
|
193
|
|
|
|
|
782
|
role => $role, |
219
|
|
|
|
|
|
|
); |
220
|
|
|
|
|
|
|
} |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
sub maybe_type { |
223
|
1
|
|
|
1
|
0
|
2
|
my $param = shift; |
224
|
1
|
|
|
|
|
3
|
return _find_or_create_parameterized_type($TYPE{Maybe}, $param); |
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
sub duck_type { |
228
|
6
|
|
|
6
|
1
|
31
|
my($name, @methods); |
229
|
|
|
|
|
|
|
|
230
|
6
|
100
|
|
|
|
15
|
if(ref($_[0]) ne 'ARRAY'){ |
231
|
4
|
|
|
|
|
7
|
$name = shift; |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
|
234
|
6
|
100
|
66
|
|
|
56
|
@methods = (@_ == 1 && ref($_[0]) eq 'ARRAY') ? @{$_[0]} : @_; |
|
4
|
|
|
|
|
6
|
|
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
# DuckType |
237
|
|
|
|
|
|
|
return _define_type 1, $name => ( |
238
|
|
|
|
|
|
|
as => 'Object', |
239
|
|
|
|
|
|
|
optimized_as => Mouse::Util::generate_can_predicate_for(\@methods), |
240
|
|
|
|
|
|
|
message => sub { |
241
|
1
|
|
|
1
|
|
2
|
my($object) = @_; |
242
|
1
|
|
|
|
|
2
|
my @missing = grep { !$object->can($_) } @methods; |
|
1
|
|
|
|
|
5
|
|
243
|
1
|
|
|
|
|
10
|
return ref($object) |
244
|
|
|
|
|
|
|
. ' is missing methods ' |
245
|
|
|
|
|
|
|
. Mouse::Util::quoted_english_list(@missing); |
246
|
|
|
|
|
|
|
}, |
247
|
6
|
|
|
|
|
78
|
methods => \@methods, |
248
|
|
|
|
|
|
|
); |
249
|
|
|
|
|
|
|
} |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
sub enum { |
252
|
7
|
|
|
7
|
1
|
1048
|
my($name, %valid); |
253
|
|
|
|
|
|
|
|
254
|
7
|
100
|
66
|
|
|
47
|
if(!(@_ == 1 && ref($_[0]) eq 'ARRAY')){ |
255
|
5
|
|
|
|
|
7
|
$name = shift; |
256
|
|
|
|
|
|
|
} |
257
|
|
|
|
|
|
|
|
258
|
78
|
|
|
|
|
120
|
%valid = map{ $_ => undef } |
259
|
7
|
100
|
66
|
|
|
37
|
(@_ == 1 && ref($_[0]) eq 'ARRAY' ? @{$_[0]} : @_); |
|
3
|
|
|
|
|
10
|
|
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
# EnumType |
262
|
|
|
|
|
|
|
return _define_type 1, $name => ( |
263
|
|
|
|
|
|
|
as => 'Str', |
264
|
|
|
|
|
|
|
optimized_as => sub{ |
265
|
120
|
|
66
|
120
|
|
32940
|
return defined($_[0]) && !ref($_[0]) && exists $valid{$_[0]}; |
266
|
|
|
|
|
|
|
}, |
267
|
7
|
|
|
|
|
49
|
); |
268
|
|
|
|
|
|
|
} |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
sub _find_or_create_regular_type{ |
271
|
128
|
|
|
128
|
|
215
|
my($spec, $create) = @_; |
272
|
|
|
|
|
|
|
|
273
|
128
|
100
|
|
|
|
451
|
return $TYPE{$spec} if exists $TYPE{$spec}; |
274
|
|
|
|
|
|
|
|
275
|
13
|
|
|
|
|
50
|
my $meta = Mouse::Util::get_metaclass_by_name($spec); |
276
|
|
|
|
|
|
|
|
277
|
13
|
50
|
|
|
|
37
|
if(!defined $meta){ |
278
|
13
|
100
|
|
|
|
44
|
return $create ? class_type($spec) : undef; |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
|
281
|
0
|
0
|
|
|
|
0
|
if(Mouse::Util::is_a_metarole($meta)){ |
282
|
0
|
|
|
|
|
0
|
return role_type($spec); |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
else{ |
285
|
0
|
|
|
|
|
0
|
return class_type($spec); |
286
|
|
|
|
|
|
|
} |
287
|
|
|
|
|
|
|
} |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
sub _find_or_create_parameterized_type{ |
290
|
45
|
|
|
45
|
|
52
|
my($base, $param) = @_; |
291
|
|
|
|
|
|
|
|
292
|
45
|
|
|
|
|
307
|
my $name = sprintf '%s[%s]', $base->name, $param->name; |
293
|
|
|
|
|
|
|
|
294
|
45
|
|
100
|
|
|
254
|
$TYPE{$name} ||= $base->parameterize($param, $name); |
295
|
|
|
|
|
|
|
} |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
sub _find_or_create_union_type{ |
298
|
22
|
50
|
|
22
|
|
32
|
return if grep{ not defined } @_; # all things must be defined |
|
48
|
|
|
|
|
92
|
|
299
|
|
|
|
|
|
|
my @types = sort |
300
|
22
|
100
|
|
|
|
27
|
map{ $_->{type_constraints} ? @{$_->{type_constraints}} : $_ } @_; |
|
48
|
|
|
|
|
277
|
|
|
2
|
|
|
|
|
3
|
|
301
|
|
|
|
|
|
|
|
302
|
22
|
|
|
|
|
53
|
my $name = join '|', @types; |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
# UnionType |
305
|
22
|
|
66
|
|
|
145
|
$TYPE{$name} ||= Mouse::Meta::TypeConstraint->new( |
306
|
|
|
|
|
|
|
name => $name, |
307
|
|
|
|
|
|
|
type_constraints => \@types, |
308
|
|
|
|
|
|
|
); |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
# The type parser |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
# param : '[' type ']' | NOTHING |
314
|
|
|
|
|
|
|
sub _parse_param { |
315
|
128
|
|
|
128
|
|
245
|
my($c) = @_; |
316
|
|
|
|
|
|
|
|
317
|
128
|
100
|
|
|
|
474
|
if($c->{spec} =~ s/^\[//){ |
318
|
44
|
|
|
|
|
118
|
my $type = _parse_type($c, 1); |
319
|
|
|
|
|
|
|
|
320
|
44
|
50
|
|
|
|
176
|
if($c->{spec} =~ s/^\]//){ |
321
|
44
|
|
|
|
|
64
|
return $type; |
322
|
|
|
|
|
|
|
} |
323
|
0
|
|
|
|
|
0
|
Carp::croak("Syntax error in type: missing right square bracket in '$c->{orig}'"); |
324
|
|
|
|
|
|
|
} |
325
|
|
|
|
|
|
|
|
326
|
84
|
|
|
|
|
114
|
return undef; |
327
|
|
|
|
|
|
|
} |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
# name : [\w.:]+ |
330
|
|
|
|
|
|
|
sub _parse_name { |
331
|
128
|
|
|
128
|
|
97
|
my($c, $create) = @_; |
332
|
|
|
|
|
|
|
|
333
|
128
|
50
|
|
|
|
551
|
if($c->{spec} =~ s/\A ([\w.:]+) //xms){ |
334
|
128
|
|
|
|
|
234
|
return _find_or_create_regular_type($1, $create); |
335
|
|
|
|
|
|
|
} |
336
|
0
|
|
|
|
|
0
|
Carp::croak("Syntax error in type: expect type name near '$c->{spec}' in '$c->{orig}'"); |
337
|
|
|
|
|
|
|
} |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
# single_type : name param |
340
|
|
|
|
|
|
|
sub _parse_single_type { |
341
|
128
|
|
|
128
|
|
116
|
my($c, $create) = @_; |
342
|
|
|
|
|
|
|
|
343
|
128
|
|
|
|
|
187
|
my $type = _parse_name($c, $create); |
344
|
128
|
|
|
|
|
227
|
my $param = _parse_param($c); |
345
|
|
|
|
|
|
|
|
346
|
128
|
100
|
|
|
|
228
|
if(defined $type){ |
|
|
50
|
|
|
|
|
|
347
|
118
|
100
|
|
|
|
150
|
if(defined $param){ |
348
|
44
|
|
|
|
|
89
|
return _find_or_create_parameterized_type($type, $param); |
349
|
|
|
|
|
|
|
} |
350
|
|
|
|
|
|
|
else { |
351
|
74
|
|
|
|
|
127
|
return $type; |
352
|
|
|
|
|
|
|
} |
353
|
|
|
|
|
|
|
} |
354
|
|
|
|
|
|
|
elsif(defined $param){ |
355
|
0
|
|
|
|
|
0
|
Carp::croak("Undefined type with parameter [$param] in '$c->{orig}'"); |
356
|
|
|
|
|
|
|
} |
357
|
|
|
|
|
|
|
else{ |
358
|
10
|
|
|
|
|
15
|
return undef; |
359
|
|
|
|
|
|
|
} |
360
|
|
|
|
|
|
|
} |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
# type : single_type ('|' single_type)* |
363
|
|
|
|
|
|
|
sub _parse_type { |
364
|
108
|
|
|
108
|
|
117
|
my($c, $create) = @_; |
365
|
|
|
|
|
|
|
|
366
|
108
|
|
|
|
|
202
|
my $type = _parse_single_type($c, $create); |
367
|
107
|
100
|
|
|
|
238
|
if($c->{spec}){ # can be an union type |
368
|
58
|
|
|
|
|
57
|
my @types; |
369
|
58
|
|
|
|
|
167
|
while($c->{spec} =~ s/^\|//){ |
370
|
20
|
|
|
|
|
27
|
push @types, _parse_single_type($c, $create); |
371
|
|
|
|
|
|
|
} |
372
|
58
|
100
|
|
|
|
125
|
if(@types){ |
373
|
16
|
|
|
|
|
37
|
return _find_or_create_union_type($type, @types); |
374
|
|
|
|
|
|
|
} |
375
|
|
|
|
|
|
|
} |
376
|
91
|
|
|
|
|
106
|
return $type; |
377
|
|
|
|
|
|
|
} |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
sub find_type_constraint { |
381
|
972
|
|
|
972
|
1
|
21362
|
my($spec) = @_; |
382
|
972
|
100
|
66
|
|
|
4489
|
return $spec if Mouse::Util::is_a_type_constraint($spec) or not defined $spec; |
383
|
|
|
|
|
|
|
|
384
|
971
|
|
|
|
|
2075
|
$spec =~ s/\s+//g; |
385
|
971
|
|
|
|
|
4047
|
return $TYPE{$spec}; |
386
|
|
|
|
|
|
|
} |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
sub register_type_constraint { |
389
|
2
|
|
|
2
|
0
|
7
|
my($constraint) = @_; |
390
|
2
|
50
|
|
|
|
8
|
Carp::croak("No type supplied / type is not a valid type constraint") |
391
|
|
|
|
|
|
|
unless Mouse::Util::is_a_type_constraint($constraint); |
392
|
2
|
|
|
|
|
7
|
return $TYPE{$constraint->name} = $constraint; |
393
|
|
|
|
|
|
|
} |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
sub find_or_parse_type_constraint { |
396
|
1251
|
|
|
1251
|
0
|
8502
|
my($spec) = @_; |
397
|
1251
|
100
|
66
|
|
|
5227
|
return $spec if Mouse::Util::is_a_type_constraint($spec) or not defined $spec; |
398
|
|
|
|
|
|
|
|
399
|
1233
|
|
|
|
|
1999
|
$spec =~ tr/ \t\r\n//d; |
400
|
|
|
|
|
|
|
|
401
|
1233
|
|
|
|
|
1693
|
my $tc = $TYPE{$spec}; |
402
|
1233
|
100
|
|
|
|
2476
|
if(defined $tc) { |
403
|
1169
|
|
|
|
|
1759
|
return $tc; |
404
|
|
|
|
|
|
|
} |
405
|
|
|
|
|
|
|
|
406
|
64
|
|
|
|
|
198
|
my %context = ( |
407
|
|
|
|
|
|
|
spec => $spec, |
408
|
|
|
|
|
|
|
orig => $spec, |
409
|
|
|
|
|
|
|
); |
410
|
64
|
|
|
|
|
168
|
$tc = _parse_type(\%context); |
411
|
|
|
|
|
|
|
|
412
|
63
|
50
|
|
|
|
157
|
if($context{spec}){ |
413
|
0
|
|
|
|
|
0
|
Carp::croak("Syntax error: extra elements '$context{spec}' in '$context{orig}'"); |
414
|
|
|
|
|
|
|
} |
415
|
|
|
|
|
|
|
|
416
|
63
|
|
|
|
|
177
|
return $TYPE{$spec} = $tc; |
417
|
|
|
|
|
|
|
} |
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
sub find_or_create_does_type_constraint{ |
420
|
|
|
|
|
|
|
# XXX: Moose does not register a new role_type, but Mouse does. |
421
|
5
|
|
|
5
|
0
|
13
|
my $tc = find_or_parse_type_constraint(@_); |
422
|
5
|
50
|
|
|
|
24
|
return defined($tc) ? $tc : role_type(@_); |
423
|
|
|
|
|
|
|
} |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
sub find_or_create_isa_type_constraint { |
426
|
|
|
|
|
|
|
# XXX: Moose does not register a new class_type, but Mouse does. |
427
|
1196
|
|
|
1196
|
0
|
2069
|
my $tc = find_or_parse_type_constraint(@_); |
428
|
1195
|
100
|
|
|
|
3123
|
return defined($tc) ? $tc : class_type(@_); |
429
|
|
|
|
|
|
|
} |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
1; |
432
|
|
|
|
|
|
|
__END__ |