Settle for respecting inline_constructor for now
[gitmo/Mouse.git] / lib / Mouse / Meta / Method / Constructor.pm
CommitLineData
fc1d8369 1package Mouse::Meta::Method::Constructor;
2use strict;
3use warnings;
4
5sub generate_constructor_method_inline {
41cdacce 6 my ($class, $meta) = @_;
24ad3f66 7
a4d5249c 8 my @attrs = $meta->compute_all_applicable_attributes;
fc1d8369 9 my $buildall = $class->_generate_BUILDALL($meta);
9dcd7d23 10 my $buildargs = $class->_generate_BUILDARGS($meta);
c12edd9a 11 my $processattrs = $class->_generate_processattrs($meta, \@attrs);
fc1d8369 12
24ad3f66 13 my $code = <<"...";
fc1d8369 14 sub {
15 my \$class = shift;
16 my \$args = $buildargs;
24ad3f66 17 my \$instance = bless {}, \$class;
fc1d8369 18 $processattrs;
19 $buildall;
20 return \$instance;
21 }
22...
24ad3f66 23
24ad3f66 24 local $@;
25 my $res = eval $code;
26 die $@ if $@;
27 $res;
fc1d8369 28}
29
30sub _generate_processattrs {
c12edd9a 31 my ($class, $meta, $attrs) = @_;
fc1d8369 32 my @res;
9df6f0cd 33
34 for my $index (0 .. @$attrs - 1) {
c12edd9a 35 my $attr = $attrs->[$index];
fc1d8369 36 my $key = $attr->name;
9df6f0cd 37 my $code = '';
38
39 if (defined $attr->init_arg) {
40 my $from = $attr->init_arg;
c91862e8 41
9df6f0cd 42 $code .= "if (exists \$args->{'$from'}) {\n";
c91862e8 43
b3b74cc6 44 if ($attr->should_coerce && $attr->type_constraint) {
3b46bd49 45 $code .= "my \$value = Mouse::Util::TypeConstraints->typecast_constraints('".$attr->associated_class->name."', \$attrs[$index]->{find_type_constraint}, \$attrs[$index]->{type_constraint}, \$args->{'$from'});\n";
7bf66a9b 46 }
47 else {
7756897f 48 $code .= "my \$value = \$args->{'$from'};\n";
fc1d8369 49 }
c91862e8 50
fc1d8369 51 if ($attr->has_type_constraint) {
7756897f 52 $code .= "{
53 local \$_ = \$value;
54 unless (\$attrs[$index]->{find_type_constraint}->(\$_)) {
55 \$attrs[$index]->verify_type_constraint_error('$key', \$_, \$attrs[$index]->type_constraint)
56 }
57 }";
fc1d8369 58 }
c91862e8 59
7756897f 60 $code .= "\$instance->{'$key'} = \$value;\n";
c91862e8 61
41cdacce 62 if ($attr->is_weak_ref) {
7756897f 63 $code .= "Scalar::Util::weaken( \$instance->{'$key'} ) if ref( \$value );\n";
41cdacce 64 }
c91862e8 65
9df6f0cd 66 if ($attr->has_trigger) {
7756897f 67 $code .= "\$attrs[$index]->{trigger}->( \$instance, \$value, \$attrs[$index] );\n";
fc1d8369 68 }
c91862e8 69
7756897f 70 $code .= "\n} else {\n";
9df6f0cd 71 }
c91862e8 72
9df6f0cd 73 if ($attr->has_default || $attr->has_builder) {
74 unless ($attr->is_lazy) {
75 my $default = $attr->default;
76 my $builder = $attr->builder;
e8ba7b26 77
9df6f0cd 78 $code .= "my \$value = ";
e8ba7b26 79
9df6f0cd 80 if ($attr->should_coerce && $attr->type_constraint) {
3b46bd49 81 $code .= "Mouse::Util::TypeConstraints->typecast_constraints('".$attr->associated_class->name."', \$attrs[$index]->{find_type_constraint}, \$attrs[$index]->{type_constraint}, ";
9df6f0cd 82 }
e8ba7b26 83
9df6f0cd 84 if ($attr->has_builder) {
85 $code .= "\$instance->$builder";
fc1d8369 86 }
9df6f0cd 87 elsif (ref($default) eq 'CODE') {
88 $code .= "\$attrs[$index]->{default}->(\$instance)";
e8ba7b26 89 }
9df6f0cd 90 elsif (!defined($default)) {
91 $code .= 'undef';
fc1d8369 92 }
9df6f0cd 93 elsif ($default =~ /^\-?[0-9]+(?:\.[0-9]+)$/) {
94 $code .= $default;
95 }
96 else {
97 $code .= "'$default'";
fc1d8369 98 }
e8ba7b26 99
9df6f0cd 100 if ($attr->should_coerce) {
7756897f 101 $code .= ");\n";
9df6f0cd 102 }
103 else {
7756897f 104 $code .= ";\n";
9df6f0cd 105 }
e8ba7b26 106
9df6f0cd 107 if ($attr->has_type_constraint) {
7756897f 108 $code .= "{
109 local \$_ = \$value;
110 unless (\$attrs[$index]->{find_type_constraint}->(\$_)) {
111 \$attrs[$index]->verify_type_constraint_error('$key', \$_, \$attrs[$index]->type_constraint)
112 }
113 }";
fc1d8369 114 }
9df6f0cd 115
7756897f 116 $code .= "\$instance->{'$key'} = \$value;\n";
9df6f0cd 117
118 if ($attr->is_weak_ref) {
7756897f 119 $code .= "Scalar::Util::weaken( \$instance->{'$key'} ) if ref( \$value );\n";
fc1d8369 120 }
121 }
713a2a05 122 }
9df6f0cd 123 elsif ($attr->is_required) {
7756897f 124 $code .= "Carp::confess('Attribute ($key) is required');";
9df6f0cd 125 }
126
7756897f 127 $code .= "}\n" if defined $attr->init_arg;
9df6f0cd 128
fc1d8369 129 push @res, $code;
130 }
9df6f0cd 131
fc1d8369 132 return join "\n", @res;
133}
134
135sub _generate_BUILDARGS {
9dcd7d23 136 my $self = shift;
137 my $meta = shift;
138
139 if ($meta->name->can('BUILDARGS') != Mouse::Object->can('BUILDARGS')) {
140 return '$class->BUILDARGS(@_)';
141 }
142
143 return <<'...';
fc1d8369 144 do {
145 if ( scalar @_ == 1 ) {
146 if ( defined $_[0] ) {
147 ( ref( $_[0] ) eq 'HASH' )
148 || Carp::confess "Single parameters to new() must be a HASH ref";
149 +{ %{ $_[0] } };
150 }
151 else {
152 +{};
153 }
154 }
155 else {
156 +{@_};
157 }
158 };
159...
160}
161
162sub _generate_BUILDALL {
163 my ($class, $meta) = @_;
164 return '' unless $meta->name->can('BUILD');
165
166 my @code = ();
167 push @code, q{no strict 'refs';};
168 push @code, q{no warnings 'once';};
169 no strict 'refs';
f2becec7 170 no warnings 'once';
ca3bebbd 171 for my $klass ($meta->linearized_isa) {
172 if (*{ $klass . '::BUILD' }{CODE}) {
63d74d7a 173 push @code, qq{${klass}::BUILD(\$instance, \$args);};
fc1d8369 174 }
175 }
176 return join "\n", @code;
177}
178
1791;