File Coverage

blib/lib/Sub/HandlesVia/CodeGenerator.pm
Criterion Covered Total %
statement 206 219 94.0
branch 62 76 81.5
condition 45 53 84.9
subroutine 46 48 95.8
pod 3 4 75.0
total 362 400 90.5


line stmt bran cond sub pod time code
1 92     92   106283 use 5.008;
  92         429  
2 92     92   701 use strict;
  92         232  
  92         2375  
3 92     92   536 use warnings;
  92         243  
  92         7259  
4              
5              
6             our $AUTHORITY = 'cpan:TOBYINK';
7             our $VERSION = '0.045';
8              
9             use Sub::HandlesVia::Mite -all;
10 92     92   1254  
  92         274  
  92         1168  
11             has toolkit => (
12             is => ro,
13             );
14              
15             has target => (
16             is => ro,
17             );
18              
19             has attribute => (
20             is => ro,
21             );
22              
23             has attribute_spec => (
24             is => ro,
25             isa => 'HashRef',
26             );
27              
28             has isa => (
29             is => ro,
30             );
31              
32             has coerce => (
33             is => ro,
34             isa => 'Bool',
35             );
36              
37             has env => (
38             is => ro,
39             isa => 'HashRef',
40             default => \ '{}',
41             default_is_trusted => true,
42             );
43              
44             has sandboxing_package => (
45             is => ro,
46             isa => 'Str|Undef',
47             default => sprintf( '%s::__SANDBOX__', __PACKAGE__ ),
48             default_is_trusted => true,
49             );
50              
51             has [ 'generator_for_slot', 'generator_for_get', 'generator_for_set', 'generator_for_default' ] => (
52             is => ro,
53             isa => 'CodeRef',
54             );
55              
56             has generator_for_args => (
57             is => ro,
58             isa => 'CodeRef',
59             builder => sub {
60             return sub {
61             '@_[1..$#_]';
62 134     134   738 };
63 342     342   1959 },
64             default_is_trusted => true,
65             );
66              
67             has generator_for_arg => (
68             is => ro,
69             isa => 'CodeRef',
70             builder => sub {
71             return sub {
72             @_==2 or die;
73 4571 50   4571   10411 my $n = pop;
74 4571         8269 "\$_[$n]";
75 4571         20022 };
76 342     342   1989 },
77             default_is_trusted => true,
78             );
79              
80             has generator_for_argc => (
81             is => ro,
82             isa => 'CodeRef',
83             builder => sub {
84             return sub {
85             '(@_-1)';
86 472     472   1980 };
87 342     342   1614 },
88             default_is_trusted => true,
89             );
90              
91             has generator_for_currying => (
92             is => ro,
93             isa => 'CodeRef',
94             builder => sub {
95             return sub {
96             @_==2 or die;
97 0 0   0   0 my $arr = pop;
98 0         0 "splice(\@_,1,0,$arr);";
99 0         0 };
100 342     342   1814 },
101             default_is_trusted => true,
102             );
103              
104             has generator_for_usage_string => (
105             is => ro,
106             isa => 'CodeRef',
107             builder => sub {
108             return sub {
109             @_==3 or die;
110 2638 50   2638   6208 shift;
111 2638         4195 my $method_name = shift;
112 2638         4221 my $guts = shift;
113 2638         4093 "\$instance->$method_name($guts)";
114 2638         21558 };
115 342     342   1852 },
116             default_is_trusted => true,
117             );
118              
119             has generator_for_self => (
120             is => ro,
121             isa => 'CodeRef',
122             builder => sub {
123             return sub {
124             '$_[0]';
125 5372     5372   18132 };
126 342     342   1536 },
127             default_is_trusted => true,
128             );
129              
130             has generator_for_type_assertion => (
131             is => ro,
132             isa => 'CodeRef',
133             builder => sub {
134             return sub {
135             my ( $gen, $env, $type, $varname ) = @_;
136 790     790   1916 my $i = 0;
137 790         1291 my $type_varname = sprintf '$shv_type_constraint_%d', $type->{uniq};
138 790         3163 $env->{$type_varname} = \$type;
139 790         2092 if ( $gen->coerce and $type->has_coercion ) {
140 790 100 100     2765 if ( $type->coercion->can_be_inlined ) {
141 8 50       110 return sprintf '%s=%s;%s;',
142 8         728 $varname,
143             $type->coercion->inline_coercion($varname),
144             $type->inline_assert( $varname, $type_varname );
145             }
146             else {
147             return sprintf '%s=%s->assert_coerce(%s);',
148 0         0 $varname, $type_varname, $varname;
149             }
150             }
151             return $type->inline_assert( $varname, $type_varname );
152 782         3558 };
153 342     342   2115 },
154             default_is_trusted => true,
155             );
156              
157             has generator_for_error => (
158             is => ro,
159             isa => 'CodeRef',
160             builder => sub {
161             return sub {
162             my ( $gen, $error ) = @_;
163 2723     2723   5984 sprintf 'do { require Carp; Carp::croak(%s) }', $error;
164 2723         9359 };
165 342     342   1816 },
166             default_is_trusted => true,
167             );
168              
169             has generator_for_prelude => (
170             is => ro,
171             isa => 'CodeRef',
172             builder => sub {
173             return sub { '' };
174 2172     2172   5639 },
  2388         6264  
175             default_is_trusted => true,
176             );
177              
178             has method_installer => (
179             is => rw,
180             isa => 'CodeRef',
181             );
182              
183             has _override => (
184             is => rw,
185             init_arg => undef,
186             );
187              
188             has is_method => (
189             is => ro,
190             default => true,
191             );
192              
193             has get_is_lvalue => (
194             is => ro,
195             default => false,
196             );
197              
198             has set_checks_isa => (
199             is => ro,
200             default => false,
201             );
202              
203             has set_strictly => (
204             is => ro,
205             default => true,
206             );
207              
208             my $REASONABLE_SCALAR = qr/^
209             \$ # scalar access
210             [^\W0-9]\w* # normal-looking variable name (including $_)
211             (?: # then...
212             (?:\-\>)? # dereference maybe
213             [\[\{] # opening [ or {
214             [\'\"]? # quote maybe
215             \w+ # word characters (includes digits)
216             [\'\"]? # quote maybe
217             [\]\}] # closing ] or }
218             ){0,3} # ... up to thrice
219             $/x;
220              
221             my @generatable_things = qw(
222             slot get set default arg args argc currying usage_string self
223             type_assertion error prelude
224             );
225              
226             for my $thing ( @generatable_things ) {
227             my $generator = "generator_for_$thing";
228             my $method_name = "generate_$thing";
229             my $method = sub {
230             my $gen = shift;
231 37396     37396   95962 local ${^GENERATOR} = $gen;
232 37396         55386
233             if ( @{ $gen->_override->{$thing} || [] } ) {
234 37396 100       49391 my $coderef = pop @{ $gen->_override->{$thing} };
  37396 100       138090  
235 8523         12772 my $guard = guard {
  8523         18128  
236             push @{ $gen->_override->{$thing} ||= [] }, $coderef;
237 8523   50 8523   12385 };
  8523         58755  
238 8523         40375 return $gen->$coderef( @_ );
239 8523         20304 }
240            
241             return $gen->$generator->( $gen, @_ );
242 28873         100249 };
243             no strict 'refs';
244 92     92   108761 *$method_name = $method;
  92         276  
  92         49629  
245             }
246              
247             my $self = shift;
248             my $attr = $self->attribute;
249 3     3 0 8
250 3         9 return $attr
251             if !ref $attr;
252 3 50       15
253             return sprintf '$instance->%s', $attr->[0]
254             if ref($attr) eq 'ARRAY';
255 0 0       0
256             return '$attribute_value';
257             }
258 0         0  
259             my $self = shift;
260             $self->_override( {} );
261             return guard {
262 4221     4221   6898 $self->_override( {} );
263 4221         13811 };
264             }
265 4221     4221   31748  
266 4221         22936 {
267             my %generatable_thing = map +( $_ => 1 ), @generatable_things;
268            
269             my ( $self, %overrides ) = @_;
270             while ( my ( $key, $value ) = each %overrides ) {
271             next if !defined $value;
272             next if !$generatable_thing{$key};
273 3069     3069   11161 push @{ $self->_override->{$key} ||= [] }, $value;
274 3069         11644 }
275 11112 100       22249 return $self;
276 10840 100       24466 }
277 8836   100     13596 }
  8836         46118  
278              
279 3069         7614 my ( $self, $method_name, $handler ) = @_;
280            
281             $self->install_method(
282             $method_name,
283             $self->generate_coderef_for_handler( $method_name, $handler ),
284 4219     4219 1 8863 );
285             }
286 4219         10620  
287             {
288             my $sub_rename;
289             if ( eval { require Sub::Util } ) {
290             $sub_rename = Sub::Util->can('set_subname');
291             }
292             elsif ( eval { require Sub::Name } ) {
293             $sub_rename = Sub::Name->can('subname');
294             }
295            
296             my ( $self, $method_name, $coderef ) = @_;
297             my $target = $self->target;
298            
299             eval {
300             $coderef = $sub_rename->( "$target\::$method_name", $coderef )
301             } if ref $sub_rename;
302 4219     4219 1 1791530
303 4219         13515 if ( $self->method_installer ) {
304             $self->method_installer->( $method_name, $coderef );
305 4219 50       13758 }
306 4219         33256 else {
307             no strict 'refs';
308             *{"$target\::$method_name"} = $coderef;
309 4219 100       16691 }
310 2593         7235 }
311             }
312              
313 92     92   868 my ( $self, $method_name, $handler ) = @_;
  92         272  
  92         220263  
314 1626         2681
  1626         11241  
315             my $ec_args = $self->_generate_ec_args_for_handler( $method_name, $handler );
316            
317             # warn "#### $method_name";
318             # warn join("\n", @{$ec_args->{source}});
319             # for my $key (sort keys %{$ec_args->{environment}}) {
320 4220     4220 1 7924 # warn ">> $key : ".ref($ec_args->{environment}{$key});
321             # if ( ref($ec_args->{environment}{$key}) eq 'REF' and ref(${$ec_args->{environment}{$key}}) eq 'CODE' ) {
322 4220         9166 # require B::Deparse;
323             # warn B::Deparse->new->coderef2text(${$ec_args->{environment}{$key}});
324             # }
325             # }
326            
327             require Eval::TypeTiny;
328             Eval::TypeTiny::eval_closure( %$ec_args );
329             }
330              
331             my ( $self, $method_name, $handler ) = @_;
332            
333             # Later on, we might need to override the generators for
334 4220         24069 # arg, argc, args, set, etc.
335 4220         19006 #
336             my $guard = $self->_start_overriding_generators;
337            
338             # Make a COPY of $self->env!
339 4221     4221   7271 #
340             my $env = { %{$self->env} };
341            
342             # Preamble code.
343             #
344 4221         8887 my $code = [
345             'sub {',
346             ];
347            
348 4221         7737 push @$code, sprintf( 'package %s;', $self->sandboxing_package )
  4221         13755  
349             if $self->sandboxing_package;
350              
351             # Need to maintain state between following method calls. A proper
352 4221         9731 # object might be nice, but a hashref will do for now.
353             #
354             my $state = {
355             signature_check_needed => true, # hasn't been done yet
356 4221 50       24393 final_type_check_needed => $handler->is_mutator,
357             getter => scalar($self->generate_get),
358             getter_is_lvalue => $self->get_is_lvalue,
359             template_wrapper => undef, # nothing yet
360             add_later => undef, # nothing yet
361             shifted_self => false,
362 4221         14166 };
363              
364             # use Hash::Util qw( lock_ref_keys );
365             # lock_ref_keys( $state );
366            
367             my @args = (
368             $method_name, # Intended name for the coderef being generated
369             $handler, # Info about the functionality being delegated
370             $env, # Variables which need to be closed over
371             $code, # Lines of code in the method
372             $state, # Shared state while building method. (Minimal!)
373             );
374             $self
375 4221         24243 ->_handle_sigcheck( @args ) # check method sigs
376             ->_handle_prelude( @args ) # insert any prelude
377             ->_handle_shiftself( @args ) # $self = shift
378             ->_handle_currying( @args ) # push curried values to @_
379             ->_handle_additional_validation( @args ) # additional type checks
380             ->_handle_getter_code( @args ) # optimize calling getter
381             ->_handle_setter_code( @args ) # make calling setter safer
382 4221         10565 ->_handle_template( @args ) # perform code substitutes
383             ->_handle_chaining( @args ); # return $self if requested
384            
385             # Postamble code. Can't really do much here because the template
386             # might want to be able to return something.
387             #
388             push @$code, "}";
389            
390             # Allow the handler to inject variables into the environment.
391             # Rarely needed.
392             #
393             $handler->_tweak_env( $env );
394            
395             return {
396 4221         9622 source => $code,
397             environment => $env,
398             description => sprintf(
399             "%s=%s",
400             $method_name || '__ANON__',
401 4221         14517 $handler->name,
402             ),
403             };
404 4221   50     43879 }
405              
406             my ( $self, $method_name, $handler, $env, $code, $state ) = @_;
407              
408             # If there's a proper signature for the method...
409             #
410             if ( @{ $handler->signature || [] } ) {
411            
412             # Generate code using Type::Params to check the signature.
413             # We also need to close over the signature.
414             #
415 4221     4221   9102 require Type::Params;
416             unshift @$code, 'my $__sigcheck;';
417             $env->{'@__sig'} = $handler->signature;
418             if ( $state->{shifted_self} ) {
419 4221 100       6013 push @$code, '$__sigcheck||=Type::Params::compile(@__sig);@_=&$__sigcheck;';
  4221 100       17536  
420             }
421             else {
422             push @$code, '$__sigcheck||=Type::Params::compile(1, @__sig);@_=&$__sigcheck;';
423             }
424 1583         9017
425 1583         4664 # As we've now inserted a signature check, we can stop worrying
426 1583         3869 # about signature checks.
427 1583 50       3379 #
428 0         0 $state->{signature_check_needed} = 0;
429             }
430             # There is no proper signature, but there's still check the
431 1583         3696 # arity of the method.
432             #
433             else {
434             # What is the arity?
435             #
436             my $min_args = $handler->min_args || 0;
437 1583         2952 my $max_args = $handler->max_args;
438            
439             my $plus = 1;
440             if ( $state->{shifted_self} ) {
441             $plus = 0;
442             }
443            
444             # What usage message do we want to print if wrong arity?
445 2638   100     7587 #
446 2638         7286 my $usg = $self->generate_error( sprintf(
447             ' "Wrong number of parameters; usage: " . %s ',
448 2638         4653 B::perlstring( $self->generate_usage_string( $method_name, $handler->usage ) ),
449 2638 50       6304 ) );
450 0         0
451             # Insert the check into the code.
452             #
453             if (defined $min_args and defined $max_args and $min_args==$max_args) {
454             push @$code, sprintf('@_==%d or %s;', $min_args + $plus, $usg);
455 2638         8132 }
456             elsif (defined $min_args and defined $max_args) {
457             push @$code, sprintf('(@_ >= %d and @_ <= %d) or %s;', $min_args + $plus, $max_args + $plus, $usg);
458             }
459             elsif (defined $min_args and $min_args > 0) {
460             push @$code, sprintf('@_ >= %d or %s;', $min_args + $plus, $usg);
461             }
462 2638 100 66     17685
    100 100        
    100 66        
      66        
463 1789         6750 # We are still lacking a proper signature check though, so note
464             # that in the state. The information can be used by
465             # additional_validation coderefs.
466 264         1237 #
467             $state->{signature_check_needed} = true;
468             }
469 187         898
470             return $self;
471             }
472              
473             my ( $self, $method_name, $handler, $env, $code, $state ) = @_;
474            
475             push @$code, $self->generate_prelude();
476 2638         6509
477             return $self;
478             }
479 4221         12498  
480             my ( $self, $method_name, $handler, $env, $code, $state ) = @_;
481              
482             # Handlers which use @ARG will benefit from shifting $self
483 4221     4221   9241 # off @_, but for other handlers, this will just slow compilation
484             # down (but not much).
485 4221         9242 #
486             return $self
487 4221         10925 unless $handler->curried || $handler->prefer_shift_self;
488              
489             # Shift off the invocant.
490             #
491 4221     4221   8730 push @$code, 'my $shv_self=shift;';
492            
493             $self->_add_generator_override(
494            
495             # Override $ARG[$n] because the array has been reindexed.
496             #
497 4221 100 100     20065 arg => sub { my ($gen, $n) = @_; $gen->generate_arg( $n - 1 ) },
498            
499             # Overrride @ARG to point to the whole array. This is the
500             # real speed-up!
501             #
502 1692         3581 args => sub { '@_' },
503            
504             # Override #ARG to no longer subtract 1.
505             #
506             argc => sub { 'scalar(@_)' },
507            
508 2458     2458   6484 # $SELF is now '$shv_self'.
  2458         6857  
509             #
510             self => sub { '$shv_self' },
511            
512             # The default currying callback will splice the list into
513 681     681   2606 # @_ at index 1. Instead unshift the list at the start of @_.
514             #
515             currying => sub {
516             my ($gen, $list) = @_;
517 875     875   2783 "CORE::unshift(\@_, $list);";
518             },
519             );
520            
521 2612     2612   9136 # Getter was cached in $state and needs update.
522             #
523             $state->{getter} = $self->generate_get;
524             $state->{shifted_self} = true;
525            
526             return $self;
527 1389     1389   3665 }
528 1389         6220  
529             # Insert code into method for currying.
530 1692         19013 #
531             my ( $self, $method_name, $handler, $env, $code, $state ) = @_;
532            
533             if ( my $curried = $handler->curried ) {
534 1692         4323
535 1692         7047 # If the curried values are non-simple, we close over an array
536             # called @curry.
537 1692         4556 #
538             if ( grep ref, @$curried ) {
539            
540             # Note that generate_currying will generate code that unshifts whatever
541             # parameters it is given onto @_.
542             push @$code, $self->generate_currying('@curry');
543 4221     4221   9090 $env->{'@curry'} = $curried;
544             }
545 4221 100       11179 # If it's just strings, numbers, and undef, it should be pretty
546             # trivial to hard-code the values into the generated Perl string.
547             #
548             else {
549             require B;
550 1389 100       5299 my $values = join(
551             ',',
552             map { defined($_) ? B::perlstring($_) : 'undef' } @$curried,
553             );
554 360         1082 push @$code, $self->generate_currying( "($values)" );
555 360         1115 }
556             }
557            
558             return $self;
559             }
560              
561 1029         5663 my ( $self, $method_name, $handler, $env, $code, $state ) = @_;
562            
563             # If the handler specifies no validation needed, or the attribute
564 1029 50       2266 # simply has no type check, we don't need to check the type of the
  1545         7034  
565             # final attribute value.
566 1029         4406 #
567             if ( $handler->no_validation_needed or not $self->isa ) {
568             $state->{final_type_check_needed} = false;
569             }
570 4221         11136
571             # The handler can define some additional validation to be performed
572             # on arguments either now or later, such that if this additional
573             # validation is performed, the type check we were planning later
574 4221     4221   8439 # will be known to be unnecessary.
575             #
576             # An example for this is that is the attribute value is already an
577             # arrayref of numbers, and we're pushing a new value onto it, by checking
578             # up front that the INCOMING value is a number, it becomes unnecessary
579             # to check the whole arrayref contains numbers after the push.
580 4221 100 66     33137 #
581 177         348 # Not all handlers define an additional_validation coderef to do
582             # this, because in many cases it doesn't make sense to.
583             #
584             # Also if we've already decided a final type check isn't needed, we
585             # can skip this step.
586             #
587             if ( $state->{final_type_check_needed}
588             and defined $handler->additional_validation ) {
589            
590             my $real_av_method = $handler->_real_additional_validation;
591            
592             # The additional_validation coderef is called as a method and takes
593             # two additional parameters:
594             #
595             my $opt = $handler->$real_av_method(
596             !$state->{signature_check_needed}, # $sig_was_checked
597             $self, # $gen
598             );
599             $opt ||= {}; # can return undef
600 4221 100 100     31213
601             # The additional_validation coderef will often generate code which
602             # coerces incoming data, thus moving it from @_ to some other array.
603 1377         4817 # This means that the generators for @ARG, $ARG, etc will need to
604             # need to be overridden to point to the new array.
605             #
606             $self->_add_generator_override( %$opt );
607            
608             # The additional_validation coderef may supply extra variables
609             # to close over.
610 1377         5331 #
611             $env->{$_} = $opt->{env}{$_}
612 1377   100     6704 for keys %{ $opt->{env} || {} };
613            
614             # The additional_validation coderef will normally generate
615             # new code.
616             #
617             if ( defined $opt->{code} ) {
618            
619 1377         6144 # Code can be inserted into the generated method straight away,
620             # or may need to be inserted in a special placeholder position
621             # later.
622             #
623             $opt->{add_later}
624             ? ( $state->{add_later} = $opt->{code} )
625 1377 100       2352 : push( @$code, $opt->{code} );
  1377         6441  
626            
627             # Final type check is often no longer needed.
628             #
629             $state->{final_type_check_needed} = $opt->{final_type_check_needed} || false;
630 1377 100       5539 }
631             }
632            
633             return $self;
634             }
635              
636             my ( $self, $method_name, $handler, $env, $code, $state ) = @_;
637            
638 885 100       2709 # If there's a complicated way to fetch the attribute value (perhaps
639             # involving a lazy builder)...
640             #
641             if ( $state->{getter} !~ $REASONABLE_SCALAR ) {
642 885   100     5827
643             # And if it's definitely a reference anyway, then get it straight away,
644             # and store it in $shv_ref_invocant so we don't have to keep doing the
645             # complicated thing.
646 4221         11358 #
647             if ( $handler->name =~ /^(Array|Hash):/ ) {
648             push @$code, "my \$shv_ref_invocant = do { $state->{getter} };";
649             $state->{getter} = '$shv_ref_invocant';
650 4221     4221   9319 $state->{getter_is_lvalue} = true;
651             }
652            
653             # Alternatively, unless the handler doesn't want us to, or the template
654             # doesn't want to get the attribute value anyway, then we'll do something
655 4221 100       38196 # similar. Here it can't be used as an lvalue though.
656             #
657             elsif ( $handler->allow_getter_shortcuts
658             and $handler->template.($handler->lvalue_template||'') =~ /\$GET/ ) {
659             ( my $g = $state->{getter} ) =~ s/%/%%/g;
660             $state->{template_wrapper} = "do { my \$shv_real_invocant = $g; %s }";
661 822 100 100     6300 $state->{getter} = '$shv_real_invocant';
    100 66        
662 490         1729 }
663 490         919 }
664 490         952
665             return $self;
666             }
667              
668             my ( $self, $method_name, $handler, $env, $code, $state ) = @_;
669            
670             # If a type check is needed, but the setter doesn't do type checks,
671             # then override the setter. Now the setter does the type check, so
672             # we no longer need to worry about it.
673 329         1175 #
674 329         938 # XXX: I don't think any of the tests currently exercise this.
675 329         680 #
676             if ( $state->{final_type_check_needed} and not $self->set_checks_isa ) {
677             $self->_add_generator_override( set => sub {
678             my ( $me, $value_code ) = @_;
679 4221         11921 $me->generate_set( sprintf(
680             'do { my $shv_final_unchecked = %s; %s }',
681             $value_code,
682             $me->generate_type_assertion( $env, $me->isa, '$shv_final_unchecked' ),
683 4221     4221   9240 ) );
684             } );
685            
686             # In this case we can no longer use the getter as an lvalue, if we
687             # ever could.
688             #
689             $state->{getter_is_lvalue} = false;
690            
691 4221 50 66     13848 # Stop worrying about the final type check. The setter does that now.
692             #
693 0     0   0 $state->{final_type_check_needed} = false;
694 0         0 }
695            
696             return $self;
697             }
698              
699 0         0 my ( $self, $method_name, $handler, $env, $code, $state ) = @_;
700            
701             my $template;
702            
703             # If the getter is an lvalue, the handler has a special template
704 0         0 # for lvalues, we haven't been told to set strictly, and we have taken
705             # care of any type checks, then use the special lvalue template.
706             #
707             if ( $state->{getter_is_lvalue}
708 0         0 and $handler->lvalue_template
709             and !$self->set_strictly
710             and !$state->{final_type_check_needed} ) {
711 4221         10079 $template = $handler->lvalue_template;
712             }
713             else {
714             $template = $handler->template;
715 4221     4221   8347 }
716            
717 4221         6767 # Perform substitutions of special codes in the template string.
718             #
719             $template =~ s/\$SLOT/$self->generate_slot()/eg;
720             $template =~ s/\$GET/$state->{getter}/g;
721             $template =~ s/\$ATTRNAME/$self->attribute_name()/eg;
722             $template =~ s/\$ARG\[([0-9]+)\]/$self->generate_arg($1)/eg;
723 4221 100 100     25186 $template =~ s/\$ARG/$self->generate_arg(1)/eg;
      100        
      100        
724             $template =~ s/\#ARG/$self->generate_argc()/eg;
725             $template =~ s/\@ARG/$self->generate_args()/eg;
726             $template =~ s/⸨(.+?)⸩/$self->generate_error($1)/eg;
727 461         981 $template =~ s/«(.+?)»/$self->generate_set($1)/eg;
728             $template =~ s/\$DEFAULT/$self->generate_default($handler)/eg;
729             $template =~ s/\$SELF/$self->generate_self()/eg;
730 3760         8890
731             # Apply wrapper (if any). This wrapper is given
732             # by _handle_getter_code (sometimes).
733             #
734             $template = sprintf( $state->{template_wrapper}, $template )
735 4221         9599 if $state->{template_wrapper};
  2         6  
736 4221         24346
737 4221         10198 # If validation needs to be added late...
  3         9  
738 4221         9535 #
  2586         6214  
739 4221         9905 $template =~ s/\"?____VALIDATION_HERE____\"?/$state->{add_later}/
  2051         5575  
740 4221         9066 if defined $state->{add_later};
  865         2180  
741 4221         8135
  585         1681  
742 4221         7370 push @$code, $template;
  85         263  
743 4221         14199
  1982         5358  
744 4221         8788 return $self;
  55         229  
745 4221         7078 }
  47         126  
746              
747             my ( $self, $method_name, $handler, $env, $code, $state ) = @_;
748            
749             # Will just insert a string like ';$_[0]' at the end
750             #
751 4221 100       11047 push @$code, ';' . $self->generate_self,
752             if $handler->is_chainable;
753            
754             return $self;
755             }
756 4221 100       9792  
757             1;
758 4221         9571  
759              
760 4221         15237 =pod
761              
762             =encoding utf-8
763              
764 4221     4221   8836 =head1 NAME
765              
766             Sub::HandlesVia::CodeGenerator - looks at a Handler and generates a string of Perl code for it
767              
768 4221 100       12061 =head1 DESCRIPTION
769              
770             B<< This module is part of Sub::HandlesVia's internal API. >>
771 4221         7318 It is mostly of interest to people extending Sub::HandlesVia.
772              
773             Sub::HandlesVia toolkits create a code generator for each attribute they're
774             dealing with, and use the code generator to generate Perl code for one or
775             more delegated methods.
776              
777             =head1 CONSTRUCTORS
778              
779             =head2 C<< new( %attributes ) >>
780              
781             Standard Moose-like constructor.
782              
783             =head1 ATTRIBUTES
784              
785             =head2 C<toolkit> B<Object>
786              
787             The toolkit which made this code generator.
788              
789             =head2 C<target> B<< ClassName|RoleName >>
790              
791             The target package for generated methods.
792              
793             =head2 C<sandboxing_package> B<< ClassName|RoleName|Undef >>
794              
795             Package name to use as a sandbox; the default is usually fine.
796              
797             =head2 C<attribute> B<< Str|ArrayRef >>
798              
799             The attribute delegated to.
800              
801             =head2 C<attribute_spec> B<< HashRef >>
802              
803             Informational only.
804              
805             =head2 C<is_method> B<< Bool >>
806              
807             Indicates whether the generated code should be methods rather than functions.
808             This defaults to true, and false isn't really tested or well-defined.
809              
810             =head2 C<env> B<< HashRef >>
811              
812             Variables which need to be closed over when compiling coderefs.
813              
814             =head2 C<isa> B<< Maybe[TypeTiny] >>
815              
816             The type constraint for the attribute.
817              
818             =head2 C<coerce> B<< Bool >>
819              
820             Should the attribute coerce?
821              
822             =head2 C<method_installer> B<CodeRef>
823              
824             A coderef which can be called with C<< $method_name >> and C<< $coderef >>,
825             will install the method. Note that it isn't passed the package to install
826             into (which can be found in C<target>), so that would need to be closed
827             over.
828              
829             =head2 C<generator_for_self> B<< CodeRef >>
830              
831             A coderef which if called, generates a string like C<< '$_[0]' >>.
832              
833             Has a sensible default.
834              
835             All the C<generator_for_XXX> methods are called as methods, so have
836             the code generator object as an invocant.
837              
838             =head2 C<generator_for_slot> B<< CodeRef >>
839              
840             A coderef which if called, generates a string like C<< '$_[0]{attrname}' >>.
841              
842             =head2 C<generator_for_get> B<< CodeRef >>
843              
844             A coderef which if called, generates a string like C<< '$_[0]->attrname' >>.
845              
846             =head2 C<generator_for_set> B<< CodeRef >>
847              
848             A coderef which if called with a parameter, generates a string like
849             C<< "\$_[0]->_set_attrname( $parameter )" >>.
850              
851             =head2 C<generator_for_simple_default> B<< CodeRef >>
852              
853             A coderef which if called with a parameter, generates a string like
854             C<< 'undef' >> or C<< 'q[]' >> or C<< '{}' >>.
855              
856             The parameter is a handler object, which offers a C<default_for_reset>
857             attribute which might be able to provide a useful fallback.
858              
859             =head2 C<generator_for_args> B<< CodeRef >>
860              
861             A coderef which if called, generates a string like C<< '@_[1..$#_]' >>.
862              
863             Has a sensible default.
864              
865             =head2 C<generator_for_argc> B<< CodeRef >>
866              
867             A coderef which if called, generates a string like C<< '$#_' >>.
868              
869             Has a sensible default.
870              
871             =head2 C<generator_for_argc> B<< CodeRef >>
872              
873             A coderef which if called with a parameter, generates a string like
874             C<< "\$_[$parameter + 1]" >>.
875              
876             Has a sensible default.
877              
878             =head2 C<generator_for_currying> B<< CodeRef >>
879              
880             A coderef which if called with a parameter, generates a string like
881             C<< "splice(\@_,1,0,$parameter);" >>.
882              
883             Has a sensible default.
884              
885             =head2 C<generator_for_usage_string> B<< CodeRef >>
886              
887             The default is this coderef:
888              
889             sub {
890             @_==3 or die;
891             shift;
892             my $method_name = shift;
893             my $guts = shift;
894             return "\$instance->$method_name($guts)";
895             }
896              
897             =head2 C<generator_for_type_assertion> B<< CodeRef >>
898              
899             Called as a method and passed a hashref compilation environment, a type
900             constraint, and a variable name. Generates code to assert that the variable
901             value meets the type constraint, with coercion if appropriate.
902              
903             =head2 C<generator_for_error> B<< CodeRef >>
904              
905             Called as a method and passed a Perl string which is an expression evaluating
906             to an error message. Generates code to throw the error.
907              
908             =head2 C<generator_for_prelude> B<< CodeRef >>
909              
910             By default is a coderef returning the empty string. Can be used to generate
911             some additional statements which will be inserted near the top of the
912             method being generated. (Typically after parameter checks but before
913             doing anything serious.) This can be used to unlock a read-only attribute,
914             for example.
915              
916             =head2 C<get_is_lvalue> B<Bool>
917              
918             Indicates wheter the code generated by C<generator_for_get>
919             will be suitable for used as an lvalue.
920              
921             =head2 C<set_checks_isa> B<Bool>
922              
923             Indicates wheter the code generated by C<generator_for_set>
924             will do type checks.
925              
926             =head2 C<set_strictly> B<Bool>
927              
928             Indicates wheter we want to ensure that the setter is always called,
929             and we should not try to bypass it, even if we have an lvalue getter.
930              
931             =head1 METHODS
932              
933             For each C<generator_for_XXX> attribute, there's a corresponding
934             C<generate_XXX> method to actually call the coderef, possibly including
935             additional processing.
936              
937             =head2 C<< generate_and_install_method( $method_name, $handler ) >>
938              
939             Given a handler and a method name, will generate a coderef for the handler
940             and install it into the target package.
941              
942             =head2 C<< generate_coderef_for_handler( $method_name, $handler ) >>
943              
944             As above, but just returns the coderef rather than installs it.
945              
946             =head2 C<< install_method( $method_name, $coderef ) >>
947              
948             Installs a coderef into the target package with the given name.
949              
950             =head1 BUGS
951              
952             Please report any bugs to
953             L<https://github.com/tobyink/p5-sub-handlesvia/issues>.
954              
955             =head1 SEE ALSO
956              
957             L<Sub::HandlesVia>.
958              
959             =head1 AUTHOR
960              
961             Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
962              
963             =head1 COPYRIGHT AND LICENCE
964              
965             This software is copyright (c) 2020, 2022 by Toby Inkster.
966              
967             This is free software; you can redistribute it and/or modify it under
968             the same terms as the Perl 5 programming language system itself.
969              
970             =head1 DISCLAIMER OF WARRANTIES
971              
972             THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
973             WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
974             MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.