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