X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMouse%2FUtil%2FTypeConstraints.pm;h=0d0bf643c3f321e5de007357fe51005c34d3ba7e;hb=32ec255c44d36d63cce20f5e21386d5cd11396b9;hp=97de7179c47b175e8785de5ebd7c0381e82309b9;hpb=b6f6f7b2fcaeacaecaf85662e7a1ff2c87b087e2;p=gitmo%2FMouse.git diff --git a/lib/Mouse/Util/TypeConstraints.pm b/lib/Mouse/Util/TypeConstraints.pm index 97de717..0d0bf64 100644 --- a/lib/Mouse/Util/TypeConstraints.pm +++ b/lib/Mouse/Util/TypeConstraints.pm @@ -1,5 +1,5 @@ package Mouse::Util::TypeConstraints; -use Mouse::Util qw(does_role not_supported); # enables strict and warnings +use Mouse::Util; # enables strict and warnings use Carp (); use Scalar::Util (); @@ -104,23 +104,22 @@ sub list_all_builtin_type_constraints { @builtins } sub list_all_type_constraints { keys %TYPE } -sub _create_type{ - my $mode = shift; - +sub _define_type { + my $is_subtype = shift; my $name; my %args; - if(@_ == 1 && ref $_[0]){ # @_ : { name => $name, where => ... } + if(@_ == 1 && ref $_[0] ){ # @_ : { name => $name, where => ... } %args = %{$_[0]}; } - elsif(@_ == 2 && ref $_[1]){ # @_ : $name => { where => ... } + elsif(@_ == 2 && ref $_[1]) { # @_ : $name => { where => ... } $name = $_[0]; %args = %{$_[1]}; } - elsif(@_ % 2){ # @_ : $name => ( where => ... ) + elsif(@_ % 2) { # @_ : $name => ( where => ... ) ($name, %args) = @_; } - else{ # @_ : (name => $name, where => ...) + else{ # @_ : (name => $name, where => ...) %args = @_; } @@ -129,13 +128,15 @@ sub _create_type{ } $args{name} = $name; - my $parent; - if($mode eq 'subtype'){ - $parent = delete $args{as}; - if(!$parent){ - $parent = delete $args{name}; - $name = undef; - } + + my $parent = delete $args{as}; + if($is_subtype && !$parent){ + $parent = delete $args{name}; + $name = undef; + } + + if(defined $parent) { + $args{parent} = find_or_create_isa_type_constraint($parent); } if(defined $name){ @@ -164,20 +165,11 @@ sub _create_type{ } } } - else{ - $args{name} = '__ANON__'; - } $args{constraint} = delete $args{where} if exists $args{where}; $args{optimized} = delete $args{optimized_as} if exists $args{optimized_as}; - my $constraint; - if($mode eq 'subtype'){ - $constraint = find_or_create_isa_type_constraint($parent)->create_child_type(%args); - } - else{ - $constraint = Mouse::Meta::TypeConstraint->new(%args); - } + my $constraint = Mouse::Meta::TypeConstraint->new(%args); if(defined $name){ return $TYPE{$name} = $constraint; @@ -188,11 +180,11 @@ sub _create_type{ } sub type { - return _create_type('type', @_); + return _define_type 0, @_; } sub subtype { - return _create_type('subtype', @_); + return _define_type 1, @_; } sub coerce { @@ -210,9 +202,10 @@ sub class_type { my $class = $options->{class} || $name; # ClassType - return _create_type 'subtype', $name => ( + return _define_type 1, $name => ( as => 'Object', optimized_as => Mouse::Util::generate_isa_predicate_for($class), + class => $class, ); } @@ -221,25 +214,37 @@ sub role_type { my $role = $options->{role} || $name; # RoleType - return _create_type 'subtype', $name => ( + return _define_type 1, $name => ( as => 'Object', - optimized_as => sub { Scalar::Util::blessed($_[0]) && does_role($_[0], $role) }, + optimized_as => sub { + return Scalar::Util::blessed($_[0]) + && Mouse::Util::does_role($_[0], $role); + }, + role => $role, ); } sub duck_type { my($name, @methods); - if(!(@_ == 1 && ref($_[0]) eq 'ARRAY')){ + if(ref($_[0]) ne 'ARRAY'){ $name = shift; } @methods = (@_ == 1 && ref($_[0]) eq 'ARRAY') ? @{$_[0]} : @_; # DuckType - return _create_type 'subtype', $name => ( + return _define_type 1, $name => ( as => 'Object', optimized_as => Mouse::Util::generate_can_predicate_for(\@methods), + message => sub { + my($object) = @_; + my @missing = grep { !$object->can($_) } @methods; + return ref($object) + . ' is missing methods ' + . Mouse::Util::quoted_english_list(@missing); + }, + methods => \@methods, ); } @@ -250,12 +255,15 @@ sub enum { $name = shift; } - %valid = map{ $_ => undef } (@_ == 1 && ref($_[0]) eq 'ARRAY' ? @{$_[0]} : @_); + %valid = map{ $_ => undef } + (@_ == 1 && ref($_[0]) eq 'ARRAY' ? @{$_[0]} : @_); # EnumType - return _create_type 'subtype', $name => ( + return _define_type 1, $name => ( as => 'Str', - optimized_as => sub{ defined($_[0]) && !ref($_[0]) && exists $valid{$_[0]} }, + optimized_as => sub{ + return defined($_[0]) && !ref($_[0]) && exists $valid{$_[0]}; + }, ); } @@ -370,8 +378,7 @@ sub _parse_type { sub find_type_constraint { my($spec) = @_; - return $spec if Mouse::Util::is_a_type_constraint($spec); - return undef if !defined $spec; + return $spec if Mouse::Util::is_a_type_constraint($spec) or not defined $spec; $spec =~ s/\s+//g; return $TYPE{$spec}; @@ -382,15 +389,14 @@ sub register_type_constraint { Carp::croak("No type supplied / type is not a valid type constraint") unless Mouse::Util::is_a_type_constraint($constraint); my $name = $constraint->name; - Carp::croak("can't register an unnamed type constraint") + Carp::croak("Can't register an unnamed type constraint") unless defined $name; return $TYPE{$name} = $constraint; } sub find_or_parse_type_constraint { my($spec) = @_; - return $spec if Mouse::Util::is_a_type_constraint($spec); - return undef if !defined $spec; + return $spec if Mouse::Util::is_a_type_constraint($spec) or not defined $spec; $spec =~ s/\s+//g; return $TYPE{$spec} || do{ @@ -426,7 +432,7 @@ Mouse::Util::TypeConstraints - Type constraint system for Mouse =head1 VERSION -This document describes Mouse version 0.64 +This document describes Mouse version 0.75 =head2 SYNOPSIS