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