21:49 <@stevan> and mention jrockways alternate solution "fork all of CPAN instead"
[gitmo/Moose.git] / lib / Moose / Util / TypeConstraints.pm
CommitLineData
a15dff8d 1
2package Moose::Util::TypeConstraints;
3
4use strict;
5use warnings;
6
998a8a25 7use Carp ();
9e856c83 8use List::MoreUtils qw( all any );
9a63faba 9use Scalar::Util qw( blessed reftype );
e606ae5f 10use Moose::Exporter;
a15dff8d 11
180899ed 12our $VERSION = '0.73';
e606ae5f 13$VERSION = eval $VERSION;
d44714be 14our $AUTHORITY = 'cpan:STEVAN';
a15dff8d 15
d9b40005 16## --------------------------------------------------------
e85d2a5d 17# Prototyped subs must be predeclared because we have a
18# circular dependency with Moose::Meta::Attribute et. al.
19# so in case of us being use'd first the predeclaration
d9b40005 20# ensures the prototypes are in scope when consumers are
21# compiled.
22
d9b40005 23# dah sugah!
180899ed 24sub where (&);
25sub via (&);
26sub message (&);
d9b40005 27sub optimize_as (&);
d9b40005 28
d9b40005 29## --------------------------------------------------------
8c4acc60 30
4e036ee4 31use Moose::Meta::TypeConstraint;
3726f905 32use Moose::Meta::TypeConstraint::Union;
0fbd4b0a 33use Moose::Meta::TypeConstraint::Parameterized;
7e4e1ad4 34use Moose::Meta::TypeConstraint::Parameterizable;
620db045 35use Moose::Meta::TypeConstraint::Class;
36use Moose::Meta::TypeConstraint::Role;
dabed765 37use Moose::Meta::TypeConstraint::Enum;
2ca63f5d 38use Moose::Meta::TypeCoercion;
3726f905 39use Moose::Meta::TypeCoercion::Union;
22aed3c0 40use Moose::Meta::TypeConstraint::Registry;
28ffb449 41use Moose::Util::TypeConstraints::OptimizedConstraints;
4e036ee4 42
e606ae5f 43Moose::Exporter->setup_import_methods(
44 as_is => [
45 qw(
180899ed 46 type subtype class_type role_type maybe_type duck_type
1b2c9bda 47 as where message optimize_as
e606ae5f 48 coerce from via
49 enum
50 find_type_constraint
51 register_type_constraint )
52 ],
53 _export_to_main => 1,
54);
a15dff8d 55
d9b40005 56## --------------------------------------------------------
57## type registry and some useful functions for it
58## --------------------------------------------------------
59
22aed3c0 60my $REGISTRY = Moose::Meta::TypeConstraint::Registry->new;
587ae0d2 61
180899ed 62sub get_type_constraint_registry {$REGISTRY}
63sub list_all_type_constraints { keys %{ $REGISTRY->type_constraints } }
64
d9b40005 65sub export_type_constraints_as_functions {
66 my $pkg = caller();
67 no strict 'refs';
180899ed 68 foreach my $constraint ( keys %{ $REGISTRY->type_constraints } ) {
69 my $tc = $REGISTRY->get_type_constraint($constraint)
70 ->_compiled_type_constraint;
71 *{"${pkg}::${constraint}"}
72 = sub { $tc->( $_[0] ) ? 1 : undef }; # the undef is for compat
a0f8153d 73 }
d9b40005 74}
182134e8 75
0c015f1b 76sub create_type_constraint_union {
d9b40005 77 my @type_constraint_names;
e85d2a5d 78
180899ed 79 if ( scalar @_ == 1 && _detect_type_constraint_union( $_[0] ) ) {
80 @type_constraint_names = _parse_type_constraint_union( $_[0] );
d9b40005 81 }
82 else {
83 @type_constraint_names = @_;
429ccc11 84 }
180899ed 85
86 ( scalar @type_constraint_names >= 2 )
87 || __PACKAGE__->_throw_error(
88 "You must pass in at least 2 type names to make a union");
e85d2a5d 89
84a9c64c 90 my @type_constraints = map {
180899ed 91 find_or_parse_type_constraint($_)
92 || __PACKAGE__->_throw_error(
93 "Could not locate type constraint ($_) for the union");
08380fdb 94 } @type_constraint_names;
84a9c64c 95
3726f905 96 return Moose::Meta::TypeConstraint::Union->new(
180899ed 97 type_constraints => \@type_constraints );
182134e8 98}
a15dff8d 99
0c015f1b 100sub create_parameterized_type_constraint {
d9b40005 101 my $type_constraint_name = shift;
180899ed 102 my ( $base_type, $type_parameter )
103 = _parse_parameterized_type_constraint($type_constraint_name);
e85d2a5d 104
180899ed 105 ( defined $base_type && defined $type_parameter )
106 || __PACKAGE__->_throw_error(
107 "Could not parse type name ($type_constraint_name) correctly");
e85d2a5d 108
180899ed 109 if ( $REGISTRY->has_type_constraint($base_type) ) {
90e78884 110 my $base_type_tc = $REGISTRY->get_type_constraint($base_type);
111 return _create_parameterized_type_constraint(
112 $base_type_tc,
113 $type_parameter
114 );
180899ed 115 }
116 else {
117 __PACKAGE__->_throw_error(
118 "Could not locate the base type ($base_type)");
90e78884 119 }
22aed3c0 120}
121
90e78884 122sub _create_parameterized_type_constraint {
123 my ( $base_type_tc, $type_parameter ) = @_;
124 if ( $base_type_tc->can('parameterize') ) {
125 return $base_type_tc->parameterize($type_parameter);
180899ed 126 }
127 else {
90e78884 128 return Moose::Meta::TypeConstraint::Parameterized->new(
180899ed 129 name => $base_type_tc->name . '[' . $type_parameter . ']',
90e78884 130 parent => $base_type_tc,
180899ed 131 type_parameter =>
132 find_or_create_isa_type_constraint($type_parameter),
90e78884 133 );
134 }
180899ed 135}
90e78884 136
4ab662d6 137#should we also support optimized checks?
0c015f1b 138sub create_class_type_constraint {
620db045 139 my ( $class, $options ) = @_;
140
180899ed 141# too early for this check
142#find_type_constraint("ClassName")->check($class)
143# || __PACKAGE__->_throw_error("Can't create a class type constraint because '$class' is not a class name");
3fef8ce8 144
620db045 145 my %options = (
146 class => $class,
147 name => $class,
148 %{ $options || {} },
4ab662d6 149 );
620db045 150
151 $options{name} ||= "__ANON__";
152
180899ed 153 Moose::Meta::TypeConstraint::Class->new(%options);
3fef8ce8 154}
155
0c015f1b 156sub create_role_type_constraint {
620db045 157 my ( $role, $options ) = @_;
e85d2a5d 158
180899ed 159# too early for this check
160#find_type_constraint("ClassName")->check($class)
161# || __PACKAGE__->_throw_error("Can't create a class type constraint because '$class' is not a class name");
e85d2a5d 162
620db045 163 my %options = (
164 role => $role,
165 name => $role,
166 %{ $options || {} },
167 );
e85d2a5d 168
620db045 169 $options{name} ||= "__ANON__";
170
180899ed 171 Moose::Meta::TypeConstraint::Role->new(%options);
620db045 172}
173
0c015f1b 174sub find_or_create_type_constraint {
620db045 175 my ( $type_constraint_name, $options_for_anon_type ) = @_;
176
180899ed 177 if ( my $constraint
178 = find_or_parse_type_constraint($type_constraint_name) ) {
620db045 179 return $constraint;
d9b40005 180 }
620db045 181 elsif ( defined $options_for_anon_type ) {
180899ed 182
d9b40005 183 # NOTE:
4ab662d6 184 # if there is no $options_for_anon_type
185 # specified, then we assume they don't
f3c4e20e 186 # want to create one, and return nothing.
f3c4e20e 187
d9b40005 188 # otherwise assume that we should create
e85d2a5d 189 # an ANON type with the $options_for_anon_type
d9b40005 190 # options which can be passed in. It should
e85d2a5d 191 # be noted that these don't get registered
d9b40005 192 # so we need to return it.
193 # - SL
194 return Moose::Meta::TypeConstraint->new(
195 name => '__ANON__',
e85d2a5d 196 %{$options_for_anon_type}
d9b40005 197 );
198 }
e85d2a5d 199
620db045 200 return;
201}
202
0c015f1b 203sub find_or_create_isa_type_constraint {
620db045 204 my $type_constraint_name = shift;
180899ed 205 find_or_parse_type_constraint($type_constraint_name)
206 || create_class_type_constraint($type_constraint_name);
620db045 207}
208
0c015f1b 209sub find_or_create_does_type_constraint {
620db045 210 my $type_constraint_name = shift;
180899ed 211 find_or_parse_type_constraint($type_constraint_name)
212 || create_role_type_constraint($type_constraint_name);
620db045 213}
214
0c015f1b 215sub find_or_parse_type_constraint {
eb4c4e82 216 my $type_constraint_name = normalize_type_constraint_name(shift);
620db045 217 my $constraint;
180899ed 218
219 if ( $constraint = find_type_constraint($type_constraint_name) ) {
e606ae5f 220 return $constraint;
180899ed 221 }
222 elsif ( _detect_type_constraint_union($type_constraint_name) ) {
620db045 223 $constraint = create_type_constraint_union($type_constraint_name);
180899ed 224 }
225 elsif ( _detect_parameterized_type_constraint($type_constraint_name) ) {
226 $constraint
227 = create_parameterized_type_constraint($type_constraint_name);
228 }
229 else {
620db045 230 return;
231 }
bb6c8335 232
d9b40005 233 $REGISTRY->add_type_constraint($constraint);
e85d2a5d 234 return $constraint;
d9b40005 235}
22aed3c0 236
eb4c4e82 237sub normalize_type_constraint_name {
84a9c64c 238 my $type_constraint_name = shift;
c8f663b2 239 $type_constraint_name =~ s/\s//g;
eb4c4e82 240 return $type_constraint_name;
241}
242
5f223879 243sub _confess {
244 my $error = shift;
245
246 local $Carp::CarpLevel = $Carp::CarpLevel + 1;
247 Carp::confess($error);
248}
249
22aed3c0 250## --------------------------------------------------------
251## exported functions ...
252## --------------------------------------------------------
253
0c015f1b 254sub find_type_constraint {
eeedfc8a 255 my $type = shift;
256
257 if ( blessed $type and $type->isa("Moose::Meta::TypeConstraint") ) {
258 return $type;
e606ae5f 259 }
260 else {
261 return unless $REGISTRY->has_type_constraint($type);
eeedfc8a 262 return $REGISTRY->get_type_constraint($type);
263 }
264}
22aed3c0 265
0c015f1b 266sub register_type_constraint {
3fef8ce8 267 my $constraint = shift;
180899ed 268 __PACKAGE__->_throw_error("can't register an unnamed type constraint")
269 unless defined $constraint->name;
3fef8ce8 270 $REGISTRY->add_type_constraint($constraint);
dabed765 271 return $constraint;
3fef8ce8 272}
273
7c13858b 274# type constructors
a15dff8d 275
9c27968f 276sub type {
180899ed 277
9e856c83 278 # back-compat version, called without sugar
180899ed 279 if ( !any { ( reftype($_) || '' ) eq 'HASH' } @_ ) {
9e856c83 280 return _create_type_constraint( $_[0], undef, $_[1] );
9a63faba 281 }
9a63faba 282
9e856c83 283 my $name = shift;
9a63faba 284
9e856c83 285 my %p = map { %{$_} } @_;
286
180899ed 287 return _create_type_constraint(
288 $name, undef, $p{where}, $p{message},
289 $p{optimize_as}
290 );
a15dff8d 291}
292
9c27968f 293sub subtype {
180899ed 294
9a63faba 295 # crazy back-compat code for being called without sugar ...
e3979c3e 296 #
9a63faba 297 # subtype 'Parent', sub { where };
298 if ( scalar @_ == 2 && ( reftype( $_[1] ) || '' ) eq 'CODE' ) {
299 return _create_type_constraint( undef, @_ );
300 }
301
302 # subtype 'Parent', sub { where }, sub { message };
303 # subtype 'Parent', sub { where }, sub { message }, sub { optimized };
304 if ( scalar @_ >= 3 && all { ( reftype($_) || '' ) eq 'CODE' }
180899ed 305 @_[ 1 .. $#_ ] ) {
9a63faba 306 return _create_type_constraint( undef, @_ );
307 }
308
309 # subtype 'Name', 'Parent', ...
310 if ( scalar @_ >= 2 && all { !ref } @_[ 0, 1 ] ) {
311 return _create_type_constraint(@_);
312 }
313
180899ed 314 if ( @_ == 1 && !ref $_[0] ) {
315 __PACKAGE__->_throw_error(
316 'A subtype cannot consist solely of a name, it must have a parent'
317 );
f75f625d 318 }
319
f6c0c589 320 # The blessed check is mostly to accommodate MooseX::Types, which
321 # uses an object which overloads stringification as a type name.
180899ed 322 my $name = ref $_[0] && !blessed $_[0] ? undef : shift;
9a63faba 323
324 my %p = map { %{$_} } @_;
325
326 # subtype Str => where { ... };
180899ed 327 if ( !exists $p{as} ) {
9e856c83 328 $p{as} = $name;
9a63faba 329 $name = undef;
330 }
331
180899ed 332 return _create_type_constraint(
333 $name, $p{as}, $p{where}, $p{message},
334 $p{optimize_as}
335 );
a15dff8d 336}
337
9c27968f 338sub class_type {
4ab662d6 339 register_type_constraint(
340 create_class_type_constraint(
341 $_[0],
180899ed 342 ( defined( $_[1] ) ? $_[1] : () ),
4ab662d6 343 )
344 );
3fef8ce8 345}
346
620db045 347sub role_type ($;$) {
348 register_type_constraint(
349 create_role_type_constraint(
350 $_[0],
180899ed 351 ( defined( $_[1] ) ? $_[1] : () ),
620db045 352 )
353 );
354}
355
1b2c9bda 356sub maybe_type {
357 my ($type_parameter) = @_;
358
28ce1444 359 register_type_constraint(
ed7060d9 360 $REGISTRY->get_type_constraint('Maybe')->parameterize($type_parameter)
28ce1444 361 );
1b2c9bda 362}
363
180899ed 364sub duck_type {
365 my ($type_name, @methods) = @_;
366 if ( ref $type_name eq 'ARRAY' && !@methods ) {
367 @methods = @$type_name;
368 $type_name = undef;
369 }
370
371 register_type_constraint(
372 _create_type_constraint(
373 $type_name, 'Object',
374 sub {
375 my $obj = $_;
376 my @missing_methods = grep { !$obj->can($_) } @methods;
377 return ! scalar @missing_methods;
378 },
379 sub {
380 my $obj = $_;
381 my @missing_methods = grep { !$obj->can($_) } @methods;
382 return
383 "${\blessed($obj)} is missing methods '@missing_methods'";
384 },
385 )
386 );
387}
388
9c27968f 389sub coerce {
180899ed 390 my ( $type_name, @coercion_map ) = @_;
391 _install_type_coercions( $type_name, \@coercion_map );
182134e8 392}
393
f6c0c589 394# The trick of returning @_ lets us avoid having to specify a
395# prototype. Perl will parse this:
396#
397# subtype 'Foo'
398# => as 'Str'
399# => where { ... }
400#
401# as this:
402#
403# subtype( 'Foo', as( 'Str', where { ... } ) );
404#
405# If as() returns all it's extra arguments, this just works, and
406# preserves backwards compatibility.
180899ed 407sub as { { as => shift }, @_ }
9e856c83 408sub where (&) { { where => $_[0] } }
409sub message (&) { { message => $_[0] } }
410sub optimize_as (&) { { optimize_as => $_[0] } }
8ecb1fa0 411
9a63faba 412sub from {@_}
413sub via (&) { $_[0] }
a15dff8d 414
9c27968f 415sub enum {
180899ed 416 my ( $type_name, @values ) = @_;
417
4ab662d6 418 # NOTE:
419 # if only an array-ref is passed then
9f4334a1 420 # you get an anon-enum
421 # - SL
180899ed 422 if ( ref $type_name eq 'ARRAY' && !@values ) {
9f4334a1 423 @values = @$type_name;
424 $type_name = undef;
425 }
180899ed 426 ( scalar @values >= 2 )
427 || __PACKAGE__->_throw_error(
428 "You must have at least two values to enumerate through");
c4fe165f 429 my %valid = map { $_ => 1 } @values;
dabed765 430
431 register_type_constraint(
432 create_enum_type_constraint(
433 $type_name,
434 \@values,
435 )
436 );
437}
438
0c015f1b 439sub create_enum_type_constraint {
dabed765 440 my ( $type_name, $values ) = @_;
e606ae5f 441
dabed765 442 Moose::Meta::TypeConstraint::Enum->new(
180899ed 443 name => $type_name || '__ANON__',
dabed765 444 values => $values,
a0f8153d 445 );
fcec2383 446}
447
d9b40005 448## --------------------------------------------------------
449## desugaring functions ...
450## --------------------------------------------------------
451
e85d2a5d 452sub _create_type_constraint ($$$;$$) {
9a63faba 453 my $name = shift;
454 my $parent = shift;
455 my $check = shift;
456 my $message = shift;
457 my $optimized = shift;
d9b40005 458
9a63faba 459 my $pkg_defined_in = scalar( caller(1) );
e85d2a5d 460
1da6728b 461 if ( defined $name ) {
d9b40005 462 my $type = $REGISTRY->get_type_constraint($name);
e85d2a5d 463
5f223879 464 ( $type->_package_defined_in eq $pkg_defined_in )
465 || _confess(
466 "The type constraint '$name' has already been created in "
467 . $type->_package_defined_in
468 . " and cannot be created again in "
469 . $pkg_defined_in )
470 if defined $type;
eee1a213 471
472 $name =~ /^[\w:\.]+$/
473 or die qq{$name contains invalid characters for a type name.}
33c8a6d0 474 . qq{ Names can contain alphanumeric character, ":", and "."\n};
e85d2a5d 475 }
1da6728b 476
9ceb576e 477 my %opts = (
9a63faba 478 name => $name,
d9b40005 479 package_defined_in => $pkg_defined_in,
e85d2a5d 480
1da6728b 481 ( $check ? ( constraint => $check ) : () ),
482 ( $message ? ( message => $message ) : () ),
483 ( $optimized ? ( optimized => $optimized ) : () ),
d9b40005 484 );
1da6728b 485
9ceb576e 486 my $constraint;
180899ed 487 if (
488 defined $parent
1da6728b 489 and $parent
180899ed 490 = blessed $parent
491 ? $parent
492 : find_or_create_isa_type_constraint($parent)
493 ) {
85a9908f 494 $constraint = $parent->create_child_type(%opts);
1da6728b 495 }
496 else {
497 $constraint = Moose::Meta::TypeConstraint->new(%opts);
4ab662d6 498 }
d9b40005 499
500 $REGISTRY->add_type_constraint($constraint)
501 if defined $name;
502
503 return $constraint;
504}
505
e85d2a5d 506sub _install_type_coercions ($$) {
180899ed 507 my ( $type_name, $coercion_map ) = @_;
e606ae5f 508 my $type = find_type_constraint($type_name);
180899ed 509 ( defined $type )
510 || __PACKAGE__->_throw_error(
511 "Cannot find type '$type_name', perhaps you forgot to load it.");
512 if ( $type->has_coercion ) {
41e007e4 513 $type->coercion->add_type_coercions(@$coercion_map);
514 }
515 else {
516 my $type_coercion = Moose::Meta::TypeCoercion->new(
517 type_coercion_map => $coercion_map,
518 type_constraint => $type
519 );
520 $type->coercion($type_coercion);
521 }
d9b40005 522}
523
524## --------------------------------------------------------
f1917f58 525## type notation parsing ...
526## --------------------------------------------------------
527
528{
180899ed 529
e85d2a5d 530 # All I have to say is mugwump++ cause I know
531 # do not even have enough regexp-fu to be able
532 # to have written this (I can only barely
f1917f58 533 # understand it as it is)
e85d2a5d 534 # - SL
535
f1917f58 536 use re "eval";
537
eee1a213 538 my $valid_chars = qr{[\w:\.]};
f1917f58 539 my $type_atom = qr{ $valid_chars+ };
540
be722745 541 my $any;
542
180899ed 543 my $type = qr{ $valid_chars+ (?: \[ \s* (??{$any}) \s* \] )? }x;
544 my $type_capture_parts
545 = qr{ ($valid_chars+) (?: \[ \s* ((??{$any})) \s* \] )? }x;
546 my $type_with_parameter
547 = qr{ $valid_chars+ \[ \s* (??{$any}) \s* \] }x;
f1917f58 548
3796382a 549 my $op_union = qr{ \s* \| \s* }x;
f1917f58 550 my $union = qr{ $type (?: $op_union $type )+ }x;
551
84a9c64c 552 $any = qr{ $type | $union }x;
f1917f58 553
0fbd4b0a 554 sub _parse_parameterized_type_constraint {
180899ed 555 { no warnings 'void'; $any; } # force capture of interpolated lexical
84a9c64c 556 $_[0] =~ m{ $type_capture_parts }x;
180899ed 557 return ( $1, $2 );
f1917f58 558 }
559
0fbd4b0a 560 sub _detect_parameterized_type_constraint {
180899ed 561 { no warnings 'void'; $any; } # force capture of interpolated lexical
e85d2a5d 562 $_[0] =~ m{ ^ $type_with_parameter $ }x;
f1917f58 563 }
564
565 sub _parse_type_constraint_union {
180899ed 566 { no warnings 'void'; $any; } # force capture of interpolated lexical
e85d2a5d 567 my $given = shift;
568 my @rv;
569 while ( $given =~ m{ \G (?: $op_union )? ($type) }gcx ) {
82a5b1a7 570 push @rv => $1;
e85d2a5d 571 }
180899ed 572 ( pos($given) eq length($given) )
573 || __PACKAGE__->_throw_error( "'$given' didn't parse (parse-pos="
574 . pos($given)
575 . " and str-length="
576 . length($given)
577 . ")" );
e85d2a5d 578 @rv;
f1917f58 579 }
580
581 sub _detect_type_constraint_union {
180899ed 582 { no warnings 'void'; $any; } # force capture of interpolated lexical
e85d2a5d 583 $_[0] =~ m{^ $type $op_union $type ( $op_union .* )? $}x;
f1917f58 584 }
585}
586
587## --------------------------------------------------------
d9b40005 588# define some basic built-in types
589## --------------------------------------------------------
a15dff8d 590
3cae4250 591# By making these classes immutable before creating all the types we
592# below, we avoid repeatedly calling the slow MOP-based accessors.
593$_->make_immutable(
594 inline_constructor => 1,
595 constructor_name => "_new",
596
597 # these are Class::MOP accessors, so they need inlining
598 inline_accessors => 1
599 ) for grep { $_->is_mutable }
600 map { $_->meta }
601 qw(
602 Moose::Meta::TypeConstraint
603 Moose::Meta::TypeConstraint::Union
604 Moose::Meta::TypeConstraint::Parameterized
605 Moose::Meta::TypeConstraint::Parameterizable
606 Moose::Meta::TypeConstraint::Class
607 Moose::Meta::TypeConstraint::Role
608 Moose::Meta::TypeConstraint::Enum
609 Moose::Meta::TypeConstraint::Registry
610);
611
180899ed 612type 'Any' => where {1}; # meta-type including all
613type 'Item' => where {1}; # base-type
a15dff8d 614
fd542f49 615subtype 'Undef' => as 'Item' => where { !defined($_) };
180899ed 616subtype 'Defined' => as 'Item' => where { defined($_) };
617
618subtype 'Bool' => as 'Item' =>
619 where { !defined($_) || $_ eq "" || "$_" eq '1' || "$_" eq '0' };
620
621subtype 'Value' => as 'Defined' => where { !ref($_) } =>
622 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Value;
623
624subtype 'Ref' => as 'Defined' => where { ref($_) } =>
625 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Ref;
626
627subtype 'Str' => as 'Value' => where {1} =>
628 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Str;
629
630subtype 'Num' => as 'Value' =>
631 where { Scalar::Util::looks_like_number($_) } =>
632 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Num;
633
634subtype 'Int' => as 'Num' => where { "$_" =~ /^-?[0-9]+$/ } =>
635 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Int;
636
637subtype 'ScalarRef' => as 'Ref' => where { ref($_) eq 'SCALAR' } =>
638 optimize_as
639 \&Moose::Util::TypeConstraints::OptimizedConstraints::ScalarRef;
640subtype 'CodeRef' => as 'Ref' => where { ref($_) eq 'CODE' } =>
641 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::CodeRef;
642subtype 'RegexpRef' => as 'Ref' => where { ref($_) eq 'Regexp' } =>
643 optimize_as
644 \&Moose::Util::TypeConstraints::OptimizedConstraints::RegexpRef;
645subtype 'GlobRef' => as 'Ref' => where { ref($_) eq 'GLOB' } =>
646 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::GlobRef;
a15dff8d 647
0a5bd159 648# NOTE:
e85d2a5d 649# scalar filehandles are GLOB refs,
0a5bd159 650# but a GLOB ref is not always a filehandle
180899ed 651subtype 'FileHandle' => as 'GlobRef' => where {
652 Scalar::Util::openhandle($_) || ( blessed($_) && $_->isa("IO::Handle") );
653} => optimize_as
654 \&Moose::Util::TypeConstraints::OptimizedConstraints::FileHandle;
0a5bd159 655
e85d2a5d 656# NOTE:
a15dff8d 657# blessed(qr/.../) returns true,.. how odd
180899ed 658subtype 'Object' => as 'Ref' =>
659 where { blessed($_) && blessed($_) ne 'Regexp' } =>
660 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Object;
a15dff8d 661
180899ed 662subtype 'Role' => as 'Object' => where { $_->can('does') } =>
663 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Role;
e85d2a5d 664
180899ed 665my $_class_name_checker = sub { };
0e0709ea 666
180899ed 667subtype 'ClassName' => as 'Str' =>
668 where { Class::MOP::is_class_loaded($_) } => optimize_as
669 \&Moose::Util::TypeConstraints::OptimizedConstraints::ClassName;
02a0fb52 670
180899ed 671subtype 'RoleName' => as 'ClassName' => where {
672 ( ( $_->can('meta') || return )->($_) || return )
673 ->isa('Moose::Meta::Role');
674} => optimize_as
675 \&Moose::Util::TypeConstraints::OptimizedConstraints::RoleName;
f0cac16f 676
d9b40005 677## --------------------------------------------------------
7e4e1ad4 678# parameterizable types ...
679
680$REGISTRY->add_type_constraint(
681 Moose::Meta::TypeConstraint::Parameterizable->new(
180899ed 682 name => 'ArrayRef',
683 package_defined_in => __PACKAGE__,
684 parent => find_type_constraint('Ref'),
685 constraint => sub { ref($_) eq 'ARRAY' },
686 optimized =>
687 \&Moose::Util::TypeConstraints::OptimizedConstraints::ArrayRef,
7e4e1ad4 688 constraint_generator => sub {
689 my $type_parameter = shift;
180899ed 690 my $check = $type_parameter->_compiled_type_constraint;
7e4e1ad4 691 return sub {
692 foreach my $x (@$_) {
180899ed 693 ( $check->($x) ) || return;
694 }
695 1;
696 }
7e4e1ad4 697 }
698 )
699);
700
701$REGISTRY->add_type_constraint(
702 Moose::Meta::TypeConstraint::Parameterizable->new(
180899ed 703 name => 'HashRef',
704 package_defined_in => __PACKAGE__,
705 parent => find_type_constraint('Ref'),
706 constraint => sub { ref($_) eq 'HASH' },
707 optimized =>
708 \&Moose::Util::TypeConstraints::OptimizedConstraints::HashRef,
7e4e1ad4 709 constraint_generator => sub {
4ab662d6 710 my $type_parameter = shift;
180899ed 711 my $check = $type_parameter->_compiled_type_constraint;
7e4e1ad4 712 return sub {
180899ed 713 foreach my $x ( values %$_ ) {
714 ( $check->($x) ) || return;
715 }
716 1;
717 }
7e4e1ad4 718 }
719 )
720);
721
722$REGISTRY->add_type_constraint(
723 Moose::Meta::TypeConstraint::Parameterizable->new(
724 name => 'Maybe',
725 package_defined_in => __PACKAGE__,
726 parent => find_type_constraint('Item'),
180899ed 727 constraint => sub {1},
7e4e1ad4 728 constraint_generator => sub {
4ab662d6 729 my $type_parameter = shift;
180899ed 730 my $check = $type_parameter->_compiled_type_constraint;
7e4e1ad4 731 return sub {
180899ed 732 return 1 if not( defined($_) ) || $check->($_);
7e4e1ad4 733 return;
180899ed 734 }
7e4e1ad4 735 }
736 )
737);
738
180899ed 739my @PARAMETERIZABLE_TYPES
740 = map { $REGISTRY->get_type_constraint($_) } qw[ArrayRef HashRef Maybe];
741
742sub get_all_parameterizable_types {@PARAMETERIZABLE_TYPES}
7e4e1ad4 743
4ab662d6 744sub add_parameterizable_type {
7e4e1ad4 745 my $type = shift;
180899ed 746 ( blessed $type
747 && $type->isa('Moose::Meta::TypeConstraint::Parameterizable') )
748 || __PACKAGE__->_throw_error(
749 "Type must be a Moose::Meta::TypeConstraint::Parameterizable not $type"
750 );
7e4e1ad4 751 push @PARAMETERIZABLE_TYPES => $type;
4ab662d6 752}
7e4e1ad4 753
754## --------------------------------------------------------
d9b40005 755# end of built-in types ...
756## --------------------------------------------------------
757
943596a6 758{
759 my @BUILTINS = list_all_type_constraints();
180899ed 760 sub list_all_builtin_type_constraints {@BUILTINS}
943596a6 761}
762
6ea98933 763sub _throw_error {
6b83828f 764 shift;
6ea98933 765 require Moose;
766 unshift @_, 'Moose';
767 goto &Moose::throw_error;
768}
769
a15dff8d 7701;
771
772__END__
773
774=pod
775
776=head1 NAME
777
e522431d 778Moose::Util::TypeConstraints - Type constraint system for Moose
a15dff8d 779
780=head1 SYNOPSIS
781
782 use Moose::Util::TypeConstraints;
783
e85d2a5d 784 subtype 'Natural'
e606ae5f 785 => as 'Int'
a15dff8d 786 => where { $_ > 0 };
e85d2a5d 787
788 subtype 'NaturalLessThanTen'
2c0cbef7 789 => as 'Natural'
79592a54 790 => where { $_ < 10 }
791 => message { "This number ($_) is not less than ten!" };
e85d2a5d 792
793 coerce 'Num'
2c0cbef7 794 => from 'Str'
e85d2a5d 795 => via { 0+$_ };
796
2c0cbef7 797 enum 'RGBColors' => qw(red green blue);
a15dff8d 798
e7fcb7b2 799 no Moose::Util::TypeConstraints;
800
a15dff8d 801=head1 DESCRIPTION
802
e85d2a5d 803This module provides Moose with the ability to create custom type
6549b0d1 804constraints to be used in attribute definition.
e522431d 805
6ba6d68c 806=head2 Important Caveat
807
e85d2a5d 808This is B<NOT> a type system for Perl 5. These are type constraints,
809and they are not used by Moose unless you tell it to. No type
e7fcb7b2 810inference is performed, expressions are not typed, etc. etc. etc.
6ba6d68c 811
e7fcb7b2 812A type constraint is at heart a small "check if a value is valid"
813function. A constraint can be associated with an attribute. This
814simplifies parameter validation, and makes your code clearer to read,
815because you can refer to constraints by name.
6ba6d68c 816
2c0cbef7 817=head2 Slightly Less Important Caveat
818
e7fcb7b2 819It is B<always> a good idea to quote your type names.
004222dc 820
e7fcb7b2 821This prevents Perl from trying to execute the call as an indirect
822object call. This can be an issue when you have a subtype with the
823same name as a valid class.
2c0cbef7 824
e7fcb7b2 825For instance:
e85d2a5d 826
2c0cbef7 827 subtype DateTime => as Object => where { $_->isa('DateTime') };
828
e7fcb7b2 829will I<just work>, while this:
2c0cbef7 830
831 use DateTime;
832 subtype DateTime => as Object => where { $_->isa('DateTime') };
833
e85d2a5d 834will fail silently and cause many headaches. The simple way to solve
835this, as well as future proof your subtypes from classes which have
e7fcb7b2 836yet to have been created, is to quote the type name:
2c0cbef7 837
838 use DateTime;
d44714be 839 subtype 'DateTime' => as 'Object' => where { $_->isa('DateTime') };
2c0cbef7 840
6ba6d68c 841=head2 Default Type Constraints
e522431d 842
e606ae5f 843This module also provides a simple hierarchy for Perl 5 types, here is
004222dc 844that hierarchy represented visually.
e522431d 845
846 Any
e85d2a5d 847 Item
5a4c5493 848 Bool
7e4e1ad4 849 Maybe[`a]
f65cb534 850 Undef
851 Defined
5a4c5493 852 Value
853 Num
854 Int
855 Str
9af1d28b 856 ClassName
ed87d4fd 857 RoleName
5a4c5493 858 Ref
859 ScalarRef
7e4e1ad4 860 ArrayRef[`a]
861 HashRef[`a]
5a4c5493 862 CodeRef
863 RegexpRef
3f7376b0 864 GlobRef
0a5bd159 865 FileHandle
e85d2a5d 866 Object
2cbb5233 867 Role
e522431d 868
4ab662d6 869B<NOTE:> Any type followed by a type parameter C<[`a]> can be
7e4e1ad4 870parameterized, this means you can say:
871
757e07ef 872 ArrayRef[Int] # an array of integers
7e4e1ad4 873 HashRef[CodeRef] # a hash of str to CODE ref mappings
874 Maybe[Str] # value may be a string, may be undefined
875
4e8a0f64 876If Moose finds a name in brackets that it does not recognize as an
877existing type, it assumes that this is a class name, for example
878C<ArrayRef[DateTime]>.
879
e7fcb7b2 880B<NOTE:> Unless you parameterize a type, then it is invalid to include
881the square brackets. I.e. C<ArrayRef[]> will be treated as a new type
882name, I<not> as a parameterization of C<ArrayRef>.
e606ae5f 883
4ab662d6 884B<NOTE:> The C<Undef> type constraint for the most part works
885correctly now, but edge cases may still exist, please use it
6549b0d1 886sparingly.
703e92fb 887
7e4e1ad4 888B<NOTE:> The C<ClassName> type constraint does a complex package
e7fcb7b2 889existence check. This means that your class B<must> be loaded for this
890type constraint to pass.
9af1d28b 891
e7fcb7b2 892B<NOTE:> The C<RoleName> constraint checks a string is a I<package
893name> which is a role, like C<'MyApp::Role::Comparable'>. The C<Role>
894constraint checks that an I<object does> the named role.
ed87d4fd 895
e606ae5f 896=head2 Type Constraint Naming
004222dc 897
eee1a213 898Type name declared via this module can only contain alphanumeric
899characters, colons (:), and periods (.).
900
e606ae5f 901Since the types created by this module are global, it is suggested
902that you namespace your types just as you would namespace your
e7fcb7b2 903modules. So instead of creating a I<Color> type for your
904B<My::Graphics> module, you would call the type
905I<My::Graphics::Types::Color> instead.
004222dc 906
703e92fb 907=head2 Use with Other Constraint Modules
908
e7fcb7b2 909This module can play nicely with other constraint modules with some
910slight tweaking. The C<where> clause in types is expected to be a
911C<CODE> reference which checks it's first argument and returns a
912boolean. Since most constraint modules work in a similar way, it
913should be simple to adapt them to work with Moose.
703e92fb 914
e85d2a5d 915For instance, this is how you could use it with
916L<Declare::Constraints::Simple> to declare a completely new type.
703e92fb 917
9e856c83 918 type 'HashOfArrayOfObjects',
919 {
920 where => IsHashRef(
703e92fb 921 -keys => HasLength,
9e856c83 922 -values => IsArrayRef(IsObject)
923 )
924 };
703e92fb 925
e7fcb7b2 926For more examples see the F<t/200_examples/004_example_w_DCS.t> test
927file.
703e92fb 928
e85d2a5d 929Here is an example of using L<Test::Deep> and it's non-test
930related C<eq_deeply> function.
703e92fb 931
e85d2a5d 932 type 'ArrayOfHashOfBarsAndRandomNumbers'
703e92fb 933 => where {
e85d2a5d 934 eq_deeply($_,
703e92fb 935 array_each(subhashof({
936 bar => isa('Bar'),
937 random_number => ignore()
e85d2a5d 938 })))
703e92fb 939 };
940
e606ae5f 941For a complete example see the
e7fcb7b2 942F<t/200_examples/005_example_w_TestDeep.t> test file.
e85d2a5d 943
a15dff8d 944=head1 FUNCTIONS
945
946=head2 Type Constraint Constructors
947
e7fcb7b2 948The following functions are used to create type constraints. They
949will also register the type constraints your create in a global
950registry that is used to look types up by name.
a15dff8d 951
25f2c3fc 952See the L<SYNOPSIS> for an example of how to use these.
a15dff8d 953
6ba6d68c 954=over 4
a15dff8d 955
9a63faba 956=item B<subtype 'Name' => as 'Parent' => where { } ...>
182134e8 957
e85d2a5d 958This creates a named subtype.
d6e2d9a1 959
dba9208a 960If you provide a parent that Moose does not recognize, it will
961automatically create a new class type constraint for this name.
962
9e856c83 963When creating a named type, the C<subtype> function should either be
964called with the sugar helpers (C<where>, C<message>, etc), or with a
965name and a hashref of parameters:
966
967 subtype( 'Foo', { where => ..., message => ... } );
968
969The valid hashref keys are C<as> (the parent), C<where>, C<message>,
970and C<optimize_as>.
9a63faba 971
972=item B<subtype as 'Parent' => where { } ...>
182134e8 973
e85d2a5d 974This creates an unnamed subtype and will return the type
975constraint meta-object, which will be an instance of
976L<Moose::Meta::TypeConstraint>.
a15dff8d 977
9e856c83 978When creating an anonymous type, the C<subtype> function should either
979be called with the sugar helpers (C<where>, C<message>, etc), or with
980just a hashref of parameters:
981
982 subtype( { where => ..., message => ... } );
983
620db045 984=item B<class_type ($class, ?$options)>
3fef8ce8 985
ed87d4fd 986Creates a new subtype of C<Object> with the name C<$class> and the
987metaclass L<Moose::Meta::TypeConstraint::Class>.
3fef8ce8 988
620db045 989=item B<role_type ($role, ?$options)>
990
ed87d4fd 991Creates a C<Role> type constraint with the name C<$role> and the
992metaclass L<Moose::Meta::TypeConstraint::Role>.
620db045 993
1b2c9bda 994=item B<maybe_type ($type)>
995
996Creates a type constraint for either C<undef> or something of the
997given type.
998
e451e855 999=item B<duck_type ($name, @methods)>
1000
88b68372 1001This will create a subtype of Object and test to make sure the value
1002C<can()> do the methods in C<@methods>.
1003
1004This is intended as an easy way to accept non-Moose objects that
1005provide a certain interface. If you're using Moose classes, we
1006recommend that you use a C<requires>-only Role instead.
e451e855 1007
1008=item B<duck_type (\@methods)>
1009
88b68372 1010If passed an ARRAY reference instead of the C<$name>, C<@methods>
1011pair, this will create an unnamed duck type. This can be used in an
1012attribute definiton like so:
e451e855 1013
88b68372 1014 has 'cache' => (
1015 is => 'ro',
1016 isa => duck_type( [qw( get_set )] ),
1017 );
e451e855 1018
fcec2383 1019=item B<enum ($name, @values)>
1020
e85d2a5d 1021This will create a basic subtype for a given set of strings.
1022The resulting constraint will be a subtype of C<Str> and
4ce56d04 1023will match any of the items in C<@values>. It is case sensitive.
1024See the L<SYNOPSIS> for a simple example.
2c0cbef7 1025
6549b0d1 1026B<NOTE:> This is not a true proper enum type, it is simply
1027a convenient constraint builder.
2c0cbef7 1028
9f4334a1 1029=item B<enum (\@values)>
1030
4ab662d6 1031If passed an ARRAY reference instead of the C<$name>, C<@values> pair,
9f4334a1 1032this will create an unnamed enum. This can then be used in an attribute
1033definition like so:
1034
1035 has 'sort_order' => (
1036 is => 'ro',
4ab662d6 1037 isa => enum([qw[ ascending descending ]]),
9f4334a1 1038 );
1039
e7fcb7b2 1040=item B<as 'Parent'>
a15dff8d 1041
6ba6d68c 1042This is just sugar for the type constraint construction syntax.
a15dff8d 1043
e7fcb7b2 1044It takes a single argument, which is the name of a parent type.
1045
1046=item B<where { ... }>
a15dff8d 1047
6ba6d68c 1048This is just sugar for the type constraint construction syntax.
76d37e5a 1049
e7fcb7b2 1050It takes a subroutine reference as an argument. When the type
1051constraint is tested, the reference is run with the value to be tested
1052in C<$_>. This reference should return true or false to indicate
1053whether or not the constraint check passed.
e606ae5f 1054
e7fcb7b2 1055=item B<message { ... }>
76d37e5a 1056
1057This is just sugar for the type constraint construction syntax.
a15dff8d 1058
e7fcb7b2 1059It takes a subroutine reference as an argument. When the type
1060constraint fails, then the code block is run with the value provided
1061in C<$_>. This reference should return a string, which will be used in
1062the text of the exception thrown.
e606ae5f 1063
e7fcb7b2 1064=item B<optimize_as { ... }>
8ecb1fa0 1065
e85d2a5d 1066This can be used to define a "hand optimized" version of your
d44714be 1067type constraint which can be used to avoid traversing a subtype
6549b0d1 1068constraint hierarchy.
d44714be 1069
e85d2a5d 1070B<NOTE:> You should only use this if you know what you are doing,
1071all the built in types use this, so your subtypes (assuming they
d44714be 1072are shallow) will not likely need to use this.
1073
e7fcb7b2 1074=item B<type 'Name' => where { } ... >
1075
1076This creates a base type, which has no parent.
1077
1078The C<type> function should either be called with the sugar helpers
1079(C<where>, C<message>, etc), or with a name and a hashref of
1080parameters:
1081
1082 type( 'Foo', { where => ..., message => ... } );
1083
1084The valid hashref keys are C<where>, C<message>, and C<optimize_as>.
1085
6ba6d68c 1086=back
a15dff8d 1087
6ba6d68c 1088=head2 Type Coercion Constructors
a15dff8d 1089
e7fcb7b2 1090You can define coercions for type constraints, which allow you to
1091automatically transform values to something valid for the type
1092constraint. If you ask your accessor to coerce, then Moose will run
1093the type-coercion code first, followed by the type constraint
1094check. This feature should be used carefully as it is very powerful
1095and could easily take off a limb if you are not careful.
a15dff8d 1096
25f2c3fc 1097See the L<SYNOPSIS> for an example of how to use these.
a15dff8d 1098
6ba6d68c 1099=over 4
a15dff8d 1100
e7fcb7b2 1101=item B<< coerce 'Name' => from 'OtherName' => via { ... } >>
a15dff8d 1102
e7fcb7b2 1103This defines a coercion from one type to another. The C<Name> argument
1104is the type you are coercing I<to>.
1105
1106=item B<from 'OtherName'>
a15dff8d 1107
6ba6d68c 1108This is just sugar for the type coercion construction syntax.
1109
e7fcb7b2 1110It takes a single type name (or type object), which is the type being
1111coerced I<from>.
1112
1113=item B<via { ... }>
a15dff8d 1114
6ba6d68c 1115This is just sugar for the type coercion construction syntax.
a15dff8d 1116
e7fcb7b2 1117It takes a subroutine reference. This reference will be called with
1118the value to be coerced in C<$_>. It is expected to return a new value
1119of the proper type for the coercion.
1120
a15dff8d 1121=back
1122
e7fcb7b2 1123=head2 Creating and Finding Type Constraints
1124
1125These are additional functions for creating and finding type
1126constraints. Most of these functions are not available for
1127importing. The ones that are importable as specified.
004222dc 1128
1129=over 4
1130
e7fcb7b2 1131=item B<find_type_constraint($type_name)>
eb4c4e82 1132
e7fcb7b2 1133This function can be used to locate the L<Moose::Meta::TypeConstraint>
1134object for a named type.
eb4c4e82 1135
e7fcb7b2 1136This function is importable.
004222dc 1137
e7fcb7b2 1138=item B<register_type_constraint($type_object)>
004222dc 1139
e7fcb7b2 1140This function will register a L<Moose::Meta::TypeConstraint> with the
1141global type registry.
004222dc 1142
e7fcb7b2 1143This function is importable.
004222dc 1144
e7fcb7b2 1145=item B<normalize_type_constraint_name($type_constraint_name)>
004222dc 1146
e7fcb7b2 1147This method takes a type constraint name and returns the normalized
1148form. This removes any whitespace in the string.
004222dc 1149
e7fcb7b2 1150=item B<create_type_constraint_union($pipe_separated_types | @type_constraint_names)>
004222dc 1151
e7fcb7b2 1152This can take a union type specification like C<'Int|ArrayRef[Int]'>,
1153or a list of names. It returns a new
1154L<Moose::Meta::TypeConstraint::Union> object.
004222dc 1155
e7fcb7b2 1156=item B<create_parameterized_type_constraint($type_name)>
620db045 1157
e7fcb7b2 1158Given a C<$type_name> in the form of C<'BaseType[ContainerType]'>,
1159this will create a new L<Moose::Meta::TypeConstraint::Parameterized>
1160object. The C<BaseType> must exist already exist as a parameterizable
1161type.
620db045 1162
e7fcb7b2 1163=item B<create_class_type_constraint($class, $options)>
dabed765 1164
e7fcb7b2 1165Given a class name this function will create a new
1166L<Moose::Meta::TypeConstraint::Class> object for that class name.
004222dc 1167
e7fcb7b2 1168The C<$options> is a hash reference that will be passed to the
1169L<Moose::Meta::TypeConstraint::Class> constructor (as a hash).
620db045 1170
e7fcb7b2 1171=item B<create_role_type_constraint($role, $options)>
620db045 1172
e7fcb7b2 1173Given a role name this function will create a new
1174L<Moose::Meta::TypeConstraint::Role> object for that role name.
620db045 1175
e7fcb7b2 1176The C<$options> is a hash reference that will be passed to the
1177L<Moose::Meta::TypeConstraint::Role> constructor (as a hash).
620db045 1178
8a6c8c47 1179=item B<create_enum_type_constraint($name, $values)>
1180
1181Given a enum name this function will create a new
1182L<Moose::Meta::TypeConstraint::Enum> object for that enum name.
1183
e7fcb7b2 1184=item B<find_or_parse_type_constraint($type_name)>
620db045 1185
ec4b72d2 1186Given a type name, this first attempts to find a matching constraint
e7fcb7b2 1187in the global registry.
620db045 1188
e7fcb7b2 1189If the type name is a union or parameterized type, it will create a
1190new object of the appropriate, but if given a "regular" type that does
1191not yet exist, it simply returns false.
620db045 1192
e7fcb7b2 1193When given a union or parameterized type, the member or base type must
1194already exist.
620db045 1195
e7fcb7b2 1196If it creates a new union or parameterized type, it will add it to the
1197global registry.
004222dc 1198
e7fcb7b2 1199=item B<find_or_create_isa_type_constraint($type_name)>
004222dc 1200
e7fcb7b2 1201=item B<find_or_create_does_type_constraint($type_name)>
004222dc 1202
e7fcb7b2 1203These functions will first call C<find_or_parse_type_constraint>. If
1204that function does not return a type, a new anonymous type object will
1205be created.
004222dc 1206
e7fcb7b2 1207The C<isa> variant will use C<create_class_type_constraint> and the
1208C<does> variant will use C<create_role_type_constraint>.
004222dc 1209
1210=item B<get_type_constraint_registry>
1211
e7fcb7b2 1212Returns the L<Moose::Meta::TypeConstraint::Registry> object which
004222dc 1213keeps track of all type constraints.
1214
1215=item B<list_all_type_constraints>
1216
e7fcb7b2 1217This will return a list of type constraint names in the global
1218registry. You can then fetch the actual type object using
1219C<find_type_constraint($type_name)>.
004222dc 1220
1221=item B<list_all_builtin_type_constraints>
1222
e7fcb7b2 1223This will return a list of builtin type constraints, meaning those
1224which are defined in this module. See the L<Default Type Constraints>
1225section for a complete list.
004222dc 1226
1227=item B<export_type_constraints_as_functions>
1228
e7fcb7b2 1229This will export all the current type constraints as functions into
1230the caller's namespace (C<Int()>, C<Str()>, etc). Right now, this is
1231mostly used for testing, but it might prove useful to others.
004222dc 1232
1233=item B<get_all_parameterizable_types>
1234
e7fcb7b2 1235This returns all the parameterizable types that have been registered,
1236as a list of type objects.
004222dc 1237
e7fcb7b2 1238=item B<add_parameterizable_type($type)>
004222dc 1239
1240Adds C<$type> to the list of parameterizable types
1241
1242=back
1243
a15dff8d 1244=head1 BUGS
1245
e85d2a5d 1246All complex software has bugs lurking in it, and this module is no
a15dff8d 1247exception. If you find a bug please either email me, or add the bug
1248to cpan-RT.
1249
a15dff8d 1250=head1 AUTHOR
1251
1252Stevan Little E<lt>stevan@iinteractive.comE<gt>
1253
1254=head1 COPYRIGHT AND LICENSE
1255
2840a3b2 1256Copyright 2006-2009 by Infinity Interactive, Inc.
a15dff8d 1257
1258L<http://www.iinteractive.com>
1259
1260This library is free software; you can redistribute it and/or modify
e85d2a5d 1261it under the same terms as Perl itself.
a15dff8d 1262
81dc201f 1263=cut