Changes to date added for wu-lee.
[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);
3fee6f68 12 my @compiled_constraints = map { $_ ? $_->{_compiled_type_constraint} : undef } map { $_->{type_constraint} } @attrs;
fc1d8369 13
24ad3f66 14 my $code = <<"...";
fc1d8369 15 sub {
16 my \$class = shift;
53d4053e 17 $buildargs;
24ad3f66 18 my \$instance = bless {}, \$class;
fc1d8369 19 $processattrs;
20 $buildall;
21 return \$instance;
22 }
23...
24ad3f66 24
24ad3f66 25 local $@;
3fee6f68 26 # warn $code;
24ad3f66 27 my $res = eval $code;
28 die $@ if $@;
29 $res;
fc1d8369 30}
31
32sub _generate_processattrs {
c12edd9a 33 my ($class, $meta, $attrs) = @_;
fc1d8369 34 my @res;
9df6f0cd 35
36 for my $index (0 .. @$attrs - 1) {
c12edd9a 37 my $attr = $attrs->[$index];
fc1d8369 38 my $key = $attr->name;
9df6f0cd 39 my $code = '';
40
41 if (defined $attr->init_arg) {
42 my $from = $attr->init_arg;
c91862e8 43
9df6f0cd 44 $code .= "if (exists \$args->{'$from'}) {\n";
c91862e8 45
b3b74cc6 46 if ($attr->should_coerce && $attr->type_constraint) {
86b99892 47 $code .= "my \$value = Mouse::Util::TypeConstraints->typecast_constraints('".$attr->associated_class->name."', \$attrs[$index]->{type_constraint}, \$args->{'$from'});\n";
7bf66a9b 48 }
49 else {
7756897f 50 $code .= "my \$value = \$args->{'$from'};\n";
fc1d8369 51 }
c91862e8 52
fc1d8369 53 if ($attr->has_type_constraint) {
3fee6f68 54 if ($attr->type_constraint->{_compiled_type_constraint}) {
55 $code .= "unless (\$compiled_constraints[$index](\$value)) {";
56 } else {
57 $code .= "unless (\$attrs[$index]->{type_constraint}->check(\$value)) {";
58 }
59 $code .= "
60 \$attrs[$index]->verify_type_constraint_error(
61 '$key', \$_, \$attrs[$index]->type_constraint
62 )
7756897f 63 }
3fee6f68 64 ";
fc1d8369 65 }
c91862e8 66
7756897f 67 $code .= "\$instance->{'$key'} = \$value;\n";
c91862e8 68
41cdacce 69 if ($attr->is_weak_ref) {
7756897f 70 $code .= "Scalar::Util::weaken( \$instance->{'$key'} ) if ref( \$value );\n";
41cdacce 71 }
c91862e8 72
9df6f0cd 73 if ($attr->has_trigger) {
88b6c018 74 $code .= "\$attrs[$index]->{trigger}->( \$instance, \$value );\n";
fc1d8369 75 }
c91862e8 76
7756897f 77 $code .= "\n} else {\n";
9df6f0cd 78 }
c91862e8 79
9df6f0cd 80 if ($attr->has_default || $attr->has_builder) {
81 unless ($attr->is_lazy) {
82 my $default = $attr->default;
83 my $builder = $attr->builder;
e8ba7b26 84
9df6f0cd 85 $code .= "my \$value = ";
e8ba7b26 86
9df6f0cd 87 if ($attr->should_coerce && $attr->type_constraint) {
86b99892 88 $code .= "Mouse::Util::TypeConstraints->typecast_constraints('".$attr->associated_class->name."', \$attrs[$index]->{type_constraint}, ";
9df6f0cd 89 }
e8ba7b26 90
9df6f0cd 91 if ($attr->has_builder) {
92 $code .= "\$instance->$builder";
fc1d8369 93 }
9df6f0cd 94 elsif (ref($default) eq 'CODE') {
95 $code .= "\$attrs[$index]->{default}->(\$instance)";
e8ba7b26 96 }
9df6f0cd 97 elsif (!defined($default)) {
98 $code .= 'undef';
fc1d8369 99 }
9df6f0cd 100 elsif ($default =~ /^\-?[0-9]+(?:\.[0-9]+)$/) {
101 $code .= $default;
102 }
103 else {
104 $code .= "'$default'";
fc1d8369 105 }
e8ba7b26 106
9df6f0cd 107 if ($attr->should_coerce) {
7756897f 108 $code .= ");\n";
9df6f0cd 109 }
110 else {
7756897f 111 $code .= ";\n";
9df6f0cd 112 }
e8ba7b26 113
9df6f0cd 114 if ($attr->has_type_constraint) {
7756897f 115 $code .= "{
684db121 116 unless (\$attrs[$index]->{type_constraint}->check(\$value)) {
7756897f 117 \$attrs[$index]->verify_type_constraint_error('$key', \$_, \$attrs[$index]->type_constraint)
118 }
119 }";
fc1d8369 120 }
9df6f0cd 121
7756897f 122 $code .= "\$instance->{'$key'} = \$value;\n";
9df6f0cd 123
124 if ($attr->is_weak_ref) {
7756897f 125 $code .= "Scalar::Util::weaken( \$instance->{'$key'} ) if ref( \$value );\n";
fc1d8369 126 }
127 }
713a2a05 128 }
9df6f0cd 129 elsif ($attr->is_required) {
7756897f 130 $code .= "Carp::confess('Attribute ($key) is required');";
9df6f0cd 131 }
132
7756897f 133 $code .= "}\n" if defined $attr->init_arg;
9df6f0cd 134
fc1d8369 135 push @res, $code;
136 }
9df6f0cd 137
fc1d8369 138 return join "\n", @res;
139}
140
141sub _generate_BUILDARGS {
9dcd7d23 142 my $self = shift;
143 my $meta = shift;
144
58600853 145 if ($meta->name->can('BUILDARGS') && $meta->name->can('BUILDARGS') != Mouse::Object->can('BUILDARGS')) {
53d4053e 146 return 'my $args = $class->BUILDARGS(@_)';
9dcd7d23 147 }
148
149 return <<'...';
53d4053e 150 my $args;
fc1d8369 151 if ( scalar @_ == 1 ) {
c9aefe26 152 ( ref( $_[0] ) eq 'HASH' )
fc1d8369 153 || Carp::confess "Single parameters to new() must be a HASH ref";
53d4053e 154 $args = +{ %{ $_[0] } };
fc1d8369 155 }
156 else {
53d4053e 157 $args = +{@_};
fc1d8369 158 }
fc1d8369 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}) {
813197f3 173 unshift @code, qq{${klass}::BUILD(\$instance, \$args);};
fc1d8369 174 }
175 }
176 return join "\n", @code;
177}
178
1791;