sorry konobi, not enough of a perf win, so lets wait till we get something more befor...
[gitmo/Moose.git] / lib / Moose / Util / TypeConstraints.pm
1
2 package Moose::Util::TypeConstraints;
3
4 use strict;
5 use warnings;
6
7 use Carp         'confess';
8 use Scalar::Util 'blessed', 'reftype';
9 use Sub::Exporter;
10
11 our $VERSION   = '0.21';
12 our $AUTHORITY = 'cpan:STEVAN';
13
14 ## --------------------------------------------------------
15 # Prototyped subs must be predeclared because we have a
16 # circular dependency with Moose::Meta::Attribute et. al.
17 # so in case of us being use'd first the predeclaration
18 # ensures the prototypes are in scope when consumers are
19 # compiled.
20
21 # creation and location
22 sub find_type_constraint                 ($);
23 sub register_type_constraint             ($);
24 sub find_or_create_type_constraint       ($;$);
25 sub create_type_constraint_union         (@);
26 sub create_parameterized_type_constraint ($);
27 sub create_class_type_constraint         ($);
28
29 # dah sugah!
30 sub type        ($$;$$);
31 sub subtype     ($$;$$$);
32 sub class_type  ($);
33 sub coerce      ($@);
34 sub as          ($);
35 sub from        ($);
36 sub where       (&);
37 sub via         (&);
38 sub message     (&);
39 sub optimize_as (&);
40 sub enum        ($;@);
41
42 ## private stuff ...
43 sub _create_type_constraint ($$$;$$);
44 sub _install_type_coercions ($$);
45
46 ## --------------------------------------------------------
47
48 use Moose::Meta::TypeConstraint;
49 use Moose::Meta::TypeConstraint::Union;
50 use Moose::Meta::TypeConstraint::Parameterized;
51 use Moose::Meta::TypeConstraint::Parameterizable;
52 use Moose::Meta::TypeCoercion;
53 use Moose::Meta::TypeCoercion::Union;
54 use Moose::Meta::TypeConstraint::Registry;
55 use Moose::Util::TypeConstraints::OptimizedConstraints;
56
57 my @exports = qw/
58     type subtype class_type as where message optimize_as
59     coerce from via
60     enum
61     find_type_constraint
62     register_type_constraint
63 /;
64
65 Sub::Exporter::setup_exporter({
66     exports => \@exports,
67     groups  => { default => [':all'] }
68 });
69
70 sub unimport {
71     no strict 'refs';
72     my $class = caller();
73     # loop through the exports ...
74     foreach my $name (@exports) {
75         # if we find one ...
76         if (defined &{$class . '::' . $name}) {
77             my $keyword = \&{$class . '::' . $name};
78
79             # make sure it is from Moose
80             my ($pkg_name) = Class::MOP::get_code_info($keyword);
81             next if $@;
82             next if $pkg_name ne 'Moose::Util::TypeConstraints';
83
84             # and if it is from Moose then undef the slot
85             delete ${$class . '::'}{$name};
86         }
87     }
88 }
89
90 ## --------------------------------------------------------
91 ## type registry and some useful functions for it
92 ## --------------------------------------------------------
93
94 my $REGISTRY = Moose::Meta::TypeConstraint::Registry->new;
95
96 sub get_type_constraint_registry         { $REGISTRY }
97 sub list_all_type_constraints            { keys %{$REGISTRY->type_constraints} }
98 sub export_type_constraints_as_functions {
99     my $pkg = caller();
100     no strict 'refs';
101     foreach my $constraint (keys %{$REGISTRY->type_constraints}) {
102         my $tc = $REGISTRY->get_type_constraint($constraint)->_compiled_type_constraint;
103         *{"${pkg}::${constraint}"} = sub { $tc->($_[0]) ? 1 : undef };
104     }
105 }
106
107 sub create_type_constraint_union (@) {
108     my @type_constraint_names;
109
110     if (scalar @_ == 1 && _detect_type_constraint_union($_[0])) {
111         @type_constraint_names = _parse_type_constraint_union($_[0]);
112     }
113     else {
114         @type_constraint_names = @_;
115     }
116
117     (scalar @type_constraint_names >= 2)
118         || confess "You must pass in at least 2 type names to make a union";
119
120     ($REGISTRY->has_type_constraint($_))
121         || confess "Could not locate type constraint ($_) for the union"
122             foreach @type_constraint_names;
123
124     return Moose::Meta::TypeConstraint::Union->new(
125         type_constraints => [
126             map {
127                 $REGISTRY->get_type_constraint($_)
128             } @type_constraint_names
129         ],
130     );
131 }
132
133 sub create_parameterized_type_constraint ($) {
134     my $type_constraint_name = shift;
135
136     my ($base_type, $type_parameter) = _parse_parameterized_type_constraint($type_constraint_name);
137
138     (defined $base_type && defined $type_parameter)
139         || confess "Could not parse type name ($type_constraint_name) correctly";
140
141     ($REGISTRY->has_type_constraint($base_type))
142         || confess "Could not locate the base type ($base_type)";
143
144     return Moose::Meta::TypeConstraint::Parameterized->new(
145         name           => $type_constraint_name,
146         parent         => $REGISTRY->get_type_constraint($base_type),
147         type_parameter => find_or_create_type_constraint(
148             $type_parameter => {
149                 parent     => $REGISTRY->get_type_constraint('Object'),
150                 constraint => sub { $_[0]->isa($type_parameter) }
151             }
152         ),
153     );
154 }
155
156 sub create_class_type_constraint ($) {
157     my $class = shift;
158
159     # too early for this check
160     #find_type_constraint("ClassName")->check($class)
161     #    || confess "Can't create a class type constraint because '$class' is not a class name";
162
163     Moose::Meta::TypeConstraint::Class->new( name => $class );
164 }
165
166 sub find_or_create_type_constraint ($;$) {
167     my ($type_constraint_name, $options_for_anon_type) = @_;
168
169     return $REGISTRY->get_type_constraint($type_constraint_name)
170         if $REGISTRY->has_type_constraint($type_constraint_name);
171
172     my $constraint;
173
174     if (_detect_type_constraint_union($type_constraint_name)) {
175         $constraint = create_type_constraint_union($type_constraint_name);
176     }
177     elsif (_detect_parameterized_type_constraint($type_constraint_name)) {
178         $constraint = create_parameterized_type_constraint($type_constraint_name);
179     }
180     else {
181         # NOTE:
182         # if there is no $options_for_anon_type 
183         # specified, then we assume they don't 
184         # want to create one, and return nothing.
185         return unless defined $options_for_anon_type;        
186
187         # NOTE:
188         # otherwise assume that we should create
189         # an ANON type with the $options_for_anon_type
190         # options which can be passed in. It should
191         # be noted that these don't get registered
192         # so we need to return it.
193         # - SL
194         return Moose::Meta::TypeConstraint->new(
195             name => '__ANON__',
196             %{$options_for_anon_type}
197         );
198     }
199
200     $REGISTRY->add_type_constraint($constraint);
201     return $constraint;
202 }
203
204 ## --------------------------------------------------------
205 ## exported functions ...
206 ## --------------------------------------------------------
207
208 sub find_type_constraint ($) { $REGISTRY->get_type_constraint(@_) }
209
210 sub register_type_constraint ($) {
211     my $constraint = shift;
212     confess "can't register an unnamed type constraint" unless defined $constraint->name;
213     $REGISTRY->add_type_constraint($constraint);
214 }
215
216 # type constructors
217
218 sub type ($$;$$) {
219     splice(@_, 1, 0, undef);
220     goto &_create_type_constraint;
221 }
222
223 sub subtype ($$;$$$) {
224     # NOTE:
225     # this adds an undef for the name
226     # if this is an anon-subtype:
227     #   subtype(Num => where { $_ % 2 == 0 }) # anon 'even' subtype
228     # but if the last arg is not a code
229     # ref then it is a subtype alias:
230     #   subtype(MyNumbers => as Num); # now MyNumbers is the same as Num
231     # ... yeah I know it's ugly code
232     # - SL
233     unshift @_ => undef if scalar @_ <= 2 && (reftype($_[1]) || '') eq 'CODE';
234     goto &_create_type_constraint;
235 }
236
237 sub class_type ($) {
238     register_type_constraint( create_class_type_constraint(shift) );
239 }
240
241 sub coerce ($@) {
242     my ($type_name, @coercion_map) = @_;
243     _install_type_coercions($type_name, \@coercion_map);
244 }
245
246 sub as      ($) { $_[0] }
247 sub from    ($) { $_[0] }
248 sub where   (&) { $_[0] }
249 sub via     (&) { $_[0] }
250
251 sub message     (&) { +{ message   => $_[0] } }
252 sub optimize_as (&) { +{ optimized => $_[0] } }
253
254 sub enum ($;@) {
255     my ($type_name, @values) = @_;
256     (scalar @values >= 2)
257         || confess "You must have at least two values to enumerate through";
258     my %valid = map { $_ => 1 } @values;
259     _create_type_constraint(
260         $type_name,
261         'Str',
262         sub { $valid{$_} }
263     );
264 }
265
266 ## --------------------------------------------------------
267 ## desugaring functions ...
268 ## --------------------------------------------------------
269
270 sub _create_type_constraint ($$$;$$) {
271     my $name   = shift;
272     my $parent = shift;
273     my $check  = shift;
274
275     my ($message, $optimized);
276     for (@_) {
277         $message   = $_->{message}   if exists $_->{message};
278         $optimized = $_->{optimized} if exists $_->{optimized};
279     }
280
281     my $pkg_defined_in = scalar(caller(0));
282
283     if (defined $name) {
284         my $type = $REGISTRY->get_type_constraint($name);
285
286         ($type->_package_defined_in eq $pkg_defined_in)
287             || confess ("The type constraint '$name' has already been created in "
288                        . $type->_package_defined_in . " and cannot be created again in "
289                        . $pkg_defined_in)
290                  if defined $type;
291     }
292
293     $parent = find_or_create_type_constraint($parent) if defined $parent;
294     
295     my $constraint = Moose::Meta::TypeConstraint->new(
296         name               => $name || '__ANON__',
297         package_defined_in => $pkg_defined_in,
298
299         ($parent    ? (parent     => $parent )   : ()),
300         ($check     ? (constraint => $check)     : ()),
301         ($message   ? (message    => $message)   : ()),
302         ($optimized ? (optimized  => $optimized) : ()),
303     );
304     
305     # NOTE:
306     # if we have a type constraint union, and no 
307     # type check, this means we are just aliasing
308     # the union constraint, which means we need to 
309     # handle this differently.
310     # - SL
311     if (not(defined $check) 
312         && $parent->isa('Moose::Meta::TypeConstraint::Union') 
313         && $parent->has_coercion 
314         ){
315         $constraint->coercion(Moose::Meta::TypeCoercion::Union->new(
316             type_constraint => $parent
317         ));
318     }    
319
320     $REGISTRY->add_type_constraint($constraint)
321         if defined $name;
322
323     return $constraint;
324 }
325
326 sub _install_type_coercions ($$) {
327     my ($type_name, $coercion_map) = @_;
328     my $type = $REGISTRY->get_type_constraint($type_name);
329     (defined $type)
330         || confess "Cannot find type '$type_name', perhaps you forgot to load it.";
331     if ($type->has_coercion) {
332         $type->coercion->add_type_coercions(@$coercion_map);
333     }
334     else {
335         my $type_coercion = Moose::Meta::TypeCoercion->new(
336             type_coercion_map => $coercion_map,
337             type_constraint   => $type
338         );
339         $type->coercion($type_coercion);
340     }
341 }
342
343 ## --------------------------------------------------------
344 ## type notation parsing ...
345 ## --------------------------------------------------------
346
347 {
348     # All I have to say is mugwump++ cause I know
349     # do not even have enough regexp-fu to be able
350     # to have written this (I can only barely
351     # understand it as it is)
352     # - SL
353
354     use re "eval";
355
356     my $valid_chars = qr{[\w:]};
357     my $type_atom   = qr{ $valid_chars+ };
358
359     my $type                = qr{  $valid_chars+  (?: \[  (??{$any})  \] )? }x;
360     my $type_capture_parts  = qr{ ($valid_chars+) (?: \[ ((??{$any})) \] )? }x;
361     my $type_with_parameter = qr{  $valid_chars+      \[  (??{$any})  \]    }x;
362
363     my $op_union = qr{ \s* \| \s* }x;
364     my $union    = qr{ $type (?: $op_union $type )+ }x;
365
366     our $any = qr{ $type | $union }x;
367
368     sub _parse_parameterized_type_constraint {
369         $_[0] =~ m{ $type_capture_parts }x;
370         return ($1, $2);
371     }
372
373     sub _detect_parameterized_type_constraint {
374         $_[0] =~ m{ ^ $type_with_parameter $ }x;
375     }
376
377     sub _parse_type_constraint_union {
378         my $given = shift;
379         my @rv;
380         while ( $given =~ m{ \G (?: $op_union )? ($type) }gcx ) {
381                 push @rv => $1;
382         }
383         (pos($given) eq length($given))
384             || confess "'$given' didn't parse (parse-pos="
385                      . pos($given)
386                      . " and str-length="
387                      . length($given)
388                      . ")";
389         @rv;
390     }
391
392     sub _detect_type_constraint_union {
393         $_[0] =~ m{^ $type $op_union $type ( $op_union .* )? $}x;
394     }
395 }
396
397 ## --------------------------------------------------------
398 # define some basic built-in types
399 ## --------------------------------------------------------
400
401 type 'Any'  => where { 1 }; # meta-type including all
402 type 'Item' => where { 1 }; # base-type
403
404 subtype 'Undef'   => as 'Item' => where { !defined($_) };
405 subtype 'Defined' => as 'Item' => where {  defined($_) };
406
407 subtype 'Bool'
408     => as 'Item'
409     => where { !defined($_) || $_ eq "" || "$_" eq '1' || "$_" eq '0' };
410
411 subtype 'Value'
412     => as 'Defined'
413     => where { !ref($_) }
414     => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Value;
415
416 subtype 'Ref'
417     => as 'Defined'
418     => where {  ref($_) }
419     => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Ref;
420
421 subtype 'Str'
422     => as 'Value'
423     => where { 1 }
424     => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Str;
425
426 subtype 'Num'
427     => as 'Value'
428     => where { Scalar::Util::looks_like_number($_) }
429     => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Num;
430
431 subtype 'Int'
432     => as 'Num'
433     => where { "$_" =~ /^-?[0-9]+$/ }
434     => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Int;
435
436 subtype 'ScalarRef' => as 'Ref' => where { ref($_) eq 'SCALAR' } => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::ScalarRef;
437 subtype 'CodeRef'   => as 'Ref' => where { ref($_) eq 'CODE'   } => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::CodeRef;
438 subtype 'RegexpRef' => as 'Ref' => where { ref($_) eq 'Regexp' } => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::RegexpRef;
439 subtype 'GlobRef'   => as 'Ref' => where { ref($_) eq 'GLOB'   } => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::GlobRef;
440
441 # NOTE:
442 # scalar filehandles are GLOB refs,
443 # but a GLOB ref is not always a filehandle
444 subtype 'FileHandle'
445     => as 'GlobRef'
446     => where { Scalar::Util::openhandle($_) || ( blessed($_) && $_->isa("IO::Handle") ) }
447     => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::FileHandle;
448
449 # NOTE:
450 # blessed(qr/.../) returns true,.. how odd
451 subtype 'Object'
452     => as 'Ref'
453     => where { blessed($_) && blessed($_) ne 'Regexp' }
454     => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Object;
455
456 subtype 'Role'
457     => as 'Object'
458     => where { $_->can('does') }
459     => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Role;
460
461 my $_class_name_checker = sub {
462     return if ref($_[0]);
463     return unless defined($_[0]) && length($_[0]);
464
465     # walk the symbol table tree to avoid autovififying
466     # \*{${main::}{"Foo::"}} == \*main::Foo::
467
468     my $pack = \*::;
469     foreach my $part (split('::', $_[0])) {
470         return unless exists ${$$pack}{"${part}::"};
471         $pack = \*{${$$pack}{"${part}::"}};
472     }
473
474     # check for $VERSION or @ISA
475     return 1 if exists ${$$pack}{VERSION}
476              && defined *{${$$pack}{VERSION}}{SCALAR};
477     return 1 if exists ${$$pack}{ISA}
478              && defined *{${$$pack}{ISA}}{ARRAY};
479
480     # check for any method
481     foreach ( keys %{$$pack} ) {
482         next if substr($_, -2, 2) eq '::';
483         return 1 if defined *{${$$pack}{$_}}{CODE};
484     }
485
486     # fail
487     return;
488 };
489
490 subtype 'ClassName'
491     => as 'Str'
492     => $_class_name_checker # where ...
493     => { optimize => $_class_name_checker };
494
495 ## --------------------------------------------------------
496 # parameterizable types ...
497
498 $REGISTRY->add_type_constraint(
499     Moose::Meta::TypeConstraint::Parameterizable->new(
500         name                 => 'ArrayRef',
501         package_defined_in   => __PACKAGE__,
502         parent               => find_type_constraint('Ref'),
503         constraint           => sub { ref($_) eq 'ARRAY'  },
504         optimized            => \&Moose::Util::TypeConstraints::OptimizedConstraints::ArrayRef,
505         constraint_generator => sub {
506             my $type_parameter = shift;
507             return sub {
508                 foreach my $x (@$_) {
509                     ($type_parameter->check($x)) || return
510                 } 1;
511             }
512         }
513     )
514 );
515
516 $REGISTRY->add_type_constraint(
517     Moose::Meta::TypeConstraint::Parameterizable->new(
518         name                 => 'HashRef',
519         package_defined_in   => __PACKAGE__,
520         parent               => find_type_constraint('Ref'),
521         constraint           => sub { ref($_) eq 'HASH'  },
522         optimized            => \&Moose::Util::TypeConstraints::OptimizedConstraints::HashRef,
523         constraint_generator => sub {
524             my $type_parameter = shift;            
525             return sub {
526                 foreach my $x (values %$_) {
527                     ($type_parameter->check($x)) || return
528                 } 1;
529             }
530         }
531     )
532 );
533
534 $REGISTRY->add_type_constraint(
535     Moose::Meta::TypeConstraint::Parameterizable->new(
536         name                 => 'Maybe',
537         package_defined_in   => __PACKAGE__,
538         parent               => find_type_constraint('Item'),
539         constraint           => sub { 1 },
540         constraint_generator => sub {
541             my $type_parameter = shift;            
542             return sub {
543                 return 1 if not(defined($_)) || $type_parameter->check($_);
544                 return;
545             }
546         }
547     )
548 );
549
550 my @PARAMETERIZABLE_TYPES = map { 
551     $REGISTRY->get_type_constraint($_) 
552 } qw[ArrayRef HashRef Maybe];
553
554 sub get_all_parameterizable_types { @PARAMETERIZABLE_TYPES }
555 sub add_parameterizable_type { 
556     my $type = shift;
557     (blessed $type && $type->isa('Moose::Meta::TypeConstraint::Parameterizable'))
558         || confess "Type must be a Moose::Meta::TypeConstraint::Parameterizable not $type";
559     push @PARAMETERIZABLE_TYPES => $type;
560 }    
561
562 ## --------------------------------------------------------
563 # end of built-in types ...
564 ## --------------------------------------------------------
565
566 {
567     my @BUILTINS = list_all_type_constraints();
568     sub list_all_builtin_type_constraints { @BUILTINS }
569 }
570
571 1;
572
573 __END__
574
575 =pod
576
577 =head1 NAME
578
579 Moose::Util::TypeConstraints - Type constraint system for Moose
580
581 =head1 SYNOPSIS
582
583   use Moose::Util::TypeConstraints;
584
585   type 'Num' => where { Scalar::Util::looks_like_number($_) };
586
587   subtype 'Natural'
588       => as 'Num'
589       => where { $_ > 0 };
590
591   subtype 'NaturalLessThanTen'
592       => as 'Natural'
593       => where { $_ < 10 }
594       => message { "This number ($_) is not less than ten!" };
595
596   coerce 'Num'
597       => from 'Str'
598         => via { 0+$_ };
599
600   enum 'RGBColors' => qw(red green blue);
601
602 =head1 DESCRIPTION
603
604 This module provides Moose with the ability to create custom type
605 contraints to be used in attribute definition.
606
607 =head2 Important Caveat
608
609 This is B<NOT> a type system for Perl 5. These are type constraints,
610 and they are not used by Moose unless you tell it to. No type
611 inference is performed, expression are not typed, etc. etc. etc.
612
613 This is simply a means of creating small constraint functions which
614 can be used to simplify your own type-checking code.
615
616 =head2 Slightly Less Important Caveat
617
618 It is almost always a good idea to quote your type and subtype names.
619 This is to prevent perl from trying to execute the call as an indirect
620 object call. This issue only seems to come up when you have a subtype
621 the same name as a valid class, but when the issue does arise it tends
622 to be quite annoying to debug.
623
624 So for instance, this:
625
626   subtype DateTime => as Object => where { $_->isa('DateTime') };
627
628 will I<Just Work>, while this:
629
630   use DateTime;
631   subtype DateTime => as Object => where { $_->isa('DateTime') };
632
633 will fail silently and cause many headaches. The simple way to solve
634 this, as well as future proof your subtypes from classes which have
635 yet to have been created yet, is to simply do this:
636
637   use DateTime;
638   subtype 'DateTime' => as 'Object' => where { $_->isa('DateTime') };
639
640 =head2 Default Type Constraints
641
642 This module also provides a simple hierarchy for Perl 5 types, this
643 could probably use some work, but it works for me at the moment.
644
645   Any
646   Item
647       Bool
648       Maybe[`a]
649       Undef
650       Defined
651           Value
652               Num
653                 Int
654               Str
655                 ClassName
656           Ref
657               ScalarRef
658               ArrayRef[`a]
659               HashRef[`a]
660               CodeRef
661               RegexpRef
662               GlobRef
663                 FileHandle
664               Object
665                   Role
666
667 Suggestions for improvement are welcome.
668
669 B<NOTE:> Any type followed by a type parameter C<[`a]> can be 
670 parameterized, this means you can say:
671
672   ArrayRef[Int]    # an array of intergers
673   HashRef[CodeRef] # a hash of str to CODE ref mappings
674   Maybe[Str]       # value may be a string, may be undefined
675
676 B<NOTE:> The C<Undef> type constraint for the most part works 
677 correctly now, but edge cases may still exist, please use it 
678 sparringly.
679
680 B<NOTE:> The C<ClassName> type constraint does a complex package
681 existence check. This means that your class B<must> be loaded for 
682 this type constraint to pass. I know this is not ideal for all, 
683 but it is a saner restriction than most others.
684
685 =head2 Use with Other Constraint Modules
686
687 This module should play fairly nicely with other constraint
688 modules with only some slight tweaking. The C<where> clause
689 in types is expected to be a C<CODE> reference which checks
690 it's first argument and returns a bool. Since most constraint
691 modules work in a similar way, it should be simple to adapt
692 them to work with Moose.
693
694 For instance, this is how you could use it with
695 L<Declare::Constraints::Simple> to declare a completely new type.
696
697   type 'HashOfArrayOfObjects'
698       => IsHashRef(
699           -keys   => HasLength,
700           -values => IsArrayRef( IsObject ));
701
702 For more examples see the F<t/204_example_w_DCS.t> test file.
703
704 Here is an example of using L<Test::Deep> and it's non-test
705 related C<eq_deeply> function.
706
707   type 'ArrayOfHashOfBarsAndRandomNumbers'
708       => where {
709           eq_deeply($_,
710               array_each(subhashof({
711                   bar           => isa('Bar'),
712                   random_number => ignore()
713               })))
714         };
715
716 For a complete example see the F<t/205_example_w_TestDeep.t>
717 test file.
718
719 =head1 FUNCTIONS
720
721 =head2 Type Constraint Construction & Locating
722
723 =over 4
724
725 =item B<create_type_constraint_union ($pipe_seperated_types | @type_constraint_names)>
726
727 Given string with C<$pipe_seperated_types> or a list of C<@type_constraint_names>,
728 this will return a L<Moose::Meta::TypeConstraint::Union> instance.
729
730 =item B<create_parameterized_type_constraint ($type_name)>
731
732 Given a C<$type_name> in the form of:
733
734   BaseType[ContainerType]
735
736 this will extract the base type and container type and build an instance of
737 L<Moose::Meta::TypeConstraint::Parameterized> for it. 
738
739 =item B<create_class_type_constraint ($class)>
740
741 Given a class name it will create a new L<Moose::Meta::TypeConstraint::Class>
742 object for that class name.
743
744 =item B<find_or_create_type_constraint ($type_name, ?$options_for_anon_type)>
745
746 This will attempt to find or create a type constraint given the a C<$type_name>.
747 If it cannot find it in the registry, it will see if it should be a union or
748 container type an create one if appropriate, and lastly if nothing can be
749 found or created that way, it will create an anon-type using the
750 C<$options_for_anon_type> HASH ref to populate it. If the C<$options_for_anon_type>
751 is not specified (it is C<undef>), then it will not create anything and simply
752 return.
753
754 =item B<find_type_constraint ($type_name)>
755
756 This function can be used to locate a specific type constraint
757 meta-object, of the class L<Moose::Meta::TypeConstraint> or a
758 derivative. What you do with it from there is up to you :)
759
760 =item B<register_type_constraint ($type_object)>
761
762 This function will register a named type constraint with the type registry.
763
764 =item B<get_type_constraint_registry>
765
766 Fetch the L<Moose::Meta::TypeConstraint::Registry> object which
767 keeps track of all type constraints.
768
769 =item B<list_all_type_constraints>
770
771 This will return a list of type constraint names, you can then
772 fetch them using C<find_type_constraint ($type_name)> if you
773 want to.
774
775 =item B<list_all_builtin_type_constraints>
776
777 This will return a list of builtin type constraints, meaning,
778 those which are defined in this module. See the section
779 labeled L<Default Type Constraints> for a complete list.
780
781 =item B<export_type_constraints_as_functions>
782
783 This will export all the current type constraints as functions
784 into the caller's namespace. Right now, this is mostly used for
785 testing, but it might prove useful to others.
786
787 =item B<get_all_parameterizable_types>
788
789 This returns all the parameterizable types that have been registered.
790
791 =item B<add_parameterizable_type ($type)>
792
793 Adds C<$type> to the list of parameterizable types
794
795 =back
796
797 =head2 Type Constraint Constructors
798
799 The following functions are used to create type constraints.
800 They will then register the type constraints in a global store
801 where Moose can get to them if it needs to.
802
803 See the L<SYNOPSIS> for an example of how to use these.
804
805 =over 4
806
807 =item B<type ($name, $where_clause)>
808
809 This creates a base type, which has no parent.
810
811 =item B<subtype ($name, $parent, $where_clause, ?$message)>
812
813 This creates a named subtype.
814
815 =item B<subtype ($parent, $where_clause, ?$message)>
816
817 This creates an unnamed subtype and will return the type
818 constraint meta-object, which will be an instance of
819 L<Moose::Meta::TypeConstraint>.
820
821 =item B<class_type ($class)>
822
823 Creates a type constraint with the name C<$class> and the metaclass
824 L<Moose::Meta::TypeConstraint::Class>.
825
826 =item B<enum ($name, @values)>
827
828 This will create a basic subtype for a given set of strings.
829 The resulting constraint will be a subtype of C<Str> and
830 will match any of the items in C<@values>. It is case sensitive.
831 See the L<SYNOPSIS> for a simple example.
832
833 B<NOTE:> This is not a true proper enum type, it is simple
834 a convient constraint builder.
835
836 =item B<as>
837
838 This is just sugar for the type constraint construction syntax.
839
840 =item B<where>
841
842 This is just sugar for the type constraint construction syntax.
843
844 =item B<message>
845
846 This is just sugar for the type constraint construction syntax.
847
848 =item B<optimize_as>
849
850 This can be used to define a "hand optimized" version of your
851 type constraint which can be used to avoid traversing a subtype
852 constraint heirarchy.
853
854 B<NOTE:> You should only use this if you know what you are doing,
855 all the built in types use this, so your subtypes (assuming they
856 are shallow) will not likely need to use this.
857
858 =back
859
860 =head2 Type Coercion Constructors
861
862 Type constraints can also contain type coercions as well. If you
863 ask your accessor to coerce, then Moose will run the type-coercion
864 code first, followed by the type constraint check. This feature
865 should be used carefully as it is very powerful and could easily
866 take off a limb if you are not careful.
867
868 See the L<SYNOPSIS> for an example of how to use these.
869
870 =over 4
871
872 =item B<coerce>
873
874 =item B<from>
875
876 This is just sugar for the type coercion construction syntax.
877
878 =item B<via>
879
880 This is just sugar for the type coercion construction syntax.
881
882 =back
883
884 =head2 Namespace Management
885
886 =over 4
887
888 =item B<unimport>
889
890 This will remove all the type constraint keywords from the
891 calling class namespace.
892
893 =back
894
895 =head1 BUGS
896
897 All complex software has bugs lurking in it, and this module is no
898 exception. If you find a bug please either email me, or add the bug
899 to cpan-RT.
900
901 =head1 AUTHOR
902
903 Stevan Little E<lt>stevan@iinteractive.comE<gt>
904
905 =head1 COPYRIGHT AND LICENSE
906
907 Copyright 2006-2008 by Infinity Interactive, Inc.
908
909 L<http://www.iinteractive.com>
910
911 This library is free software; you can redistribute it and/or modify
912 it under the same terms as Perl itself.
913
914 =cut