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