required does not throw an error if it has a default value
[gitmo/Moose.git] / lib / Moose / Util / TypeConstraints.pm
CommitLineData
a15dff8d 1
2package Moose::Util::TypeConstraints;
3
4use strict;
5use warnings;
6
e90c03d0 7use Carp 'confess';
a15dff8d 8use Scalar::Util 'blessed';
9
446e850f 10our $VERSION = '0.04';
a15dff8d 11
4e036ee4 12use Moose::Meta::TypeConstraint;
2ca63f5d 13use Moose::Meta::TypeCoercion;
4e036ee4 14
a15dff8d 15sub import {
16 shift;
17 my $pkg = shift || caller();
34a66aa3 18 return if $pkg eq '-no-export';
a15dff8d 19 no strict 'refs';
76d37e5a 20 foreach my $export (qw(type subtype as where message coerce from via find_type_constraint)) {
a15dff8d 21 *{"${pkg}::${export}"} = \&{"${export}"};
a15dff8d 22 }
a15dff8d 23}
24
182134e8 25{
26 my %TYPES;
446e850f 27 sub find_type_constraint {
28 return $TYPES{$_[0]}->[1]
29 if exists $TYPES{$_[0]};
30 return;
31 }
32
33 sub _dump_type_constraints {
34 require Data::Dumper;
256903b6 35 Data::Dumper::Dumper(\%TYPES);
446e850f 36 }
37
7c13858b 38 sub _create_type_constraint {
76d37e5a 39 my ($name, $parent, $check, $message) = @_;
0e6614c3 40 my $pkg_defined_in = scalar(caller(1));
41 ($TYPES{$name}->[0] eq $pkg_defined_in)
446e850f 42 || confess "The type constraint '$name' has already been created "
0e6614c3 43 if defined $name && exists $TYPES{$name};
44 $parent = find_type_constraint($parent) if defined $parent;
a27aa600 45 my $constraint = Moose::Meta::TypeConstraint->new(
46 name => $name || '__ANON__',
66811d63 47 parent => $parent,
76d37e5a 48 constraint => $check,
49 message => $message,
4e036ee4 50 );
0e6614c3 51 $TYPES{$name} = [ $pkg_defined_in, $constraint ] if defined $name;
a27aa600 52 return $constraint;
182134e8 53 }
182134e8 54
7c13858b 55 sub _install_type_coercions {
a27aa600 56 my ($type_name, $coercion_map) = @_;
0e6614c3 57 my $type = find_type_constraint($type_name);
4e036ee4 58 (!$type->has_coercion)
d46a48f3 59 || confess "The type coercion for '$type_name' has already been registered";
a27aa600 60 my $type_coercion = Moose::Meta::TypeCoercion->new(
61 type_coercion_map => $coercion_map,
62 type_constraint => $type
63 );
64 $type->coercion($type_coercion);
182134e8 65 }
66811d63 66
67 sub export_type_contstraints_as_functions {
68 my $pkg = caller();
69 no strict 'refs';
70 foreach my $constraint (keys %TYPES) {
0e6614c3 71 *{"${pkg}::${constraint}"} = find_type_constraint($constraint)->_compiled_type_constraint;
66811d63 72 }
73 }
182134e8 74}
a15dff8d 75
7c13858b 76# type constructors
a15dff8d 77
78sub type ($$) {
79 my ($name, $check) = @_;
7c13858b 80 _create_type_constraint($name, undef, $check);
a15dff8d 81}
82
76d37e5a 83sub subtype ($$;$$) {
84 unshift @_ => undef if scalar @_ <= 2;
7c13858b 85 _create_type_constraint(@_);
a15dff8d 86}
87
4b598ea3 88sub coerce ($@) {
66811d63 89 my ($type_name, @coercion_map) = @_;
7c13858b 90 _install_type_coercions($type_name, \@coercion_map);
182134e8 91}
92
76d37e5a 93sub as ($) { $_[0] }
94sub from ($) { $_[0] }
95sub where (&) { $_[0] }
96sub via (&) { $_[0] }
97sub message (&) { $_[0] }
a15dff8d 98
99# define some basic types
100
e9ec68d6 101type 'Any' => where { 1 };
a15dff8d 102
76d37e5a 103subtype 'Value' => as 'Any' => where { !ref($_) };
104subtype 'Ref' => as 'Any' => where { ref($_) };
a15dff8d 105
e9ec68d6 106subtype 'Int' => as 'Value' => where { Scalar::Util::looks_like_number($_) };
107subtype 'Str' => as 'Value' => where { !Scalar::Util::looks_like_number($_) };
a15dff8d 108
e9ec68d6 109subtype 'ScalarRef' => as 'Ref' => where { ref($_) eq 'SCALAR' };
110subtype 'ArrayRef' => as 'Ref' => where { ref($_) eq 'ARRAY' };
111subtype 'HashRef' => as 'Ref' => where { ref($_) eq 'HASH' };
112subtype 'CodeRef' => as 'Ref' => where { ref($_) eq 'CODE' };
113subtype 'RegexpRef' => as 'Ref' => where { ref($_) eq 'Regexp' };
a15dff8d 114
115# NOTE:
116# blessed(qr/.../) returns true,.. how odd
e9ec68d6 117subtype 'Object' => as 'Ref' => where { blessed($_) && blessed($_) ne 'Regexp' };
a15dff8d 118
02a0fb52 119subtype 'Role' => as 'Object' => where { $_->can('does') };
120
a15dff8d 1211;
122
123__END__
124
125=pod
126
127=head1 NAME
128
e522431d 129Moose::Util::TypeConstraints - Type constraint system for Moose
a15dff8d 130
131=head1 SYNOPSIS
132
133 use Moose::Util::TypeConstraints;
134
135 type Num => where { Scalar::Util::looks_like_number($_) };
136
137 subtype Natural
138 => as Num
139 => where { $_ > 0 };
140
141 subtype NaturalLessThanTen
142 => as Natural
79592a54 143 => where { $_ < 10 }
144 => message { "This number ($_) is not less than ten!" };
6b8bd8d3 145
146 coerce Num
d6e2d9a1 147 => from Str
148 => via { 0+$_ };
a15dff8d 149
150=head1 DESCRIPTION
151
e522431d 152This module provides Moose with the ability to create type contraints
153to be are used in both attribute definitions and for method argument
154validation.
155
6ba6d68c 156=head2 Important Caveat
157
158This is B<NOT> a type system for Perl 5. These are type constraints,
159and they are not used by Moose unless you tell it to. No type
160inference is performed, expression are not typed, etc. etc. etc.
161
162This is simply a means of creating small constraint functions which
a7d0cd00 163can be used to simplify your own type-checking code.
6ba6d68c 164
165=head2 Default Type Constraints
e522431d 166
e522431d 167This module also provides a simple hierarchy for Perl 5 types, this
168could probably use some work, but it works for me at the moment.
169
170 Any
171 Value
172 Int
173 Str
174 Ref
175 ScalarRef
176 ArrayRef
177 HashRef
178 CodeRef
179 RegexpRef
180 Object
02a0fb52 181 Role
e522431d 182
6ba6d68c 183Suggestions for improvement are welcome.
e522431d 184
a15dff8d 185=head1 FUNCTIONS
186
182134e8 187=head2 Type Constraint Registry
188
189=over 4
190
191=item B<find_type_constraint ($type_name)>
192
6ba6d68c 193This function can be used to locate a specific type constraint
194meta-object. What you do with it from there is up to you :)
182134e8 195
196=item B<export_type_contstraints_as_functions>
197
6ba6d68c 198This will export all the current type constraints as functions
199into the caller's namespace. Right now, this is mostly used for
200testing, but it might prove useful to others.
201
182134e8 202=back
203
a15dff8d 204=head2 Type Constraint Constructors
205
6ba6d68c 206The following functions are used to create type constraints.
207They will then register the type constraints in a global store
208where Moose can get to them if it needs to.
a15dff8d 209
6ba6d68c 210See the L<SYNOPOSIS> for an example of how to use these.
a15dff8d 211
6ba6d68c 212=over 4
a15dff8d 213
6ba6d68c 214=item B<type ($name, $where_clause)>
a15dff8d 215
6ba6d68c 216This creates a base type, which has no parent.
a15dff8d 217
79592a54 218=item B<subtype ($name, $parent, $where_clause, ?$message)>
182134e8 219
6ba6d68c 220This creates a named subtype.
d6e2d9a1 221
79592a54 222=item B<subtype ($parent, $where_clause, ?$message)>
182134e8 223
6ba6d68c 224This creates an unnamed subtype and will return the type
225constraint meta-object, which will be an instance of
226L<Moose::Meta::TypeConstraint>.
a15dff8d 227
6ba6d68c 228=item B<as>
a15dff8d 229
6ba6d68c 230This is just sugar for the type constraint construction syntax.
a15dff8d 231
6ba6d68c 232=item B<where>
a15dff8d 233
6ba6d68c 234This is just sugar for the type constraint construction syntax.
76d37e5a 235
236=item B<message>
237
238This is just sugar for the type constraint construction syntax.
a15dff8d 239
6ba6d68c 240=back
a15dff8d 241
6ba6d68c 242=head2 Type Coercion Constructors
a15dff8d 243
6ba6d68c 244Type constraints can also contain type coercions as well. In most
245cases Moose will run the type-coercion code first, followed by the
246type constraint check. This feature should be used carefully as it
247is very powerful and could easily take off a limb if you are not
248careful.
a15dff8d 249
6ba6d68c 250See the L<SYNOPOSIS> for an example of how to use these.
a15dff8d 251
6ba6d68c 252=over 4
a15dff8d 253
6ba6d68c 254=item B<coerce>
a15dff8d 255
6ba6d68c 256=item B<from>
a15dff8d 257
6ba6d68c 258This is just sugar for the type coercion construction syntax.
259
260=item B<via>
a15dff8d 261
6ba6d68c 262This is just sugar for the type coercion construction syntax.
a15dff8d 263
264=back
265
266=head1 BUGS
267
268All complex software has bugs lurking in it, and this module is no
269exception. If you find a bug please either email me, or add the bug
270to cpan-RT.
271
a15dff8d 272=head1 AUTHOR
273
274Stevan Little E<lt>stevan@iinteractive.comE<gt>
275
276=head1 COPYRIGHT AND LICENSE
277
278Copyright 2006 by Infinity Interactive, Inc.
279
280L<http://www.iinteractive.com>
281
282This library is free software; you can redistribute it and/or modify
283it under the same terms as Perl itself.
284
285=cut