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