Remove all uses of CMOP::{load_class, is_class_loaded, load_first_existing_class...
[gitmo/Moose.git] / lib / Moose / Util / TypeConstraints / Builtins.pm
CommitLineData
06d02aac 1package Moose::Util::TypeConstraints::Builtins;
2
3use strict;
4use warnings;
5
b5ae7c00 6use Class::Load qw( is_class_loaded );
7fb4b360 7use List::MoreUtils ();
9882ca98 8use Scalar::Util qw( blessed looks_like_number reftype );
06d02aac 9
10sub type { goto &Moose::Util::TypeConstraints::type }
11sub subtype { goto &Moose::Util::TypeConstraints::subtype }
12sub as { goto &Moose::Util::TypeConstraints::as }
13sub where (&) { goto &Moose::Util::TypeConstraints::where }
14sub optimize_as (&) { goto &Moose::Util::TypeConstraints::optimize_as }
4e36cf24 15sub inline_as (&) { goto &Moose::Util::TypeConstraints::inline_as }
06d02aac 16
17sub define_builtins {
18 my $registry = shift;
19
4e36cf24 20 type 'Any' # meta-type including all
21 => where {1}
22 => inline_as { '1' };
06d02aac 23
d5807e74 24 subtype 'Item' # base type
94ab1609 25 => as 'Any'
26 => inline_as { '1' };
4e36cf24 27
28 subtype 'Undef'
29 => as 'Item'
30 => where { !defined($_) }
d5807e74 31 => inline_as {
295129da 32 '!defined(' . $_[1] . ')'
d5807e74 33 };
4e36cf24 34
35 subtype 'Defined'
36 => as 'Item'
37 => where { defined($_) }
d5807e74 38 => inline_as {
295129da 39 'defined(' . $_[1] . ')'
d5807e74 40 };
06d02aac 41
42 subtype 'Bool'
43 => as 'Item'
4e36cf24 44 => where { !defined($_) || $_ eq "" || "$_" eq '1' || "$_" eq '0' }
3975b592 45 => inline_as {
295129da 46 '('
d5807e74 47 . '!defined(' . $_[1] . ') '
48 . '|| ' . $_[1] . ' eq "" '
cd660a0f 49 . '|| (' . $_[1] . '."") eq "1" '
50 . '|| (' . $_[1] . '."") eq "0"'
d5807e74 51 . ')'
3975b592 52 };
06d02aac 53
54 subtype 'Value'
55 => as 'Defined'
56 => where { !ref($_) }
d5807e74 57 => inline_as {
58 $_[0]->parent()->_inline_check($_[1])
59 . ' && !ref(' . $_[1] . ')'
60 };
06d02aac 61
62 subtype 'Ref'
63 => as 'Defined'
64 => where { ref($_) }
d5807e74 65 # no need to call parent - ref also checks for definedness
3975b592 66 => inline_as { 'ref(' . $_[1] . ')' };
06d02aac 67
68 subtype 'Str'
69 => as 'Value'
a79639df 70 => where { ref(\$_) eq 'SCALAR' || ref(\(my $val = $_)) eq 'SCALAR' }
4e36cf24 71 => inline_as {
d5807e74 72 $_[0]->parent()->_inline_check($_[1])
73 . ' && ('
74 . 'ref(\\' . $_[1] . ') eq "SCALAR"'
75 . ' || ref(\\(my $val = ' . $_[1] . ')) eq "SCALAR"'
76 . ')'
4e36cf24 77 };
06d02aac 78
b47527bf 79 my $value_type = Moose::Util::TypeConstraints::find_type_constraint('Value');
06d02aac 80 subtype 'Num'
81 => as 'Str'
82 => where { Scalar::Util::looks_like_number($_) }
3975b592 83 => inline_as {
d5807e74 84 # the long Str tests are redundant here
b47527bf 85 $value_type->_inline_check($_[1])
d5807e74 86 . ' && Scalar::Util::looks_like_number(' . $_[1] . ')'
3975b592 87 };
06d02aac 88
89 subtype 'Int'
90 => as 'Num'
a79639df 91 => where { (my $val = $_) =~ /\A-?[0-9]+\z/ }
4e36cf24 92 => inline_as {
b47527bf 93 $value_type->_inline_check($_[1])
d5807e74 94 . ' && (my $val = ' . $_[1] . ') =~ /\A-?[0-9]+\z/'
4e36cf24 95 };
06d02aac 96
97 subtype 'CodeRef'
98 => as 'Ref'
99 => where { ref($_) eq 'CODE' }
3975b592 100 => inline_as { 'ref(' . $_[1] . ') eq "CODE"' };
06d02aac 101
102 subtype 'RegexpRef'
103 => as 'Ref'
9882ca98 104 => where( \&_RegexpRef )
3975b592 105 => inline_as {
106 'Moose::Util::TypeConstraints::Builtins::_RegexpRef(' . $_[1] . ')'
107 };
06d02aac 108
109 subtype 'GlobRef'
110 => as 'Ref'
111 => where { ref($_) eq 'GLOB' }
3975b592 112 => inline_as { 'ref(' . $_[1] . ') eq "GLOB"' };
06d02aac 113
114 # NOTE: scalar filehandles are GLOB refs, but a GLOB ref is not always a
115 # filehandle
116 subtype 'FileHandle'
94ab1609 117 => as 'Ref'
06d02aac 118 => where {
188ba420 119 (ref($_) eq "GLOB" && Scalar::Util::openhandle($_))
120 || (blessed($_) && $_->isa("IO::Handle"));
06d02aac 121 }
4e36cf24 122 => inline_as {
3975b592 123 '(ref(' . $_[1] . ') eq "GLOB" '
d5807e74 124 . '&& Scalar::Util::openhandle(' . $_[1] . ')) '
125 . '|| (Scalar::Util::blessed(' . $_[1] . ') '
126 . '&& ' . $_[1] . '->isa("IO::Handle"))'
4e36cf24 127 };
06d02aac 128
129 subtype 'Object'
130 => as 'Ref'
131 => where { blessed($_) }
3975b592 132 => inline_as { 'Scalar::Util::blessed(' . $_[1] . ')' };
06d02aac 133
06d02aac 134 subtype 'ClassName'
135 => as 'Str'
b5ae7c00 136 => where { is_class_loaded($_) }
d5807e74 137 # the long Str tests are redundant here
b5ae7c00 138 => inline_as { 'Class::Load::is_class_loaded(' . $_[1] . ')' };
06d02aac 139
140 subtype 'RoleName'
141 => as 'ClassName'
142 => where {
143 (Class::MOP::class_of($_) || return)->isa('Moose::Meta::Role');
144 }
4e36cf24 145 => inline_as {
d5807e74 146 $_[0]->parent()->_inline_check($_[1])
147 . ' && do {'
148 . 'my $meta = Class::MOP::class_of(' . $_[1] . ');'
149 . '$meta && $meta->isa("Moose::Meta::Role");'
150 . '}'
4e36cf24 151 };
06d02aac 152
153 $registry->add_type_constraint(
154 Moose::Meta::TypeConstraint::Parameterizable->new(
155 name => 'ScalarRef',
156 package_defined_in => __PACKAGE__,
157 parent =>
158 Moose::Util::TypeConstraints::find_type_constraint('Ref'),
159 constraint => sub { ref($_) eq 'SCALAR' || ref($_) eq 'REF' },
06d02aac 160 constraint_generator => sub {
161 my $type_parameter = shift;
162 my $check = $type_parameter->_compiled_type_constraint;
163 return sub {
164 return $check->( ${$_} );
165 };
7fb4b360 166 },
3975b592 167 inlined => sub {
168 'ref(' . $_[1] . ') eq "SCALAR" '
169 . '|| ref(' . $_[1] . ') eq "REF"'
170 },
7fb4b360 171 inline_generator => sub {
964294c1 172 my $self = shift;
7fb4b360 173 my $type_parameter = shift;
174 my $val = shift;
3975b592 175 '(ref(' . $val . ') eq "SCALAR" || ref(' . $val . ') eq "REF") '
176 . '&& ' . $type_parameter->_inline_check('${(' . $val . ')}')
7fb4b360 177 },
06d02aac 178 )
179 );
180
181 $registry->add_type_constraint(
182 Moose::Meta::TypeConstraint::Parameterizable->new(
183 name => 'ArrayRef',
184 package_defined_in => __PACKAGE__,
185 parent =>
186 Moose::Util::TypeConstraints::find_type_constraint('Ref'),
187 constraint => sub { ref($_) eq 'ARRAY' },
06d02aac 188 constraint_generator => sub {
189 my $type_parameter = shift;
190 my $check = $type_parameter->_compiled_type_constraint;
191 return sub {
192 foreach my $x (@$_) {
193 ( $check->($x) ) || return;
194 }
195 1;
196 }
7fb4b360 197 },
3975b592 198 inlined => sub { 'ref(' . $_[1] . ') eq "ARRAY"' },
7fb4b360 199 inline_generator => sub {
964294c1 200 my $self = shift;
7fb4b360 201 my $type_parameter = shift;
202 my $val = shift;
d6874ac6 203
204 'do {'
205 . 'my $check = ' . $val . ';'
206 . 'ref($check) eq "ARRAY" '
207 . '&& &List::MoreUtils::all('
208 . 'sub { ' . $type_parameter->_inline_check('$_') . ' }, '
209 . '@{$check}'
210 . ')'
211 . '}';
7fb4b360 212 },
06d02aac 213 )
214 );
215
216 $registry->add_type_constraint(
217 Moose::Meta::TypeConstraint::Parameterizable->new(
218 name => 'HashRef',
219 package_defined_in => __PACKAGE__,
220 parent =>
221 Moose::Util::TypeConstraints::find_type_constraint('Ref'),
222 constraint => sub { ref($_) eq 'HASH' },
06d02aac 223 constraint_generator => sub {
224 my $type_parameter = shift;
225 my $check = $type_parameter->_compiled_type_constraint;
226 return sub {
227 foreach my $x ( values %$_ ) {
228 ( $check->($x) ) || return;
229 }
230 1;
231 }
7fb4b360 232 },
3975b592 233 inlined => sub { 'ref(' . $_[1] . ') eq "HASH"' },
7fb4b360 234 inline_generator => sub {
964294c1 235 my $self = shift;
7fb4b360 236 my $type_parameter = shift;
237 my $val = shift;
d6874ac6 238
239 'do {'
240 . 'my $check = ' . $val . ';'
241 . 'ref($check) eq "HASH" '
242 . '&& &List::MoreUtils::all('
243 . 'sub { ' . $type_parameter->_inline_check('$_') . ' }, '
244 . 'values %{$check}'
245 . ')'
246 . '}';
7fb4b360 247 },
06d02aac 248 )
249 );
250
251 $registry->add_type_constraint(
252 Moose::Meta::TypeConstraint::Parameterizable->new(
253 name => 'Maybe',
254 package_defined_in => __PACKAGE__,
255 parent =>
256 Moose::Util::TypeConstraints::find_type_constraint('Item'),
257 constraint => sub {1},
258 constraint_generator => sub {
259 my $type_parameter = shift;
260 my $check = $type_parameter->_compiled_type_constraint;
261 return sub {
262 return 1 if not( defined($_) ) || $check->($_);
263 return;
264 }
7fb4b360 265 },
266 inlined => sub {'1'},
267 inline_generator => sub {
964294c1 268 my $self = shift;
7fb4b360 269 my $type_parameter = shift;
270 my $val = shift;
3975b592 271 '!defined(' . $val . ') '
272 . '|| (' . $type_parameter->_inline_check($val) . ')'
7fb4b360 273 },
06d02aac 274 )
275 );
276}
277
2781;
297899d1 279
280__END__
281
282=pod
283
284=for pod_coverage_needs_some_pod
285
286=cut
287