if ($self->has_weak_ref) {
return sub {
if (scalar(@_) == 2) {
- (defined $self->type_constraint->constraint_code->($_[1]))
+ (defined $self->type_constraint->check($_[1]))
|| confess "Attribute ($attr_name) does not pass the type contraint with '$_[1]'"
if defined $_[1];
$_[0]->{$attr_name} = $_[1];
if ($self->has_coercion) {
return sub {
if (scalar(@_) == 2) {
- my $val = $self->type_constraint->coercion_code->($_[1]);
- (defined $self->type_constraint->constraint_code->($val))
+ my $val = $self->type_constraint->coercion->coerce($_[1]);
+ (defined $self->type_constraint->check($val))
|| confess "Attribute ($attr_name) does not pass the type contraint with '$val'"
if defined $val;
$_[0]->{$attr_name} = $val;
else {
return sub {
if (scalar(@_) == 2) {
- (defined $self->type_constraint->constraint_code->($_[1]))
+ (defined $self->type_constraint->check($_[1]))
|| confess "Attribute ($attr_name) does not pass the type contraint with '$_[1]'"
if defined $_[1];
$_[0]->{$attr_name} = $_[1];
if ($self->has_type_constraint) {
if ($self->has_weak_ref) {
return sub {
- (defined $self->type_constraint->constraint_code->($_[1]))
+ (defined $self->type_constraint->check($_[1]))
|| confess "Attribute ($attr_name) does not pass the type contraint with '$_[1]'"
if defined $_[1];
$_[0]->{$attr_name} = $_[1];
else {
if ($self->has_coercion) {
return sub {
- my $val = $self->type_constraint->coercion_code->($_[1]);
- (defined $self->type_constraint->constraint_code->($val))
+ my $val = $self->type_constraint->coercion->coerce($_[1]);
+ (defined $self->type_constraint->check($val))
|| confess "Attribute ($attr_name) does not pass the type contraint with '$val'"
if defined $val;
$_[0]->{$attr_name} = $val;
}
else {
return sub {
- (defined $self->type_constraint->constraint_code->($_[1]))
+ (defined $self->type_constraint->check($_[1]))
|| confess "Attribute ($attr_name) does not pass the type contraint with '$_[1]'"
if defined $_[1];
$_[0]->{$attr_name} = $_[1];
if (defined $val) {
if ($attr->has_type_constraint) {
if ($attr->has_coercion && $attr->type_constraint->has_coercion) {
- $val = $attr->type_constraint->coercion_code->($val);
+ $val = $attr->type_constraint->coercion->coerce($val);
}
- (defined($attr->type_constraint->constraint_code->($val)))
+ (defined($attr->type_constraint->check($val)))
|| confess "Attribute (" . $attr->name . ") does not pass the type contraint with '$val'";
}
}
use Carp 'confess';
+use Moose::Meta::Attribute;
+use Moose::Util::TypeConstraints;
+
our $VERSION = '0.01';
+__PACKAGE__->meta->add_attribute('type_coercion_map' => (
+ reader => 'type_coercion_map',
+ default => sub { [] }
+));
+__PACKAGE__->meta->add_attribute(
+ Moose::Meta::Attribute->new('type_constraint' => (
+ reader => 'type_constraint',
+ weak_ref => 1
+ ))
+);
+
+# private accessor
+__PACKAGE__->meta->add_attribute('compiled_type_coercion' => (
+ accessor => '_compiled_type_coercion'
+));
+
+sub new {
+ my $class = shift;
+ my $self = $class->meta->new_object(@_);
+ $self->compile_type_coercion();
+ return $self;
+}
+
+sub compile_type_coercion {
+ my $self = shift;
+ my @coercion_map = @{$self->type_coercion_map};
+ my @coercions;
+ while (@coercion_map) {
+ my ($constraint_name, $action) = splice(@coercion_map, 0, 2);
+ my $constraint = Moose::Util::TypeConstraints::find_type_constraint($constraint_name)->_compiled_type_constraint;
+ (defined $constraint)
+ || confess "Could not find the type constraint ($constraint_name)";
+ push @coercions => [ $constraint, $action ];
+ }
+ $self->_compiled_type_coercion(sub {
+ my $thing = shift;
+ foreach my $coercion (@coercions) {
+ my ($constraint, $converter) = @$coercion;
+ if (defined $constraint->($thing)) {
+ local $_ = $thing;
+ return $converter->($thing);
+ }
+ }
+ return $thing;
+ });
+}
+
+sub coerce { $_[0]->_compiled_type_coercion->($_[1]) }
+
+
1;
__END__
=item B<meta>
+=item B<new>
+
+=item B<coerce>
+
+=item B<compile_type_coercion>
+
+=item B<type_coercion_map>
+
+=item B<type_constraint>
+
=back
=head1 BUGS
__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('coercion' => (
+ accessor => 'coercion',
+ predicate => 'has_coercion'
+));
# private accessor
__PACKAGE__->meta->add_attribute('compiled_type_constraint' => (
accessor => '_compiled_type_constraint'
));
-__PACKAGE__->meta->add_attribute('coercion_code' => (
- reader => 'coercion_code',
- writer => 'set_coercion_code',
- predicate => 'has_coercion'
-));
-
sub new {
- my $class = shift;
- my $self = $class->meta->new_object(@_);
+ my $class = shift;
+ my $self = $class->meta->new_object(@_);
$self->compile_type_constraint();
return $self;
}
sub compile_type_constraint () {
- my $self = shift;
- my $check = $self->constraint;
+ my $self = shift;
+ my $check = $self->constraint;
(defined $check)
|| confess "Could not compile type constraint '" . $self->name . "' because no constraint check";
my $parent = $self->parent;
if (defined $parent) {
+ # we have a subtype ...
$parent = $parent->_compiled_type_constraint;
$self->_compiled_type_constraint(subname $self->name => sub {
local $_ = $_[0];
});
}
else {
+ # we have a type ....
$self->_compiled_type_constraint(subname $self->name => sub {
local $_ = $_[0];
return undef unless $check->($_[0]);
}
}
-# backwards for now
-sub constraint_code { (shift)->_compiled_type_constraint }
+sub check { $_[0]->_compiled_type_constraint->($_[1]) }
1;
=item B<constraint>
-=item B<coerce>
-
-=item B<coercion_code>
-
-=item B<set_coercion_code>
-
-=item B<constraint_code>
-
=item B<has_coercion>
+=item B<coercion>
+
=item B<compile_type_constraint>
=back
sub find_type_constraint { $TYPES{$_[0]} }
sub create_type_constraint {
- my ($name, $parent, $constraint) = @_;
- (not exists $TYPES{$name})
- || confess "The type constraint '$name' has already been created";
+ my ($name, $parent, $check) = @_;
+ (!exists $TYPES{$name})
+ || confess "The type constraint '$name' has already been created"
+ if defined $name;
$parent = find_type_constraint($parent) if defined $parent;
- $TYPES{$name} = Moose::Meta::TypeConstraint->new(
- name => $name,
+ my $constraint = Moose::Meta::TypeConstraint->new(
+ name => $name || '__ANON__',
parent => $parent,
- constraint => $constraint,
+ constraint => $check,
);
+ $TYPES{$name} = $constraint if defined $name;
+ return $constraint;
}
- sub find_type_coercion {
- my $type_name = shift;
- $TYPES{$type_name}->coercion_code;
- }
-
- sub register_type_coercion {
- my ($type_name, $type_coercion) = @_;
- my $type = $TYPES{$type_name};
+ sub install_type_coercions {
+ my ($type_name, $coercion_map) = @_;
+ my $type = find_type_constraint($type_name);
(!$type->has_coercion)
|| confess "The type coercion for '$type_name' has already been registered";
- $type->set_coercion_code($type_coercion);
+ 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}->constraint_code;
+ *{"${pkg}::${constraint}"} = $TYPES{$constraint}->_compiled_type_constraint;
}
}
}
}
sub subtype ($$;$) {
- if (scalar @_ == 3) {
- my ($name, $parent, $check) = @_;
- create_type_constraint($name, $parent, $check);
- }
- else {
- my ($parent, $check) = @_;
- $parent = find_type_constraint($parent);
- return Moose::Meta::TypeConstraint->new(
- name => '__ANON__',
- parent => $parent,
- constraint => $check,
- );
- }
+ unshift @_ => undef if scalar @_ == 2;
+ create_type_constraint(@_);
}
sub coerce ($@) {
my ($type_name, @coercion_map) = @_;
- my @coercions;
- while (@coercion_map) {
- my ($constraint_name, $action) = splice(@coercion_map, 0, 2);
- my $constraint = find_type_constraint($constraint_name)->constraint_code;
- (defined $constraint)
- || confess "Could not find the type constraint ($constraint_name)";
- push @coercions => [ $constraint, $action ];
- }
- register_type_coercion($type_name, sub {
- my $thing = shift;
- foreach my $coercion (@coercions) {
- my ($constraint, $converter) = @$coercion;
- if (defined $constraint->($thing)) {
- local $_ = $thing;
- return $converter->($thing);
- }
- }
- return $thing;
- });
+ install_type_coercions($type_name, \@coercion_map);
}
sub as ($) { $_[0] }
=item B<create_type_constraint ($type_name, $type_constraint)>
-=item B<find_type_coercion>
-
-=item B<register_type_coercion>
+=item B<install_type_coercions>
=item B<export_type_contstraints_as_functions>
-=item B<dump_type_constraints>
-
=back
=head2 Type Constraint Constructors
ok(defined $negative, '... got a value back from negative');
isa_ok($negative, 'Moose::Meta::TypeConstraint');
-is($negative->_compiled_type_constraint->(-5), -5, '... this is a negative number');
-ok(!defined($negative->_compiled_type_constraint->(5)), '... this is not a negative number');
-is($negative->_compiled_type_constraint->('Foo'), undef, '... this is not a negative number');
+is($negative->check(-5), -5, '... this is a negative number');
+ok(!defined($negative->check(5)), '... this is not a negative number');
+is($negative->check('Foo'), undef, '... this is not a negative number');
+
+
+
ok(!Header([]), '... this did not pass the type test');
ok(!Header({}), '... this did not pass the type test');
-my $coercion = Moose::Util::TypeConstraints::find_type_coercion('Header');
-is(ref($coercion), 'CODE', '... got the right type of coercion');
+my $coercion = Moose::Util::TypeConstraints::find_type_constraint('Header')->coercion;
+isa_ok($coercion, 'Moose::Meta::TypeCoercion');
{
- my $coerced = $coercion->([ 1, 2, 3 ]);
+ my $coerced = $coercion->coerce([ 1, 2, 3 ]);
isa_ok($coerced, 'HTTPHeader');
is_deeply(
}
{
- my $coerced = $coercion->({ one => 1, two => 2, three => 3 });
+ my $coerced = $coercion->coerce({ one => 1, two => 2, three => 3 });
isa_ok($coerced, 'HTTPHeader');
is_deeply(
{
my $scalar_ref = \(my $var);
- my $coerced = $coercion->($scalar_ref);
+ my $coerced = $coercion->coerce($scalar_ref);
is($coerced, $scalar_ref, '... got back what we put in');
}
{
- my $coerced = $coercion->("Foo");
+ my $coerced = $coercion->coerce("Foo");
is($coerced, "Foo", '... got back what we put in');
}