18a0f43b219752beaffb7906ab2e7d1a9d60f2f5
[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'   
405     => as 'Item' 
406     => where { !defined($_) }
407     => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Undef;
408
409 subtype 'Defined' 
410     => as 'Item' 
411     => where {  defined($_) }
412     => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Defined;
413
414 subtype 'Bool'
415     => as 'Item'
416     => where { !defined($_) || $_ eq "" || "$_" eq '1' || "$_" eq '0' };
417
418 subtype 'Value'
419     => as 'Defined'
420     => where { !ref($_) }
421     => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Value;
422
423 subtype 'Ref'
424     => as 'Defined'
425     => where {  ref($_) }
426     => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Ref;
427
428 subtype 'Str'
429     => as 'Value'
430     => where { 1 }
431     => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Str;
432
433 subtype 'Num'
434     => as 'Value'
435     => where { Scalar::Util::looks_like_number($_) }
436     => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Num;
437
438 subtype 'Int'
439     => as 'Num'
440     => where { "$_" =~ /^-?[0-9]+$/ }
441     => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Int;
442
443 subtype 'ScalarRef' => as 'Ref' => where { ref($_) eq 'SCALAR' } => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::ScalarRef;
444 subtype 'CodeRef'   => as 'Ref' => where { ref($_) eq 'CODE'   } => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::CodeRef;
445 subtype 'RegexpRef' => as 'Ref' => where { ref($_) eq 'Regexp' } => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::RegexpRef;
446 subtype 'GlobRef'   => as 'Ref' => where { ref($_) eq 'GLOB'   } => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::GlobRef;
447
448 # NOTE:
449 # scalar filehandles are GLOB refs,
450 # but a GLOB ref is not always a filehandle
451 subtype 'FileHandle'
452     => as 'GlobRef'
453     => where { Scalar::Util::openhandle($_) || ( blessed($_) && $_->isa("IO::Handle") ) }
454     => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::FileHandle;
455
456 # NOTE:
457 # blessed(qr/.../) returns true,.. how odd
458 subtype 'Object'
459     => as 'Ref'
460     => where { blessed($_) && blessed($_) ne 'Regexp' }
461     => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Object;
462
463 subtype 'Role'
464     => as 'Object'
465     => where { $_->can('does') }
466     => optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Role;
467
468 my $_class_name_checker = sub {
469     return if ref($_[0]);
470     return unless defined($_[0]) && length($_[0]);
471
472     # walk the symbol table tree to avoid autovififying
473     # \*{${main::}{"Foo::"}} == \*main::Foo::
474
475     my $pack = \*::;
476     foreach my $part (split('::', $_[0])) {
477         return unless exists ${$$pack}{"${part}::"};
478         $pack = \*{${$$pack}{"${part}::"}};
479     }
480
481     # check for $VERSION or @ISA
482     return 1 if exists ${$$pack}{VERSION}
483              && defined *{${$$pack}{VERSION}}{SCALAR};
484     return 1 if exists ${$$pack}{ISA}
485              && defined *{${$$pack}{ISA}}{ARRAY};
486
487     # check for any method
488     foreach ( keys %{$$pack} ) {
489         next if substr($_, -2, 2) eq '::';
490         return 1 if defined *{${$$pack}{$_}}{CODE};
491     }
492
493     # fail
494     return;
495 };
496
497 subtype 'ClassName'
498     => as 'Str'
499     => $_class_name_checker # where ...
500     => { optimize => $_class_name_checker };
501
502 ## --------------------------------------------------------
503 # parameterizable types ...
504
505 $REGISTRY->add_type_constraint(
506     Moose::Meta::TypeConstraint::Parameterizable->new(
507         name                 => 'ArrayRef',
508         package_defined_in   => __PACKAGE__,
509         parent               => find_type_constraint('Ref'),
510         constraint           => sub { ref($_) eq 'ARRAY'  },
511         optimized            => \&Moose::Util::TypeConstraints::OptimizedConstraints::ArrayRef,
512         constraint_generator => sub {
513             my $type_parameter = shift;
514             return sub {
515                 foreach my $x (@$_) {
516                     ($type_parameter->check($x)) || return
517                 } 1;
518             }
519         }
520     )
521 );
522
523 $REGISTRY->add_type_constraint(
524     Moose::Meta::TypeConstraint::Parameterizable->new(
525         name                 => 'HashRef',
526         package_defined_in   => __PACKAGE__,
527         parent               => find_type_constraint('Ref'),
528         constraint           => sub { ref($_) eq 'HASH'  },
529         optimized            => \&Moose::Util::TypeConstraints::OptimizedConstraints::HashRef,
530         constraint_generator => sub {
531             my $type_parameter = shift;            
532             return sub {
533                 foreach my $x (values %$_) {
534                     ($type_parameter->check($x)) || return
535                 } 1;
536             }
537         }
538     )
539 );
540
541 $REGISTRY->add_type_constraint(
542     Moose::Meta::TypeConstraint::Parameterizable->new(
543         name                 => 'Maybe',
544         package_defined_in   => __PACKAGE__,
545         parent               => find_type_constraint('Item'),
546         constraint           => sub { 1 },
547         constraint_generator => sub {
548             my $type_parameter = shift;            
549             return sub {
550                 return 1 if not(defined($_)) || $type_parameter->check($_);
551                 return;
552             }
553         }
554     )
555 );
556
557 my @PARAMETERIZABLE_TYPES = map { 
558     $REGISTRY->get_type_constraint($_) 
559 } qw[ArrayRef HashRef Maybe];
560
561 sub get_all_parameterizable_types { @PARAMETERIZABLE_TYPES }
562 sub add_parameterizable_type { 
563     my $type = shift;
564     (blessed $type && $type->isa('Moose::Meta::TypeConstraint::Parameterizable'))
565         || confess "Type must be a Moose::Meta::TypeConstraint::Parameterizable not $type";
566     push @PARAMETERIZABLE_TYPES => $type;
567 }    
568
569 ## --------------------------------------------------------
570 # end of built-in types ...
571 ## --------------------------------------------------------
572
573 {
574     my @BUILTINS = list_all_type_constraints();
575     sub list_all_builtin_type_constraints { @BUILTINS }
576 }
577
578 1;
579
580 __END__
581
582 =pod
583
584 =head1 NAME
585
586 Moose::Util::TypeConstraints - Type constraint system for Moose
587
588 =head1 SYNOPSIS
589
590   use Moose::Util::TypeConstraints;
591
592   type 'Num' => where { Scalar::Util::looks_like_number($_) };
593
594   subtype 'Natural'
595       => as 'Num'
596       => where { $_ > 0 };
597
598   subtype 'NaturalLessThanTen'
599       => as 'Natural'
600       => where { $_ < 10 }
601       => message { "This number ($_) is not less than ten!" };
602
603   coerce 'Num'
604       => from 'Str'
605         => via { 0+$_ };
606
607   enum 'RGBColors' => qw(red green blue);
608
609 =head1 DESCRIPTION
610
611 This module provides Moose with the ability to create custom type
612 contraints to be used in attribute definition.
613
614 =head2 Important Caveat
615
616 This is B<NOT> a type system for Perl 5. These are type constraints,
617 and they are not used by Moose unless you tell it to. No type
618 inference is performed, expression are not typed, etc. etc. etc.
619
620 This is simply a means of creating small constraint functions which
621 can be used to simplify your own type-checking code.
622
623 =head2 Slightly Less Important Caveat
624
625 It is almost always a good idea to quote your type and subtype names.
626 This is to prevent perl from trying to execute the call as an indirect
627 object call. This issue only seems to come up when you have a subtype
628 the same name as a valid class, but when the issue does arise it tends
629 to be quite annoying to debug.
630
631 So for instance, this:
632
633   subtype DateTime => as Object => where { $_->isa('DateTime') };
634
635 will I<Just Work>, while this:
636
637   use DateTime;
638   subtype DateTime => as Object => where { $_->isa('DateTime') };
639
640 will fail silently and cause many headaches. The simple way to solve
641 this, as well as future proof your subtypes from classes which have
642 yet to have been created yet, is to simply do this:
643
644   use DateTime;
645   subtype 'DateTime' => as 'Object' => where { $_->isa('DateTime') };
646
647 =head2 Default Type Constraints
648
649 This module also provides a simple hierarchy for Perl 5 types, this
650 could probably use some work, but it works for me at the moment.
651
652   Any
653   Item
654       Bool
655       Maybe[`a]
656       Undef
657       Defined
658           Value
659               Num
660                 Int
661               Str
662                 ClassName
663           Ref
664               ScalarRef
665               ArrayRef[`a]
666               HashRef[`a]
667               CodeRef
668               RegexpRef
669               GlobRef
670                 FileHandle
671               Object
672                   Role
673
674 Suggestions for improvement are welcome.
675
676 B<NOTE:> Any type followed by a type parameter C<[`a]> can be 
677 parameterized, this means you can say:
678
679   ArrayRef[Int]    # an array of intergers
680   HashRef[CodeRef] # a hash of str to CODE ref mappings
681   Maybe[Str]       # value may be a string, may be undefined
682
683 B<NOTE:> The C<Undef> type constraint for the most part works 
684 correctly now, but edge cases may still exist, please use it 
685 sparringly.
686
687 B<NOTE:> The C<ClassName> type constraint does a complex package
688 existence check. This means that your class B<must> be loaded for 
689 this type constraint to pass. I know this is not ideal for all, 
690 but it is a saner restriction than most others.
691
692 =head2 Use with Other Constraint Modules
693
694 This module should play fairly nicely with other constraint
695 modules with only some slight tweaking. The C<where> clause
696 in types is expected to be a C<CODE> reference which checks
697 it's first argument and returns a bool. Since most constraint
698 modules work in a similar way, it should be simple to adapt
699 them to work with Moose.
700
701 For instance, this is how you could use it with
702 L<Declare::Constraints::Simple> to declare a completely new type.
703
704   type 'HashOfArrayOfObjects'
705       => IsHashRef(
706           -keys   => HasLength,
707           -values => IsArrayRef( IsObject ));
708
709 For more examples see the F<t/204_example_w_DCS.t> test file.
710
711 Here is an example of using L<Test::Deep> and it's non-test
712 related C<eq_deeply> function.
713
714   type 'ArrayOfHashOfBarsAndRandomNumbers'
715       => where {
716           eq_deeply($_,
717               array_each(subhashof({
718                   bar           => isa('Bar'),
719                   random_number => ignore()
720               })))
721         };
722
723 For a complete example see the F<t/205_example_w_TestDeep.t>
724 test file.
725
726 =head1 FUNCTIONS
727
728 =head2 Type Constraint Construction & Locating
729
730 =over 4
731
732 =item B<create_type_constraint_union ($pipe_seperated_types | @type_constraint_names)>
733
734 Given string with C<$pipe_seperated_types> or a list of C<@type_constraint_names>,
735 this will return a L<Moose::Meta::TypeConstraint::Union> instance.
736
737 =item B<create_parameterized_type_constraint ($type_name)>
738
739 Given a C<$type_name> in the form of:
740
741   BaseType[ContainerType]
742
743 this will extract the base type and container type and build an instance of
744 L<Moose::Meta::TypeConstraint::Parameterized> for it. 
745
746 =item B<create_class_type_constraint ($class)>
747
748 Given a class name it will create a new L<Moose::Meta::TypeConstraint::Class>
749 object for that class name.
750
751 =item B<find_or_create_type_constraint ($type_name, ?$options_for_anon_type)>
752
753 This will attempt to find or create a type constraint given the a C<$type_name>.
754 If it cannot find it in the registry, it will see if it should be a union or
755 container type an create one if appropriate, and lastly if nothing can be
756 found or created that way, it will create an anon-type using the
757 C<$options_for_anon_type> HASH ref to populate it. If the C<$options_for_anon_type>
758 is not specified (it is C<undef>), then it will not create anything and simply
759 return.
760
761 =item B<find_type_constraint ($type_name)>
762
763 This function can be used to locate a specific type constraint
764 meta-object, of the class L<Moose::Meta::TypeConstraint> or a
765 derivative. What you do with it from there is up to you :)
766
767 =item B<register_type_constraint ($type_object)>
768
769 This function will register a named type constraint with the type registry.
770
771 =item B<get_type_constraint_registry>
772
773 Fetch the L<Moose::Meta::TypeConstraint::Registry> object which
774 keeps track of all type constraints.
775
776 =item B<list_all_type_constraints>
777
778 This will return a list of type constraint names, you can then
779 fetch them using C<find_type_constraint ($type_name)> if you
780 want to.
781
782 =item B<list_all_builtin_type_constraints>
783
784 This will return a list of builtin type constraints, meaning,
785 those which are defined in this module. See the section
786 labeled L<Default Type Constraints> for a complete list.
787
788 =item B<export_type_constraints_as_functions>
789
790 This will export all the current type constraints as functions
791 into the caller's namespace. Right now, this is mostly used for
792 testing, but it might prove useful to others.
793
794 =item B<get_all_parameterizable_types>
795
796 This returns all the parameterizable types that have been registered.
797
798 =item B<add_parameterizable_type ($type)>
799
800 Adds C<$type> to the list of parameterizable types
801
802 =back
803
804 =head2 Type Constraint Constructors
805
806 The following functions are used to create type constraints.
807 They will then register the type constraints in a global store
808 where Moose can get to them if it needs to.
809
810 See the L<SYNOPSIS> for an example of how to use these.
811
812 =over 4
813
814 =item B<type ($name, $where_clause)>
815
816 This creates a base type, which has no parent.
817
818 =item B<subtype ($name, $parent, $where_clause, ?$message)>
819
820 This creates a named subtype.
821
822 =item B<subtype ($parent, $where_clause, ?$message)>
823
824 This creates an unnamed subtype and will return the type
825 constraint meta-object, which will be an instance of
826 L<Moose::Meta::TypeConstraint>.
827
828 =item B<class_type ($class)>
829
830 Creates a type constraint with the name C<$class> and the metaclass
831 L<Moose::Meta::TypeConstraint::Class>.
832
833 =item B<enum ($name, @values)>
834
835 This will create a basic subtype for a given set of strings.
836 The resulting constraint will be a subtype of C<Str> and
837 will match any of the items in C<@values>. It is case sensitive.
838 See the L<SYNOPSIS> for a simple example.
839
840 B<NOTE:> This is not a true proper enum type, it is simple
841 a convient constraint builder.
842
843 =item B<as>
844
845 This is just sugar for the type constraint construction syntax.
846
847 =item B<where>
848
849 This is just sugar for the type constraint construction syntax.
850
851 =item B<message>
852
853 This is just sugar for the type constraint construction syntax.
854
855 =item B<optimize_as>
856
857 This can be used to define a "hand optimized" version of your
858 type constraint which can be used to avoid traversing a subtype
859 constraint heirarchy.
860
861 B<NOTE:> You should only use this if you know what you are doing,
862 all the built in types use this, so your subtypes (assuming they
863 are shallow) will not likely need to use this.
864
865 =back
866
867 =head2 Type Coercion Constructors
868
869 Type constraints can also contain type coercions as well. If you
870 ask your accessor to coerce, then Moose will run the type-coercion
871 code first, followed by the type constraint check. This feature
872 should be used carefully as it is very powerful and could easily
873 take off a limb if you are not careful.
874
875 See the L<SYNOPSIS> for an example of how to use these.
876
877 =over 4
878
879 =item B<coerce>
880
881 =item B<from>
882
883 This is just sugar for the type coercion construction syntax.
884
885 =item B<via>
886
887 This is just sugar for the type coercion construction syntax.
888
889 =back
890
891 =head2 Namespace Management
892
893 =over 4
894
895 =item B<unimport>
896
897 This will remove all the type constraint keywords from the
898 calling class namespace.
899
900 =back
901
902 =head1 BUGS
903
904 All complex software has bugs lurking in it, and this module is no
905 exception. If you find a bug please either email me, or add the bug
906 to cpan-RT.
907
908 =head1 AUTHOR
909
910 Stevan Little E<lt>stevan@iinteractive.comE<gt>
911
912 =head1 COPYRIGHT AND LICENSE
913
914 Copyright 2006-2008 by Infinity Interactive, Inc.
915
916 L<http://www.iinteractive.com>
917
918 This library is free software; you can redistribute it and/or modify
919 it under the same terms as Perl itself.
920
921 =cut