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