X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMoose%2FUtil%2FTypeConstraints.pm;h=b70c8707a6b4a382e34f044b099630d1bbac2275;hb=34a66aa3423e251341c77ba790950eae4fbcfff9;hp=3e6a8546731ef42be971b2abf131c64f2380fcb2;hpb=182134e8438a301a8e75a95cdd74e65987d11f13;p=gitmo%2FMoose.git diff --git a/lib/Moose/Util/TypeConstraints.pm b/lib/Moose/Util/TypeConstraints.pm index 3e6a854..b70c870 100644 --- a/lib/Moose/Util/TypeConstraints.pm +++ b/lib/Moose/Util/TypeConstraints.pm @@ -4,102 +4,85 @@ package Moose::Util::TypeConstraints; use strict; use warnings; -use Sub::Name 'subname'; +use Carp 'confess'; use Scalar::Util 'blessed'; our $VERSION = '0.02'; +use Moose::Meta::TypeConstraint; +use Moose::Meta::TypeCoercion; + sub import { shift; my $pkg = shift || caller(); - return if $pkg eq ':no_export'; + return if $pkg eq '-no-export'; no strict 'refs'; - foreach my $export (qw(type subtype coerce as where to)) { + foreach my $export (qw(type subtype as where coerce from via find_type_constraint)) { *{"${pkg}::${export}"} = \&{"${export}"}; } } { my %TYPES; - sub find_type_constraint { - my $type_name = shift; - $TYPES{$type_name}; + sub find_type_constraint { $TYPES{$_[0]} } + + sub _create_type_constraint { + my ($name, $parent, $check) = @_; + (!exists $TYPES{$name}) + || confess "The type constraint '$name' has already been created" + if defined $name; + $parent = $TYPES{$parent} if defined $parent; + my $constraint = Moose::Meta::TypeConstraint->new( + name => $name || '__ANON__', + parent => $parent, + constraint => $check, + ); + $TYPES{$name} = $constraint if defined $name; + return $constraint; } - sub register_type_constraint { - my ($type_name, $type_constraint) = @_; - $TYPES{$type_name} = $type_constraint; + sub _install_type_coercions { + my ($type_name, $coercion_map) = @_; + my $type = $TYPES{$type_name}; + (!$type->has_coercion) + || confess "The type coercion for '$type_name' has already been registered"; + my $type_coercion = Moose::Meta::TypeCoercion->new( + type_coercion_map => $coercion_map, + type_constraint => $type + ); + $type->coercion($type_coercion); } sub export_type_contstraints_as_functions { my $pkg = caller(); no strict 'refs'; foreach my $constraint (keys %TYPES) { - *{"${pkg}::${constraint}"} = $TYPES{$constraint}; + *{"${pkg}::${constraint}"} = $TYPES{$constraint}->_compiled_type_constraint; } - } -} - -{ - my %COERCIONS; - sub find_type_coercion { - my $type_name = shift; - $COERCIONS{$type_name}; - } - - sub register_type_coercion { - my ($type_name, $type_coercion) = @_; - $COERCIONS{$type_name} = $type_coercion; - } + } } +# type constructors sub type ($$) { my ($name, $check) = @_; - my $full_name = caller() . "::${name}"; - register_type_constraint($name => subname $full_name => sub { - return find_type_constraint($name) unless defined $_[0]; - local $_ = $_[0]; - return undef unless $check->($_[0]); - $_[0]; - }); + _create_type_constraint($name, undef, $check); } sub subtype ($$;$) { - my ($name, $parent, $check) = @_; - if (defined $check) { - my $full_name = caller() . "::${name}"; - $parent = find_type_constraint($parent) - unless $parent && ref($parent) eq 'CODE'; - register_type_constraint($name => subname $full_name => sub { - return find_type_constraint($name) unless defined $_[0]; - local $_ = $_[0]; - return undef unless defined $parent->($_[0]) && $check->($_[0]); - $_[0]; - }); - } - else { - ($parent, $check) = ($name, $parent); - $parent = find_type_constraint($parent) - unless $parent && ref($parent) eq 'CODE'; - return subname '__anon_subtype__' => sub { - local $_ = $_[0]; - return undef unless defined $parent->($_[0]) && $check->($_[0]); - $_[0]; - }; - } + unshift @_ => undef if scalar @_ == 2; + _create_type_constraint(@_); } -sub coerce { - my ($type_name, %coercion_map) = @_; - register_type_coercion($type_name, sub { - %coercion_map - }); +sub coerce ($@) { + my ($type_name, @coercion_map) = @_; + _install_type_coercions($type_name, \@coercion_map); } sub as ($) { $_[0] } +sub from ($) { $_[0] } sub where (&) { $_[0] } -sub to (&) { $_[0] } +sub via (&) { $_[0] } # define some basic types @@ -144,6 +127,10 @@ Moose::Util::TypeConstraints - Type constraint system for Moose subtype NaturalLessThanTen => as Natural => where { $_ < 10 }; + + coerce Num + => from Str + => via { 0+$_ }; =head1 DESCRIPTION @@ -153,10 +140,6 @@ validation. This is B a type system for Perl 5. -The type and subtype constraints are basically functions which will -validate their first argument. If called with no arguments, they will -return themselves (this is syntactic sugar for Moose attributes). - This module also provides a simple hierarchy for Perl 5 types, this could probably use some work, but it works for me at the moment. @@ -182,11 +165,9 @@ Suggestions for improvement are welcome. =item B -=item B +=item B<_create_type_constraint ($type_name, $type_constraint)> -=item B - -=item B +=item B<_install_type_coercions> =item B @@ -206,7 +187,9 @@ Suggestions for improvement are welcome. =item B -=item B +=item B + +=item B =back