Add SYNOPSIS
[p5sagit/Class-Accessor-Grouped.git] / lib / Class / Accessor / Grouped.pm
1 package Class::Accessor::Grouped;
2 use strict;
3 use warnings;
4 use Carp ();
5 use Scalar::Util ();
6
7 BEGIN {
8   if ($] < 5.009_005) {
9     require MRO::Compat;
10   }
11   else {
12     require mro;
13   }
14 }
15
16 our $VERSION = '0.10002';
17 $VERSION = eval $VERSION if $VERSION =~ /_/; # numify for warning-free dev releases
18
19 # when changing minimum version don't forget to adjust L</PERFORMANCE> and
20 # the Makefile.PL as well
21 our $__minimum_xsa_version;
22 BEGIN {
23     $__minimum_xsa_version = '1.11';
24 }
25
26 our $USE_XS;
27 # the unless defined is here so that we can override the value
28 # before require/use, *regardless* of the state of $ENV{CAG_USE_XS}
29 $USE_XS = $ENV{CAG_USE_XS}
30     unless defined $USE_XS;
31
32 # Yes this method is undocumented
33 # Yes it should be a private coderef like all the rest at the end of this file
34 # No we can't do that (yet) because the DBIC-CDBI compat layer overrides it
35 # %$*@!?&!&#*$!!!
36 sub _mk_group_accessors {
37     my($self, $maker, $group, @fields) = @_;
38     my $class = Scalar::Util::blessed $self || $self;
39
40     no strict 'refs';
41     no warnings 'redefine';
42
43     # So we don't have to do lots of lookups inside the loop.
44     $maker = $self->can($maker) unless ref $maker;
45
46     foreach (@fields) {
47         if( $_ eq 'DESTROY' ) {
48             Carp::carp("Having a data accessor named DESTROY in ".
49                        "'$class' is unwise.");
50         }
51
52         my ($name, $field) = (ref $_)
53             ? (@$_)
54             : ($_, $_)
55         ;
56
57         my $alias = "_${name}_accessor";
58
59         for my $meth ($name, $alias) {
60
61             # the maker may elect to not return anything, meaning it already
62             # installed the coderef for us (e.g. lack of Sub::Name)
63             my $cref = $self->$maker($group, $field, $meth)
64                 or next;
65
66             my $fq_meth = "${class}::${meth}";
67
68             *$fq_meth = Sub::Name::subname($fq_meth, $cref);
69                 #unless defined &{$class."\:\:$field"}
70         }
71     }
72 };
73
74 # coderef is setup at the end for clarity
75 my $gen_accessor;
76
77 =head1 NAME
78
79 Class::Accessor::Grouped - Lets you build groups of accessors
80
81 =head1 SYNOPSIS
82
83  use base 'Class::Accessor::Grouped';
84
85  # make basic accessors for objects
86  __PACKAGE__->mk_group_accessors(simple => qw(id name email));
87
88  # make accessor that works for objects and classes
89  __PACKAGE__->mk_group_accessors(inherited => 'awesome_level');
90
91 =head1 DESCRIPTION
92
93 This class lets you build groups of accessors that will call different
94 getters and setters.
95
96 =head1 METHODS
97
98 =head2 mk_group_accessors
99
100 =over 4
101
102 =item Arguments: $group, @fieldspec
103
104 Returns: none
105
106 =back
107
108 Creates a set of accessors in a given group.
109
110 $group is the name of the accessor group for the generated accessors; they
111 will call get_$group($field) on get and set_$group($field, $value) on set.
112
113 If you want to mimic Class::Accessor's mk_accessors $group has to be 'simple'
114 to tell Class::Accessor::Grouped to use its own get_simple and set_simple
115 methods.
116
117 @fieldspec is a list of field/accessor names; if a fieldspec is a scalar
118 this is used as both field and accessor name, if a listref it is expected to
119 be of the form [ $accessor, $field ].
120
121 =cut
122
123 sub mk_group_accessors {
124     my ($self, $group, @fields) = @_;
125
126     $self->_mk_group_accessors('make_group_accessor', $group, @fields);
127     return;
128 }
129
130 =head2 mk_group_ro_accessors
131
132 =over 4
133
134 =item Arguments: $group, @fieldspec
135
136 Returns: none
137
138 =back
139
140 Creates a set of read only accessors in a given group. Identical to
141 L</mk_group_accessors> but accessors will throw an error if passed a value
142 rather than setting the value.
143
144 =cut
145
146 sub mk_group_ro_accessors {
147     my($self, $group, @fields) = @_;
148
149     $self->_mk_group_accessors('make_group_ro_accessor', $group, @fields);
150 }
151
152 =head2 mk_group_wo_accessors
153
154 =over 4
155
156 =item Arguments: $group, @fieldspec
157
158 Returns: none
159
160 =back
161
162 Creates a set of write only accessors in a given group. Identical to
163 L</mk_group_accessors> but accessors will throw an error if not passed a
164 value rather than getting the value.
165
166 =cut
167
168 sub mk_group_wo_accessors {
169     my($self, $group, @fields) = @_;
170
171     $self->_mk_group_accessors('make_group_wo_accessor', $group, @fields);
172 }
173
174 =head2 make_group_accessor
175
176 =over 4
177
178 =item Arguments: $group, $field, $method
179
180 Returns: \&accessor_coderef ?
181
182 =back
183
184 Called by mk_group_accessors for each entry in @fieldspec. Either returns
185 a coderef which will be installed at C<&__PACKAGE__::$method>, or returns
186 C<undef> if it elects to install the coderef on its own.
187
188 =cut
189
190 sub make_group_accessor { $gen_accessor->('rw', @_) }
191
192 =head2 make_group_ro_accessor
193
194 =over 4
195
196 =item Arguments: $group, $field, $method
197
198 Returns: \&accessor_coderef ?
199
200 =back
201
202 Called by mk_group_ro_accessors for each entry in @fieldspec. Either returns
203 a coderef which will be installed at C<&__PACKAGE__::$method>, or returns
204 C<undef> if it elects to install the coderef on its own.
205
206 =cut
207
208 sub make_group_ro_accessor { $gen_accessor->('ro', @_) }
209
210 =head2 make_group_wo_accessor
211
212 =over 4
213
214 =item Arguments: $group, $field, $method
215
216 Returns: \&accessor_coderef ?
217
218 =back
219
220 Called by mk_group_wo_accessors for each entry in @fieldspec. Either returns
221 a coderef which will be installed at C<&__PACKAGE__::$method>, or returns
222 C<undef> if it elects to install the coderef on its own.
223
224 =cut
225
226 sub make_group_wo_accessor { $gen_accessor->('wo', @_) }
227
228 =head2 get_simple
229
230 =over 4
231
232 =item Arguments: $field
233
234 Returns: $value
235
236 =back
237
238 Simple getter for hash-based objects which returns the value for the field
239 name passed as an argument.
240
241 =cut
242
243 sub get_simple {
244     return $_[0]->{$_[1]};
245 }
246
247 =head2 set_simple
248
249 =over 4
250
251 =item Arguments: $field, $new_value
252
253 Returns: $new_value
254
255 =back
256
257 Simple setter for hash-based objects which sets and then returns the value
258 for the field name passed as an argument.
259
260 =cut
261
262 sub set_simple {
263     return $_[0]->{$_[1]} = $_[2];
264 }
265
266
267 =head2 get_inherited
268
269 =over 4
270
271 =item Arguments: $field
272
273 Returns: $value
274
275 =back
276
277 Simple getter for Classes and hash-based objects which returns the value for
278 the field name passed as an argument. This behaves much like
279 L<Class::Data::Accessor> where the field can be set in a base class,
280 inherited and changed in subclasses, and inherited and changed for object
281 instances.
282
283 =cut
284
285 sub get_inherited {
286     my $class;
287
288     if ( defined( $class = Scalar::Util::blessed $_[0] ) ) {
289         if (Scalar::Util::reftype $_[0] eq 'HASH') {
290           return $_[0]->{$_[1]} if exists $_[0]->{$_[1]};
291         }
292         else {
293           Carp::croak('Cannot get inherited value on an object instance that is not hash-based');
294         }
295     }
296     else {
297         $class = $_[0];
298     }
299
300     no strict 'refs';
301     no warnings 'uninitialized';
302
303     my $cag_slot = '::__cag_'. $_[1];
304     return ${$class.$cag_slot} if defined(${$class.$cag_slot});
305
306     # we need to be smarter about recalculation, as @ISA (thus supers) can very well change in-flight
307     my $cur_gen = mro::get_pkg_gen ($class);
308     if ( $cur_gen != ${$class.'::__cag_pkg_gen__'} ) {
309         @{$class.'::__cag_supers__'} = $_[0]->get_super_paths;
310         ${$class.'::__cag_pkg_gen__'} = $cur_gen;
311     }
312
313     for (@{$class.'::__cag_supers__'}) {
314         return ${$_.$cag_slot} if defined(${$_.$cag_slot});
315     };
316
317     return undef;
318 }
319
320 =head2 set_inherited
321
322 =over 4
323
324 =item Arguments: $field, $new_value
325
326 Returns: $new_value
327
328 =back
329
330 Simple setter for Classes and hash-based objects which sets and then returns
331 the value for the field name passed as an argument. When called on a hash-based
332 object it will set the appropriate hash key value. When called on a class, it
333 will set a class level variable.
334
335 B<Note:>: This method will die if you try to set an object variable on a non
336 hash-based object.
337
338 =cut
339
340 sub set_inherited {
341     if (defined Scalar::Util::blessed $_[0]) {
342         if (Scalar::Util::reftype $_[0] eq 'HASH') {
343             return $_[0]->{$_[1]} = $_[2];
344         } else {
345             Carp::croak('Cannot set inherited value on an object instance that is not hash-based');
346         };
347     } else {
348         no strict 'refs';
349
350         return ${$_[0].'::__cag_'.$_[1]} = $_[2];
351     };
352 }
353
354 =head2 get_component_class
355
356 =over 4
357
358 =item Arguments: $field
359
360 Returns: $value
361
362 =back
363
364 Gets the value of the specified component class.
365
366     __PACKAGE__->mk_group_accessors('component_class' => 'result_class');
367
368     $self->result_class->method();
369
370     ## same as
371     $self->get_component_class('result_class')->method();
372
373 =cut
374
375 sub get_component_class {
376     return $_[0]->get_inherited($_[1]);
377 };
378
379 =head2 set_component_class
380
381 =over 4
382
383 =item Arguments: $field, $class
384
385 Returns: $new_value
386
387 =back
388
389 Inherited accessor that automatically loads the specified class before setting
390 it. This method will die if the specified class could not be loaded.
391
392     __PACKAGE__->mk_group_accessors('component_class' => 'result_class');
393     __PACKAGE__->result_class('MyClass');
394
395     $self->result_class->method();
396
397 =cut
398
399 sub set_component_class {
400     if ($_[2]) {
401         local $^W = 0;
402         require Class::Inspector;
403         if (Class::Inspector->installed($_[2]) && !Class::Inspector->loaded($_[2])) {
404             eval "require $_[2]";
405
406             Carp::croak("Could not load $_[1] '$_[2]': ", $@) if $@;
407         };
408     };
409
410     return $_[0]->set_inherited($_[1], $_[2]);
411 };
412
413 =head2 get_super_paths
414
415 Returns a list of 'parent' or 'super' class names that the current class inherited from.
416
417 =cut
418
419 sub get_super_paths {
420     return @{mro::get_linear_isa( ref($_[0]) || $_[0] )};
421 };
422
423 =head1 PERFORMANCE
424
425 To provide total flexibility L<Class::Accessor::Grouped> calls methods
426 internally while performing get/set actions, which makes it noticeably
427 slower than similar modules. To compensate, this module will automatically
428 use the insanely fast L<Class::XSAccessor> to generate the C<simple>-group
429 accessors if this module is available on your system.
430
431 =head2 Benchmark
432
433 This is the result of a set/get/set loop benchmark on perl 5.12.1 with
434 thread support, showcasing most popular accessor builders: L<Moose>, L<Mouse>,
435 L<Moo>, L<CAF|Class::Accessor::Fast>, L<CAF_XS|Class::Accessor::Fast::XS>,
436 L<XSA|Class::XSAccessor>, and L<CAF_XSA|Class::XSAccessor::Compat>:
437
438            Rate  CAG moOse  CAF moUse  moo HANDMADE CAF_XS moUse_XS moo_XS CAF_XSA  XSA CAG_XS
439  CAG      169/s   --  -21% -24%  -32% -32%     -34%   -59%     -63%   -67%    -67% -67%   -67%
440  moOse    215/s  27%    --  -3%  -13% -13%     -15%   -48%     -53%   -58%    -58% -58%   -58%
441  CAF      222/s  31%    3%   --  -10% -10%     -13%   -46%     -52%   -57%    -57% -57%   -57%
442  moUse    248/s  46%   15%  11%    --  -0%      -3%   -40%     -46%   -52%    -52% -52%   -52%
443  moo      248/s  46%   15%  11%    0%   --      -3%   -40%     -46%   -52%    -52% -52%   -52%
444  HANDMADE 255/s  50%   18%  14%    3%   3%       --   -38%     -45%   -50%    -51% -51%   -51%
445  CAF_XS   411/s 143%   91%  85%   66%  66%      61%     --     -11%   -20%    -20% -21%   -21%
446  moUse_XS 461/s 172%  114% 107%   86%  86%      81%    12%       --   -10%    -11% -11%   -11%
447  moo_XS   514/s 204%  139% 131%  107% 107%     102%    25%      12%     --     -0%  -1%    -1%
448  CAF_XSA  516/s 205%  140% 132%  108% 108%     103%    26%      12%     0%      --  -0%    -0%
449  XSA      519/s 206%  141% 133%  109% 109%     104%    26%      13%     1%      0%   --    -0%
450  CAG_XS   519/s 206%  141% 133%  109% 109%     104%    26%      13%     1%      0%   0%     --
451
452 Benchmark program is available in the root of the
453 L<repository|http://search.cpan.org/dist/Class-Accessor-Grouped/>:
454
455 =head2 Notes on Class::XSAccessor
456
457 You can force (or disable) the use of L<Class::XSAccessor> before creating a
458 particular C<simple> accessor by either manipulating the global variable
459 C<$Class::Accessor::Grouped::USE_XS> to true or false (preferably with
460 L<localization|perlfunc/local>, or you can do so before runtime via the
461 C<CAG_USE_XS> environment variable.
462
463 Since L<Class::XSAccessor> has no knowledge of L</get_simple> and
464 L</set_simple> this module does its best to detect if you are overriding
465 one of these methods and will fall back to using the perl version of the
466 accessor in order to maintain consistency. However be aware that if you
467 enable use of C<Class::XSAccessor> (automatically or explicitly), create
468 an object, invoke a simple accessor on that object, and B<then> manipulate
469 the symbol table to install a C<get/set_simple> override - you get to keep
470 all the pieces.
471
472 =head1 AUTHORS
473
474 Matt S. Trout <mst@shadowcatsystems.co.uk>
475
476 Christopher H. Laco <claco@chrislaco.com>
477
478 =head1 CONTRIBUTORS
479
480 Caelum: Rafael Kitover <rkitover@cpan.org>
481
482 frew: Arthur Axel "fREW" Schmidt <frioux@gmail.com>
483
484 groditi: Guillermo Roditi <groditi@cpan.org>
485
486 Jason Plum <jason.plum@bmmsi.com>
487
488 ribasushi: Peter Rabbitson <ribasushi@cpan.org>
489
490
491 =head1 COPYRIGHT & LICENSE
492
493 Copyright (c) 2006-2010 Matt S. Trout <mst@shadowcatsystems.co.uk>
494
495 This program is free software; you can redistribute it and/or modify
496 it under the same terms as perl itself.
497
498 =cut
499
500 ########################################################################
501 ########################################################################
502 ########################################################################
503 #
504 # Here be many angry dragons
505 # (all code is in private coderefs since everything inherits CAG)
506 #
507 ########################################################################
508 ########################################################################
509
510 BEGIN {
511
512   die "Huh?! No minimum C::XSA version?!\n"
513     unless $__minimum_xsa_version;
514
515   local $@;
516   my $err;
517
518
519   $err = eval { require Sub::Name; 1; } ? undef : do {
520     delete $INC{'Sub/Name.pm'};   # because older perls suck
521     $@;
522   };
523   *__CAG_NO_SUBNAME = $err
524     ? sub () { $err }
525     : sub () { 0 }
526   ;
527
528
529   $err = eval {
530     require Class::XSAccessor;
531     Class::XSAccessor->VERSION($__minimum_xsa_version);
532     require Sub::Name;
533     1;
534   } ? undef : do {
535     delete $INC{'Sub/Name.pm'};   # because older perls suck
536     delete $INC{'Class/XSAccessor.pm'};
537     $@;
538   };
539   *__CAG_NO_CXSA = $err
540     ? sub () { $err }
541     : sub () { 0 }
542   ;
543
544
545   *__CAG_BROKEN_GOTO = ($] < '5.008009')
546     ? sub () { 1 }
547     : sub () { 0 }
548   ;
549
550
551   *__CAG_UNSTABLE_DOLLARAT = ($] < '5.013002')
552     ? sub () { 1 }
553     : sub () { 0 }
554   ;
555
556
557   *__CAG_TRACK_UNDEFER_FAIL = (
558     $INC{'Test/Builder.pm'} || $INC{'Test/Builder2.pm'}
559       and
560     $0 =~ m|^ x?t / .+ \.t $|x
561   ) ? sub () { 1 }
562     : sub () { 0 }
563   ;
564 }
565
566 # Autodetect unless flag supplied
567 my $xsa_autodetected;
568 if (! defined $USE_XS) {
569   $USE_XS = __CAG_NO_CXSA ? 0 : 1;
570   $xsa_autodetected++;
571 }
572
573 my $maker_templates = {
574   rw => {
575     xs_call => 'accessors',
576     pp_code => sub {
577       my $set = "set_$_[0]";
578       my $get = "get_$_[0]";
579       my $field = $_[1];
580       $field =~ s/'/\\'/g;
581
582       "
583         \@_ != 1
584           ? shift->$set('$field', \@_)
585           : shift->$get('$field')
586       "
587     },
588   },
589   ro => {
590     xs_call => 'getters',
591     pp_code => sub {
592       my $get = "get_$_[0]";
593       my $field = $_[1];
594       $field =~ s/'/\\'/g;
595
596       "
597         \@_ == 1
598           ? shift->$get('$field')
599           : do {
600             my \$caller = caller;
601             my \$class = ref \$_[0] || \$_[0];
602             Carp::croak(\"'\$caller' cannot alter the value of '$field' \".
603                         \"(read-only attributes of class '\$class')\");
604           }
605       "
606     },
607   },
608   wo => {
609     xs_call => 'setters',
610     pp_code => sub {
611       my $set = "set_$_[0]";
612       my $field = $_[1];
613       $field =~ s/'/\\'/g;
614
615       "
616         \@_ != 1
617           ? shift->$set('$field', \@_)
618           : do {
619             my \$caller = caller;
620             my \$class = ref \$_[0] || \$_[0];
621             Carp::croak(\"'\$caller' cannot access the value of '$field' \".
622                         \"(write-only attributes of class '\$class')\");
623           }
624       "
625     },
626   },
627 };
628
629
630 my ($accessor_maker_cache, $no_xsa_warned_classes);
631
632 # can't use pkg_gen to track this stuff, as it doesn't
633 # detect superclass mucking
634 my $original_simple_getter = __PACKAGE__->can ('get_simple');
635 my $original_simple_setter = __PACKAGE__->can ('set_simple');
636
637 # Note!!! Unusual signature
638 $gen_accessor = sub {
639   my ($type, $class, $group, $field, $methname) = @_;
640   if (my $c = Scalar::Util::blessed( $class )) {
641     $class = $c;
642   }
643
644   # When installing an XSA simple accessor, we need to make sure we are not
645   # short-circuiting a (compile or runtime) get_simple/set_simple override.
646   # What we do here is install a lazy first-access check, which will decide
647   # the ultimate coderef being placed in the accessor slot
648   #
649   # Also note that the *original* class will always retain this shim, as
650   # different branches inheriting from it may have different overrides.
651   # Thus the final method (properly labeled and all) is installed in the
652   # calling-package's namespace
653   if ($USE_XS and $group eq 'simple') {
654     die sprintf( "Class::XSAccessor requested but not available:\n%s\n", __CAG_NO_CXSA )
655       if __CAG_NO_CXSA;
656
657     my ($expected_cref, $cached_implementation);
658     my $ret = $expected_cref = sub {
659       my $current_class = Scalar::Util::blessed( $_[0] ) || $_[0];
660
661       # $cached_implementation will be set only if the shim got
662       # 'around'ed, in which case it is handy to avoid re-running
663       # this block over and over again
664       my $resolved_implementation = $cached_implementation->{$current_class} || do {
665         if (
666           $current_class->can('get_simple') == $original_simple_getter
667             &&
668           $current_class->can('set_simple') == $original_simple_setter
669         ) {
670           # nothing has changed, might as well use the XS crefs
671           #
672           # note that by the time this code executes, we already have
673           # *objects* (since XSA works on 'simple' only by definition).
674           # If someone is mucking with the symbol table *after* there
675           # are some objects already - look! many, shiny pieces! :)
676           #
677           # The weird breeder thingy is because XSA does not have an
678           # interface returning *just* a coderef, without installing it
679           # anywhere :(
680           Class::XSAccessor->import(
681             replace => 1,
682             class => '__CAG__XSA__BREEDER__',
683             $maker_templates->{$type}{xs_call} => {
684               $methname => $field,
685             },
686           );
687           __CAG__XSA__BREEDER__->can($methname);
688         }
689         else {
690           if (! $xsa_autodetected and ! $no_xsa_warned_classes->{$current_class}++) {
691             # not using Carp since the line where this happens doesn't mean much
692             warn 'Explicitly requested use of Class::XSAccessor disabled for objects of class '
693               . "'$current_class' inheriting from '$class' due to an overriden get_simple and/or "
694               . "set_simple\n";
695           }
696
697           do {
698             # that's faster than local
699             $USE_XS = 0;
700             my $c = $gen_accessor->($type, $class, 'simple', $field, $methname);
701             $USE_XS = 1;
702             $c;
703           };
704         }
705       };
706
707       # if after this shim was created someone wrapped it with an 'around',
708       # we can not blindly reinstall the method slot - we will destroy the
709       # wrapper. Silently chain execution further...
710       if ( !$expected_cref or $expected_cref != $current_class->can($methname) ) {
711
712         # there is no point in re-determining it on every subsequent call,
713         # just store for future reference
714         $cached_implementation->{$current_class} ||= $resolved_implementation;
715
716         # older perls segfault if the cref behind the goto throws
717         # http://rt.perl.org/rt3/Public/Bug/Display.html?id=35878
718         return $resolved_implementation->(@_) if __CAG_BROKEN_GOTO;
719
720         goto $resolved_implementation;
721       }
722
723       if (__CAG_TRACK_UNDEFER_FAIL) {
724         my $deferred_calls_seen = do {
725           no strict 'refs';
726           \%{"${current_class}::__cag_deferred_xs_shim_invocations"}
727         };
728         my @cframe = caller(0);
729         if (my $already_seen = $deferred_calls_seen->{$cframe[3]}) {
730           Carp::carp (
731             "Deferred version of method $cframe[3] invoked more than once (originally "
732           . "invoked at $already_seen). This is a strong indication your code has "
733           . 'cached the original ->can derived method coderef, and is using it instead '
734           . 'of the proper method re-lookup, causing performance regressions'
735           );
736         }
737         else {
738           $deferred_calls_seen->{$cframe[3]} = "$cframe[1] line $cframe[2]";
739         }
740       }
741
742       # install the resolved implementation into the code slot so we do not
743       # come here anymore (hopefully)
744       # since XSAccessor was available - so is Sub::Name
745       {
746         no strict 'refs';
747         no warnings 'redefine';
748
749         my $fq_name = "${current_class}::${methname}";
750         *$fq_name = Sub::Name::subname($fq_name, $resolved_implementation);
751
752         # need to update what the shim expects too *in case* its
753         # ->can was cached for some moronic reason
754         $expected_cref = $resolved_implementation;
755         Scalar::Util::weaken($expected_cref);
756       }
757
758       # older perls segfault if the cref behind the goto throws
759       # http://rt.perl.org/rt3/Public/Bug/Display.html?id=35878
760       return $resolved_implementation->(@_) if __CAG_BROKEN_GOTO;
761
762       goto $resolved_implementation;
763     };
764
765     Scalar::Util::weaken($expected_cref); # to break the self-reference
766     $ret;
767   }
768
769   # no Sub::Name - just install the coderefs directly (compiling every time)
770   elsif (__CAG_NO_SUBNAME) {
771     my $src = $accessor_maker_cache->{source}{$type}{$group}{$field} ||=
772       $maker_templates->{$type}{pp_code}->($group, $field);
773
774     no warnings 'redefine';
775     local $@ if __CAG_UNSTABLE_DOLLARAT;
776     eval "sub ${class}::${methname} { $src }";
777
778     undef;  # so that no further attempt will be made to install anything
779   }
780
781   # a coderef generator with a variable pad (returns a fresh cref on every invocation)
782   else {
783     ($accessor_maker_cache->{pp}{$type}{$group}{$field} ||= do {
784       my $src = $accessor_maker_cache->{source}{$type}{$group}{$field} ||=
785         $maker_templates->{$type}{pp_code}->($group, $field);
786
787       local $@ if __CAG_UNSTABLE_DOLLARAT;
788       eval "sub { my \$dummy; sub { \$dummy if 0; $src } }" or die $@;
789     })->()
790   }
791 };
792
793 1;