X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMoose%2FMeta%2FMethod%2FAccessor%2FNative.pm;h=e9ccde7976374be9210b067520a39e9818b55361;hb=1e2c801e852e22b0ab5af1efc34667710ba952de;hp=77fc6b92a0aa4486c41bb07c51e7016ccb261691;hpb=f7fd22b6d12dedd3c0666e30c05b2e02b3e8acb3;p=gitmo%2FMoose.git diff --git a/lib/Moose/Meta/Method/Accessor/Native.pm b/lib/Moose/Meta/Method/Accessor/Native.pm index 77fc6b9..e9ccde7 100644 --- a/lib/Moose/Meta/Method/Accessor/Native.pm +++ b/lib/Moose/Meta/Method/Accessor/Native.pm @@ -6,62 +6,150 @@ use warnings; use Carp qw( confess ); use Scalar::Util qw( blessed weaken ); -our $VERSION = '1.13'; +our $VERSION = '1.19'; $VERSION = eval $VERSION; our $AUTHORITY = 'cpan:STEVAN'; -use base 'Moose::Meta::Method::Accessor', 'Moose::Meta::Method::Delegation'; +use Moose::Role; -sub new { +around new => sub { + my $orig = shift; my $class = shift; my %options = @_; - die "Cannot instantiate a $class object directly" - if $class eq __PACKAGE__; + $options{curried_arguments} = [] + unless exists $options{curried_arguments}; - ( exists $options{attribute} ) - || confess "You must supply an attribute to construct with"; + confess 'You must supply a curried_arguments which is an ARRAY reference' + unless $options{curried_arguments} + && ref($options{curried_arguments}) eq 'ARRAY'; - ( blessed( $options{attribute} ) - && $options{attribute}->isa('Class::MOP::Attribute') ) - || confess - "You must supply an attribute which is a 'Class::MOP::Attribute' instance"; + $options{definition_context} = $options{attribute}->definition_context; - ( $options{package_name} && $options{name} ) - || confess "You must supply the package_name and name parameters"; + $options{accessor_type} = 'native'; - exists $options{curried_arguments} - || ( $options{curried_arguments} = [] ); + return $class->$orig(%options); +}; - ( $options{curried_arguments} - && ( 'ARRAY' eq ref $options{curried_arguments} ) ) - || confess - 'You must supply a curried_arguments which is an ARRAY reference'; +sub _new { + my $class = shift; + my $options = @_ == 1 ? $_[0] : {@_}; - $options{delegate_to_method} = lc( ( split /::/, $class)[-1] ); + return bless $options, $class; +} - my $self = $class->_new( \%options ); +sub root_types { (shift)->{'root_types'} } - weaken( $self->{'attribute'} ); +sub _initialize_body { + my $self = shift; - $self->_initialize_body; + $self->{'body'} = $self->_compile_code( [$self->_generate_method] ); - return $self; + return; } -sub _new { - my $class = shift; - my $options = @_ == 1 ? $_[0] : {@_}; +sub _inline_curried_arguments { + my $self = shift; - return bless $options, $class; + return unless @{ $self->curried_arguments }; + + return 'unshift @_, @curried;'; } -sub _initialize_body { +sub _inline_check_argument_count { my $self = shift; - $self->{'body'} = $self->_eval_code( $self->_generate_method ); + my @code; + + if (my $min = $self->_minimum_arguments) { + push @code, ( + 'if (@_ < ' . $min . ') {', + $self->_inline_throw_error( + sprintf( + '"Cannot call %s without at least %s argument%s"', + $self->delegate_to_method, + $min, + ($min == 1 ? '' : 's'), + ) + ) . ';', + '}', + ); + } + + if (defined(my $max = $self->_maximum_arguments)) { + push @code, ( + 'if (@_ > ' . $max . ') {', + $self->_inline_throw_error( + sprintf( + '"Cannot call %s with %s argument%s"', + $self->delegate_to_method, + $max ? "more than $max" : 'any', + ($max == 1 ? '' : 's'), + ) + ) . ';', + '}', + ); + } + + return @code; +} + +sub _inline_return_value { + my $self = shift; + my ($slot_access, $for_writer) = @_; - return; + return 'return ' . $self->_return_value($slot_access, $for_writer) . ';'; } +sub _minimum_arguments { 0 } +sub _maximum_arguments { undef } + +override _get_value => sub { + my $self = shift; + my ($instance) = @_; + + return $self->_slot_access_can_be_inlined + ? super() + : $instance . '->$reader'; +}; + +override _store_value => sub { + my $self = shift; + my ($instance, $value) = @_; + + return $self->_slot_access_can_be_inlined + ? super() + : $instance . '->$writer(' . $value . ')'; +}; + +override _eval_environment => sub { + my $self = shift; + + my $env = super(); + + $env->{'@curried'} = $self->curried_arguments; + + return $env if $self->_slot_access_can_be_inlined; + + my $reader = $self->associated_attribute->get_read_method_ref; + $reader = $reader->body if blessed $reader; + + $env->{'$reader'} = \$reader; + + my $writer = $self->associated_attribute->get_write_method_ref; + $writer = $writer->body if blessed $writer; + + $env->{'$writer'} = \$writer; + + return $env; +}; + +sub _slot_access_can_be_inlined { + my $self = shift; + + return $self->is_inline && $self->_instance_is_inlinable; +} + +no Moose::Role; + 1;