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