When an attribute property is malformed (such as lazy without a default), give the...
[gitmo/Moose.git] / lib / Moose / Meta / TypeConstraint.pm
CommitLineData
4e036ee4 1
2package Moose::Meta::TypeConstraint;
3
4use strict;
5use warnings;
6use metaclass;
7
b644e331 8use overload '""' => sub { shift->name }, # stringify to tc name
9 fallback => 1;
900466d6 10
c07af9d2 11use Sub::Name 'subname';
12use Carp 'confess';
13use Scalar::Util 'blessed';
66811d63 14
c14746bc 15our $VERSION = '0.12';
d44714be 16our $AUTHORITY = 'cpan:STEVAN';
66811d63 17
3726f905 18__PACKAGE__->meta->add_attribute('name' => (reader => 'name'));
19__PACKAGE__->meta->add_attribute('parent' => (
20 reader => 'parent',
21 predicate => 'has_parent',
22));
d67145ed 23__PACKAGE__->meta->add_attribute('constraint' => (
8de73ff1 24 reader => 'constraint',
25 writer => '_set_constraint',
26 default => sub { sub { 1 } }
d67145ed 27));
76d37e5a 28__PACKAGE__->meta->add_attribute('message' => (
29 accessor => 'message',
30 predicate => 'has_message'
31));
a27aa600 32__PACKAGE__->meta->add_attribute('coercion' => (
33 accessor => 'coercion',
34 predicate => 'has_coercion'
35));
c8cf9aaa 36__PACKAGE__->meta->add_attribute('hand_optimized_type_constraint' => (
37 init_arg => 'optimized',
38 accessor => 'hand_optimized_type_constraint',
e27dfc11 39 predicate => 'has_hand_optimized_type_constraint',
c8cf9aaa 40));
41
3726f905 42# private accessors
43
44__PACKAGE__->meta->add_attribute('compiled_type_constraint' => (
45 accessor => '_compiled_type_constraint',
46 predicate => '_has_compiled_type_constraint'
47));
22aed3c0 48__PACKAGE__->meta->add_attribute('package_defined_in' => (
49 accessor => '_package_defined_in'
50));
51
e27dfc11 52sub new {
a27aa600 53 my $class = shift;
54 my $self = $class->meta->new_object(@_);
3726f905 55 $self->compile_type_constraint()
56 unless $self->_has_compiled_type_constraint;
66811d63 57 return $self;
58}
59
3726f905 60sub coerce { ((shift)->coercion || confess "Cannot coerce without a type coercion")->coerce(@_) }
42bc21a4 61sub check { $_[0]->_compiled_type_constraint->($_[1]) ? 1 : undef }
e27dfc11 62sub validate {
76d37e5a 63 my ($self, $value) = @_;
64 if ($self->_compiled_type_constraint->($value)) {
65 return undef;
66 }
67 else {
688fcdda 68 $self->get_message($value);
76d37e5a 69 }
70}
71
688fcdda 72sub get_message {
73 my ($self, $value) = @_;
74 $value = (defined $value ? overload::StrVal($value) : 'undef');
75 if (my $msg = $self->message) {
76 local $_ = $value;
77 return $msg->($value);
78 }
79 else {
80 return "Validation failed for '" . $self->name . "' failed with value $value";
81 }
82}
83
3726f905 84## type predicates ...
85
b26e162e 86sub is_a_type_of {
87 my ($self, $type_name) = @_;
88 ($self->name eq $type_name || $self->is_subtype_of($type_name));
89}
90
cce8198b 91sub is_subtype_of {
92 my ($self, $type_name) = @_;
93 my $current = $self;
94 while (my $parent = $current->parent) {
95 return 1 if $parent->name eq $type_name;
96 $current = $parent;
97 }
98 return 0;
99}
100
3726f905 101## compiling the type constraint
102
103sub compile_type_constraint {
104 my $self = shift;
105 $self->_compiled_type_constraint($self->_actually_compile_type_constraint);
451c8248 106}
107
3726f905 108## type compilers ...
109
110sub _actually_compile_type_constraint {
111 my $self = shift;
e27dfc11 112
3726f905 113 return $self->_compile_hand_optimized_type_constraint
114 if $self->has_hand_optimized_type_constraint;
e27dfc11 115
3726f905 116 my $check = $self->constraint;
117 (defined $check)
e27dfc11 118 || confess "Could not compile type constraint '"
119 . $self->name
3726f905 120 . "' because no constraint check";
e27dfc11 121
3726f905 122 return $self->_compile_subtype($check)
123 if $self->has_parent;
e27dfc11 124
3726f905 125 return $self->_compile_type($check);
126}
127
128sub _compile_hand_optimized_type_constraint {
129 my $self = shift;
e27dfc11 130
3726f905 131 my $type_constraint = $self->hand_optimized_type_constraint;
e27dfc11 132
42bc21a4 133 confess unless ref $type_constraint;
134
135 return $type_constraint;
3726f905 136}
137
138sub _compile_subtype {
139 my ($self, $check) = @_;
e27dfc11 140
3726f905 141 # so we gather all the parents in order
142 # and grab their constraints ...
143 my @parents;
144 foreach my $parent ($self->_collect_all_parents) {
145 if ($parent->has_hand_optimized_type_constraint) {
146 unshift @parents => $parent->hand_optimized_type_constraint;
e27dfc11 147 last;
3726f905 148 }
149 else {
150 unshift @parents => $parent->constraint;
151 }
152 }
e27dfc11 153
3726f905 154 # then we compile them to run without
155 # having to recurse as we did before
6f9ff1af 156 return subname $self->name => sub {
157 local $_ = $_[0];
3726f905 158 foreach my $parent (@parents) {
159 return undef unless $parent->($_[0]);
160 }
6f9ff1af 161 return undef unless $check->($_[0]);
162 1;
163 };
3726f905 164}
165
166sub _compile_type {
167 my ($self, $check) = @_;
6f9ff1af 168 return subname $self->name => sub {
169 local $_ = $_[0];
170 return undef unless $check->($_[0]);
171 1;
172 };
3726f905 173}
174
175## other utils ...
176
177sub _collect_all_parents {
178 my $self = shift;
179 my @parents;
180 my $current = $self->parent;
181 while (defined $current) {
182 push @parents => $current;
183 $current = $current->parent;
184 }
185 return @parents;
186}
187
188## this should get deprecated actually ...
189
190sub union { die "DEPRECATED" }
191
4e036ee4 1921;
193
194__END__
195
196=pod
197
198=head1 NAME
199
6ba6d68c 200Moose::Meta::TypeConstraint - The Moose Type Constraint metaclass
4e036ee4 201
202=head1 DESCRIPTION
203
e27dfc11 204For the most part, the only time you will ever encounter an
205instance of this class is if you are doing some serious deep
206introspection. This API should not be considered final, but
207it is B<highly unlikely> that this will matter to a regular
6ba6d68c 208Moose user.
209
e27dfc11 210If you wish to use features at this depth, please come to the
6ba6d68c 211#moose IRC channel on irc.perl.org and we can talk :)
212
4e036ee4 213=head1 METHODS
214
215=over 4
216
217=item B<meta>
218
219=item B<new>
220
b26e162e 221=item B<is_a_type_of ($type_name)>
222
e27dfc11 223This checks the current type name, and if it does not match,
b26e162e 224checks if it is a subtype of it.
225
226=item B<is_subtype_of ($type_name)>
cce8198b 227
6ba6d68c 228=item B<compile_type_constraint>
229
0a5bd159 230=item B<coerce ($value)>
231
232This will apply the type-coercion if applicable.
233
76d37e5a 234=item B<check ($value)>
235
e27dfc11 236This method will return a true (C<1>) if the C<$value> passes the
76d37e5a 237constraint, and false (C<0>) otherwise.
238
239=item B<validate ($value)>
240
e27dfc11 241This method is similar to C<check>, but it deals with the error
242message. If the C<$value> passes the constraint, C<undef> will be
243returned. If the C<$value> does B<not> pass the constraint, then
244the C<message> will be used to construct a custom error message.
6ba6d68c 245
4e036ee4 246=item B<name>
247
66811d63 248=item B<parent>
249
3726f905 250=item B<has_parent>
251
66811d63 252=item B<constraint>
253
76d37e5a 254=item B<has_message>
255
256=item B<message>
257
688fcdda 258=item B<get_message ($value)>
259
4e036ee4 260=item B<has_coercion>
261
a27aa600 262=item B<coercion>
263
c8cf9aaa 264=item B<hand_optimized_type_constraint>
265
266=item B<has_hand_optimized_type_constraint>
267
4e036ee4 268=back
269
3726f905 270=head2 DEPRECATED METHOD
271
451c8248 272=over 4
273
3726f905 274=item B<union>
275
276This was just bad idea on my part,.. use the L<Moose::Meta::TypeConstraint::Union>
277itself instead.
451c8248 278
279=back
280
4e036ee4 281=head1 BUGS
282
e27dfc11 283All complex software has bugs lurking in it, and this module is no
4e036ee4 284exception. If you find a bug please either email me, or add the bug
285to cpan-RT.
286
287=head1 AUTHOR
288
289Stevan Little E<lt>stevan@iinteractive.comE<gt>
290
291=head1 COPYRIGHT AND LICENSE
292
778db3ac 293Copyright 2006-2008 by Infinity Interactive, Inc.
4e036ee4 294
295L<http://www.iinteractive.com>
296
297This library is free software; you can redistribute it and/or modify
e27dfc11 298it under the same terms as Perl itself.
4e036ee4 299
c8cf9aaa 300=cut