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