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;