The Object type constraint filters out Regexp
[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
e6ab9ca5 9our $VERSION = '0.83';
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 = $_;
58936059 374 my $class = blessed($obj) || return;
21e16327 375 return 0 unless all { $obj->can($_) } @methods;
cdacfaf3 376 return 1;
180899ed 377 },
378 sub {
379 my $obj = $_;
58936059 380 my $class = blessed($obj);
180899ed 381 my @missing_methods = grep { !$obj->can($_) } @methods;
382 return
58936059 383 "$class is missing methods '@missing_methods'";
180899ed 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(
a885c019 511 "Cannot find type '$type_name', perhaps you forgot to load it");
180899ed 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 }
37edf27e 600 map { Class::MOP::class_of($_) }
3cae4250 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
3054a5c9 613subtype 'Item' => as 'Any'; # 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
c29e3978 630subtype 'Num' => as 'Str' =>
180899ed 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 {
6b885dfa 672 (Class::MOP::class_of($_) || return)->isa('Moose::Meta::Role');
180899ed 673} => optimize_as
674 \&Moose::Util::TypeConstraints::OptimizedConstraints::RoleName;
f0cac16f 675
d9b40005 676## --------------------------------------------------------
7e4e1ad4 677# parameterizable types ...
678
679$REGISTRY->add_type_constraint(
680 Moose::Meta::TypeConstraint::Parameterizable->new(
180899ed 681 name => 'ArrayRef',
682 package_defined_in => __PACKAGE__,
683 parent => find_type_constraint('Ref'),
684 constraint => sub { ref($_) eq 'ARRAY' },
685 optimized =>
686 \&Moose::Util::TypeConstraints::OptimizedConstraints::ArrayRef,
7e4e1ad4 687 constraint_generator => sub {
688 my $type_parameter = shift;
180899ed 689 my $check = $type_parameter->_compiled_type_constraint;
7e4e1ad4 690 return sub {
691 foreach my $x (@$_) {
180899ed 692 ( $check->($x) ) || return;
693 }
694 1;
695 }
7e4e1ad4 696 }
697 )
698);
699
700$REGISTRY->add_type_constraint(
701 Moose::Meta::TypeConstraint::Parameterizable->new(
180899ed 702 name => 'HashRef',
703 package_defined_in => __PACKAGE__,
704 parent => find_type_constraint('Ref'),
705 constraint => sub { ref($_) eq 'HASH' },
706 optimized =>
707 \&Moose::Util::TypeConstraints::OptimizedConstraints::HashRef,
7e4e1ad4 708 constraint_generator => sub {
4ab662d6 709 my $type_parameter = shift;
180899ed 710 my $check = $type_parameter->_compiled_type_constraint;
7e4e1ad4 711 return sub {
180899ed 712 foreach my $x ( values %$_ ) {
713 ( $check->($x) ) || return;
714 }
715 1;
716 }
7e4e1ad4 717 }
718 )
719);
720
721$REGISTRY->add_type_constraint(
722 Moose::Meta::TypeConstraint::Parameterizable->new(
723 name => 'Maybe',
724 package_defined_in => __PACKAGE__,
725 parent => find_type_constraint('Item'),
180899ed 726 constraint => sub {1},
7e4e1ad4 727 constraint_generator => sub {
4ab662d6 728 my $type_parameter = shift;
180899ed 729 my $check = $type_parameter->_compiled_type_constraint;
7e4e1ad4 730 return sub {
180899ed 731 return 1 if not( defined($_) ) || $check->($_);
7e4e1ad4 732 return;
180899ed 733 }
7e4e1ad4 734 }
735 )
736);
737
180899ed 738my @PARAMETERIZABLE_TYPES
739 = map { $REGISTRY->get_type_constraint($_) } qw[ArrayRef HashRef Maybe];
740
741sub get_all_parameterizable_types {@PARAMETERIZABLE_TYPES}
7e4e1ad4 742
4ab662d6 743sub add_parameterizable_type {
7e4e1ad4 744 my $type = shift;
180899ed 745 ( blessed $type
746 && $type->isa('Moose::Meta::TypeConstraint::Parameterizable') )
747 || __PACKAGE__->_throw_error(
748 "Type must be a Moose::Meta::TypeConstraint::Parameterizable not $type"
749 );
7e4e1ad4 750 push @PARAMETERIZABLE_TYPES => $type;
4ab662d6 751}
7e4e1ad4 752
753## --------------------------------------------------------
d9b40005 754# end of built-in types ...
755## --------------------------------------------------------
756
943596a6 757{
758 my @BUILTINS = list_all_type_constraints();
180899ed 759 sub list_all_builtin_type_constraints {@BUILTINS}
943596a6 760}
761
6ea98933 762sub _throw_error {
6b83828f 763 shift;
6ea98933 764 require Moose;
765 unshift @_, 'Moose';
766 goto &Moose::throw_error;
767}
768
a15dff8d 7691;
770
771__END__
772
773=pod
774
775=head1 NAME
776
e522431d 777Moose::Util::TypeConstraints - Type constraint system for Moose
a15dff8d 778
779=head1 SYNOPSIS
780
781 use Moose::Util::TypeConstraints;
782
e85d2a5d 783 subtype 'Natural'
e606ae5f 784 => as 'Int'
a15dff8d 785 => where { $_ > 0 };
e85d2a5d 786
787 subtype 'NaturalLessThanTen'
2c0cbef7 788 => as 'Natural'
79592a54 789 => where { $_ < 10 }
790 => message { "This number ($_) is not less than ten!" };
e85d2a5d 791
792 coerce 'Num'
2c0cbef7 793 => from 'Str'
e85d2a5d 794 => via { 0+$_ };
795
2c0cbef7 796 enum 'RGBColors' => qw(red green blue);
a15dff8d 797
e7fcb7b2 798 no Moose::Util::TypeConstraints;
799
a15dff8d 800=head1 DESCRIPTION
801
e85d2a5d 802This module provides Moose with the ability to create custom type
6549b0d1 803constraints to be used in attribute definition.
e522431d 804
6ba6d68c 805=head2 Important Caveat
806
e85d2a5d 807This is B<NOT> a type system for Perl 5. These are type constraints,
808and they are not used by Moose unless you tell it to. No type
e7fcb7b2 809inference is performed, expressions are not typed, etc. etc. etc.
6ba6d68c 810
e7fcb7b2 811A type constraint is at heart a small "check if a value is valid"
812function. A constraint can be associated with an attribute. This
813simplifies parameter validation, and makes your code clearer to read,
814because you can refer to constraints by name.
6ba6d68c 815
2c0cbef7 816=head2 Slightly Less Important Caveat
817
e7fcb7b2 818It is B<always> a good idea to quote your type names.
004222dc 819
e7fcb7b2 820This prevents Perl from trying to execute the call as an indirect
821object call. This can be an issue when you have a subtype with the
822same name as a valid class.
2c0cbef7 823
e7fcb7b2 824For instance:
e85d2a5d 825
2c0cbef7 826 subtype DateTime => as Object => where { $_->isa('DateTime') };
827
e7fcb7b2 828will I<just work>, while this:
2c0cbef7 829
830 use DateTime;
831 subtype DateTime => as Object => where { $_->isa('DateTime') };
832
e85d2a5d 833will fail silently and cause many headaches. The simple way to solve
834this, as well as future proof your subtypes from classes which have
e7fcb7b2 835yet to have been created, is to quote the type name:
2c0cbef7 836
837 use DateTime;
d44714be 838 subtype 'DateTime' => as 'Object' => where { $_->isa('DateTime') };
2c0cbef7 839
6ba6d68c 840=head2 Default Type Constraints
e522431d 841
e606ae5f 842This module also provides a simple hierarchy for Perl 5 types, here is
004222dc 843that hierarchy represented visually.
e522431d 844
845 Any
e85d2a5d 846 Item
5a4c5493 847 Bool
7e4e1ad4 848 Maybe[`a]
f65cb534 849 Undef
850 Defined
5a4c5493 851 Value
852 Num
853 Int
854 Str
9af1d28b 855 ClassName
ed87d4fd 856 RoleName
5a4c5493 857 Ref
858 ScalarRef
7e4e1ad4 859 ArrayRef[`a]
860 HashRef[`a]
5a4c5493 861 CodeRef
862 RegexpRef
3f7376b0 863 GlobRef
0a5bd159 864 FileHandle
e85d2a5d 865 Object
2cbb5233 866 Role
e522431d 867
4ab662d6 868B<NOTE:> Any type followed by a type parameter C<[`a]> can be
7e4e1ad4 869parameterized, this means you can say:
870
757e07ef 871 ArrayRef[Int] # an array of integers
7e4e1ad4 872 HashRef[CodeRef] # a hash of str to CODE ref mappings
873 Maybe[Str] # value may be a string, may be undefined
874
4e8a0f64 875If Moose finds a name in brackets that it does not recognize as an
876existing type, it assumes that this is a class name, for example
877C<ArrayRef[DateTime]>.
878
e7fcb7b2 879B<NOTE:> Unless you parameterize a type, then it is invalid to include
880the square brackets. I.e. C<ArrayRef[]> will be treated as a new type
881name, I<not> as a parameterization of C<ArrayRef>.
e606ae5f 882
4ab662d6 883B<NOTE:> The C<Undef> type constraint for the most part works
884correctly now, but edge cases may still exist, please use it
6549b0d1 885sparingly.
703e92fb 886
7e4e1ad4 887B<NOTE:> The C<ClassName> type constraint does a complex package
e7fcb7b2 888existence check. This means that your class B<must> be loaded for this
889type constraint to pass.
9af1d28b 890
e7fcb7b2 891B<NOTE:> The C<RoleName> constraint checks a string is a I<package
892name> which is a role, like C<'MyApp::Role::Comparable'>. The C<Role>
893constraint checks that an I<object does> the named role.
ed87d4fd 894
e606ae5f 895=head2 Type Constraint Naming
004222dc 896
eee1a213 897Type name declared via this module can only contain alphanumeric
898characters, colons (:), and periods (.).
899
e606ae5f 900Since the types created by this module are global, it is suggested
901that you namespace your types just as you would namespace your
e7fcb7b2 902modules. So instead of creating a I<Color> type for your
903B<My::Graphics> module, you would call the type
904I<My::Graphics::Types::Color> instead.
004222dc 905
703e92fb 906=head2 Use with Other Constraint Modules
907
e7fcb7b2 908This module can play nicely with other constraint modules with some
909slight tweaking. The C<where> clause in types is expected to be a
910C<CODE> reference which checks it's first argument and returns a
911boolean. Since most constraint modules work in a similar way, it
912should be simple to adapt them to work with Moose.
703e92fb 913
e85d2a5d 914For instance, this is how you could use it with
915L<Declare::Constraints::Simple> to declare a completely new type.
703e92fb 916
9e856c83 917 type 'HashOfArrayOfObjects',
918 {
919 where => IsHashRef(
703e92fb 920 -keys => HasLength,
9e856c83 921 -values => IsArrayRef(IsObject)
922 )
923 };
703e92fb 924
e7fcb7b2 925For more examples see the F<t/200_examples/004_example_w_DCS.t> test
926file.
703e92fb 927
e85d2a5d 928Here is an example of using L<Test::Deep> and it's non-test
929related C<eq_deeply> function.
703e92fb 930
e85d2a5d 931 type 'ArrayOfHashOfBarsAndRandomNumbers'
703e92fb 932 => where {
e85d2a5d 933 eq_deeply($_,
703e92fb 934 array_each(subhashof({
935 bar => isa('Bar'),
936 random_number => ignore()
e85d2a5d 937 })))
703e92fb 938 };
939
e606ae5f 940For a complete example see the
e7fcb7b2 941F<t/200_examples/005_example_w_TestDeep.t> test file.
e85d2a5d 942
a15dff8d 943=head1 FUNCTIONS
944
945=head2 Type Constraint Constructors
946
e7fcb7b2 947The following functions are used to create type constraints. They
948will also register the type constraints your create in a global
949registry that is used to look types up by name.
a15dff8d 950
25f2c3fc 951See the L<SYNOPSIS> for an example of how to use these.
a15dff8d 952
6ba6d68c 953=over 4
a15dff8d 954
fbe1e4a5 955=item B<< subtype 'Name' => as 'Parent' => where { } ... >>
182134e8 956
e85d2a5d 957This creates a named subtype.
d6e2d9a1 958
dba9208a 959If you provide a parent that Moose does not recognize, it will
960automatically create a new class type constraint for this name.
961
9e856c83 962When creating a named type, the C<subtype> function should either be
963called with the sugar helpers (C<where>, C<message>, etc), or with a
964name and a hashref of parameters:
965
966 subtype( 'Foo', { where => ..., message => ... } );
967
968The valid hashref keys are C<as> (the parent), C<where>, C<message>,
969and C<optimize_as>.
9a63faba 970
fbe1e4a5 971=item B<< subtype as 'Parent' => where { } ... >>
182134e8 972
e85d2a5d 973This creates an unnamed subtype and will return the type
974constraint meta-object, which will be an instance of
975L<Moose::Meta::TypeConstraint>.
a15dff8d 976
9e856c83 977When creating an anonymous type, the C<subtype> function should either
978be called with the sugar helpers (C<where>, C<message>, etc), or with
979just a hashref of parameters:
980
981 subtype( { where => ..., message => ... } );
982
620db045 983=item B<class_type ($class, ?$options)>
3fef8ce8 984
ed87d4fd 985Creates a new subtype of C<Object> with the name C<$class> and the
986metaclass L<Moose::Meta::TypeConstraint::Class>.
3fef8ce8 987
620db045 988=item B<role_type ($role, ?$options)>
989
ed87d4fd 990Creates a C<Role> type constraint with the name C<$role> and the
991metaclass L<Moose::Meta::TypeConstraint::Role>.
620db045 992
1b2c9bda 993=item B<maybe_type ($type)>
994
995Creates a type constraint for either C<undef> or something of the
996given type.
997
e451e855 998=item B<duck_type ($name, @methods)>
999
88b68372 1000This will create a subtype of Object and test to make sure the value
1001C<can()> do the methods in C<@methods>.
1002
1003This is intended as an easy way to accept non-Moose objects that
1004provide a certain interface. If you're using Moose classes, we
1005recommend that you use a C<requires>-only Role instead.
e451e855 1006
1007=item B<duck_type (\@methods)>
1008
88b68372 1009If passed an ARRAY reference instead of the C<$name>, C<@methods>
1010pair, this will create an unnamed duck type. This can be used in an
91aecfa0 1011attribute definition like so:
e451e855 1012
88b68372 1013 has 'cache' => (
1014 is => 'ro',
1015 isa => duck_type( [qw( get_set )] ),
1016 );
e451e855 1017
fcec2383 1018=item B<enum ($name, @values)>
1019
e85d2a5d 1020This will create a basic subtype for a given set of strings.
1021The resulting constraint will be a subtype of C<Str> and
4ce56d04 1022will match any of the items in C<@values>. It is case sensitive.
1023See the L<SYNOPSIS> for a simple example.
2c0cbef7 1024
6549b0d1 1025B<NOTE:> This is not a true proper enum type, it is simply
1026a convenient constraint builder.
2c0cbef7 1027
9f4334a1 1028=item B<enum (\@values)>
1029
4ab662d6 1030If passed an ARRAY reference instead of the C<$name>, C<@values> pair,
9f4334a1 1031this will create an unnamed enum. This can then be used in an attribute
1032definition like so:
1033
1034 has 'sort_order' => (
1035 is => 'ro',
4ab662d6 1036 isa => enum([qw[ ascending descending ]]),
9f4334a1 1037 );
1038
e7fcb7b2 1039=item B<as 'Parent'>
a15dff8d 1040
6ba6d68c 1041This is just sugar for the type constraint construction syntax.
a15dff8d 1042
e7fcb7b2 1043It takes a single argument, which is the name of a parent type.
1044
1045=item B<where { ... }>
a15dff8d 1046
6ba6d68c 1047This is just sugar for the type constraint construction syntax.
76d37e5a 1048
e7fcb7b2 1049It takes a subroutine reference as an argument. When the type
1050constraint is tested, the reference is run with the value to be tested
1051in C<$_>. This reference should return true or false to indicate
1052whether or not the constraint check passed.
e606ae5f 1053
e7fcb7b2 1054=item B<message { ... }>
76d37e5a 1055
1056This is just sugar for the type constraint construction syntax.
a15dff8d 1057
e7fcb7b2 1058It takes a subroutine reference as an argument. When the type
1059constraint fails, then the code block is run with the value provided
1060in C<$_>. This reference should return a string, which will be used in
1061the text of the exception thrown.
e606ae5f 1062
e7fcb7b2 1063=item B<optimize_as { ... }>
8ecb1fa0 1064
e85d2a5d 1065This can be used to define a "hand optimized" version of your
d44714be 1066type constraint which can be used to avoid traversing a subtype
6549b0d1 1067constraint hierarchy.
d44714be 1068
e85d2a5d 1069B<NOTE:> You should only use this if you know what you are doing,
1070all the built in types use this, so your subtypes (assuming they
d44714be 1071are shallow) will not likely need to use this.
1072
e7fcb7b2 1073=item B<type 'Name' => where { } ... >
1074
1075This creates a base type, which has no parent.
1076
1077The C<type> function should either be called with the sugar helpers
1078(C<where>, C<message>, etc), or with a name and a hashref of
1079parameters:
1080
1081 type( 'Foo', { where => ..., message => ... } );
1082
1083The valid hashref keys are C<where>, C<message>, and C<optimize_as>.
1084
6ba6d68c 1085=back
a15dff8d 1086
6ba6d68c 1087=head2 Type Coercion Constructors
a15dff8d 1088
e7fcb7b2 1089You can define coercions for type constraints, which allow you to
1090automatically transform values to something valid for the type
1091constraint. If you ask your accessor to coerce, then Moose will run
1092the type-coercion code first, followed by the type constraint
1093check. This feature should be used carefully as it is very powerful
1094and could easily take off a limb if you are not careful.
a15dff8d 1095
25f2c3fc 1096See the L<SYNOPSIS> for an example of how to use these.
a15dff8d 1097
6ba6d68c 1098=over 4
a15dff8d 1099
e7fcb7b2 1100=item B<< coerce 'Name' => from 'OtherName' => via { ... } >>
a15dff8d 1101
e7fcb7b2 1102This defines a coercion from one type to another. The C<Name> argument
1103is the type you are coercing I<to>.
1104
1105=item B<from 'OtherName'>
a15dff8d 1106
6ba6d68c 1107This is just sugar for the type coercion construction syntax.
1108
e7fcb7b2 1109It takes a single type name (or type object), which is the type being
1110coerced I<from>.
1111
1112=item B<via { ... }>
a15dff8d 1113
6ba6d68c 1114This is just sugar for the type coercion construction syntax.
a15dff8d 1115
e7fcb7b2 1116It takes a subroutine reference. This reference will be called with
1117the value to be coerced in C<$_>. It is expected to return a new value
1118of the proper type for the coercion.
1119
a15dff8d 1120=back
1121
e7fcb7b2 1122=head2 Creating and Finding Type Constraints
1123
1124These are additional functions for creating and finding type
1125constraints. Most of these functions are not available for
1126importing. The ones that are importable as specified.
004222dc 1127
1128=over 4
1129
e7fcb7b2 1130=item B<find_type_constraint($type_name)>
eb4c4e82 1131
e7fcb7b2 1132This function can be used to locate the L<Moose::Meta::TypeConstraint>
1133object for a named type.
eb4c4e82 1134
e7fcb7b2 1135This function is importable.
004222dc 1136
e7fcb7b2 1137=item B<register_type_constraint($type_object)>
004222dc 1138
e7fcb7b2 1139This function will register a L<Moose::Meta::TypeConstraint> with the
1140global type registry.
004222dc 1141
e7fcb7b2 1142This function is importable.
004222dc 1143
e7fcb7b2 1144=item B<normalize_type_constraint_name($type_constraint_name)>
004222dc 1145
e7fcb7b2 1146This method takes a type constraint name and returns the normalized
1147form. This removes any whitespace in the string.
004222dc 1148
e7fcb7b2 1149=item B<create_type_constraint_union($pipe_separated_types | @type_constraint_names)>
004222dc 1150
e7fcb7b2 1151This can take a union type specification like C<'Int|ArrayRef[Int]'>,
1152or a list of names. It returns a new
1153L<Moose::Meta::TypeConstraint::Union> object.
004222dc 1154
e7fcb7b2 1155=item B<create_parameterized_type_constraint($type_name)>
620db045 1156
e7fcb7b2 1157Given a C<$type_name> in the form of C<'BaseType[ContainerType]'>,
1158this will create a new L<Moose::Meta::TypeConstraint::Parameterized>
1159object. The C<BaseType> must exist already exist as a parameterizable
1160type.
620db045 1161
e7fcb7b2 1162=item B<create_class_type_constraint($class, $options)>
dabed765 1163
e7fcb7b2 1164Given a class name this function will create a new
1165L<Moose::Meta::TypeConstraint::Class> object for that class name.
004222dc 1166
e7fcb7b2 1167The C<$options> is a hash reference that will be passed to the
1168L<Moose::Meta::TypeConstraint::Class> constructor (as a hash).
620db045 1169
e7fcb7b2 1170=item B<create_role_type_constraint($role, $options)>
620db045 1171
e7fcb7b2 1172Given a role name this function will create a new
1173L<Moose::Meta::TypeConstraint::Role> object for that role name.
620db045 1174
e7fcb7b2 1175The C<$options> is a hash reference that will be passed to the
1176L<Moose::Meta::TypeConstraint::Role> constructor (as a hash).
620db045 1177
8a6c8c47 1178=item B<create_enum_type_constraint($name, $values)>
1179
1180Given a enum name this function will create a new
1181L<Moose::Meta::TypeConstraint::Enum> object for that enum name.
1182
e7fcb7b2 1183=item B<find_or_parse_type_constraint($type_name)>
620db045 1184
ec4b72d2 1185Given a type name, this first attempts to find a matching constraint
e7fcb7b2 1186in the global registry.
620db045 1187
e7fcb7b2 1188If the type name is a union or parameterized type, it will create a
1189new object of the appropriate, but if given a "regular" type that does
1190not yet exist, it simply returns false.
620db045 1191
e7fcb7b2 1192When given a union or parameterized type, the member or base type must
1193already exist.
620db045 1194
e7fcb7b2 1195If it creates a new union or parameterized type, it will add it to the
1196global registry.
004222dc 1197
e7fcb7b2 1198=item B<find_or_create_isa_type_constraint($type_name)>
004222dc 1199
e7fcb7b2 1200=item B<find_or_create_does_type_constraint($type_name)>
004222dc 1201
e7fcb7b2 1202These functions will first call C<find_or_parse_type_constraint>. If
1203that function does not return a type, a new anonymous type object will
1204be created.
004222dc 1205
e7fcb7b2 1206The C<isa> variant will use C<create_class_type_constraint> and the
1207C<does> variant will use C<create_role_type_constraint>.
004222dc 1208
1209=item B<get_type_constraint_registry>
1210
e7fcb7b2 1211Returns the L<Moose::Meta::TypeConstraint::Registry> object which
004222dc 1212keeps track of all type constraints.
1213
1214=item B<list_all_type_constraints>
1215
e7fcb7b2 1216This will return a list of type constraint names in the global
1217registry. You can then fetch the actual type object using
1218C<find_type_constraint($type_name)>.
004222dc 1219
1220=item B<list_all_builtin_type_constraints>
1221
e7fcb7b2 1222This will return a list of builtin type constraints, meaning those
1223which are defined in this module. See the L<Default Type Constraints>
1224section for a complete list.
004222dc 1225
1226=item B<export_type_constraints_as_functions>
1227
e7fcb7b2 1228This will export all the current type constraints as functions into
1229the caller's namespace (C<Int()>, C<Str()>, etc). Right now, this is
1230mostly used for testing, but it might prove useful to others.
004222dc 1231
1232=item B<get_all_parameterizable_types>
1233
e7fcb7b2 1234This returns all the parameterizable types that have been registered,
1235as a list of type objects.
004222dc 1236
e7fcb7b2 1237=item B<add_parameterizable_type($type)>
004222dc 1238
1239Adds C<$type> to the list of parameterizable types
1240
1241=back
1242
a15dff8d 1243=head1 BUGS
1244
e85d2a5d 1245All complex software has bugs lurking in it, and this module is no
a15dff8d 1246exception. If you find a bug please either email me, or add the bug
1247to cpan-RT.
1248
a15dff8d 1249=head1 AUTHOR
1250
1251Stevan Little E<lt>stevan@iinteractive.comE<gt>
1252
1253=head1 COPYRIGHT AND LICENSE
1254
2840a3b2 1255Copyright 2006-2009 by Infinity Interactive, Inc.
a15dff8d 1256
1257L<http://www.iinteractive.com>
1258
1259This library is free software; you can redistribute it and/or modify
e85d2a5d 1260it under the same terms as Perl itself.
a15dff8d 1261
81dc201f 1262=cut