adding the match_on_type function to Moose::Util::TypeConstraints
[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
113d3174 9our $VERSION = '0.91';
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 }
470 {
471 local $_ = $to_match;
472 return $default->($to_match) if $default;
473 }
474}
475
476
d9b40005 477## --------------------------------------------------------
478## desugaring functions ...
479## --------------------------------------------------------
480
e85d2a5d 481sub _create_type_constraint ($$$;$$) {
9a63faba 482 my $name = shift;
483 my $parent = shift;
484 my $check = shift;
485 my $message = shift;
486 my $optimized = shift;
d9b40005 487
9a63faba 488 my $pkg_defined_in = scalar( caller(1) );
e85d2a5d 489
1da6728b 490 if ( defined $name ) {
d9b40005 491 my $type = $REGISTRY->get_type_constraint($name);
e85d2a5d 492
5f223879 493 ( $type->_package_defined_in eq $pkg_defined_in )
494 || _confess(
495 "The type constraint '$name' has already been created in "
496 . $type->_package_defined_in
497 . " and cannot be created again in "
498 . $pkg_defined_in )
499 if defined $type;
eee1a213 500
501 $name =~ /^[\w:\.]+$/
502 or die qq{$name contains invalid characters for a type name.}
33c8a6d0 503 . qq{ Names can contain alphanumeric character, ":", and "."\n};
e85d2a5d 504 }
1da6728b 505
9ceb576e 506 my %opts = (
9a63faba 507 name => $name,
d9b40005 508 package_defined_in => $pkg_defined_in,
e85d2a5d 509
1da6728b 510 ( $check ? ( constraint => $check ) : () ),
511 ( $message ? ( message => $message ) : () ),
512 ( $optimized ? ( optimized => $optimized ) : () ),
d9b40005 513 );
1da6728b 514
9ceb576e 515 my $constraint;
180899ed 516 if (
517 defined $parent
1da6728b 518 and $parent
180899ed 519 = blessed $parent
520 ? $parent
521 : find_or_create_isa_type_constraint($parent)
522 ) {
85a9908f 523 $constraint = $parent->create_child_type(%opts);
1da6728b 524 }
525 else {
526 $constraint = Moose::Meta::TypeConstraint->new(%opts);
4ab662d6 527 }
d9b40005 528
529 $REGISTRY->add_type_constraint($constraint)
530 if defined $name;
531
532 return $constraint;
533}
534
e85d2a5d 535sub _install_type_coercions ($$) {
180899ed 536 my ( $type_name, $coercion_map ) = @_;
e606ae5f 537 my $type = find_type_constraint($type_name);
180899ed 538 ( defined $type )
539 || __PACKAGE__->_throw_error(
a885c019 540 "Cannot find type '$type_name', perhaps you forgot to load it");
180899ed 541 if ( $type->has_coercion ) {
41e007e4 542 $type->coercion->add_type_coercions(@$coercion_map);
543 }
544 else {
545 my $type_coercion = Moose::Meta::TypeCoercion->new(
546 type_coercion_map => $coercion_map,
547 type_constraint => $type
548 );
549 $type->coercion($type_coercion);
550 }
d9b40005 551}
552
553## --------------------------------------------------------
f1917f58 554## type notation parsing ...
555## --------------------------------------------------------
556
557{
180899ed 558
e85d2a5d 559 # All I have to say is mugwump++ cause I know
560 # do not even have enough regexp-fu to be able
561 # to have written this (I can only barely
f1917f58 562 # understand it as it is)
e85d2a5d 563 # - SL
564
f1917f58 565 use re "eval";
566
eee1a213 567 my $valid_chars = qr{[\w:\.]};
f1917f58 568 my $type_atom = qr{ $valid_chars+ };
569
be722745 570 my $any;
571
180899ed 572 my $type = qr{ $valid_chars+ (?: \[ \s* (??{$any}) \s* \] )? }x;
573 my $type_capture_parts
574 = qr{ ($valid_chars+) (?: \[ \s* ((??{$any})) \s* \] )? }x;
575 my $type_with_parameter
576 = qr{ $valid_chars+ \[ \s* (??{$any}) \s* \] }x;
f1917f58 577
3796382a 578 my $op_union = qr{ \s* \| \s* }x;
f1917f58 579 my $union = qr{ $type (?: $op_union $type )+ }x;
580
84a9c64c 581 $any = qr{ $type | $union }x;
f1917f58 582
0fbd4b0a 583 sub _parse_parameterized_type_constraint {
180899ed 584 { no warnings 'void'; $any; } # force capture of interpolated lexical
84a9c64c 585 $_[0] =~ m{ $type_capture_parts }x;
180899ed 586 return ( $1, $2 );
f1917f58 587 }
588
0fbd4b0a 589 sub _detect_parameterized_type_constraint {
180899ed 590 { no warnings 'void'; $any; } # force capture of interpolated lexical
e85d2a5d 591 $_[0] =~ m{ ^ $type_with_parameter $ }x;
f1917f58 592 }
593
594 sub _parse_type_constraint_union {
180899ed 595 { no warnings 'void'; $any; } # force capture of interpolated lexical
e85d2a5d 596 my $given = shift;
597 my @rv;
598 while ( $given =~ m{ \G (?: $op_union )? ($type) }gcx ) {
82a5b1a7 599 push @rv => $1;
e85d2a5d 600 }
180899ed 601 ( pos($given) eq length($given) )
602 || __PACKAGE__->_throw_error( "'$given' didn't parse (parse-pos="
603 . pos($given)
604 . " and str-length="
605 . length($given)
606 . ")" );
e85d2a5d 607 @rv;
f1917f58 608 }
609
610 sub _detect_type_constraint_union {
180899ed 611 { no warnings 'void'; $any; } # force capture of interpolated lexical
e85d2a5d 612 $_[0] =~ m{^ $type $op_union $type ( $op_union .* )? $}x;
f1917f58 613 }
614}
615
616## --------------------------------------------------------
d9b40005 617# define some basic built-in types
618## --------------------------------------------------------
a15dff8d 619
3cae4250 620# By making these classes immutable before creating all the types we
621# below, we avoid repeatedly calling the slow MOP-based accessors.
622$_->make_immutable(
623 inline_constructor => 1,
624 constructor_name => "_new",
625
626 # these are Class::MOP accessors, so they need inlining
627 inline_accessors => 1
628 ) for grep { $_->is_mutable }
37edf27e 629 map { Class::MOP::class_of($_) }
3cae4250 630 qw(
631 Moose::Meta::TypeConstraint
632 Moose::Meta::TypeConstraint::Union
633 Moose::Meta::TypeConstraint::Parameterized
634 Moose::Meta::TypeConstraint::Parameterizable
635 Moose::Meta::TypeConstraint::Class
636 Moose::Meta::TypeConstraint::Role
637 Moose::Meta::TypeConstraint::Enum
0a6bff54 638 Moose::Meta::TypeConstraint::DuckType
3cae4250 639 Moose::Meta::TypeConstraint::Registry
640);
641
180899ed 642type 'Any' => where {1}; # meta-type including all
3054a5c9 643subtype 'Item' => as 'Any'; # base-type
a15dff8d 644
fd542f49 645subtype 'Undef' => as 'Item' => where { !defined($_) };
180899ed 646subtype 'Defined' => as 'Item' => where { defined($_) };
647
648subtype 'Bool' => as 'Item' =>
649 where { !defined($_) || $_ eq "" || "$_" eq '1' || "$_" eq '0' };
650
651subtype 'Value' => as 'Defined' => where { !ref($_) } =>
652 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Value;
653
654subtype 'Ref' => as 'Defined' => where { ref($_) } =>
655 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Ref;
656
657subtype 'Str' => as 'Value' => where {1} =>
658 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Str;
659
c29e3978 660subtype 'Num' => as 'Str' =>
180899ed 661 where { Scalar::Util::looks_like_number($_) } =>
662 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Num;
663
664subtype 'Int' => as 'Num' => where { "$_" =~ /^-?[0-9]+$/ } =>
665 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Int;
666
667subtype 'ScalarRef' => as 'Ref' => where { ref($_) eq 'SCALAR' } =>
668 optimize_as
669 \&Moose::Util::TypeConstraints::OptimizedConstraints::ScalarRef;
670subtype 'CodeRef' => as 'Ref' => where { ref($_) eq 'CODE' } =>
671 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::CodeRef;
672subtype 'RegexpRef' => as 'Ref' => where { ref($_) eq 'Regexp' } =>
673 optimize_as
674 \&Moose::Util::TypeConstraints::OptimizedConstraints::RegexpRef;
675subtype 'GlobRef' => as 'Ref' => where { ref($_) eq 'GLOB' } =>
676 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::GlobRef;
a15dff8d 677
0a5bd159 678# NOTE:
e85d2a5d 679# scalar filehandles are GLOB refs,
0a5bd159 680# but a GLOB ref is not always a filehandle
180899ed 681subtype 'FileHandle' => as 'GlobRef' => where {
682 Scalar::Util::openhandle($_) || ( blessed($_) && $_->isa("IO::Handle") );
683} => optimize_as
684 \&Moose::Util::TypeConstraints::OptimizedConstraints::FileHandle;
0a5bd159 685
e85d2a5d 686# NOTE:
a15dff8d 687# blessed(qr/.../) returns true,.. how odd
180899ed 688subtype 'Object' => as 'Ref' =>
689 where { blessed($_) && blessed($_) ne 'Regexp' } =>
690 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Object;
a15dff8d 691
4831e2de 692# This type is deprecated.
180899ed 693subtype 'Role' => as 'Object' => where { $_->can('does') } =>
694 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Role;
e85d2a5d 695
180899ed 696my $_class_name_checker = sub { };
0e0709ea 697
180899ed 698subtype 'ClassName' => as 'Str' =>
699 where { Class::MOP::is_class_loaded($_) } => optimize_as
700 \&Moose::Util::TypeConstraints::OptimizedConstraints::ClassName;
02a0fb52 701
180899ed 702subtype 'RoleName' => as 'ClassName' => where {
6b885dfa 703 (Class::MOP::class_of($_) || return)->isa('Moose::Meta::Role');
180899ed 704} => optimize_as
705 \&Moose::Util::TypeConstraints::OptimizedConstraints::RoleName;
f0cac16f 706
d9b40005 707## --------------------------------------------------------
7e4e1ad4 708# parameterizable types ...
709
710$REGISTRY->add_type_constraint(
711 Moose::Meta::TypeConstraint::Parameterizable->new(
180899ed 712 name => 'ArrayRef',
713 package_defined_in => __PACKAGE__,
714 parent => find_type_constraint('Ref'),
715 constraint => sub { ref($_) eq 'ARRAY' },
716 optimized =>
717 \&Moose::Util::TypeConstraints::OptimizedConstraints::ArrayRef,
7e4e1ad4 718 constraint_generator => sub {
719 my $type_parameter = shift;
180899ed 720 my $check = $type_parameter->_compiled_type_constraint;
7e4e1ad4 721 return sub {
722 foreach my $x (@$_) {
180899ed 723 ( $check->($x) ) || return;
724 }
725 1;
726 }
7e4e1ad4 727 }
728 )
729);
730
731$REGISTRY->add_type_constraint(
732 Moose::Meta::TypeConstraint::Parameterizable->new(
180899ed 733 name => 'HashRef',
734 package_defined_in => __PACKAGE__,
735 parent => find_type_constraint('Ref'),
736 constraint => sub { ref($_) eq 'HASH' },
737 optimized =>
738 \&Moose::Util::TypeConstraints::OptimizedConstraints::HashRef,
7e4e1ad4 739 constraint_generator => sub {
4ab662d6 740 my $type_parameter = shift;
180899ed 741 my $check = $type_parameter->_compiled_type_constraint;
7e4e1ad4 742 return sub {
180899ed 743 foreach my $x ( values %$_ ) {
744 ( $check->($x) ) || return;
745 }
746 1;
747 }
7e4e1ad4 748 }
749 )
750);
751
752$REGISTRY->add_type_constraint(
753 Moose::Meta::TypeConstraint::Parameterizable->new(
754 name => 'Maybe',
755 package_defined_in => __PACKAGE__,
756 parent => find_type_constraint('Item'),
180899ed 757 constraint => sub {1},
7e4e1ad4 758 constraint_generator => sub {
4ab662d6 759 my $type_parameter = shift;
180899ed 760 my $check = $type_parameter->_compiled_type_constraint;
7e4e1ad4 761 return sub {
180899ed 762 return 1 if not( defined($_) ) || $check->($_);
7e4e1ad4 763 return;
180899ed 764 }
7e4e1ad4 765 }
766 )
767);
768
180899ed 769my @PARAMETERIZABLE_TYPES
770 = map { $REGISTRY->get_type_constraint($_) } qw[ArrayRef HashRef Maybe];
771
772sub get_all_parameterizable_types {@PARAMETERIZABLE_TYPES}
7e4e1ad4 773
4ab662d6 774sub add_parameterizable_type {
7e4e1ad4 775 my $type = shift;
180899ed 776 ( blessed $type
777 && $type->isa('Moose::Meta::TypeConstraint::Parameterizable') )
778 || __PACKAGE__->_throw_error(
779 "Type must be a Moose::Meta::TypeConstraint::Parameterizable not $type"
780 );
7e4e1ad4 781 push @PARAMETERIZABLE_TYPES => $type;
4ab662d6 782}
7e4e1ad4 783
784## --------------------------------------------------------
d9b40005 785# end of built-in types ...
786## --------------------------------------------------------
787
943596a6 788{
789 my @BUILTINS = list_all_type_constraints();
180899ed 790 sub list_all_builtin_type_constraints {@BUILTINS}
943596a6 791}
792
6ea98933 793sub _throw_error {
6b83828f 794 shift;
6ea98933 795 require Moose;
796 unshift @_, 'Moose';
797 goto &Moose::throw_error;
798}
799
a15dff8d 8001;
801
802__END__
803
804=pod
805
806=head1 NAME
807
e522431d 808Moose::Util::TypeConstraints - Type constraint system for Moose
a15dff8d 809
810=head1 SYNOPSIS
811
812 use Moose::Util::TypeConstraints;
813
e85d2a5d 814 subtype 'Natural'
e606ae5f 815 => as 'Int'
a15dff8d 816 => where { $_ > 0 };
e85d2a5d 817
818 subtype 'NaturalLessThanTen'
2c0cbef7 819 => as 'Natural'
79592a54 820 => where { $_ < 10 }
821 => message { "This number ($_) is not less than ten!" };
e85d2a5d 822
823 coerce 'Num'
2c0cbef7 824 => from 'Str'
e85d2a5d 825 => via { 0+$_ };
826
2c0cbef7 827 enum 'RGBColors' => qw(red green blue);
a15dff8d 828
e7fcb7b2 829 no Moose::Util::TypeConstraints;
830
a15dff8d 831=head1 DESCRIPTION
832
e85d2a5d 833This module provides Moose with the ability to create custom type
6549b0d1 834constraints to be used in attribute definition.
e522431d 835
6ba6d68c 836=head2 Important Caveat
837
e85d2a5d 838This is B<NOT> a type system for Perl 5. These are type constraints,
839and they are not used by Moose unless you tell it to. No type
e7fcb7b2 840inference is performed, expressions are not typed, etc. etc. etc.
6ba6d68c 841
e7fcb7b2 842A type constraint is at heart a small "check if a value is valid"
843function. A constraint can be associated with an attribute. This
844simplifies parameter validation, and makes your code clearer to read,
845because you can refer to constraints by name.
6ba6d68c 846
2c0cbef7 847=head2 Slightly Less Important Caveat
848
e7fcb7b2 849It is B<always> a good idea to quote your type names.
004222dc 850
e7fcb7b2 851This prevents Perl from trying to execute the call as an indirect
852object call. This can be an issue when you have a subtype with the
853same name as a valid class.
2c0cbef7 854
e7fcb7b2 855For instance:
e85d2a5d 856
2c0cbef7 857 subtype DateTime => as Object => where { $_->isa('DateTime') };
858
e7fcb7b2 859will I<just work>, while this:
2c0cbef7 860
861 use DateTime;
862 subtype DateTime => as Object => where { $_->isa('DateTime') };
863
e85d2a5d 864will fail silently and cause many headaches. The simple way to solve
865this, as well as future proof your subtypes from classes which have
e7fcb7b2 866yet to have been created, is to quote the type name:
2c0cbef7 867
868 use DateTime;
d44714be 869 subtype 'DateTime' => as 'Object' => where { $_->isa('DateTime') };
2c0cbef7 870
6ba6d68c 871=head2 Default Type Constraints
e522431d 872
e606ae5f 873This module also provides a simple hierarchy for Perl 5 types, here is
004222dc 874that hierarchy represented visually.
e522431d 875
876 Any
e85d2a5d 877 Item
5a4c5493 878 Bool
7e4e1ad4 879 Maybe[`a]
f65cb534 880 Undef
881 Defined
5a4c5493 882 Value
883 Num
fcb5b0cd 884 Int
5a4c5493 885 Str
fcb5b0cd 886 ClassName
887 RoleName
5a4c5493 888 Ref
889 ScalarRef
7e4e1ad4 890 ArrayRef[`a]
891 HashRef[`a]
5a4c5493 892 CodeRef
893 RegexpRef
3f7376b0 894 GlobRef
fcb5b0cd 895 FileHandle
e85d2a5d 896 Object
e522431d 897
4ab662d6 898B<NOTE:> Any type followed by a type parameter C<[`a]> can be
7e4e1ad4 899parameterized, this means you can say:
900
757e07ef 901 ArrayRef[Int] # an array of integers
7e4e1ad4 902 HashRef[CodeRef] # a hash of str to CODE ref mappings
903 Maybe[Str] # value may be a string, may be undefined
904
4e8a0f64 905If Moose finds a name in brackets that it does not recognize as an
906existing type, it assumes that this is a class name, for example
907C<ArrayRef[DateTime]>.
908
e7fcb7b2 909B<NOTE:> Unless you parameterize a type, then it is invalid to include
910the square brackets. I.e. C<ArrayRef[]> will be treated as a new type
911name, I<not> as a parameterization of C<ArrayRef>.
e606ae5f 912
4ab662d6 913B<NOTE:> The C<Undef> type constraint for the most part works
914correctly now, but edge cases may still exist, please use it
6549b0d1 915sparingly.
703e92fb 916
7e4e1ad4 917B<NOTE:> The C<ClassName> type constraint does a complex package
e7fcb7b2 918existence check. This means that your class B<must> be loaded for this
919type constraint to pass.
9af1d28b 920
e7fcb7b2 921B<NOTE:> The C<RoleName> constraint checks a string is a I<package
4831e2de 922name> which is a role, like C<'MyApp::Role::Comparable'>.
ed87d4fd 923
e606ae5f 924=head2 Type Constraint Naming
004222dc 925
eee1a213 926Type name declared via this module can only contain alphanumeric
927characters, colons (:), and periods (.).
928
e606ae5f 929Since the types created by this module are global, it is suggested
930that you namespace your types just as you would namespace your
e7fcb7b2 931modules. So instead of creating a I<Color> type for your
932B<My::Graphics> module, you would call the type
933I<My::Graphics::Types::Color> instead.
004222dc 934
703e92fb 935=head2 Use with Other Constraint Modules
936
e7fcb7b2 937This module can play nicely with other constraint modules with some
938slight tweaking. The C<where> clause in types is expected to be a
939C<CODE> reference which checks it's first argument and returns a
940boolean. Since most constraint modules work in a similar way, it
941should be simple to adapt them to work with Moose.
703e92fb 942
e85d2a5d 943For instance, this is how you could use it with
944L<Declare::Constraints::Simple> to declare a completely new type.
703e92fb 945
9e856c83 946 type 'HashOfArrayOfObjects',
947 {
948 where => IsHashRef(
703e92fb 949 -keys => HasLength,
9e856c83 950 -values => IsArrayRef(IsObject)
951 )
952 };
703e92fb 953
e7fcb7b2 954For more examples see the F<t/200_examples/004_example_w_DCS.t> test
955file.
703e92fb 956
e85d2a5d 957Here is an example of using L<Test::Deep> and it's non-test
958related C<eq_deeply> function.
703e92fb 959
e85d2a5d 960 type 'ArrayOfHashOfBarsAndRandomNumbers'
703e92fb 961 => where {
e85d2a5d 962 eq_deeply($_,
703e92fb 963 array_each(subhashof({
964 bar => isa('Bar'),
965 random_number => ignore()
e85d2a5d 966 })))
703e92fb 967 };
968
e606ae5f 969For a complete example see the
e7fcb7b2 970F<t/200_examples/005_example_w_TestDeep.t> test file.
e85d2a5d 971
a15dff8d 972=head1 FUNCTIONS
973
974=head2 Type Constraint Constructors
975
e7fcb7b2 976The following functions are used to create type constraints. They
977will also register the type constraints your create in a global
978registry that is used to look types up by name.
a15dff8d 979
25f2c3fc 980See the L<SYNOPSIS> for an example of how to use these.
a15dff8d 981
6ba6d68c 982=over 4
a15dff8d 983
fbe1e4a5 984=item B<< subtype 'Name' => as 'Parent' => where { } ... >>
182134e8 985
e85d2a5d 986This creates a named subtype.
d6e2d9a1 987
dba9208a 988If you provide a parent that Moose does not recognize, it will
989automatically create a new class type constraint for this name.
990
9e856c83 991When creating a named type, the C<subtype> function should either be
992called with the sugar helpers (C<where>, C<message>, etc), or with a
993name and a hashref of parameters:
994
995 subtype( 'Foo', { where => ..., message => ... } );
996
997The valid hashref keys are C<as> (the parent), C<where>, C<message>,
998and C<optimize_as>.
9a63faba 999
fbe1e4a5 1000=item B<< subtype as 'Parent' => where { } ... >>
182134e8 1001
e85d2a5d 1002This creates an unnamed subtype and will return the type
1003constraint meta-object, which will be an instance of
1004L<Moose::Meta::TypeConstraint>.
a15dff8d 1005
9e856c83 1006When creating an anonymous type, the C<subtype> function should either
1007be called with the sugar helpers (C<where>, C<message>, etc), or with
1008just a hashref of parameters:
1009
1010 subtype( { where => ..., message => ... } );
1011
620db045 1012=item B<class_type ($class, ?$options)>
3fef8ce8 1013
ed87d4fd 1014Creates a new subtype of C<Object> with the name C<$class> and the
1015metaclass L<Moose::Meta::TypeConstraint::Class>.
3fef8ce8 1016
620db045 1017=item B<role_type ($role, ?$options)>
1018
ed87d4fd 1019Creates a C<Role> type constraint with the name C<$role> and the
1020metaclass L<Moose::Meta::TypeConstraint::Role>.
620db045 1021
1b2c9bda 1022=item B<maybe_type ($type)>
1023
1024Creates a type constraint for either C<undef> or something of the
1025given type.
1026
e451e855 1027=item B<duck_type ($name, @methods)>
1028
88b68372 1029This will create a subtype of Object and test to make sure the value
1030C<can()> do the methods in C<@methods>.
1031
1032This is intended as an easy way to accept non-Moose objects that
1033provide a certain interface. If you're using Moose classes, we
1034recommend that you use a C<requires>-only Role instead.
e451e855 1035
1036=item B<duck_type (\@methods)>
1037
88b68372 1038If passed an ARRAY reference instead of the C<$name>, C<@methods>
1039pair, this will create an unnamed duck type. This can be used in an
91aecfa0 1040attribute definition like so:
e451e855 1041
88b68372 1042 has 'cache' => (
1043 is => 'ro',
1044 isa => duck_type( [qw( get_set )] ),
1045 );
e451e855 1046
fcec2383 1047=item B<enum ($name, @values)>
1048
e85d2a5d 1049This will create a basic subtype for a given set of strings.
1050The resulting constraint will be a subtype of C<Str> and
4ce56d04 1051will match any of the items in C<@values>. It is case sensitive.
1052See the L<SYNOPSIS> for a simple example.
2c0cbef7 1053
6549b0d1 1054B<NOTE:> This is not a true proper enum type, it is simply
1055a convenient constraint builder.
2c0cbef7 1056
9f4334a1 1057=item B<enum (\@values)>
1058
4ab662d6 1059If passed an ARRAY reference instead of the C<$name>, C<@values> pair,
9f4334a1 1060this will create an unnamed enum. This can then be used in an attribute
1061definition like so:
1062
1063 has 'sort_order' => (
1064 is => 'ro',
4ab662d6 1065 isa => enum([qw[ ascending descending ]]),
9f4334a1 1066 );
1067
e7fcb7b2 1068=item B<as 'Parent'>
a15dff8d 1069
6ba6d68c 1070This is just sugar for the type constraint construction syntax.
a15dff8d 1071
e7fcb7b2 1072It takes a single argument, which is the name of a parent type.
1073
1074=item B<where { ... }>
a15dff8d 1075
6ba6d68c 1076This is just sugar for the type constraint construction syntax.
76d37e5a 1077
e7fcb7b2 1078It takes a subroutine reference as an argument. When the type
1079constraint is tested, the reference is run with the value to be tested
1080in C<$_>. This reference should return true or false to indicate
1081whether or not the constraint check passed.
e606ae5f 1082
e7fcb7b2 1083=item B<message { ... }>
76d37e5a 1084
1085This is just sugar for the type constraint construction syntax.
a15dff8d 1086
e7fcb7b2 1087It takes a subroutine reference as an argument. When the type
1088constraint fails, then the code block is run with the value provided
1089in C<$_>. This reference should return a string, which will be used in
1090the text of the exception thrown.
e606ae5f 1091
e7fcb7b2 1092=item B<optimize_as { ... }>
8ecb1fa0 1093
e85d2a5d 1094This can be used to define a "hand optimized" version of your
d44714be 1095type constraint which can be used to avoid traversing a subtype
6549b0d1 1096constraint hierarchy.
d44714be 1097
e85d2a5d 1098B<NOTE:> You should only use this if you know what you are doing,
1099all the built in types use this, so your subtypes (assuming they
d44714be 1100are shallow) will not likely need to use this.
1101
78d0edd7 1102=item B<< type 'Name' => where { } ... >>
e7fcb7b2 1103
1104This creates a base type, which has no parent.
1105
1106The C<type> function should either be called with the sugar helpers
1107(C<where>, C<message>, etc), or with a name and a hashref of
1108parameters:
1109
1110 type( 'Foo', { where => ..., message => ... } );
1111
1112The valid hashref keys are C<where>, C<message>, and C<optimize_as>.
1113
6ba6d68c 1114=back
a15dff8d 1115
0d29b772 1116=head2 Type Constraint Utilities
1117
1118=over 4
1119
1120=item B<< match_on_type $value => ( $type => \&action, ... ?\&default ) >>
1121
1122This is a utility function for doing simple type based dispatching
1123similar to match/case in O'Caml and case/of in Haskell. It does not
1124claim to be as featureful as either of those and does not support any
1125kind of automatic destructuring bind. However it is suitable for a fair
1126amount of your dispatching needs, for instance, here is a simple
1127Perl pretty printer dispatching over the core Moose types.
1128
1129 sub ppprint {
1130 my $x = shift;
1131 match_on_type $x =>
1132 HashRef => sub {
1133 my $hash = shift;
1134 '{ ' . (join ", " => map {
1135 $_ . ' => ' . ppprint( $hash->{ $_ } )
1136 } sort keys %$hash ) . ' }' },
1137 ArrayRef => sub {
1138 my $array = shift;
1139 '[ '.(join ", " => map { ppprint( $_ ) } @$array ).' ]' },
1140 CodeRef => sub { 'sub { ... }' },
1141 RegexpRef => sub { 'qr/' . $_ . '/' },
1142 GlobRef => sub { '*' . B::svref_2object($_)->NAME },
1143 Object => sub { $_->can('to_string') ? $_->to_string : $_ },
1144 ScalarRef => sub { '\\' . ppprint( ${$_} ) },
1145 Num => sub { $_ },
1146 Str => sub { '"'. $_ . '"' },
1147 Undef => sub { 'undef' },
1148 => sub { die "I don't know what $_ is" };
1149 }
1150
1151Based on a mapping of C<$type> to C<\&action>, where C<$type> can be
1152either a string type or a L<Moose::Meta::TypeConstraint> object, and
1153C<\&action> is a CODE ref, this function will dispatch on the first
1154match for C<$value>. It is possible to have a catch-all at the end
1155in the form of a C<\&default> CODE ref
1156
1157=back
1158
6ba6d68c 1159=head2 Type Coercion Constructors
a15dff8d 1160
e7fcb7b2 1161You can define coercions for type constraints, which allow you to
1162automatically transform values to something valid for the type
1163constraint. If you ask your accessor to coerce, then Moose will run
1164the type-coercion code first, followed by the type constraint
1165check. This feature should be used carefully as it is very powerful
1166and could easily take off a limb if you are not careful.
a15dff8d 1167
25f2c3fc 1168See the L<SYNOPSIS> for an example of how to use these.
a15dff8d 1169
6ba6d68c 1170=over 4
a15dff8d 1171
e7fcb7b2 1172=item B<< coerce 'Name' => from 'OtherName' => via { ... } >>
a15dff8d 1173
e7fcb7b2 1174This defines a coercion from one type to another. The C<Name> argument
1175is the type you are coercing I<to>.
1176
1177=item B<from 'OtherName'>
a15dff8d 1178
6ba6d68c 1179This is just sugar for the type coercion construction syntax.
1180
e7fcb7b2 1181It takes a single type name (or type object), which is the type being
1182coerced I<from>.
1183
1184=item B<via { ... }>
a15dff8d 1185
6ba6d68c 1186This is just sugar for the type coercion construction syntax.
a15dff8d 1187
e7fcb7b2 1188It takes a subroutine reference. This reference will be called with
1189the value to be coerced in C<$_>. It is expected to return a new value
1190of the proper type for the coercion.
1191
a15dff8d 1192=back
1193
e7fcb7b2 1194=head2 Creating and Finding Type Constraints
1195
1196These are additional functions for creating and finding type
1197constraints. Most of these functions are not available for
1198importing. The ones that are importable as specified.
004222dc 1199
1200=over 4
1201
e7fcb7b2 1202=item B<find_type_constraint($type_name)>
eb4c4e82 1203
e7fcb7b2 1204This function can be used to locate the L<Moose::Meta::TypeConstraint>
1205object for a named type.
eb4c4e82 1206
e7fcb7b2 1207This function is importable.
004222dc 1208
e7fcb7b2 1209=item B<register_type_constraint($type_object)>
004222dc 1210
e7fcb7b2 1211This function will register a L<Moose::Meta::TypeConstraint> with the
1212global type registry.
004222dc 1213
e7fcb7b2 1214This function is importable.
004222dc 1215
e7fcb7b2 1216=item B<normalize_type_constraint_name($type_constraint_name)>
004222dc 1217
e7fcb7b2 1218This method takes a type constraint name and returns the normalized
1219form. This removes any whitespace in the string.
004222dc 1220
e7fcb7b2 1221=item B<create_type_constraint_union($pipe_separated_types | @type_constraint_names)>
004222dc 1222
e7fcb7b2 1223This can take a union type specification like C<'Int|ArrayRef[Int]'>,
1224or a list of names. It returns a new
1225L<Moose::Meta::TypeConstraint::Union> object.
004222dc 1226
e7fcb7b2 1227=item B<create_parameterized_type_constraint($type_name)>
620db045 1228
e7fcb7b2 1229Given a C<$type_name> in the form of C<'BaseType[ContainerType]'>,
1230this will create a new L<Moose::Meta::TypeConstraint::Parameterized>
1231object. The C<BaseType> must exist already exist as a parameterizable
1232type.
620db045 1233
e7fcb7b2 1234=item B<create_class_type_constraint($class, $options)>
dabed765 1235
e7fcb7b2 1236Given a class name this function will create a new
1237L<Moose::Meta::TypeConstraint::Class> object for that class name.
004222dc 1238
e7fcb7b2 1239The C<$options> is a hash reference that will be passed to the
1240L<Moose::Meta::TypeConstraint::Class> constructor (as a hash).
620db045 1241
e7fcb7b2 1242=item B<create_role_type_constraint($role, $options)>
620db045 1243
e7fcb7b2 1244Given a role name this function will create a new
1245L<Moose::Meta::TypeConstraint::Role> object for that role name.
620db045 1246
e7fcb7b2 1247The C<$options> is a hash reference that will be passed to the
1248L<Moose::Meta::TypeConstraint::Role> constructor (as a hash).
620db045 1249
8a6c8c47 1250=item B<create_enum_type_constraint($name, $values)>
1251
1252Given a enum name this function will create a new
1253L<Moose::Meta::TypeConstraint::Enum> object for that enum name.
1254
0a6bff54 1255=item B<create_duck_type_constraint($name, $methods)>
1256
1257Given a duck type name this function will create a new
1258L<Moose::Meta::TypeConstraint::DuckType> object for that enum name.
1259
e7fcb7b2 1260=item B<find_or_parse_type_constraint($type_name)>
620db045 1261
ec4b72d2 1262Given a type name, this first attempts to find a matching constraint
e7fcb7b2 1263in the global registry.
620db045 1264
e7fcb7b2 1265If the type name is a union or parameterized type, it will create a
1266new object of the appropriate, but if given a "regular" type that does
1267not yet exist, it simply returns false.
620db045 1268
e7fcb7b2 1269When given a union or parameterized type, the member or base type must
1270already exist.
620db045 1271
e7fcb7b2 1272If it creates a new union or parameterized type, it will add it to the
1273global registry.
004222dc 1274
e7fcb7b2 1275=item B<find_or_create_isa_type_constraint($type_name)>
004222dc 1276
e7fcb7b2 1277=item B<find_or_create_does_type_constraint($type_name)>
004222dc 1278
e7fcb7b2 1279These functions will first call C<find_or_parse_type_constraint>. If
1280that function does not return a type, a new anonymous type object will
1281be created.
004222dc 1282
e7fcb7b2 1283The C<isa> variant will use C<create_class_type_constraint> and the
1284C<does> variant will use C<create_role_type_constraint>.
004222dc 1285
1286=item B<get_type_constraint_registry>
1287
e7fcb7b2 1288Returns the L<Moose::Meta::TypeConstraint::Registry> object which
004222dc 1289keeps track of all type constraints.
1290
1291=item B<list_all_type_constraints>
1292
e7fcb7b2 1293This will return a list of type constraint names in the global
1294registry. You can then fetch the actual type object using
1295C<find_type_constraint($type_name)>.
004222dc 1296
1297=item B<list_all_builtin_type_constraints>
1298
e7fcb7b2 1299This will return a list of builtin type constraints, meaning those
1300which are defined in this module. See the L<Default Type Constraints>
1301section for a complete list.
004222dc 1302
1303=item B<export_type_constraints_as_functions>
1304
e7fcb7b2 1305This will export all the current type constraints as functions into
1306the caller's namespace (C<Int()>, C<Str()>, etc). Right now, this is
1307mostly used for testing, but it might prove useful to others.
004222dc 1308
1309=item B<get_all_parameterizable_types>
1310
e7fcb7b2 1311This returns all the parameterizable types that have been registered,
1312as a list of type objects.
004222dc 1313
e7fcb7b2 1314=item B<add_parameterizable_type($type)>
004222dc 1315
1316Adds C<$type> to the list of parameterizable types
1317
1318=back
1319
a15dff8d 1320=head1 BUGS
1321
e85d2a5d 1322All complex software has bugs lurking in it, and this module is no
a15dff8d 1323exception. If you find a bug please either email me, or add the bug
1324to cpan-RT.
1325
a15dff8d 1326=head1 AUTHOR
1327
1328Stevan Little E<lt>stevan@iinteractive.comE<gt>
1329
1330=head1 COPYRIGHT AND LICENSE
1331
2840a3b2 1332Copyright 2006-2009 by Infinity Interactive, Inc.
a15dff8d 1333
1334L<http://www.iinteractive.com>
1335
1336This library is free software; you can redistribute it and/or modify
e85d2a5d 1337it under the same terms as Perl itself.
a15dff8d 1338
81dc201f 1339=cut