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