start of the TC refactor
Stevan Little [Tue, 4 Sep 2007 15:47:58 +0000 (15:47 +0000)]
Changes
PLANS [new file with mode: 0644]
lib/Moose.pm
lib/Moose/Meta/Role.pm
lib/Moose/Meta/Role/Method/Required.pm
lib/Moose/Meta/TypeConstraint.pm
lib/Moose/Meta/TypeConstraint/Container.pm [new file with mode: 0644]
lib/Moose/Meta/TypeConstraint/Union.pm
t/061_container_type_constraint.t [new file with mode: 0644]

diff --git a/Changes b/Changes
index dc179e0..a5fa13b 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,5 +1,22 @@
 Revision history for Perl extension Moose
 
+0.26
+    * Moose
+      - added all the meta classes to the immutable list and 
+        set it to inline the accessors
+
+    * Moose::Meta::TypeConstraint
+      - some minor adjustments to make subclassing easier
+      
+    * Moose::Meta::TypeConstraint::Union
+      - this is not a subclass of Moose::Meta::TypeConstraint      
+        which is more correct
+      
+    * Moose::Meta::TypeConstraint::Container
+      - added this module (taken from MooseX::AttributeHelpers)
+        to help construct nested collection types
+        - added tests for this
+
 0.25 Mon. Aug. 13, 2007
     * Moose
       - Documentation update to reference Moose::Util::TypeConstraints 
diff --git a/PLANS b/PLANS
new file mode 100644 (file)
index 0000000..e009272
--- /dev/null
+++ b/PLANS
@@ -0,0 +1,57 @@
+-----------------------------------------------------------
+-- Type Constraints refactor
+-----------------------------------------------------------
+
+- move the details of TC construction that are in Moose.pm and 
+  Moose::Util::TypeConstraints into the Moose::Meta::TypeConstraint module
+
+This will make it much easier to generate TCs on their own, without 
+having to use the sugar layer. This should also clean up their APIs 
+as well, which will make it easier to subclass them.
+
+- create an official TC registry API
+
+Right now the registration of the TC is a by-product of creation in the sugar 
+layer, this is bad and make extension of TCs difficult. I am not sure if this 
+registry API should exist as part of Moose::Util::TypeConstraints, or of we 
+should create a complete registry object itself. 
+
+This registry should be a singleton, but M::U::TC should enforce that lifecycle 
+choice so that you can use your own registry if you really want too.
+
+I mean parent of the registry. So that I can create my own registry
+object for a given class, and any retrieval of a type constraint from
+this object would automatically search parent registries as well.
+
+- refactor the various TC internals to make it more subclassing friendly
+
+This also includes the coercion stuff as well. This should give you what you 
+need to make your object/class bound stuff.
+
+- move the container TCs from MooseX::AttributeHelpers into Moose core
+
+These have proven so useful for me in the latest $work project that I think 
+they should really be core. 
+
+- allow a switch of some kind to optionally turn TC checking off at runtime 
+
+The type checks can get expensive and some people have suggested that allowing 
+the checks to be turned off would be helpful for deploying into performance 
+intensive systems. Perhaps this can actually be done as an option to make_immutable? 
+
+- misc. minor bits
+
+* make the errors for TCs use ->message
+* look into localizing the messages too
+* make ANON TCs be lazy, so they can possibly be subsituted for the real thing later
+* make ANON TCs more introspectable
+
+
+-----------------------------------------------------------
+-- Roles refactor
+-----------------------------------------------------------
+
+
+-----------------------------------------------------------
+-- Immutable refactor
+-----------------------------------------------------------
\ No newline at end of file
index 0201714..7aa481d 100644 (file)
@@ -4,7 +4,7 @@ package Moose;
 use strict;
 use warnings;
 
-our $VERSION   = '0.25';
+our $VERSION   = '0.26';
 our $AUTHORITY = 'cpan:STEVAN';
 
 use Scalar::Util 'blessed', 'reftype';
@@ -22,6 +22,8 @@ use Moose::Meta::TypeCoercion;
 use Moose::Meta::Attribute;
 use Moose::Meta::Instance;
 
+use Moose::Meta::Role;
+
 use Moose::Object;
 use Moose::Util::TypeConstraints;
 
@@ -234,7 +236,7 @@ use Moose::Util::TypeConstraints;
 
 $_->meta->make_immutable(
     inline_constructor => 0,
-    inline_accessors   => 0,    
+    inline_accessors   => 1,    
 ) for (
     'Moose::Meta::Attribute',
     'Moose::Meta::Class',
@@ -242,12 +244,18 @@ $_->meta->make_immutable(
 
     'Moose::Meta::TypeConstraint',
     'Moose::Meta::TypeConstraint::Union',
+    'Moose::Meta::TypeConstraint::Container',    
     'Moose::Meta::TypeCoercion',
 
     'Moose::Meta::Method',
     'Moose::Meta::Method::Accessor',
     'Moose::Meta::Method::Constructor',
+    'Moose::Meta::Method::Destructor',    
     'Moose::Meta::Method::Overriden',
+
+    'Moose::Meta::Role',
+    'Moose::Meta::Role::Method',    
+    'Moose::Meta::Role::Method::Required',        
 );
 
 1;
index 0609cee..cf74e9b 100644 (file)
@@ -14,6 +14,7 @@ our $AUTHORITY = 'cpan:STEVAN';
 
 use Moose::Meta::Class;
 use Moose::Meta::Role::Method;
+use Moose::Meta::Role::Method::Required;
 
 use base 'Class::MOP::Module';
 
index 18d5f56..38271c2 100644 (file)
@@ -7,6 +7,8 @@ use warnings;
 our $VERSION   = '0.01';
 our $AUTHORITY = 'cpan:STEVAN';
 
+use base 'Moose::Meta::Role::Method';
+
 1;
 
 __END__
index 8295230..7a7cddf 100644 (file)
@@ -12,14 +12,18 @@ use Sub::Name    'subname';
 use Carp         'confess';
 use Scalar::Util 'blessed';
 
-our $VERSION   = '0.08';
+our $VERSION   = '0.09';
 our $AUTHORITY = 'cpan:STEVAN';
 
 use Moose::Meta::TypeConstraint::Union;
+use Moose::Meta::TypeConstraint::Container;
 
 __PACKAGE__->meta->add_attribute('name'       => (reader => 'name'      ));
 __PACKAGE__->meta->add_attribute('parent'     => (reader => 'parent'    ));
-__PACKAGE__->meta->add_attribute('constraint' => (reader => 'constraint'));
+__PACKAGE__->meta->add_attribute('constraint' => (
+    reader => 'constraint',
+    writer => '_set_constraint',
+));
 __PACKAGE__->meta->add_attribute('message'   => (
     accessor  => 'message',
     predicate => 'has_message'
diff --git a/lib/Moose/Meta/TypeConstraint/Container.pm b/lib/Moose/Meta/TypeConstraint/Container.pm
new file mode 100644 (file)
index 0000000..d68859d
--- /dev/null
@@ -0,0 +1,104 @@
+package Moose::Meta::TypeConstraint::Container;
+
+use strict;
+use warnings;
+use metaclass;
+
+use Scalar::Util 'blessed';
+use Carp         'confess';
+
+our $VERSION   = '0.01';
+our $AUTHORITY = 'cpan:STEVAN';
+
+use base 'Moose::Meta::TypeConstraint';
+
+__PACKAGE__->meta->add_attribute('container_type' => (
+    accessor  => 'container_type',
+    predicate => 'has_container_type',
+));
+
+sub compile_type_constraint {
+    my $self = shift;
+    
+    my $parent_name = $self->parent->name;
+    
+    ($self->has_container_type)
+        || confess "You cannot create a Container type without one";
+        
+    my $container_type = $self->container_type;
+    
+    (blessed $container_type && $container_type->isa('Moose::Meta::TypeConstraint'))
+        || confess "The container type must be a Moose meta type";
+    
+    my $constraint;
+    
+    if ($parent_name eq 'ArrayRef') {
+        $constraint = sub {
+            foreach my $x (@$_) { 
+                ($container_type->check($x)) || return 
+            } 1;
+        };
+    }
+    elsif ($parent_name eq 'HashRef') {
+        $constraint = sub {
+            foreach my $x (values %$_) { 
+                ($container_type->check($x)) || return 
+            } 1;
+        };          
+    }
+    else {
+        confess "Your isa must be either ArrayRef or HashRef (sorry no subtype support yet)";
+    }
+    
+    $self->_set_constraint($constraint);
+    
+    $self->SUPER::compile_type_constraint;
+}
+
+1;
+
+__END__
+
+
+=pod
+
+=head1 NAME
+
+Moose::Meta::TypeConstraint::Container
+
+=head1 DESCRIPTION
+
+=head1 METHODS
+
+=over 4
+
+=item B<compile_type_constraint>
+
+=item B<container_type>
+
+=item B<has_container_type>
+
+=item B<meta>
+
+=back
+
+=head1 BUGS
+
+All complex software has bugs lurking in it, and this module is no 
+exception. If you find a bug please either email me, or add the bug
+to cpan-RT.
+
+=head1 AUTHOR
+
+Stevan Little E<lt>stevan@iinteractive.comE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2006, 2007 by Infinity Interactive, Inc.
+
+L<http://www.iinteractive.com>
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
index 03d7f8f..25fe9e6 100644 (file)
@@ -5,9 +5,18 @@ use strict;
 use warnings;
 use metaclass;
 
-our $VERSION   = '0.05';
+our $VERSION   = '0.06';
 our $AUTHORITY = 'cpan:STEVAN';
 
+# NOTE:
+# this is not really correct, but 
+# I think it shoul be here anyway.
+# In truth, this should implement 
+# the same abstract base/interface
+# as the TC moule.
+# - SL
+use base 'Moose::Meta::TypeConstraint';
+
 __PACKAGE__->meta->add_attribute('type_constraints' => (
     accessor  => 'type_constraints',
     default   => sub { [] }
diff --git a/t/061_container_type_constraint.t b/t/061_container_type_constraint.t
new file mode 100644 (file)
index 0000000..ea3be87
--- /dev/null
@@ -0,0 +1,67 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More no_plan => 1;
+use Test::Exception;
+
+BEGIN {
+    use_ok('Moose');           
+    use_ok('Moose::Util::TypeConstraints');               
+    use_ok('Moose::Meta::TypeConstraint::Container');               
+}
+
+# Array of Ints
+
+my $array_of_ints = Moose::Meta::TypeConstraint::Container->new(
+    name           => 'ArrayRef[Int]',
+    parent         => find_type_constraint('ArrayRef'),
+    container_type => find_type_constraint('Int'),
+);
+isa_ok($array_of_ints, 'Moose::Meta::TypeConstraint::Container');
+isa_ok($array_of_ints, 'Moose::Meta::TypeConstraint');
+
+ok($array_of_ints->check([ 1, 2, 3, 4 ]), '... [ 1, 2, 3, 4 ] passed successfully');
+ok(!$array_of_ints->check([qw/foo bar baz/]), '... [qw/foo bar baz/] failed successfully');
+ok(!$array_of_ints->check([ 1, 2, 3, qw/foo bar/]), '... [ 1, 2, 3, qw/foo bar/] failed successfully');
+
+ok(!$array_of_ints->check(1), '... 1 failed successfully');
+ok(!$array_of_ints->check({}), '... {} failed successfully');
+ok(!$array_of_ints->check(sub { () }), '... sub { () } failed successfully');
+
+# Hash of Ints
+
+my $hash_of_ints = Moose::Meta::TypeConstraint::Container->new(
+    name           => 'HashRef[Int]',
+    parent         => find_type_constraint('HashRef'),
+    container_type => find_type_constraint('Int'),
+);
+isa_ok($hash_of_ints, 'Moose::Meta::TypeConstraint::Container');
+isa_ok($hash_of_ints, 'Moose::Meta::TypeConstraint');
+
+ok($hash_of_ints->check({ one => 1, two => 2, three => 3 }), '... { one => 1, two => 2, three => 3 } passed successfully');
+ok(!$hash_of_ints->check({ 1 => 'one', 2 => 'two', 3 => 'three' }), '... { 1 => one, 2 => two, 3 => three } failed successfully');
+ok(!$hash_of_ints->check({ 1 => 'one', 2 => 'two', three => 3 }), '... { 1 => one, 2 => two, three => 3 } failed successfully');
+
+ok(!$hash_of_ints->check(1), '... 1 failed successfully');
+ok(!$hash_of_ints->check([]), '... [] failed successfully');
+ok(!$hash_of_ints->check(sub { () }), '... sub { () } failed successfully');
+
+# Array of Array of Ints
+
+my $array_of_array_of_ints = Moose::Meta::TypeConstraint::Container->new(
+    name           => 'ArrayRef[ArrayRef[Int]]',
+    parent         => find_type_constraint('ArrayRef'),
+    container_type => $array_of_ints,
+);
+isa_ok($array_of_array_of_ints, 'Moose::Meta::TypeConstraint::Container');
+isa_ok($array_of_array_of_ints, 'Moose::Meta::TypeConstraint');
+
+ok($array_of_array_of_ints->check(
+    [[ 1, 2, 3 ], [ 4, 5, 6 ]]
+), '... [[ 1, 2, 3 ], [ 4, 5, 6 ]] passed successfully');
+ok(!$array_of_array_of_ints->check(
+    [[ 1, 2, 3 ], [ qw/foo bar/ ]]
+), '... [[ 1, 2, 3 ], [ qw/foo bar/ ]] failed successfully');
+