From: Dave Rolsky Date: Thu, 23 Sep 2010 21:58:57 +0000 (-0500) Subject: Got inlining for hashes working. X-Git-Tag: 1.15~114 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=44babf1f66a06b9e1a70a0f04841439e4bc71a6a;p=gitmo%2FMoose.git Got inlining for hashes working. Lots of refactoring to push code to a shared collection mini-trait used for hashes & arrays, since the inlining code for the two is _really_ similar. --- diff --git a/lib/Moose/Meta/Attribute/Native/MethodProvider/Hash.pm b/lib/Moose/Meta/Attribute/Native/MethodProvider/Hash.pm deleted file mode 100644 index 1eb9190..0000000 --- a/lib/Moose/Meta/Attribute/Native/MethodProvider/Hash.pm +++ /dev/null @@ -1,220 +0,0 @@ -package Moose::Meta::Attribute::Native::MethodProvider::Hash; -use Moose::Role; - -our $VERSION = '1.14'; -$VERSION = eval $VERSION; -our $AUTHORITY = 'cpan:STEVAN'; - -sub exists : method { - my ( $attr, $reader, $writer ) = @_; - return sub { CORE::exists $reader->( $_[0] )->{ $_[1] } ? 1 : 0 }; -} - -sub defined : method { - my ( $attr, $reader, $writer ) = @_; - return sub { CORE::defined $reader->( $_[0] )->{ $_[1] } ? 1 : 0 }; -} - -sub get : method { - my ( $attr, $reader, $writer ) = @_; - return sub { - if ( @_ == 2 ) { - $reader->( $_[0] )->{ $_[1] }; - } - else { - my ( $self, @keys ) = @_; - @{ $reader->($self) }{@keys}; - } - }; -} - -sub keys : method { - my ( $attr, $reader, $writer ) = @_; - return sub { CORE::keys %{ $reader->( $_[0] ) } }; -} - -sub values : method { - my ( $attr, $reader, $writer ) = @_; - return sub { CORE::values %{ $reader->( $_[0] ) } }; -} - -sub kv : method { - my ( $attr, $reader, $writer ) = @_; - return sub { - my $h = $reader->( $_[0] ); - map { [ $_, $h->{$_} ] } CORE::keys %{$h}; - }; -} - -sub elements : method { - my ( $attr, $reader, $writer ) = @_; - return sub { - my $h = $reader->( $_[0] ); - map { $_, $h->{$_} } CORE::keys %{$h}; - }; -} - -sub count : method { - my ( $attr, $reader, $writer ) = @_; - return sub { scalar CORE::keys %{ $reader->( $_[0] ) } }; -} - -sub is_empty : method { - my ( $attr, $reader, $writer ) = @_; - return sub { scalar CORE::keys %{ $reader->( $_[0] ) } ? 0 : 1 }; -} - - -sub set : method { - my ( $attr, $reader, $writer ) = @_; - if ( - $attr->has_type_constraint - && $attr->type_constraint->isa( - 'Moose::Meta::TypeConstraint::Parameterized') - ) { - my $container_type_constraint - = $attr->type_constraint->type_parameter; - return sub { - my ( $self, @kvp ) = @_; - - my ( @keys, @values ); - - while (@kvp) { - my ( $key, $value ) = ( shift(@kvp), shift(@kvp) ); - ( $container_type_constraint->check($value) ) - || confess "Value " - . ( $value || 'undef' ) - . " did not pass container type constraint '$container_type_constraint'"; - push @keys, $key; - push @values, $value; - } - - if ( @values > 1 ) { - @{ $reader->($self) }{@keys} = @values; - } - else { - $reader->($self)->{ $keys[0] } = $values[0]; - } - }; - } - else { - return sub { - if ( @_ == 3 ) { - $reader->( $_[0] )->{ $_[1] } = $_[2]; - } - else { - my ( $self, @kvp ) = @_; - my ( @keys, @values ); - - while (@kvp) { - push @keys, shift @kvp; - push @values, shift @kvp; - } - - @{ $reader->( $_[0] ) }{@keys} = @values; - } - }; - } -} - -sub accessor : method { - my ( $attr, $reader, $writer ) = @_; - - if ( - $attr->has_type_constraint - && $attr->type_constraint->isa( - 'Moose::Meta::TypeConstraint::Parameterized') - ) { - my $container_type_constraint - = $attr->type_constraint->type_parameter; - return sub { - my $self = shift; - - if ( @_ == 1 ) { # reader - return $reader->($self)->{ $_[0] }; - } - elsif ( @_ == 2 ) { # writer - ( $container_type_constraint->check( $_[1] ) ) - || confess "Value " - . ( $_[1] || 'undef' ) - . " did not pass container type constraint '$container_type_constraint'"; - $reader->($self)->{ $_[0] } = $_[1]; - } - else { - confess "One or two arguments expected, not " . @_; - } - }; - } - else { - return sub { - my $self = shift; - - if ( @_ == 1 ) { # reader - return $reader->($self)->{ $_[0] }; - } - elsif ( @_ == 2 ) { # writer - $reader->($self)->{ $_[0] } = $_[1]; - } - else { - confess "One or two arguments expected, not " . @_; - } - }; - } -} - -sub clear : method { - my ( $attr, $reader, $writer ) = @_; - return sub { %{ $reader->( $_[0] ) } = () }; -} - -sub delete : method { - my ( $attr, $reader, $writer ) = @_; - return sub { - my $hashref = $reader->(shift); - CORE::delete @{$hashref}{@_}; - }; -} - -1; - -__END__ - -=pod - -=head1 NAME - -Moose::Meta::Attribute::Native::MethodProvider::Hash - role providing method generators for Hash trait - -=head1 DESCRIPTION - -This is a role which provides the method generators for -L. Please check there for -documentation on what methods are provided. - -=head1 METHODS - -=over 4 - -=item B - -=back - -=head1 BUGS - -See L for details on reporting bugs. - -=head1 AUTHOR - -Stevan Little Estevan@iinteractive.comE - -=head1 COPYRIGHT AND LICENSE - -Copyright 2007-2009 by Infinity Interactive, Inc. - -L - -This library is free software; you can redistribute it and/or modify -it under the same terms as Perl itself. - -=cut - diff --git a/lib/Moose/Meta/Attribute/Native/Trait/Hash.pm b/lib/Moose/Meta/Attribute/Native/Trait/Hash.pm index 7b8d278..b62f5c7 100644 --- a/lib/Moose/Meta/Attribute/Native/Trait/Hash.pm +++ b/lib/Moose/Meta/Attribute/Native/Trait/Hash.pm @@ -8,6 +8,19 @@ our $AUTHORITY = 'cpan:STEVAN'; use Moose::Meta::Attribute::Native::MethodProvider::Hash; +use Moose::Meta::Method::Accessor::Native::Hash::clear; +use Moose::Meta::Method::Accessor::Native::Hash::count; +use Moose::Meta::Method::Accessor::Native::Hash::defined; +use Moose::Meta::Method::Accessor::Native::Hash::delete; +use Moose::Meta::Method::Accessor::Native::Hash::elements; +use Moose::Meta::Method::Accessor::Native::Hash::exists; +use Moose::Meta::Method::Accessor::Native::Hash::get; +use Moose::Meta::Method::Accessor::Native::Hash::is_empty; +use Moose::Meta::Method::Accessor::Native::Hash::keys; +use Moose::Meta::Method::Accessor::Native::Hash::kv; +use Moose::Meta::Method::Accessor::Native::Hash::set; +use Moose::Meta::Method::Accessor::Native::Hash::values; + with 'Moose::Meta::Attribute::Native::Trait'; has 'method_provider' => ( diff --git a/lib/Moose/Meta/Method/Accessor/Native/Array.pm b/lib/Moose/Meta/Method/Accessor/Native/Array.pm index d76c246..c2dd45a 100644 --- a/lib/Moose/Meta/Method/Accessor/Native/Array.pm +++ b/lib/Moose/Meta/Method/Accessor/Native/Array.pm @@ -9,8 +9,6 @@ our $VERSION = '1.13'; $VERSION = eval $VERSION; our $AUTHORITY = 'cpan:STEVAN'; -# This package is really more of a role, so it doesn't inherit from anything. - sub _inline_check_var_is_valid_index { my ( $self, $var ) = @_; diff --git a/lib/Moose/Meta/Method/Accessor/Native/Array/Writer.pm b/lib/Moose/Meta/Method/Accessor/Native/Array/Writer.pm index ab4c7f4..39fbe4a 100644 --- a/lib/Moose/Meta/Method/Accessor/Native/Array/Writer.pm +++ b/lib/Moose/Meta/Method/Accessor/Native/Array/Writer.pm @@ -3,114 +3,27 @@ package Moose::Meta::Method::Accessor::Native::Array::Writer; use strict; use warnings; +use Class::MOP::MiniTrait; + our $VERSION = '1.13'; $VERSION = eval $VERSION; our $AUTHORITY = 'cpan:STEVAN'; -use base qw( - Moose::Meta::Method::Accessor::Native::Array - Moose::Meta::Method::Accessor::Native::Writer -); - -sub _new_value {'@_'} - -sub _value_needs_copy { - my $self = shift; - - return $self->_constraint_must_be_checked - && !$self->_check_new_members_only; -} - -sub _inline_tc_code { - my ( $self, $new_value, $potential_value ) = @_; - - return q{} unless $self->_constraint_must_be_checked; - - if ( $self->_check_new_members_only ) { - return q{} unless $self->_adds_members; - - return $self->_inline_check_member_constraint($new_value); - } - else { - return $self->_inline_check_coercion($potential_value) . "\n" - . $self->_inline_check_constraint($potential_value); - } -} - -sub _check_new_members_only { - my $self = shift; - - my $attr = $self->associated_attribute; - - my $tc = $attr->type_constraint; - - # If we have a coercion, we could come up with an entirely new value after - # coercing, so we need to check everything, - return 0 if $attr->should_coerce && $tc->has_coercion; - - # If the parent is ArrayRef, that means we can just check the new members - # of the collection, because we know that we will always be generating an - # ArrayRef. However, if this type has its own constraint, we don't know - # what the constraint checks, so we need to check the whole value, not - # just the members. - return 1 - if $tc->parent->name eq 'ArrayRef' - && $tc->isa('Moose::Meta::TypeConstraint::Parameterized'); - - return 0; -} - -sub _inline_check_member_constraint { - my ( $self, $new_value ) = @_; - - my $attr_name = $self->associated_attribute->name; - - return '$member_tc->($_) || ' - . $self->_inline_throw_error( - qq{"A new member value for '$attr_name' does not pass its type constraint because: "} - . ' . $member_tc->get_message($_)', - "data => \$_" - ) . " for $new_value;"; -} - -sub _inline_check_constraint { - my $self = shift; - - return q{} unless $self->_constraint_must_be_checked; - - return $self->SUPER::_inline_check_constraint( $_[0] ); -} +use base 'Moose::Meta::Method::Accessor::Native::Writer'; -sub _inline_get_old_value_for_trigger { - my ( $self, $instance ) = @_; - - my $attr = $self->associated_attribute; - return '' unless $attr->has_trigger; - - my $mi = $attr->associated_class->get_meta_instance; - my $pred = $mi->inline_is_slot_initialized( $instance, $attr->name ); - - return - 'my @old = ' - . $pred . q{ ? } . '[ @{' - . $self->_inline_get($instance) - . '} ] : ()' . ";\n"; -} - -sub _eval_environment { - my $self = shift; - - my $env = $self->SUPER::_eval_environment; +Class::MOP::MiniTrait::apply( __PACKAGE__, + 'Moose::Meta::Method::Accessor::Native::Array' +); +Class::MOP::MiniTrait::apply( __PACKAGE__, + 'Moose::Meta::Method::Accessor::Native::Collection' +); - return $env - unless $self->_constraint_must_be_checked - and $self->_check_new_members_only; +sub _new_members {'@_'} - $env->{'$member_tc'} - = \( $self->associated_attribute->type_constraint->type_parameter - ->_compiled_type_constraint ); +sub _inline_copy_old_value { + my ( $self, $slot_access ) = @_; - return $env; + return '[ @{' . $slot_access . '} ]'; } 1; diff --git a/lib/Moose/Meta/Method/Accessor/Native/Array/accessor.pm b/lib/Moose/Meta/Method/Accessor/Native/Array/accessor.pm index a35b729..2759cf8 100644 --- a/lib/Moose/Meta/Method/Accessor/Native/Array/accessor.pm +++ b/lib/Moose/Meta/Method/Accessor/Native/Array/accessor.pm @@ -8,8 +8,8 @@ $VERSION = eval $VERSION; our $AUTHORITY = 'cpan:STEVAN'; use base qw( - Moose::Meta::Method::Accessor::Native::Array::get Moose::Meta::Method::Accessor::Native::Array::set + Moose::Meta::Method::Accessor::Native::Array::get ); sub _generate_method { @@ -33,7 +33,13 @@ sub _generate_method { $code .= "\n" . $self->_inline_check_var_is_valid_index('$_[0]'); - $code .= "\n" . 'return ' . $self->_return_value($slot_access) . ';'; + $code + .= "\n" + . 'return ' + . $self + ->Moose::Meta::Method::Accessor::Native::Array::get::_return_value( + $slot_access) + . ';'; # set $code .= "\n" . '} else {'; @@ -45,12 +51,10 @@ sub _generate_method { . $self ->Moose::Meta::Method::Accessor::Native::Array::set::_inline_check_arguments; - my $new_values = $self->_new_values($slot_access); my $potential_value = $self->_potential_value($slot_access); $code .= "\n" . $self->_inline_tc_code( - $new_values, $potential_value, $slot_access, ); @@ -83,22 +87,6 @@ sub _potential_value { "( do { my \@potential = \@{ $slot_access }; \$potential[ \$_[0] ] = \$_[1]; \@potential } )"; } -sub _new_values {'$_[1]'} - -sub _eval_environment { - my $self = shift; - - my $env = $self->SUPER::_eval_environment; - - return $env - unless $self->_constraint_must_be_checked - and $self->_check_new_members_only; - - $env->{'$member_tc'} - = \( $self->associated_attribute->type_constraint->type_parameter - ->_compiled_type_constraint ); - - return $env; -} +sub _new_members {'$_[1]'} 1; diff --git a/lib/Moose/Meta/Method/Accessor/Native/Array/get.pm b/lib/Moose/Meta/Method/Accessor/Native/Array/get.pm index 7dc8fa8..dc77cda 100644 --- a/lib/Moose/Meta/Method/Accessor/Native/Array/get.pm +++ b/lib/Moose/Meta/Method/Accessor/Native/Array/get.pm @@ -3,13 +3,16 @@ package Moose::Meta::Method::Accessor::Native::Array::get; use strict; use warnings; +use Class::MOP::MiniTrait; + our $VERSION = '1.13'; $VERSION = eval $VERSION; our $AUTHORITY = 'cpan:STEVAN'; -use base qw( - Moose::Meta::Method::Accessor::Native::Array - Moose::Meta::Method::Accessor::Native::Reader +use base 'Moose::Meta::Method::Accessor::Native::Reader'; + +Class::MOP::MiniTrait::apply( __PACKAGE__, + 'Moose::Meta::Method::Accessor::Native::Array' ); sub _minimum_arguments { 1 } diff --git a/lib/Moose/Meta/Method/Accessor/Native/Array/insert.pm b/lib/Moose/Meta/Method/Accessor/Native/Array/insert.pm index b5b40ee..38cf6c6 100644 --- a/lib/Moose/Meta/Method/Accessor/Native/Array/insert.pm +++ b/lib/Moose/Meta/Method/Accessor/Native/Array/insert.pm @@ -22,7 +22,7 @@ sub _potential_value { "( do { my \@potential = \@{ $slot_access }; splice \@potential, \$_[0], 0, \$_[1]; \\\@potential } )"; } -sub _new_values { '$_[1]' } +sub _new_members { '$_[1]' } sub _inline_optimized_set_new_value { my ( $self, $inv, $new, $slot_access ) = @_; diff --git a/lib/Moose/Meta/Method/Accessor/Native/Array/set.pm b/lib/Moose/Meta/Method/Accessor/Native/Array/set.pm index f8541d8..43df9c5 100644 --- a/lib/Moose/Meta/Method/Accessor/Native/Array/set.pm +++ b/lib/Moose/Meta/Method/Accessor/Native/Array/set.pm @@ -28,7 +28,7 @@ sub _potential_value { "( do { my \@potential = \@{ $slot_access }; \$potential[ \$_[0] ] = \$_[1]; \\\@potential } )"; } -sub _new_values { '$_[1]' } +sub _new_members { '$_[1]' } sub _inline_optimized_set_new_value { my ( $self, $inv, $new, $slot_access ) = @_; diff --git a/lib/Moose/Meta/Method/Accessor/Native/Collection.pm b/lib/Moose/Meta/Method/Accessor/Native/Collection.pm new file mode 100644 index 0000000..359628f --- /dev/null +++ b/lib/Moose/Meta/Method/Accessor/Native/Collection.pm @@ -0,0 +1,118 @@ +package Moose::Meta::Method::Accessor::Native::Collection; + +use strict; +use warnings; + +our $VERSION = '1.13'; +$VERSION = eval $VERSION; +our $AUTHORITY = 'cpan:STEVAN'; + +sub _value_needs_copy { + shift; + my $self = shift; + + return $self->_constraint_must_be_checked + && !$self->_check_new_members_only; +} + +sub _inline_tc_code { + shift; + my ( $self, $potential_value ) = @_; + + return q{} unless $self->_constraint_must_be_checked; + + if ( $self->_check_new_members_only ) { + return q{} unless $self->_adds_members; + + return $self->_inline_check_member_constraint( $self->_new_members ); + } + else { + return $self->_inline_check_coercion($potential_value) . "\n" + . $self->_inline_check_constraint($potential_value); + } +} + +sub _check_new_members_only { + my $self = shift; + + my $attr = $self->associated_attribute; + + my $tc = $attr->type_constraint; + + # If we have a coercion, we could come up with an entirely new value after + # coercing, so we need to check everything, + return 0 if $attr->should_coerce && $tc->has_coercion; + + # If the parent is our root type (ArrayRef, HashRef, etc), that means we + # can just check the new members of the collection, because we know that + # we will always be generating an appropriate collection type. + # + # However, if this type has its own constraint (it's Parameteriz_able_, + # not Paramet_erized_), we don't know what is being checked by the + # constraint, so we need to check the whole value, not just the members. + return 1 + if $self->_is_root_type( $tc->parent ) + && $tc->isa('Moose::Meta::TypeConstraint::Parameterized'); + + return 0; +} + +sub _inline_check_member_constraint { + my ( $self, $new_value ) = @_; + + my $attr_name = $self->associated_attribute->name; + + return '$member_tc->($_) || ' + . $self->_inline_throw_error( + qq{"A new member value for '$attr_name' does not pass its type constraint because: "} + . ' . $member_tc->get_message($_)', + "data => \$_" + ) . " for $new_value;"; +} + +sub _inline_check_constraint { + my $orig = shift; + my $self = shift; + + return q{} unless $self->_constraint_must_be_checked; + + return $self->$orig( $_[0] ); +} + +sub _inline_get_old_value_for_trigger { + shift; + my ( $self, $instance ) = @_; + + my $attr = $self->associated_attribute; + return '' unless $attr->has_trigger; + + my $mi = $attr->associated_class->get_meta_instance; + my $pred = $mi->inline_is_slot_initialized( $instance, $attr->name ); + + return + 'my @old = ' + . $pred . q{ ? } + . $self->_inline_copy_old_value( $self->_inline_get($instance) ) + . " : ();\n"; +} + +sub _eval_environment { + my $orig = shift; + my $self = shift; + + my $env = $self->$orig(@_); + + return $env + unless $self->_constraint_must_be_checked + && $self->_check_new_members_only; + + $env->{'$member_tc'} + = \( $self->associated_attribute->type_constraint->type_parameter + ->_compiled_type_constraint ); + + return $env; +} + +no Moose::Role; + +1; diff --git a/lib/Moose/Meta/Method/Accessor/Native/Counter/Writer.pm b/lib/Moose/Meta/Method/Accessor/Native/Counter/Writer.pm index dd653c8..090ec8d 100644 --- a/lib/Moose/Meta/Method/Accessor/Native/Counter/Writer.pm +++ b/lib/Moose/Meta/Method/Accessor/Native/Counter/Writer.pm @@ -9,8 +9,6 @@ our $AUTHORITY = 'cpan:STEVAN'; use base 'Moose::Meta::Method::Accessor::Native::Writer'; -sub _new_value {'$_[0]'} - sub _constraint_must_be_checked { my $self = shift; diff --git a/lib/Moose/Meta/Method/Accessor/Native/Hash.pm b/lib/Moose/Meta/Method/Accessor/Native/Hash.pm new file mode 100644 index 0000000..4dd5fd6 --- /dev/null +++ b/lib/Moose/Meta/Method/Accessor/Native/Hash.pm @@ -0,0 +1,21 @@ +package Moose::Meta::Method::Accessor::Native::Hash; + +use strict; +use warnings; + +our $VERSION = '1.13'; +$VERSION = eval $VERSION; +our $AUTHORITY = 'cpan:STEVAN'; + +# This package is really more of a role, so it doesn't inherit from anything. + +sub _inline_check_var_is_valid_key { + my ( $self, $var ) = @_; + + return $self->_inline_throw_error( q{'The key passed to } + . $self->delegate_to_method + . q{ must be a defined value'} ) + . qq{ unless defined $var;}; +} + +1; diff --git a/lib/Moose/Meta/Method/Accessor/Native/Hash/Writer.pm b/lib/Moose/Meta/Method/Accessor/Native/Hash/Writer.pm new file mode 100644 index 0000000..ba9b312 --- /dev/null +++ b/lib/Moose/Meta/Method/Accessor/Native/Hash/Writer.pm @@ -0,0 +1,29 @@ +package Moose::Meta::Method::Accessor::Native::Hash::Writer; + +use strict; +use warnings; + +use Class::MOP::MiniTrait; + +our $VERSION = '1.13'; +$VERSION = eval $VERSION; +our $AUTHORITY = 'cpan:STEVAN'; + +use base 'Moose::Meta::Method::Accessor::Native::Writer'; + +Class::MOP::MiniTrait::apply( __PACKAGE__, + 'Moose::Meta::Method::Accessor::Native::Hash' +); +Class::MOP::MiniTrait::apply( __PACKAGE__, + 'Moose::Meta::Method::Accessor::Native::Collection' +); + +sub _new_values {'@values'} + +sub _inline_copy_old_value { + my ( $self, $slot_access ) = @_; + + return '{ @{' . $slot_access . '} }'; +} + +1; diff --git a/lib/Moose/Meta/Method/Accessor/Native/Hash/accessor.pm b/lib/Moose/Meta/Method/Accessor/Native/Hash/accessor.pm new file mode 100644 index 0000000..cd52e07 --- /dev/null +++ b/lib/Moose/Meta/Method/Accessor/Native/Hash/accessor.pm @@ -0,0 +1,91 @@ +package Moose::Meta::Method::Accessor::Native::Hash::accessor; + +use strict; +use warnings; + +our $VERSION = '1.13'; +$VERSION = eval $VERSION; +our $AUTHORITY = 'cpan:STEVAN'; + +use base qw( + Moose::Meta::Method::Accessor::Native::Hash::set + Moose::Meta::Method::Accessor::Native::Hash::get +); + +sub _generate_method { + my $self = shift; + + my $inv = '$self'; + + my $code = 'sub {'; + $code .= "\n" . $self->_inline_pre_body(@_); + + $code .= "\n" . 'my $self = shift;'; + + $code .= "\n" . $self->_inline_curried_arguments; + + $code .= "\n" . $self->_inline_check_lazy($inv); + + my $slot_access = $self->_inline_get($inv); + + # get + $code .= "\n" . 'if ( @_ == 1 ) {'; + + $code .= "\n" . $self->_inline_check_var_is_valid_index('$_[0]'); + + $code + .= "\n" + . 'return ' + . $self + ->Moose::Meta::Method::Accessor::Native::Hash::get::_return_value( + $slot_access) + . ';'; + + # set + $code .= "\n" . '} else {'; + + $code .= "\n" . $self->_inline_check_argument_count; + + $code + .= "\n" + . $self + ->Moose::Meta::Method::Accessor::Native::Hash::set::_inline_check_arguments; + + my $potential_value = $self->_potential_value($slot_access); + + $code .= "\n" + . $self->_inline_tc_code( + $potential_value, + $slot_access, + ); + + $code .= "\n" . $self->_inline_get_old_value_for_trigger($inv); + $code .= "\n" . $self->_inline_capture_return_value($slot_access); + + $code + .= "\n" . $self->_inline_store( $inv, '[' . $potential_value . ']' ); + + $code .= "\n" . $self->_inline_post_body(@_); + $code .= "\n" . $self->_inline_trigger( $inv, $slot_access, '@old' ); + + $code .= "\n}"; + $code .= "\n}"; + + return $code; +} + +# If we get one argument we won't check the argument count +sub _minimum_arguments {2} +sub _maximum_arguments {2} + +sub _adds_members {1} + +sub _potential_value { + my ( $self, $slot_access ) = @_; + + return "%{ $slot_access, @_ }"; +} + +sub _new_members {'$_[1]'} + +1; diff --git a/lib/Moose/Meta/Method/Accessor/Native/Hash/clear.pm b/lib/Moose/Meta/Method/Accessor/Native/Hash/clear.pm new file mode 100644 index 0000000..62a9222 --- /dev/null +++ b/lib/Moose/Meta/Method/Accessor/Native/Hash/clear.pm @@ -0,0 +1,24 @@ +package Moose::Meta::Method::Accessor::Native::Hash::clear; + +use strict; +use warnings; + +our $VERSION = '1.13'; +$VERSION = eval $VERSION; +our $AUTHORITY = 'cpan:STEVAN'; + +use base 'Moose::Meta::Method::Accessor::Native::Hash::Writer'; + +sub _maximum_arguments { 0 } + +sub _adds_members { 0 } + +sub _potential_value { return '{}' } + +sub _inline_optimized_set_new_value { + my ( $self, $inv, $new, $slot_access ) = @_; + + return "$slot_access = {};"; +} + +1; diff --git a/lib/Moose/Meta/Method/Accessor/Native/Hash/count.pm b/lib/Moose/Meta/Method/Accessor/Native/Hash/count.pm new file mode 100644 index 0000000..4dc6212 --- /dev/null +++ b/lib/Moose/Meta/Method/Accessor/Native/Hash/count.pm @@ -0,0 +1,26 @@ +package Moose::Meta::Method::Accessor::Native::Hash::count; + +use strict; +use warnings; + +use Scalar::Util qw( looks_like_number ); + +our $VERSION = '1.13'; +$VERSION = eval $VERSION; +our $AUTHORITY = 'cpan:STEVAN'; + +use base 'Moose::Meta::Method::Accessor::Native::Reader'; + +sub _minimum_arguments { 0 } + +sub _maximum_arguments { 0 } + +sub _return_value { + my $self = shift; + my $slot_access = shift; + + return "scalar keys \%{ $slot_access }"; +} + + +1; diff --git a/lib/Moose/Meta/Method/Accessor/Native/Hash/defined.pm b/lib/Moose/Meta/Method/Accessor/Native/Hash/defined.pm new file mode 100644 index 0000000..d5494ae --- /dev/null +++ b/lib/Moose/Meta/Method/Accessor/Native/Hash/defined.pm @@ -0,0 +1,35 @@ +package Moose::Meta::Method::Accessor::Native::Hash::defined; + +use strict; +use warnings; + +use Scalar::Util qw( looks_like_number ); + +our $VERSION = '1.13'; +$VERSION = eval $VERSION; +our $AUTHORITY = 'cpan:STEVAN'; + +use base qw( + Moose::Meta::Method::Accessor::Native::Hash + Moose::Meta::Method::Accessor::Native::Reader +); + +sub _minimum_arguments { 1 } + +sub _maximum_arguments { 1 } + +sub _inline_check_arguments { + my $self = shift; + + return $self->_inline_check_var_is_valid_key('$_[0]'); +} + +sub _return_value { + my $self = shift; + my $slot_access = shift; + + return "defined ${slot_access}->{ \$_[0] }"; +} + + +1; diff --git a/lib/Moose/Meta/Method/Accessor/Native/Hash/delete.pm b/lib/Moose/Meta/Method/Accessor/Native/Hash/delete.pm new file mode 100644 index 0000000..f4b6425 --- /dev/null +++ b/lib/Moose/Meta/Method/Accessor/Native/Hash/delete.pm @@ -0,0 +1,26 @@ +package Moose::Meta::Method::Accessor::Native::Hash::delete; + +use strict; +use warnings; + +our $VERSION = '1.13'; +$VERSION = eval $VERSION; +our $AUTHORITY = 'cpan:STEVAN'; + +use base 'Moose::Meta::Method::Accessor::Native::Hash::Writer'; + +sub _adds_members { 0 } + +sub _potential_value { + my ( $self, $slot_access ) = @_; + + return "( do { my \%potential = %{ $slot_access }; delete \@potential{\@_}; \\\%potential; } )"; +} + +sub _inline_optimized_set_new_value { + my ( $self, $inv, $new, $slot_access ) = @_; + + return "delete \@{ $slot_access }{\@_};"; +} + +1; diff --git a/lib/Moose/Meta/Method/Accessor/Native/Hash/elements.pm b/lib/Moose/Meta/Method/Accessor/Native/Hash/elements.pm new file mode 100644 index 0000000..f05f035 --- /dev/null +++ b/lib/Moose/Meta/Method/Accessor/Native/Hash/elements.pm @@ -0,0 +1,26 @@ +package Moose::Meta::Method::Accessor::Native::Hash::elements; + +use strict; +use warnings; + +use Scalar::Util qw( looks_like_number ); + +our $VERSION = '1.13'; +$VERSION = eval $VERSION; +our $AUTHORITY = 'cpan:STEVAN'; + +use base 'Moose::Meta::Method::Accessor::Native::Reader'; + +sub _minimum_arguments { 0 } + +sub _maximum_arguments { 0 } + +sub _return_value { + my $self = shift; + my $slot_access = shift; + + return "map { \$_, ${slot_access}->{\$_} } keys \%{ $slot_access }"; +} + + +1; diff --git a/lib/Moose/Meta/Method/Accessor/Native/Hash/exists.pm b/lib/Moose/Meta/Method/Accessor/Native/Hash/exists.pm new file mode 100644 index 0000000..cf36d2b --- /dev/null +++ b/lib/Moose/Meta/Method/Accessor/Native/Hash/exists.pm @@ -0,0 +1,35 @@ +package Moose::Meta::Method::Accessor::Native::Hash::exists; + +use strict; +use warnings; + +use Scalar::Util qw( looks_like_number ); + +our $VERSION = '1.13'; +$VERSION = eval $VERSION; +our $AUTHORITY = 'cpan:STEVAN'; + +use base qw( + Moose::Meta::Method::Accessor::Native::Hash + Moose::Meta::Method::Accessor::Native::Reader +); + +sub _minimum_arguments { 1 } + +sub _maximum_arguments { 1 } + +sub _inline_check_arguments { + my $self = shift; + + return $self->_inline_check_var_is_valid_key('$_[0]'); +} + +sub _return_value { + my $self = shift; + my $slot_access = shift; + + return "exists ${slot_access}->{ \$_[0] }"; +} + + +1; diff --git a/lib/Moose/Meta/Method/Accessor/Native/Hash/get.pm b/lib/Moose/Meta/Method/Accessor/Native/Hash/get.pm new file mode 100644 index 0000000..053a3fa --- /dev/null +++ b/lib/Moose/Meta/Method/Accessor/Native/Hash/get.pm @@ -0,0 +1,38 @@ +package Moose::Meta::Method::Accessor::Native::Hash::get; + +use strict; +use warnings; + +use Scalar::Util qw( looks_like_number ); + +our $VERSION = '1.13'; +$VERSION = eval $VERSION; +our $AUTHORITY = 'cpan:STEVAN'; + +use base 'Moose::Meta::Method::Accessor::Native::Reader'; + +Class::MOP::MiniTrait::apply( __PACKAGE__, + 'Moose::Meta::Method::Accessor::Native::Hash' +); + +sub _minimum_arguments { 1 } + +sub _maximum_arguments { undef } + +sub _inline_check_arguments { + my $self = shift; + + return + 'for (@_) {' . "\n" + . $self->_inline_check_var_is_valid_key('$_') . "\n" . '}'; +} + +sub _return_value { + my $self = shift; + my $slot_access = shift; + + return "\@_ > 1 ? \@{ $slot_access }{\@_} : ${slot_access}->{ \$_[0] }"; +} + + +1; diff --git a/lib/Moose/Meta/Method/Accessor/Native/Hash/is_empty.pm b/lib/Moose/Meta/Method/Accessor/Native/Hash/is_empty.pm new file mode 100644 index 0000000..0e0209e --- /dev/null +++ b/lib/Moose/Meta/Method/Accessor/Native/Hash/is_empty.pm @@ -0,0 +1,26 @@ +package Moose::Meta::Method::Accessor::Native::Hash::is_empty; + +use strict; +use warnings; + +use Scalar::Util qw( looks_like_number ); + +our $VERSION = '1.13'; +$VERSION = eval $VERSION; +our $AUTHORITY = 'cpan:STEVAN'; + +use base 'Moose::Meta::Method::Accessor::Native::Reader'; + +sub _minimum_arguments { 0 } + +sub _maximum_arguments { 0 } + +sub _return_value { + my $self = shift; + my $slot_access = shift; + + return "scalar keys \%{ $slot_access } ? 0 : 1"; +} + + +1; diff --git a/lib/Moose/Meta/Method/Accessor/Native/Hash/keys.pm b/lib/Moose/Meta/Method/Accessor/Native/Hash/keys.pm new file mode 100644 index 0000000..de4ed2b --- /dev/null +++ b/lib/Moose/Meta/Method/Accessor/Native/Hash/keys.pm @@ -0,0 +1,26 @@ +package Moose::Meta::Method::Accessor::Native::Hash::keys; + +use strict; +use warnings; + +use Scalar::Util qw( looks_like_number ); + +our $VERSION = '1.13'; +$VERSION = eval $VERSION; +our $AUTHORITY = 'cpan:STEVAN'; + +use base 'Moose::Meta::Method::Accessor::Native::Reader'; + +sub _minimum_arguments { 0 } + +sub _maximum_arguments { 0 } + +sub _return_value { + my $self = shift; + my $slot_access = shift; + + return "keys \%{ $slot_access }"; +} + + +1; diff --git a/lib/Moose/Meta/Method/Accessor/Native/Hash/kv.pm b/lib/Moose/Meta/Method/Accessor/Native/Hash/kv.pm new file mode 100644 index 0000000..b847b38 --- /dev/null +++ b/lib/Moose/Meta/Method/Accessor/Native/Hash/kv.pm @@ -0,0 +1,26 @@ +package Moose::Meta::Method::Accessor::Native::Hash::kv; + +use strict; +use warnings; + +use Scalar::Util qw( looks_like_number ); + +our $VERSION = '1.13'; +$VERSION = eval $VERSION; +our $AUTHORITY = 'cpan:STEVAN'; + +use base 'Moose::Meta::Method::Accessor::Native::Reader'; + +sub _minimum_arguments { 0 } + +sub _maximum_arguments { 0 } + +sub _return_value { + my $self = shift; + my $slot_access = shift; + + return "map { [ \$_, ${slot_access}->{\$_} ] } keys \%{ $slot_access }"; +} + + +1; diff --git a/lib/Moose/Meta/Method/Accessor/Native/Hash/set.pm b/lib/Moose/Meta/Method/Accessor/Native/Hash/set.pm new file mode 100644 index 0000000..611e3e9 --- /dev/null +++ b/lib/Moose/Meta/Method/Accessor/Native/Hash/set.pm @@ -0,0 +1,61 @@ +package Moose::Meta::Method::Accessor::Native::Hash::set; + +use strict; +use warnings; + +use Scalar::Util qw( looks_like_number ); + +our $VERSION = '1.13'; +$VERSION = eval $VERSION; +our $AUTHORITY = 'cpan:STEVAN'; + +use base 'Moose::Meta::Method::Accessor::Native::Hash::Writer'; + +sub _minimum_arguments { 2 } + +sub _maximum_arguments { undef } + +sub _inline_check_argument_count { + my $self = shift; + + return + $self->SUPER::_inline_check_argument_count(@_) . "\n" + . $self->_inline_throw_error( + q{'You must pass an even number of arguments to set'}) + . ' if @_ % 2;'; +} + +sub _inline_process_arguments { + my $self = shift; + + return 'my @keys_idx = grep { ! ($_ % 2) } 0..$#_;' . "\n" + . 'my @values_idx = grep { $_ % 2 } 0..$#_;'; +} + +sub _inline_check_arguments { + my $self = shift; + + return + 'for (@keys_idx) {' . "\n" + . $self->_inline_throw_error( + q{'Hash keys passed to set must be defined'}) + . ' unless defined $_[$_];' . "\n" . '}'; +} + +sub _adds_members { 1 } + +sub _potential_value { + my ( $self, $slot_access ) = @_; + + return "%{ $slot_access, @_ }"; +} + +sub _new_members { '@_[ @values_idx ]' } + +sub _inline_optimized_set_new_value { + my ( $self, $inv, $new, $slot_access ) = @_; + + return "\@{ $slot_access }{ \@_[ \@keys_idx] } = \@_[ \@values_idx ];"; +} + +1; diff --git a/lib/Moose/Meta/Method/Accessor/Native/Hash/values.pm b/lib/Moose/Meta/Method/Accessor/Native/Hash/values.pm new file mode 100644 index 0000000..48273f6 --- /dev/null +++ b/lib/Moose/Meta/Method/Accessor/Native/Hash/values.pm @@ -0,0 +1,26 @@ +package Moose::Meta::Method::Accessor::Native::Hash::values; + +use strict; +use warnings; + +use Scalar::Util qw( looks_like_number ); + +our $VERSION = '1.13'; +$VERSION = eval $VERSION; +our $AUTHORITY = 'cpan:STEVAN'; + +use base 'Moose::Meta::Method::Accessor::Native::Reader'; + +sub _minimum_arguments { 0 } + +sub _maximum_arguments { 0 } + +sub _return_value { + my $self = shift; + my $slot_access = shift; + + return "values \%{ $slot_access }"; +} + + +1; diff --git a/lib/Moose/Meta/Method/Accessor/Native/Writer.pm b/lib/Moose/Meta/Method/Accessor/Native/Writer.pm index 22549ab..b65076e 100644 --- a/lib/Moose/Meta/Method/Accessor/Native/Writer.pm +++ b/lib/Moose/Meta/Method/Accessor/Native/Writer.pm @@ -46,13 +46,11 @@ sub _writer_core { $code .= "\n" . $self->_inline_check_lazy($inv); - my $new_value = $self->_new_value($slot_access); my $potential_value = $self->_potential_value($slot_access); $code .= "\n" . $self->_inline_copy_value( \$potential_value ); $code .= "\n" . $self->_inline_tc_code( - $new_value, $potential_value ); @@ -74,8 +72,6 @@ sub _inline_process_arguments {q{}} sub _inline_check_arguments {q{}} -sub _new_value {'$_[0]'} - sub _value_needs_copy { my $self = shift; @@ -113,7 +109,7 @@ sub _inline_copy_value { } sub _inline_tc_code { - my ( $self, $new_value, $potential_value ) = @_; + my ( $self, $potential_value ) = @_; return q{} unless $self->_constraint_must_be_checked; diff --git a/t/070_native_traits/003_trait_hash.t b/t/070_native_traits/003_trait_hash.t index a4d4b38..1b621b5 100644 --- a/t/070_native_traits/003_trait_hash.t +++ b/t/070_native_traits/003_trait_hash.t @@ -55,12 +55,10 @@ is( $stuff->num_options, 0, '... we have no options' ); is_deeply( $stuff->options, {}, '... no options yet' ); ok( !$stuff->has_option('foo'), '... we have no foo option' ); -my $set_result; lives_ok { - $set_result = $stuff->set_option( foo => 'bar' ); + $stuff->set_option( foo => 'bar' ); } '... set the option okay'; -is($set_result, 'bar', '... returns value set'); ok( $stuff->is_defined('foo'), '... foo is defined' ); @@ -70,10 +68,9 @@ ok( $stuff->has_option('foo'), '... we have a foo option' ); is_deeply( $stuff->options, { foo => 'bar' }, '... got options now' ); lives_ok { - $set_result = $stuff->set_option( bar => 'baz' ); + $stuff->set_option( bar => 'baz' ); } '... set the option okay'; -is($set_result, 'baz', '... returns value set'); is( $stuff->num_options, 2, '... we have 2 option(s)' ); is_deeply( $stuff->options, { foo => 'bar', bar => 'baz' }, @@ -87,12 +84,10 @@ is_deeply( [ $stuff->get_option(qw(foo bar)) ], [qw(bar baz)], is( scalar($stuff->get_option(qw( foo bar) )), "baz", '... got last option in scalar context'); -my @set_return; lives_ok { - @set_return = $stuff->set_option( oink => "blah", xxy => "flop" ); + $stuff->set_option( oink => "blah", xxy => "flop" ); } '... set the option okay'; -is_deeply(\@set_return, [ qw(blah flop) ], '... and returns values set'); is( $stuff->num_options, 4, "4 options" ); is_deeply( [ $stuff->get_option(qw(foo bar oink xxy)) ],