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