bump version to 0.71_02 and update Changes
[gitmo/Class-MOP.git] / lib / Class / MOP / Method / Accessor.pm
CommitLineData
ba38bf08 1
2package Class::MOP::Method::Accessor;
3
4use strict;
5use warnings;
6
7use Carp 'confess';
8use Scalar::Util 'blessed', 'weaken';
9
6b5ac420 10our $VERSION = '0.71_02';
d519662a 11$VERSION = eval $VERSION;
ba38bf08 12our $AUTHORITY = 'cpan:STEVAN';
13
565f0cbb 14use base 'Class::MOP::Method::Generated';
ba38bf08 15
ba38bf08 16sub new {
17 my $class = shift;
18 my %options = @_;
8d2d4c67 19
ba38bf08 20 (exists $options{attribute})
21 || confess "You must supply an attribute to construct with";
8d2d4c67 22
ba38bf08 23 (exists $options{accessor_type})
8d2d4c67 24 || confess "You must supply an accessor_type to construct with";
25
ba38bf08 26 (blessed($options{attribute}) && $options{attribute}->isa('Class::MOP::Attribute'))
8d2d4c67 27 || confess "You must supply an attribute which is a 'Class::MOP::Attribute' instance";
28
b38f3848 29 ($options{package_name} && $options{name})
32202ce2 30 || confess "You must supply the package_name and name parameters $Class::MOP::Method::UPGRADE_ERROR_TEXT";
b38f3848 31
0bfc85b8 32 my $self = $class->_new(\%options);
8d2d4c67 33
34 # we don't want this creating
35 # a cycle in the code, if not
ba38bf08 36 # needed
8683db0e 37 weaken($self->{'attribute'});
8d2d4c67 38
565f0cbb 39 $self->initialize_body;
8d2d4c67 40
ba38bf08 41 return $self;
42}
43
a9e38dc7 44sub _new {
0bfc85b8 45 my $class = shift;
46 my $options = @_ == 1 ? $_[0] : {@_};
a9e38dc7 47
0bfc85b8 48 $options->{is_inline} ||= 0;
a9e38dc7 49
0bfc85b8 50 return bless $options, $class;
a9e38dc7 51}
52
ba38bf08 53## accessors
54
8683db0e 55sub associated_attribute { (shift)->{'attribute'} }
56sub accessor_type { (shift)->{'accessor_type'} }
ba38bf08 57
8d2d4c67 58## factory
ba38bf08 59
565f0cbb 60sub initialize_body {
ba38bf08 61 my $self = shift;
8d2d4c67 62
ba38bf08 63 my $method_name = join "_" => (
8d2d4c67 64 'generate',
65 $self->accessor_type,
ba38bf08 66 'method',
d90b42a6 67 ($self->is_inline ? 'inline' : ())
ba38bf08 68 );
8d2d4c67 69
8683db0e 70 eval { $self->{'body'} = $self->$method_name() };
ba38bf08 71 die $@ if $@;
72}
73
74## generators
75
76sub generate_accessor_method {
8d2d4c67 77 my $attr = (shift)->associated_attribute;
ba38bf08 78 return sub {
79 $attr->set_value($_[0], $_[1]) if scalar(@_) == 2;
80 $attr->get_value($_[0]);
81 };
82}
83
84sub generate_reader_method {
8d2d4c67 85 my $attr = (shift)->associated_attribute;
86 return sub {
ba38bf08 87 confess "Cannot assign a value to a read-only accessor" if @_ > 1;
88 $attr->get_value($_[0]);
8d2d4c67 89 };
ba38bf08 90}
91
92sub generate_writer_method {
8d2d4c67 93 my $attr = (shift)->associated_attribute;
ba38bf08 94 return sub {
95 $attr->set_value($_[0], $_[1]);
96 };
97}
98
99sub generate_predicate_method {
8d2d4c67 100 my $attr = (shift)->associated_attribute;
101 return sub {
3545c727 102 $attr->has_value($_[0])
ba38bf08 103 };
104}
105
106sub generate_clearer_method {
8d2d4c67 107 my $attr = (shift)->associated_attribute;
108 return sub {
3545c727 109 $attr->clear_value($_[0])
ba38bf08 110 };
111}
112
113## Inline methods
114
115
116sub generate_accessor_method_inline {
8d2d4c67 117 my $attr = (shift)->associated_attribute;
ba38bf08 118 my $attr_name = $attr->name;
119 my $meta_instance = $attr->associated_class->instance_metaclass;
120
121 my $code = eval 'sub {'
122 . $meta_instance->inline_set_slot_value('$_[0]', "'$attr_name'", '$_[1]') . ' if scalar(@_) == 2; '
123 . $meta_instance->inline_get_slot_value('$_[0]', "'$attr_name'")
124 . '}';
125 confess "Could not generate inline accessor because : $@" if $@;
126
127 return $code;
128}
129
130sub generate_reader_method_inline {
8d2d4c67 131 my $attr = (shift)->associated_attribute;
ba38bf08 132 my $attr_name = $attr->name;
133 my $meta_instance = $attr->associated_class->instance_metaclass;
134
135 my $code = eval 'sub {'
136 . 'confess "Cannot assign a value to a read-only accessor" if @_ > 1;'
137 . $meta_instance->inline_get_slot_value('$_[0]', "'$attr_name'")
138 . '}';
139 confess "Could not generate inline accessor because : $@" if $@;
140
141 return $code;
142}
143
144sub generate_writer_method_inline {
8d2d4c67 145 my $attr = (shift)->associated_attribute;
ba38bf08 146 my $attr_name = $attr->name;
147 my $meta_instance = $attr->associated_class->instance_metaclass;
148
149 my $code = eval 'sub {'
150 . $meta_instance->inline_set_slot_value('$_[0]', "'$attr_name'", '$_[1]')
151 . '}';
152 confess "Could not generate inline accessor because : $@" if $@;
153
154 return $code;
155}
156
157
158sub generate_predicate_method_inline {
8d2d4c67 159 my $attr = (shift)->associated_attribute;
ba38bf08 160 my $attr_name = $attr->name;
161 my $meta_instance = $attr->associated_class->instance_metaclass;
162
8d2d4c67 163 my $code = eval 'sub {' .
164 $meta_instance->inline_is_slot_initialized('$_[0]', "'$attr_name'")
ba38bf08 165 . '}';
166 confess "Could not generate inline predicate because : $@" if $@;
167
168 return $code;
169}
170
171sub generate_clearer_method_inline {
8d2d4c67 172 my $attr = (shift)->associated_attribute;
ba38bf08 173 my $attr_name = $attr->name;
174 my $meta_instance = $attr->associated_class->instance_metaclass;
175
176 my $code = eval 'sub {'
177 . $meta_instance->inline_deinitialize_slot('$_[0]', "'$attr_name'")
178 . '}';
179 confess "Could not generate inline clearer because : $@" if $@;
180
181 return $code;
182}
183
1841;
185
186__END__
187
188=pod
189
8d2d4c67 190=head1 NAME
ba38bf08 191
192Class::MOP::Method::Accessor - Method Meta Object for accessors
193
194=head1 SYNOPSIS
195
96e38ba6 196 use Class::MOP::Method::Accessor;
197
198 my $reader = Class::MOP::Method::Accessor->new(
199 attribute => $attribute,
200 is_inline => 1,
201 accessor_type => 'reader',
202 );
8d2d4c67 203
b7045e66 204 $reader->body->execute($instance); # call the reader method
ba38bf08 205
206=head1 DESCRIPTION
207
8d2d4c67 208This is a C<Class::MOP::Method> subclass which is used interally
209by C<Class::MOP::Attribute> to generate accessor code. It can
210handle generation of readers, writers, predicate and clearer
96e38ba6 211methods, both as closures and as more optimized inline methods.
212
ba38bf08 213=head1 METHODS
214
215=over 4
216
96e38ba6 217=item B<new (%options)>
ba38bf08 218
8d2d4c67 219This creates the method based on the criteria in C<%options>,
96e38ba6 220these options are:
221
222=over 4
223
224=item I<attribute>
225
8d2d4c67 226This must be an instance of C<Class::MOP::Attribute> which this
96e38ba6 227accessor is being generated for. This paramter is B<required>.
228
229=item I<accessor_type>
230
8d2d4c67 231This is a string from the following set; reader, writer, accessor,
232predicate or clearer. This is used to determine which type of
96e38ba6 233method is to be generated.
234
235=item I<is_inline>
236
237This is a boolean to indicate if the method should be generated
238as a closure, or as a more optimized inline version.
239
240=back
ba38bf08 241
242=item B<accessor_type>
243
96e38ba6 244This returns the accessor type which was passed into C<new>.
245
d90b42a6 246=item B<is_inline>
ba38bf08 247
96e38ba6 248This returns the boolean which was passed into C<new>.
249
ba38bf08 250=item B<associated_attribute>
251
96e38ba6 252This returns the attribute instance which was passed into C<new>.
253
565f0cbb 254=item B<initialize_body>
96e38ba6 255
8d2d4c67 256This will actually generate the method based on the specified
96e38ba6 257criteria passed to the constructor.
258
259=back
260
261=head2 Method Generators
262
8d2d4c67 263These methods will generate appropriate code references for
264the various types of accessors which are supported by
96e38ba6 265C<Class::MOP::Attribute>. The names pretty much explain it all.
266
267=over 4
268
ba38bf08 269=item B<generate_accessor_method>
270
271=item B<generate_accessor_method_inline>
272
273=item B<generate_clearer_method>
274
275=item B<generate_clearer_method_inline>
276
277=item B<generate_predicate_method>
278
279=item B<generate_predicate_method_inline>
280
281=item B<generate_reader_method>
282
283=item B<generate_reader_method_inline>
284
285=item B<generate_writer_method>
286
287=item B<generate_writer_method_inline>
288
289=back
290
291=head1 AUTHORS
292
293Stevan Little E<lt>stevan@iinteractive.comE<gt>
294
ba38bf08 295=head1 COPYRIGHT AND LICENSE
296
69e3ab0a 297Copyright 2006-2008 by Infinity Interactive, Inc.
ba38bf08 298
299L<http://www.iinteractive.com>
300
301This library is free software; you can redistribute it and/or modify
8d2d4c67 302it under the same terms as Perl itself.
ba38bf08 303
304=cut
305