From: Jesse Luehrs Date: Thu, 11 Nov 2010 05:29:35 +0000 (-0600) Subject: start pushing constructor inlining back into the metaclass X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=1322c26b43bfd579ca9f2921b7f26674a6d245f2;p=gitmo%2FClass-MOP.git start pushing constructor inlining back into the metaclass --- diff --git a/lib/Class/MOP/Class.pm b/lib/Class/MOP/Class.pm index b0ba266..983dd48 100644 --- a/lib/Class/MOP/Class.pm +++ b/lib/Class/MOP/Class.pm @@ -584,6 +584,100 @@ sub _construct_instance { return $instance; } +sub _inline_new_object { + my $self = shift; + + my $idx = 0; + return ( + 'my $class = shift;', + 'return Class::MOP::Class->initialize($class)->new_object(@_)', + 'if $class ne \'' . $self->name . '\';', + 'my $params = @_ == 1 ? $_[0] : {@_};', + 'my $instance = ' . $self->_inline_create_instance('$class') . ';', + (map { $self->_inline_slot_initializer($_, $idx++) } + $self->get_all_attributes), + $self->_inline_preserve_weak_metaclasses, + 'return $instance', + ); +} + +sub _inline_create_instance { + my $self = shift; + + return $self->get_meta_instance->inline_create_instance(@_); +} + +sub _inline_slot_initializer { + my $self = shift; + my ($attr, $idx) = @_; + + my $default = $self->_inline_default_value($attr, $idx); + + if (defined(my $init_arg = $attr->init_arg)) { + my @source = ( + 'if (exists $params->{\'' . $init_arg . '\'}) {', + $attr->_inline_set_value( + '$instance', '$params->{\'' . $init_arg . '\'}' + ), + '}', + ); + if (defined $default) { + push @source, ( + 'else {', + $attr->_inline_set_value('$instance', $default), + '}', + ); + } + return @source; + } + elsif (defined $default) { + return $attr->_inline_set_value('$instance', $default); + } + else { + return (); + } +} + +sub _inline_default_value { + my $self = shift; + my ($attr, $index) = @_; + + if ($attr->has_default) { + # NOTE: + # default values can either be CODE refs + # in which case we need to call them. Or + # they can be scalars (strings/numbers) + # in which case we can just deal with them + # in the code we eval. + if ($attr->is_default_a_coderef) { + return '$defaults->[' . $index . ']->($instance)'; + } + else { + return '$defaults->[' . $index . ']'; + } + } + elsif ($attr->has_builder) { + return '$instance->' . $attr->builder; + } + else { + return; + } +} + +sub _inline_preserve_weak_metaclasses { + my $self = shift; + if (Class::MOP::metaclass_is_weak($self->name)) { + return ( + $self->_inline_set_mop_slot( + '$instance', 'Class::MOP::class_of($class)' + ) . ';' + ); + } + else { + return (); + } +} + sub get_meta_instance { my $self = shift; @@ -604,13 +698,7 @@ sub _create_meta_instance { return $instance; } -sub inline_create_instance { - my $self = shift; - - return $self->get_meta_instance->inline_create_instance(@_); -} - -sub inline_rebless_instance { +sub _inline_rebless_instance { my $self = shift; return $self->get_meta_instance->inline_rebless_instance_structure(@_); @@ -1572,13 +1660,6 @@ metaclass. Returns an instance of the C to be used in the construction of a new instance of the class. -=item B<< $metaclass->inline_create_instance($class_var) >> - -=item B<< $metaclass->inline_rebless_instance($instance_var, $class_var) >> - -These methods takes variable names, and use them to create an inline snippet -of code that will create a new instance of the class. - =back =head2 Informational predicates diff --git a/lib/Class/MOP/Method/Constructor.pm b/lib/Class/MOP/Method/Constructor.pm index 3755a4e..b64c1c5 100644 --- a/lib/Class/MOP/Method/Constructor.pm +++ b/lib/Class/MOP/Method/Constructor.pm @@ -89,10 +89,6 @@ sub _initialize_body { $self->{'body'} = $self->$method_name; } -sub _generate_constructor_method { - return sub { Class::MOP::Class->initialize(shift)->new_object(@_) } -} - sub _eval_environment { my $self = shift; my $defaults = [map { $_->default } @{ $self->_attributes }]; @@ -101,23 +97,18 @@ sub _eval_environment { }; } +sub _generate_constructor_method { + return sub { Class::MOP::Class->initialize(shift)->new_object(@_) } +} + sub _generate_constructor_method_inline { my $self = shift; my $meta = $self->associated_metaclass; - my $idx = 0; my @source = ( 'sub {', - 'my $class = shift;', - 'return Class::MOP::Class->initialize($class)->new_object(@_)', - 'if $class ne \'' . $meta->name . '\';', - 'my $params = @_ == 1 ? $_[0] : {@_};', - 'my $instance = ' . $meta->inline_create_instance('$class') . ';', - (map { $self->_generate_slot_initializer($_, $idx++) } - @{ $self->_attributes }), - $self->_preserve_weak_metaclasses, - 'return $instance', + $meta->_inline_new_object, '}', ); @@ -134,78 +125,6 @@ sub _generate_constructor_method_inline { return $code; } -sub _generate_slot_initializer { - my $self = shift; - my ($attr, $idx) = @_; - - my $default = $self->_generate_default_value($attr, $idx); - - if (defined(my $init_arg = $attr->init_arg)) { - my @source = ( - 'if (exists $params->{\'' . $init_arg . '\'}) {', - $attr->_inline_set_value( - '$instance', '$params->{\'' . $init_arg . '\'}' - ), - '}', - ); - if (defined $default) { - push @source, ( - 'else {', - $attr->_inline_set_value('$instance', $default), - '}', - ); - } - return @source; - } - elsif (defined $default) { - return $attr->_inline_set_value('$instance', $default); - } - else { - return (); - } -} - -sub _preserve_weak_metaclasses { - my $self = shift; - my $meta = $self->associated_metaclass; - if (Class::MOP::metaclass_is_weak($meta->name)) { - return ( - $meta->_inline_set_mop_slot( - '$instance', 'Class::MOP::class_of($class)' - ) . ';' - ); - } - else { - return (); - } -} - -sub _generate_default_value { - my $self = shift; - my ($attr, $index) = @_; - - if ($attr->has_default) { - # NOTE: - # default values can either be CODE refs - # in which case we need to call them. Or - # they can be scalars (strings/numbers) - # in which case we can just deal with them - # in the code we eval. - if ($attr->is_default_a_coderef) { - return '$defaults->[' . $index . ']->($instance)'; - } - else { - return '$defaults->[' . $index . ']'; - } - } - elsif ($attr->has_builder) { - return '$instance->' . $attr->builder; - } - else { - return; - } -} - 1; __END__ diff --git a/t/010_self_introspection.t b/t/010_self_introspection.t index 99cbc87..90d2f69 100644 --- a/t/010_self_introspection.t +++ b/t/010_self_introspection.t @@ -58,11 +58,13 @@ my @class_mop_class_methods = qw( create_anon_class is_anon_class instance_metaclass get_meta_instance - inline_create_instance - inline_rebless_instance + _inline_create_instance + _inline_rebless_instance _inline_get_mop_slot _inline_set_mop_slot _inline_clear_mop_slot create_meta_instance _create_meta_instance new_object clone_object + _inline_new_object _inline_default_value _inline_preserve_weak_metaclasses + _inline_slot_initializer construct_instance _construct_instance construct_class_instance _construct_class_instance clone_instance _clone_instance