bool => sub { 1 },
fallback => 1;
+use Eval::Closure;
use Scalar::Util qw(blessed refaddr);
use Sub::Name qw(subname);
+use Try::Tiny;
use base qw(Class::MOP::Object);
-our $VERSION = '1.12';
-$VERSION = eval $VERSION;
-our $AUTHORITY = 'cpan:STEVAN';
-
__PACKAGE__->meta->add_attribute('name' => (reader => 'name'));
__PACKAGE__->meta->add_attribute('parent' => (
reader => 'parent',
predicate => 'has_hand_optimized_type_constraint',
));
+__PACKAGE__->meta->add_attribute('inlined' => (
+ init_arg => 'inlined',
+ accessor => 'inlined',
+ predicate => '_has_inlined_type_constraint',
+));
+
+__PACKAGE__->meta->add_attribute('inline_environment' => (
+ init_arg => 'inline_environment',
+ accessor => '_inline_environment',
+ default => sub { {} },
+));
+
sub parents {
my $self;
$self->parent;
return $coercion->coerce(@_);
}
+sub assert_coerce {
+ my $self = shift;
+
+ my $coercion = $self->coercion;
+
+ unless ($coercion) {
+ require Moose;
+ Moose->throw_error("Cannot coerce without a type coercion");
+ }
+
+ return $_[0] if $self->check($_[0]);
+
+ my $result = $coercion->coerce(@_);
+
+ $self->assert_valid($result);
+
+ return $result;
+}
+
sub check {
my ($self, @args) = @_;
my $constraint_subref = $self->_compiled_type_constraint;
}
}
+sub can_be_inlined {
+ my $self = shift;
+
+ if ( $self->has_parent && $self->constraint == $null_constraint ) {
+ return $self->parent->can_be_inlined;
+ }
+
+ return $self->_has_inlined_type_constraint;
+}
+
+sub _inline_check {
+ my $self = shift;
+
+ unless ( $self->can_be_inlined ) {
+ require Moose;
+ Moose->throw_error( 'Cannot inline a type constraint check for ' . $self->name );
+ }
+
+ if ( $self->has_parent && $self->constraint == $null_constraint ) {
+ return $self->parent->_inline_check(@_);
+ }
+
+ return '( do { ' . $self->inlined->( $self, @_ ) . ' } )';
+}
+
+sub inline_environment {
+ my $self = shift;
+
+ if ( $self->has_parent && $self->constraint == $null_constraint ) {
+ return $self->parent->inline_environment;
+ }
+
+ return $self->_inline_environment;
+}
+
sub assert_valid {
my ($self, $value) = @_;
return $msg->($value);
}
else {
- $value = (defined $value ? overload::StrVal($value) : 'undef');
+ # have to load it late like this, since it uses Moose itself
+ my $can_partialdump = try {
+ # versions prior to 0.14 had a potential infinite loop bug
+ Class::MOP::load_class('Devel::PartialDump', { -version => 0.14 });
+ 1;
+ };
+ if ($can_partialdump) {
+ $value = Devel::PartialDump->new->dump($value);
+ }
+ else {
+ $value = (defined $value ? overload::StrVal($value) : 'undef');
+ }
return "Validation failed for '" . $self->name . "' with value $value";
}
}
return $self->_compile_hand_optimized_type_constraint
if $self->has_hand_optimized_type_constraint;
+ if ( $self->can_be_inlined ) {
+ return eval_closure(
+ source => 'sub { ' . $self->_inline_check('$_[0]') . ' }',
+ environment => $self->inline_environment,
+ );
+ }
+
my $check = $self->constraint;
unless ( defined $check ) {
require Moose;
unless ( ref $type_constraint ) {
require Moose;
- Carp::confess ("Hand optimized type constraint for " . $self->name . " is not a code reference");
Moose->throw_error("Hand optimized type constraint is not a code reference");
}
1;
+# ABSTRACT: The Moose Type Constraint metaclass
+
__END__
=pod
-=head1 NAME
-
-Moose::Meta::TypeConstraint - The Moose Type Constraint metaclass
-
=head1 DESCRIPTION
This class represents a single type constraint. Moose's built-in type
A L<Moose::Meta::TypeCoercion> object representing the coercions to
the type. This is optional.
+=item * inlined
+
+A subroutine which returns a string suitable for inlining this type
+constraint. It will be called as a method on the type constraint object, and
+will receive a single additional parameter, a variable name to be tested
+(usually C<"$_"> or C<"$_[0]">.
+
+This is optional.
+
+=item * inline_environment
+
+A hash reference of variables to close over. The keys are variables names, and
+the values are I<references> to the variables.
+
=item * optimized
+B<This option is deprecated.>
+
This is a variant of the C<constraint> parameter that is somehow
optimized. Typically, this means incorporating both the type's
constraint and all of its parents' constraints into a single
=item B<< $constraint->coerce($value) >>
-This will attempt to coerce the value to the type. If the type does
+This will attempt to coerce the value to the type. If the type does not
have any defined coercions this will throw an error.
+If no coercion can produce a value matching C<$constraint>, the original
+value is returned.
+
+=item B<< $constraint->assert_coerce($value) >>
+
+This method behaves just like C<coerce>, but if the result is not valid
+according to C<$constraint>, an error is thrown.
+
=item B<< $constraint->check($value) >>
Returns true if the given value passes the constraint for the type.
Returns true if the type has a coercion.
+=item B<< $constraint->can_be_inlined >>
+
+Returns true if this type constraint can be inlined. A type constraint which
+subtypes an inlinable constraint and does not add an additional constraint
+"inherits" its parent type's inlining.
+
=item B<< $constraint->hand_optimized_type_constraint >>
+B<This method is deprecated.>
+
Returns the type's hand optimized constraint, as provided to the
constructor via the C<optimized> option.
=item B<< $constraint->has_hand_optimized_type_constraint >>
+B<This method is deprecated.>
+
Returns true if the type has an optimized constraint.
=item B<< $constraint->create_child_type(%options) >>
See L<Moose/BUGS> for details on reporting bugs.
-=head1 AUTHOR
-
-Stevan Little E<lt>stevan@iinteractive.comE<gt>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2006-2010 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