merging the immutable branch into trunk
[gitmo/Class-MOP.git] / lib / Class / MOP / Method / Constructor.pm
CommitLineData
d90b42a6 1
2package Class::MOP::Method::Constructor;
3
4use strict;
5use warnings;
6
7use Carp 'confess';
8use Scalar::Util 'blessed', 'weaken', 'looks_like_number';
9
10our $VERSION = '0.01';
11our $AUTHORITY = 'cpan:STEVAN';
12
13use base 'Class::MOP::Method';
14
15sub new {
16 my $class = shift;
17 my %options = @_;
18
19 (exists $options{options} && ref $options{options} eq 'HASH')
20 || confess "You must pass a hash of options";
d90b42a6 21
22 my $self = bless {
23 # from our superclass
c23184fc 24 '&!body' => undef,
d90b42a6 25 # specific to this subclass
c23184fc 26 '%!options' => $options{options},
27 '$!meta_instance' => $options{metaclass}->get_meta_instance,
28 '@!attributes' => [ $options{metaclass}->compute_all_applicable_attributes ],
29 # ...
30 '$!associated_metaclass' => $options{metaclass},
d90b42a6 31 } => $class;
32
33 # we don't want this creating
34 # a cycle in the code, if not
35 # needed
c23184fc 36# weaken($self->{'$!meta_instance'});
37 weaken($self->{'$!associated_metaclass'});
d90b42a6 38
39 $self->intialize_body;
40
41 return $self;
42}
43
c23184fc 44## predicates
45
46# NOTE:
47# if it is blessed into this class,
48# then it is always inlined, that is
49# pretty much what this class is for.
50sub is_inline { 1 }
51
d90b42a6 52## accessors
53
c23184fc 54sub options { (shift)->{'%!options'} }
55sub meta_instance { (shift)->{'$!meta_instance'} }
56sub attributes { (shift)->{'@!attributes'} }
57
58sub associated_metaclass { (shift)->{'$!associated_metaclass'} }
d90b42a6 59
60## method
61
62sub intialize_body {
63 my $self = shift;
64 # TODO:
65 # the %options should also include a both
66 # a call 'initializer' and call 'SUPER::'
67 # options, which should cover approx 90%
68 # of the possible use cases (even if it
69 # requires some adaption on the part of
70 # the author, after all, nothing is free)
71 my $source = 'sub {';
72 $source .= "\n" . 'my ($class, %params) = @_;';
73 $source .= "\n" . 'my $instance = ' . $self->meta_instance->inline_create_instance('$class');
74 $source .= ";\n" . (join ";\n" => map {
75 $self->_generate_slot_initializer($_)
76 } 0 .. (@{$self->attributes} - 1));
77 $source .= ";\n" . 'return $instance';
78 $source .= ";\n" . '}';
79 warn $source if $self->options->{debug};
80
81 my $code;
82 {
83 # NOTE:
84 # create the nessecary lexicals
85 # to be picked up in the eval
86 my $attrs = $self->attributes;
87
88 $code = eval $source;
89 confess "Could not eval the constructor :\n\n$source\n\nbecause :\n\n$@" if $@;
90 }
c23184fc 91 $self->{'&!body'} = $code;
d90b42a6 92}
93
94sub _generate_slot_initializer {
95 my $self = shift;
96 my $index = shift;
97
98 my $attr = $self->attributes->[$index];
99
100 my $default;
101 if ($attr->has_default) {
102 # NOTE:
103 # default values can either be CODE refs
104 # in which case we need to call them. Or
105 # they can be scalars (strings/numbers)
106 # in which case we can just deal with them
107 # in the code we eval.
108 if ($attr->is_default_a_coderef) {
109 $default = '$attrs->[' . $index . ']->default($instance)';
110 }
111 else {
112 $default = $attr->default;
113 # make sure to quote strings ...
114 unless (looks_like_number($default)) {
115 $default = "'$default'";
116 }
117 }
118 }
119 $self->meta_instance->inline_set_slot_value(
120 '$instance',
121 ("'" . $attr->name . "'"),
122 ('$params{\'' . $attr->init_arg . '\'}' . (defined $default ? (' || ' . $default) : ''))
123 );
124}
125
1261;
127
1281;
129
130__END__
131
132=pod
133
134=head1 NAME
135
136Class::MOP::Method::Constructor - Method Meta Object for constructors
137
138=head1 SYNOPSIS
139
140=head1 DESCRIPTION
141
142=head1 METHODS
143
144=over 4
145
146=item B<new>
147
c23184fc 148=item B<is_inline>
149
d90b42a6 150=item B<attributes>
151
152=item B<meta_instance>
153
c23184fc 154=item B<associated_metaclass>
155
d90b42a6 156=item B<options>
157
158=item B<intialize_body>
159
160=back
161
162=head1 AUTHORS
163
164Stevan Little E<lt>stevan@iinteractive.comE<gt>
165
166=head1 COPYRIGHT AND LICENSE
167
168Copyright 2006 by Infinity Interactive, Inc.
169
170L<http://www.iinteractive.com>
171
172This library is free software; you can redistribute it and/or modify
173it under the same terms as Perl itself.
174
175=cut
176