| 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__ |