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