deferred constructor construction
[gitmo/Moo.git] / lib / Method / Generate / Constructor.pm
index d8578b3..b08385d 100644 (file)
@@ -3,13 +3,23 @@ package Method::Generate::Constructor;
 use strictures 1;
 use Sub::Quote;
 use base qw(Class::Tiny::Object);
+use Sub::Defer;
 
-##{
-##  use Method::Generate::Accessor;
-##  my $gen = Method::Generate::Accessor->new;
-##  $gen->generate_method(__PACKAGE__, $_, { is => 'ro' })
-##    for qw(accessor_generator);
-##}
+sub register_attribute_spec {
+  my ($self, $name, $spec) = @_;
+  $self->{attribute_specs}{$name} = $spec;
+}
+
+sub install_delayed {
+  my ($self) = @_;
+  my $package = $self->{package};
+  defer_sub "${package}::new" => sub {
+    unquote_sub $self->generate_method(
+      $package, 'new', $self->{attribute_specs}, { no_install => 1 }
+    )
+  };
+  $self;
+}
 
 sub generate_method {
   my ($self, $into, $name, $spec, $quote_opts) = @_;
@@ -21,9 +31,9 @@ sub generate_method {
   $body .= $self->_check_required($spec);
   $body .= '    my $new = bless({}, $class);'."\n";
   $body .= $self->_assign_new($spec);
-  $body .= '    return $new;';
+  $body .= '    return $new;'."\n";
   quote_sub
-    "${into}::${name}" => '    '.$body."\n",
+    "${into}::${name}" => $body,
     (ref($quote_opts) ? ({}, $quote_opts) : ())
   ;
 }
@@ -44,6 +54,7 @@ sub _assign_new {
     };
     push @slots, $name;
   }
+  return '' unless @init;
   '    @{$new}{qw('.join(' ',@slots).')} = @{$args}{qw('.join(' ',@init).')};'
     ."\n";
 }
@@ -53,7 +64,7 @@ sub _check_required {
   my @required_init =
     map $spec->{$_}{init_arg},
       grep $spec->{$_}{required},
-       keys %$spec;
+        keys %$spec;
   return '' unless @required_init;
   '    if (my @missing = grep !exists $args->{$_}, qw('
     .join(' ',@required_init).')) {'."\n"