type-coercion-meta-object
[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 Sub::Name 'subname';
9use Scalar::Util 'blessed';
10
5569c072 11our $VERSION = '0.02';
a15dff8d 12
4e036ee4 13use Moose::Meta::TypeConstraint;
2ca63f5d 14use Moose::Meta::TypeCoercion;
4e036ee4 15
a15dff8d 16sub import {
17 shift;
18 my $pkg = shift || caller();
19 return if $pkg eq ':no_export';
20 no strict 'refs';
d6e2d9a1 21 foreach my $export (qw(type subtype as where coerce from via)) {
a15dff8d 22 *{"${pkg}::${export}"} = \&{"${export}"};
a15dff8d 23 }
a15dff8d 24}
25
182134e8 26{
27 my %TYPES;
82168dbb 28 sub find_type_constraint { $TYPES{$_[0]} }
182134e8 29
82168dbb 30 sub create_type_constraint {
a27aa600 31 my ($name, $parent, $check) = @_;
32 (!exists $TYPES{$name})
33 || confess "The type constraint '$name' has already been created"
34 if defined $name;
66811d63 35 $parent = find_type_constraint($parent) if defined $parent;
a27aa600 36 my $constraint = Moose::Meta::TypeConstraint->new(
37 name => $name || '__ANON__',
66811d63 38 parent => $parent,
a27aa600 39 constraint => $check,
4e036ee4 40 );
a27aa600 41 $TYPES{$name} = $constraint if defined $name;
42 return $constraint;
182134e8 43 }
182134e8 44
a27aa600 45 sub install_type_coercions {
46 my ($type_name, $coercion_map) = @_;
47 my $type = find_type_constraint($type_name);
4e036ee4 48 (!$type->has_coercion)
d46a48f3 49 || confess "The type coercion for '$type_name' has already been registered";
a27aa600 50 my $type_coercion = Moose::Meta::TypeCoercion->new(
51 type_coercion_map => $coercion_map,
52 type_constraint => $type
53 );
54 $type->coercion($type_coercion);
182134e8 55 }
66811d63 56
57 sub export_type_contstraints_as_functions {
58 my $pkg = caller();
59 no strict 'refs';
60 foreach my $constraint (keys %TYPES) {
a27aa600 61 *{"${pkg}::${constraint}"} = $TYPES{$constraint}->_compiled_type_constraint;
66811d63 62 }
63 }
182134e8 64}
a15dff8d 65
a15dff8d 66
67sub type ($$) {
68 my ($name, $check) = @_;
82168dbb 69 create_type_constraint($name, undef, $check);
a15dff8d 70}
71
72sub subtype ($$;$) {
a27aa600 73 unshift @_ => undef if scalar @_ == 2;
74 create_type_constraint(@_);
a15dff8d 75}
76
4b598ea3 77sub coerce ($@) {
66811d63 78 my ($type_name, @coercion_map) = @_;
a27aa600 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
141This is B<NOT> a type system for Perl 5.
142
e522431d 143This module also provides a simple hierarchy for Perl 5 types, this
144could probably use some work, but it works for me at the moment.
145
146 Any
147 Value
148 Int
149 Str
150 Ref
151 ScalarRef
152 ArrayRef
153 HashRef
154 CodeRef
155 RegexpRef
156 Object
157
158Suggestions for improvement are welcome.
159
a15dff8d 160=head1 FUNCTIONS
161
182134e8 162=head2 Type Constraint Registry
163
164=over 4
165
166=item B<find_type_constraint ($type_name)>
167
82168dbb 168=item B<create_type_constraint ($type_name, $type_constraint)>
182134e8 169
a27aa600 170=item B<install_type_coercions>
182134e8 171
172=item B<export_type_contstraints_as_functions>
173
174=back
175
a15dff8d 176=head2 Type Constraint Constructors
177
178=over 4
179
180=item B<type>
181
182=item B<subtype>
183
184=item B<as>
185
186=item B<where>
187
182134e8 188=item B<coerce>
189
d6e2d9a1 190=item B<from>
191
192=item B<via>
182134e8 193
a15dff8d 194=back
195
196=head2 Built-in Type Constraints
197
198=over 4
199
200=item B<Any>
201
202=item B<Value>
203
204=item B<Int>
205
206=item B<Str>
207
208=item B<Ref>
209
210=item B<ArrayRef>
211
212=item B<CodeRef>
213
214=item B<HashRef>
215
216=item B<RegexpRef>
217
218=item B<ScalarRef>
219
220=item B<Object>
221
222=back
223
224=head1 BUGS
225
226All complex software has bugs lurking in it, and this module is no
227exception. If you find a bug please either email me, or add the bug
228to cpan-RT.
229
a15dff8d 230=head1 AUTHOR
231
232Stevan Little E<lt>stevan@iinteractive.comE<gt>
233
234=head1 COPYRIGHT AND LICENSE
235
236Copyright 2006 by Infinity Interactive, Inc.
237
238L<http://www.iinteractive.com>
239
240This library is free software; you can redistribute it and/or modify
241it under the same terms as Perl itself.
242
243=cut