start pushing constructor inlining back into the metaclass
[gitmo/Class-MOP.git] / lib / Class / MOP / Class.pm
index b0ba266..983dd48 100644 (file)
@@ -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<instance_metaclass> 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