File Coverage

blib/lib/MooX/Pression.pm
Criterion Covered Total %
statement 578 687 84.1
branch 211 354 59.6
condition 54 96 56.2
subroutine 70 79 88.6
pod 4 6 66.6
total 917 1222 75.0


line stmt bran cond sub pod time code
1 28     28   2050083 use 5.014;
  28         318  
2 28     24   153 use strict;
  24         49  
  24         505  
3 24     23   116 use warnings;
  23         40  
  23         603  
4 23     23   132 use B ();
  23         41  
  23         419  
5 23     23   119 use Carp ();
  23         54  
  23         377  
6 23     23   10824 use Import::Into ();
  23         56908  
  23         612  
7 23     23   14669 use MooX::Press 0.025 ();
  23         2975528  
  23         851  
8 23     23   9736 use MooX::Press::Keywords ();
  23         2402746  
  23         745  
9 23     23   11479 use Syntax::Keyword::Try ();
  23         17318  
  23         587  
10 23     23   164 use feature ();
  23         48  
  23         1078  
11              
12             package MooX::Pression;
13              
14             our $AUTHORITY = 'cpan:TOBYINK';
15             our $VERSION = '0.303';
16              
17 23     23   9332 use Keyword::Simple ();
  23         54051  
  23         586  
18 23     23   17496 use PPR;
  23         901156  
  23         1038  
19 23     23   227 use B::Hooks::EndOfScope;
  23         107  
  23         300  
20 23     23   12903 use Exporter::Shiny our @EXPORT = qw( version authority overload );
  23         9577  
  23         194  
21 23     23   10886 use Devel::StrictMode qw(STRICT);
  23         8219  
  23         21433  
22              
23             BEGIN {
24             package MooX::Pression::_Gather;
25 23     23   110 my %gather;
26             my %stack;
27             sub import {
28 259     259   10138 my ($me, $action, $caller) = (shift, shift, scalar caller);
29 259 100       1381 if ($action eq -gather) {
    100          
    100          
    50          
30 96         371 while (@_) {
31 185         569 my ($k, $v) = splice @_, 0, 2;
32 185 100       1028 if (my ($kind,$pkg) = ($k =~ /^(class|role|class_generator|role_generator):(.+)$/)) {
33 67 50       153 if ( my @stack = @{ $stack{$me}{$caller}||[] } ) {
  67 50       536  
34 67 50       264 pop @stack if $stack[-1] eq $pkg;
35 67 100       219 if (@stack) {
36 25         58 $v->{_stack} = \@stack;
37 25         69 $kind = '_defer_'.$kind;
38             }
39             }
40 67   100     168 push @{ $gather{$me}{$caller}{$kind}||=[] }, $pkg, $v;
  67         2944  
41             }
42             else {
43 118         424 $gather{$me}{$caller}{$k} = $v;
44             }
45             }
46             }
47             elsif ($action eq -go) {
48 29 50       187 if ($gather{$me}{$caller}{'_defer_role'}) {
49 0         0 require Carp;
50 0         0 Carp::croak('Nested roles are not supported');
51             }
52 29 50       140 if ($gather{$me}{$caller}{'_defer_role_generator'}) {
53 0         0 require Carp;
54 0         0 Carp::croak('Nested role generators are not supported');
55             }
56 29 100       147 if ($gather{$me}{$caller}{'_defer_class_generator'}) {
57 1   50     13 $me->_undefer_class_generators($gather{$me}{$caller}{'class_generator'}||=[], delete $gather{$me}{$caller}{'_defer_class_generator'});
58             }
59 29 100       137 if ($gather{$me}{$caller}{'_defer_class'}) {
60 5         34 $me->_undefer_classes($gather{$me}{$caller}{'class'}, delete $gather{$me}{$caller}{'_defer_class'});
61             }
62            
63 26 50       130 if ($gather{$me}{$caller}{debug}) {
64 0         0 require Data::Dumper;
65 0         0 warn Data::Dumper::Dumper($gather{$me}{$caller});
66             }
67            
68 26         135 @_ = ('MooX::Press' => $gather{$me}{$caller});
69 26         263 goto \&MooX::Press::import;
70             }
71             elsif ($action eq -parent) {
72 67   100     143 push @{ $stack{$me}{$caller}||=[] }, $_[0];
  67         4028  
73             }
74             elsif ($action eq -unparent) {
75 67         130 pop @{ $stack{$me}{$caller} };
  67         1661  
76             }
77             else {
78 0         0 die;
79             }
80             }
81             sub _undefer_classes {
82 5     5   20 my ($me, $classes, $d) = @_;
83 5 100       12 my %class_hash = @{$classes||[]};
  5         36  
84 5         13 my @deferred;
85 5         12 my $max_depth = 0;
86 5         18 while (@$d) {
87 24         51 my ($class, $spec) = splice(@$d, 0, 2);
88 24         49 $spec->{_class_name} = $class;
89 24         31 $spec->{_depth} = @{ $spec->{_stack} };
  24         46  
90 24         43 push @deferred, $spec;
91 24 100       65 $max_depth = $spec->{_depth} if $spec->{_depth} > $max_depth;
92             }
93 5         25 DEPTH: for my $depth (1 .. $max_depth) {
94 8         21 SPEC: for my $spec (@deferred) {
95 84 100       159 next SPEC unless $spec->{_depth} == $depth;
96 24         37 my $parent_key = join('|', @{$spec->{_stack}});
  24         57  
97 24         50 my $my_key = join('|', @{$spec->{_stack}}, $spec->{_class_name});
  24         51  
98 24 100       54 if (not $class_hash{$parent_key}) {
99 3         14 require Carp;
100             Carp::croak(sprintf(
101             '%s is nested in %s but %s is not a class',
102             $spec->{_class_name},
103             $spec->{_stack}[-1],
104 3         1281 $spec->{_stack}[-1],
105             ));
106             }
107 21   100     29 push @{ $class_hash{$parent_key}{subclass} ||=[] }, $spec->{_class_name}, $spec;
  21         124  
108 21         70 $class_hash{$my_key} = $spec;
109             }
110             }
111 2         10 for my $spec (@deferred) {
112 21         30 delete $spec->{_stack};
113 21         28 delete $spec->{_class_name};
114 21         41 delete $spec->{_depth};
115             }
116             }
117             sub _undefer_class_generators {
118 1     1   3 my ($me, $classes, $d) = @_;
119 1         5 while (@$d) {
120 1         4 my ($class, $spec) = splice(@$d, 0, 2);
121 1         4 my $extends = $spec->{_stack}[-1];
122 1         5 my $next = delete($spec->{code});
123             $spec->{code} = sub {
124 2     2   102146 my $got = $next->(@_);
125 2   50     31 $got->{extends} ||= [$extends];
126 2         16 $got;
127 1         7 };
128 1         3 delete $spec->{_stack};
129 1         5 push @$classes, $class, $spec;
130             }
131             }
132              
133 23         108136 $INC{'MooX/Pression/_Gather.pm'} = __FILE__;
134             };
135              
136             #
137             # GRAMMAR
138             #
139              
140             our $GRAMMAR = qr{
141             (?(DEFINE)
142            
143             (?<PerlKeyword>
144            
145             (?: include (?&MxpIncludeSyntax) )|
146             (?: class (?&MxpClassSyntax) )|
147             (?: abstract (?&MxpAbstractSyntax) )|
148             (?: role (?&MxpRoleSyntax) )|
149             (?: interface (?&MxpRoleSyntax) )|
150             (?: toolkit (?&MxpToolkitSyntax) )|
151             (?: begin (?&MxpHookSyntax) )|
152             (?: end (?&MxpHookSyntax) )|
153             (?: type_name (?&MxpTypeNameSyntax) )|
154             (?: extends (?&MxpExtendsSyntax) )|
155             (?: with (?&MxpWithSyntax) )|
156             (?: requires (?&MxpWithSyntax) )|
157             (?: has (?&MxpHasSyntax) )|
158             (?: constant (?&MxpConstantSyntax) )|
159             (?: coerce (?&MxpCoerceSyntax) )|
160             (?: method (?&MxpMethodSyntax) )|
161             (?: factory (?&MxpFactorySyntax) )|
162             (?: factory (?&MxpFactoryViaSyntax))|
163             (?: before (?&MxpModifierSyntax) )|
164             (?: after (?&MxpModifierSyntax) )|
165             (?: around (?&MxpModifierSyntax) )|
166             (?: multi (?&MxpMultiSyntax) )|
167             (?: try (?&TrySyntax) )
168             )#</PerlKeyword>
169            
170             (?<MxpSimpleIdentifier>
171            
172             (?&PerlIdentifier)|(?&PerlBlock)
173             )#</MxpSimpleIdentifier>
174            
175             (?<MxpSimpleIdentifiers>
176            
177             (?&MxpSimpleIdentifier)
178             (?:
179             (?&PerlOWS)
180             ,
181             (?&PerlOWS)
182             (?&MxpSimpleIdentifier)
183             )*
184             )#</MxpSimpleIdentifiers>
185            
186             (?<MxpDecoratedIdentifier>
187            
188             (?: \+ )? # CAPTURE:plus
189             (?: \* )? # CAPTURE:asterisk
190             (?: (?&MxpSimpleIdentifier) ) # CAPTURE:name
191             (?: \! | \? )? # CAPTURE:postfix
192             )#</MxpDecoratedIdentifier>
193            
194             (?<MxpDecoratedIdentifierSolo>
195             (?: (?&MxpDecoratedIdentifier) ) # deliberately non-capturing
196             )#</MxpDecoratedIdentifierSolo>
197            
198             (?<MxpDecoratedIdentifiers>
199            
200             (?&MxpDecoratedIdentifier)
201             (?:
202             (?&PerlOWS)
203             ,
204             (?&PerlOWS)
205             (?&MxpDecoratedIdentifier)
206             )*
207             )#</MxpDecoratedIdentifiers>
208            
209             (?<MxpSimpleTypeSpec>
210            
211             ~?(?&PerlBareword)(?&PerlAnonymousArray)?
212             )#</MxpSimpleTypeSpec>
213            
214             (?<MxpTypeSpec>
215            
216             (?&MxpSimpleTypeSpec)
217             (?:
218             \s*\&\s*
219             (?&MxpSimpleTypeSpec)
220             )*
221             (?:
222             \s*\|\s*
223             (?&MxpSimpleTypeSpec)
224             (?:
225             \s*\&\s*
226             (?&MxpSimpleTypeSpec)
227             )*
228             )*
229             )#</MxpTypeSpec>
230            
231             (?<MxpExtendedTypeSpec>
232            
233             (?&MxpTypeSpec)|(?&PerlBlock)
234             )#</MxpExtendedTypeSpec>
235            
236             (?<MxpSignatureElement>
237            
238             (?&PerlOWS)
239             (?: (?&MxpExtendedTypeSpec))? # CAPTURE:type
240             (?&PerlOWS)
241             (?: # CAPTURE:name
242             (?&PerlVariable) | (\*(?&PerlIdentifier))
243             )
244             (?: # CAPTURE:postamble
245             \? | ((?&PerlOWS)=(?&PerlOWS)(?&PerlTerm))
246             )?
247             )#</MxpSignatureElement>
248            
249             (?<MxpSignatureList>
250            
251             (?&MxpSignatureElement)
252             (?:
253             (?&PerlOWS)
254             ,
255             (?&PerlOWS)
256             (?&MxpSignatureElement)
257             )*
258             )#</MxpSignatureList>
259            
260             (?<MxpAttribute>
261            
262             :
263             [^\W0-9]\w*
264             (?:
265             [(]
266             [^\)]+
267             [)]
268             )?
269             )#</MxpAttribute>
270            
271             (?<MxpRoleList>
272            
273             (?&PerlOWS)
274             (?:
275             (?&PerlBlock) | (?&PerlQualifiedIdentifier)
276             )
277             (?:
278             (?:\s*\?) | (?: (?&PerlOWS)(?&PerlList))
279             )?
280             (?:
281             (?&PerlOWS)
282             ,
283             (?&PerlOWS)
284             (?:
285             (?&PerlBlock) | (?&PerlQualifiedIdentifier)
286             )
287             (?:
288             (?:\s*\?) | (?: (?&PerlOWS)(?&PerlList))
289             )?
290             )*
291             )#</MxpRoleList>
292            
293             (?<MxpClassSyntax>
294            
295             (?&PerlOWS)
296             (?: [+] )? # CAPTURE:plus
297             (?: (?&PerlQualifiedIdentifier) )? # CAPTURE:name
298             (?&PerlOWS)
299             (?:
300             [(]
301             (?&PerlOWS)
302             (?: # CAPTURE:sig
303             (?&MxpSignatureList)?
304             )
305             (?&PerlOWS)
306             [)]
307             )?
308             (?&PerlOWS)
309             (?: (?&PerlBlock) )? # CAPTURE:block
310             (?&PerlOWS)
311             )#</MxpClassSyntax>
312            
313             (?<MxpIncludeSyntax>
314            
315             (?&PerlOWS)
316             (?: (?&PerlQualifiedIdentifier) )? # CAPTURE:name
317             (?&PerlOWS)
318             )#</MxpIncludeSyntax>
319            
320             (?<MxpAbstractSyntax>
321            
322             (?&PerlOWS)
323             class
324             (?&PerlOWS)
325             (?: [+] )? # CAPTURE:plus
326             (?: (?&PerlQualifiedIdentifier) )? # CAPTURE:name
327             (?&PerlOWS)
328             (?:
329             [(]
330             (?&PerlOWS)
331             (?: # CAPTURE:sig
332             (?&MxpSignatureList)?
333             )
334             (?&PerlOWS)
335             [)]
336             )?
337             (?&PerlOWS)
338             (?: (?&PerlBlock) )? # CAPTURE:block
339             (?&PerlOWS)
340             )#</MxpAbstractSyntax>
341            
342             (?<MxpRoleSyntax>
343            
344             (?&PerlOWS)
345             (?: (?&PerlQualifiedIdentifier) )? # CAPTURE:name
346             (?&PerlOWS)
347             (?:
348             [(]
349             (?&PerlOWS)
350             (?: # CAPTURE:sig
351             (?&MxpSignatureList)?
352             )
353             (?&PerlOWS)
354             [)]
355             )?
356             (?&PerlOWS)
357             (?: (?&PerlBlock) )? # CAPTURE:block
358             (?&PerlOWS)
359             )#</MxpRoleSyntax>
360            
361             (?<MxpHookSyntax>
362            
363             (?&PerlOWS)
364             (?: (?&PerlBlock) ) # CAPTURE:hook
365             (?&PerlOWS)
366             )#</MxpHookSyntax>
367            
368             (?<MxpTypeNameSyntax>
369            
370             (?&PerlOWS)
371             (?: (?&PerlIdentifier) ) # CAPTURE:name
372             (?&PerlOWS)
373             )#</MxpTypeNameSyntax>
374            
375             (?<MxpToolkitSyntax>
376            
377             (?&PerlOWS)
378             (?: (?&PerlIdentifier) ) # CAPTURE:name
379             (?&PerlOWS)
380             (?:
381             [(]
382             (?&PerlOWS)
383             (?: # CAPTURE:imports
384             (?: (?&PerlQualifiedIdentifier)|(?&PerlComma)|(?&PerlOWS) )*
385             )
386             (?&PerlOWS)
387             [)]
388             )?
389             (?&PerlOWS)
390             )#</MxpToolkitSyntax>
391            
392             (?<MxpExtendsSyntax>
393            
394             (?&PerlOWS)
395             (?: # CAPTURE:list
396             (?&MxpRoleList)
397             )
398             (?&PerlOWS)
399             )#</MxpExtendsSyntax>
400            
401             (?<MxpWithSyntax>
402            
403             (?&PerlOWS)
404             (?: # CAPTURE:list
405             (?&MxpRoleList)
406             )
407             (?&PerlOWS)
408             )#</MxpWithSyntax>
409            
410             (?<MxpRequiresSyntax>
411            
412             (?&PerlOWS)
413             (?: (?&MxpSimpleIdentifier) ) # CAPTURE:name
414             (?&PerlOWS)
415             (?:
416             [(]
417             (?&PerlOWS)
418             (?: # CAPTURE:sig
419             (?&MxpSignatureList)?
420             )
421             (?&PerlOWS)
422             [)]
423             )?
424             (?&PerlOWS)
425             )#</MxpRequiresSyntax>
426            
427             (?<MxpHasSyntax>
428            
429             (?&PerlOWS)
430             (?: (?&MxpDecoratedIdentifiers) ) # CAPTURE:name
431             (?&PerlOWS)
432             (?:
433             [(]
434             (?&PerlOWS)
435             (?: (?&PerlList) ) # CAPTURE:spec
436             (?&PerlOWS)
437             [)]
438             )?
439             (?&PerlOWS)
440             (?:
441             [=]
442             (?&PerlOWS)
443             (?: (?&PerlAssignment) ) # CAPTURE:default
444             )?
445             (?&PerlOWS)
446             )#</MxpHasSyntax>
447            
448             (?<MxpConstantSyntax>
449            
450             (?&PerlOWS)
451             (?: (?&PerlIdentifier) ) # CAPTURE:name
452             (?&PerlOWS)
453             =
454             (?&PerlOWS)
455             (?: (?&PerlExpression) ) # CAPTURE:expr
456             (?&PerlOWS)
457             )#</MxpConstantSyntax>
458            
459             (?<MxpMethodSyntax>
460            
461             (?&PerlOWS)
462             (?: (?&MxpSimpleIdentifier) )? # CAPTURE:name
463             (?&PerlOWS)
464             (?: ( (?&MxpAttribute) (?&PerlOWS) )+ )? # CAPTURE:attributes
465             (?&PerlOWS)
466             (?:
467             [(]
468             (?&PerlOWS)
469             (?: # CAPTURE:sig
470             (?&MxpSignatureList)?
471             )
472             (?&PerlOWS)
473             [)]
474             )?
475             (?&PerlOWS)
476             (?: (?&PerlBlock) ) # CAPTURE:code
477             (?&PerlOWS)
478             )#</MxpMethodSyntax>
479            
480             (?<MxpMultiSyntax>
481            
482             (?&PerlOWS)
483             method
484             (?&PerlOWS)
485             (?: (?&MxpSimpleIdentifier) ) # CAPTURE:name
486             (?&PerlOWS)
487             (?: ( (?&MxpAttribute) (?&PerlOWS) )+ )? # CAPTURE:attributes
488             (?&PerlOWS)
489             (?:
490             [(]
491             (?&PerlOWS)
492             (?: # CAPTURE:sig
493             (?&MxpSignatureList)?
494             )
495             (?&PerlOWS)
496             [)]
497             )?
498             (?&PerlOWS)
499             (?: (?&PerlBlock) ) # CAPTURE:code
500             (?&PerlOWS)
501             )#</MxpMultiSyntax>
502            
503             (?<MxpModifierSyntax>
504            
505             (?&PerlOWS)
506             (?: (?&MxpSimpleIdentifiers) ) # CAPTURE:name
507             (?&PerlOWS)
508             (?: ( (?&MxpAttribute) (?&PerlOWS) )+ )? # CAPTURE:attributes
509             (?&PerlOWS)
510             (?:
511             [(]
512             (?&PerlOWS)
513             (?: # CAPTURE:sig
514             (?&MxpSignatureList)?
515             )
516             (?&PerlOWS)
517             [)]
518             )?
519             (?&PerlOWS)
520             (?: (?&PerlBlock) ) # CAPTURE:code
521             (?&PerlOWS)
522             )#</MxpModifierSyntax>
523            
524             # Easier to provide two separate patterns for `factory`
525            
526             (?<MxpFactorySyntax>
527            
528             (?&PerlOWS)
529             (?: (?&MxpSimpleIdentifier) ) # CAPTURE:name
530             (?&PerlOWS)
531             (?: ( (?&MxpAttribute) (?&PerlOWS) )+ )? # CAPTURE:attributes
532             (?&PerlOWS)
533             (?:
534             [(]
535             (?&PerlOWS)
536             (?: # CAPTURE:sig
537             (?&MxpSignatureList)?
538             )
539             (?&PerlOWS)
540             [)]
541             )?
542             (?&PerlOWS)
543             (?: (?&PerlBlock) ) # CAPTURE:code
544             (?&PerlOWS)
545             )#</MxpFactorySyntax>
546            
547             (?<MxpFactoryViaSyntax>
548            
549             (?&PerlOWS)
550             (?: (?&MxpSimpleIdentifier) ) # CAPTURE:name
551             (?&PerlOWS)
552             (?:
553             (: via )
554             (?: # CAPTURE:via
555             (?&PerlBlock)|(?&PerlIdentifier)|(?&PerlString)
556             )
557             )?
558             (?&PerlOWS)
559             )#</MxpFactoryViaSyntax>
560            
561             (?<MxpCoerceSyntax>
562            
563             (?&PerlOWS)
564             (?: from )?
565             (?&PerlOWS)
566             (?: # CAPTURE:from
567             (?&MxpExtendedTypeSpec)
568             )
569             (?&PerlOWS)
570             (?: via )
571             (?&PerlOWS)
572             (?: # CAPTURE:via
573             (?&PerlBlock)|(?&PerlIdentifier)|(?&PerlString)
574             )
575             (?&PerlOWS)
576             (?: (?&PerlBlock) ) # CAPTURE:code
577             (?&PerlOWS)
578             )#</MxpCoerceSyntax>
579            
580             # try/catch/finally is implemented by another module
581             # but we need to be able to grok it to be able to parse
582             # blocks
583             #
584             (?<TrySyntax>
585            
586             (?&PerlOWS)
587             (?: do )?
588             (?&PerlOWS)
589             (?&PerlBlock)
590             (?:
591             (?&PerlOWS)
592             catch
593             (?&PerlOWS)
594             (?&PerlBlock)
595             )?
596             (?:
597             (?&PerlOWS)
598             finally
599             (?&PerlOWS)
600             (?&PerlBlock)
601             )?
602             (?&PerlOWS)
603             )#</TrySyntax>
604            
605             )
606             $PPR::GRAMMAR
607             }xso;
608              
609             my %_fetch_re_cache;
610             sub _fetch_re {
611 189     189   851 my $key = "@_";
612 189         408 my $name = shift;
613 189         647 my %opts = @_;
614            
615 189   100     918 $opts{anchor} ||= '';
616            
617 189   66     15858 $_fetch_re_cache{$key} ||= do {
618 105 50       109495 "$GRAMMAR" =~ m{<$name>(.+)</$name>}s or die "could not fetch re for $name";
619 105         1420 (my $re = $1) =~ s/\)\#$//;
620 105         1177 my @lines = split /\n/, $re;
621 105         424 for (@lines) {
622 1496 100       3950 if (my ($named_capture) = /# CAPTURE:(\w+)/) {
623 243         1499 s/\(\?\:/\(\?<$named_capture>/;
624             }
625             }
626 105         495 $re = join "\n", @lines;
627             $opts{anchor} eq 'start' ? qr/ ^ $re $GRAMMAR /xs :
628             $opts{anchor} eq 'end' ? qr/ $re $GRAMMAR $ /xs :
629 105 50       4278232 $opts{anchor} eq 'both' ? qr/ ^ $re $GRAMMAR $ /xs : qr/ $re $GRAMMAR /xs
    50          
    100          
630             }
631             }
632              
633             #
634             # HELPERS
635             #
636              
637             sub _handle_signature_list {
638 31     31   82 my $me = shift;
639 31         75 my $sig = $_[0];
640 31         82 my $seen_named = 0;
641 31         72 my $seen_pos = 0;
642 31         61 my @parsed;
643            
644             return (
645 31 100       174 0,
646             '',
647             '[]',
648             '',
649             ) if !$sig;
650            
651 26         103 while ($sig) {
652 37         175 $sig =~ s/^\s+//xs;
653 37 50       137 last if !$sig;
654            
655 37         172 push @parsed, {};
656            
657 37 100       992462 if ($sig =~ /^((?&PerlBlock)) $GRAMMAR/xso) {
    100          
658 3         106 my $type = $1;
659 3         16 $parsed[-1]{type} = $type;
660 3         10 $parsed[-1]{type_is_block} = 1;
661 3         50 $sig =~ s/^\Q$type//xs;
662 3         40093 $sig =~ s/^((?&PerlOWS)) $GRAMMAR//xso;
663             }
664             elsif ($sig =~ /^((?&MxpTypeSpec)) $GRAMMAR/xso) {
665 28         228 my $type = $1;
666 28         156 $parsed[-1]{type} = $type;
667 28         109 $parsed[-1]{type_is_block} = 0;
668 28         530 $sig =~ s/^\Q$type//xs;
669 28         431526 $sig =~ s/^((?&PerlOWS)) $GRAMMAR//xso;
670             }
671             else {
672 6         48 $parsed[-1]{type} = 'Any';
673 6         23 $parsed[-1]{type_is_block} = 0;
674             }
675            
676 37 100       997444 if ($sig =~ /^\*((?&PerlIdentifier)) $GRAMMAR/xso) {
    50          
677 5         26 my $name = $1;
678 5         20 $parsed[-1]{name} = $name;
679 5         16 $parsed[-1]{named} = 1;
680 5         11 $parsed[-1]{positional} = 0;
681 5         10 ++$seen_named;
682 5         78 $sig =~ s/^\*\Q$name//xs;
683 5         78850 $sig =~ s/^((?&PerlOWS)) $GRAMMAR//xso;
684             }
685             elsif ($sig =~ /^((?&PerlVariable)) $GRAMMAR/xso) {
686 32         333 my $name = $1;
687 32         196 $parsed[-1]{name} = $name;
688 32         114 $parsed[-1]{named} = 0;
689 32         92 $parsed[-1]{positional} = 1;
690 32         81 ++$seen_pos;
691 32         676 $sig =~ s/^\Q$name//xs;
692 32         1258197 $sig =~ s/^((?&PerlOWS)) $GRAMMAR//xs;
693             }
694            
695 37 100       549590 if ($sig =~ /^\?/) {
    100          
696 3         12 $parsed[-1]{optional} = 1;
697 3         39325 $sig =~ s/^\?((?&PerlOWS)) $GRAMMAR//xso;
698             }
699             elsif ($sig =~ /^=((?&PerlOWS))((?&PerlTerm)) $GRAMMAR/xso) {
700 2         22 my ($ws, $default) = ($1, $2);
701 2         11 $parsed[-1]{default} = $default;
702 2         52 $sig =~ s/^=\Q$ws$default//xs;
703 2         78135 $sig =~ s/^((?&PerlOWS)) $GRAMMAR//xso;
704             }
705            
706 37 100       2627 if ($sig) {
707 11 50       106 $sig =~ /^,/ or die "WEIRD SIGNATURE??? $sig";
708 11         169 $sig =~ s/^,//;
709             }
710             }
711            
712 26         100 my @signature_var_list;
713 26         160 my $type_params_stuff = '[';
714            
715 26         178 my (@head, @tail);
716 26 50 66     201 if ($seen_named and $seen_pos) {
717 0   0     0 while (@parsed and $parsed[0]{positional}) {
718 0         0 push @head, shift @parsed;
719             }
720 0   0     0 while (@parsed and $parsed[-1]{positional}) {
721 0         0 unshift @tail, pop @parsed;
722             }
723 0 0       0 if (grep $_->{positional}, @parsed) {
724 0         0 require Carp;
725 0         0 Carp::croak("Signature contains an unexpected mixture of positional and named parameters");
726             }
727 0         0 for my $p (@head, @tail) {
728 0         0 my $is_optional = $p->{optional};
729 0   0     0 $is_optional ||= ($p->{type} =~ /^Optional/s);
730 0 0       0 if ($is_optional) {
    0          
    0          
731 0         0 require Carp;
732 0         0 Carp::croak("Cannot have optional positional parameter $p->{name} in signature with named parameters");
733             }
734             elsif ($p->{default}) {
735 0         0 require Carp;
736 0         0 Carp::croak("Cannot have positional parameter $p->{name} with default in signature with named parameters");
737             }
738             elsif ($p->{name} =~ /^[\@\%]/) {
739 0         0 require Carp;
740 0         0 Carp::croak("Cannot have slurpy parameter $p->{name} in signature with named parameters");
741             }
742             }
743             }
744            
745 26         460 require B;
746              
747 26         94 my $extra = '';
748 26         78 my $count = @parsed;
749 26         155 while (my $p = shift @parsed) {
750 37 100       188 $type_params_stuff .= B::perlstring($p->{name}) . ',' if $seen_named;
751 37 100       254 if ($p->{name} =~ /^[\@\%]/) {
752 3 50       13 die "Cannot have slurpy in non-final position" if @parsed;
753             $extra .= sprintf(
754             'my (%s) = (@_==%d ? %s{$_[-1]} : ());',
755             $p->{name},
756             $count,
757 3         51 substr($p->{name}, 0, 1),
758             );
759 3         28 $p->{slurpy} = 1;
760 3 100       13 if ($p->{type} eq 'Any') {
761 2 100       11 $p->{type} = substr($p->{name}, 0, 1) eq '%' ? 'HashRef' : 'ArrayRef';
762             }
763             }
764             else {
765 34         146 push @signature_var_list, $p->{name};
766             }
767            
768 37 100       209 if ($p->{type_is_block}) {
769 3         48 $type_params_stuff .= sprintf('scalar(do %s)', $p->{type}) . ',';
770             }
771             else {
772 34         389 $type_params_stuff .= B::perlstring($p->{type}) . ',';
773             }
774 37 100 100     586 if (exists $p->{optional} or exists $p->{default} or $p->{slurpy}) {
      100        
775 8         18 $type_params_stuff .= '{';
776 8 100       35 $type_params_stuff .= sprintf('optional=>%d,', !!$p->{optional}) if exists $p->{optional};
777 8 100       51 $type_params_stuff .= sprintf('default=>sub{scalar(%s)},', $p->{default}) if exists $p->{default};
778 8 100       39 $type_params_stuff .= sprintf('slurpy=>%d,', !!$p->{slurpy}) if exists $p->{slurpy};
779 8         43 $type_params_stuff .= '},';
780             }
781             }
782            
783 26 100       117 @signature_var_list = '$arg' if $seen_named;
784 26         80 $type_params_stuff .= ']';
785            
786 26 50 33     157 if (@head or @tail) {
787 0         0 require Type::Params;
788 0         0 'Type::Params'->VERSION(1.009002);
789 0 0       0 my $head_stuff = join(q[,] => map { $_->{type_is_block} ? sprintf('scalar(do %s)', $_->{type}) : B::perlstring($_->{type}) } @head);
  0         0  
790 0 0       0 my $tail_stuff = join(q[,] => map { $_->{type_is_block} ? sprintf('scalar(do %s)', $_->{type}) : B::perlstring($_->{type}) } @tail);
  0         0  
791 0 0       0 my $opts = sprintf('{head=>%s,tail=>%s},', $head_stuff?"[$head_stuff]":0, $tail_stuff?"[$tail_stuff]":0);
    0          
792 0         0 substr($type_params_stuff, 1, 0) = $opts; # insert options after "["
793 0         0 unshift @signature_var_list, map $_->{name}, @head;
794 0         0 push @signature_var_list, map $_->{name}, @tail;
795             }
796            
797             return (
798 26         289 $seen_named,
799             join(',', @signature_var_list),
800             $type_params_stuff,
801             $extra,
802             );
803             }
804              
805             sub _handle_role_list {
806 16     16   71 my $me = shift;
807 16         60 my ($rolelist, $kind) = @_;
808 16         42 my @return;
809            
810 16         76 while (length $rolelist) {
811 18         78 $rolelist =~ s/^\s+//xs;
812            
813 18         55 my $prefix = '';
814 18         39 my $role = undef;
815 18         39 my $role_is_block = 0;
816 18         43 my $suffix = '';
817 18         58 my $role_params = undef;
818            
819 18 100       710151 if ($rolelist =~ /^((?&PerlBlock)) $GRAMMAR/xso) {
    50          
820 3         115 $role = $1;
821 3         9 $role_is_block = 1;
822 3         60 $rolelist =~ s/^\Q$role//xs;
823 3         12 $rolelist =~ s/^\s+//xs;
824             }
825             elsif ($rolelist =~ /^((?&PerlQualifiedIdentifier)) $GRAMMAR/xso) {
826 15         140 $role = $1;
827 15         343 $rolelist =~ s/^\Q$role//xs;
828 15         66 $rolelist =~ s/^\s+//xs;
829             }
830             else {
831 0         0 die "expected role name, got $rolelist";
832             }
833            
834 18 100       413446 if ($rolelist =~ /^\?/xs) {
    100          
835 4 50       22 die 'unexpected question mark' if $kind eq 'class';
836 4         12 $suffix = '?';
837 4         17 $rolelist =~ s/^\?\s*//xs;
838             }
839             elsif ($rolelist =~ /^((?&PerlList)) $GRAMMAR/xso) {
840 4         41 $role_params = $1;
841 4         98 $rolelist =~ s/^\Q$role_params//xs;
842 4         18 $rolelist =~ s/^\s+//xs;
843             }
844            
845 18 100       1430 if ($role_is_block) {
846 3         34 push @return, sprintf('sprintf(q(%s%%s%s), scalar(do %s))', $prefix, $suffix, $role);
847             }
848             else {
849 15         154 push @return, B::perlstring("$prefix$role$suffix");
850             }
851 18 100       73 if ($role_params) {
852 4         35 push @return, sprintf('[%s]', $role_params);
853             }
854            
855 18         57 $rolelist =~ s/^\s+//xs;
856 18 100       171 if (length $rolelist) {
857 2 50       15 $rolelist =~ /^,/ or die "expected comma, got $rolelist";
858 2         26 $rolelist =~ s/^\,\s*//;
859             }
860             }
861            
862 16         288 return join(",", @return);
863             }
864              
865             sub _handle_name_list {
866 29     29   101 my ($me, $names) = @_;
867 29 50       106 return unless $names;
868            
869 29         97 state $re = _fetch_re('MxpDecoratedIdentifierSolo');
870 29         2660337 my @names = grep defined, ($names =~ /($re) $GRAMMAR/xg);
871 29         9523 return @names;
872             }
873              
874             sub _handle_factory_keyword {
875 2     2   10 my ($me, $name, $via, $code, $has_sig, $sig, $attrs) = @_;
876            
877 2         6 my $optim;
878 2         9 for my $attr (@$attrs) {
879 0 0       0 $optim = 1 if $attr =~ /^:optimize\b/;
880             }
881            
882 2 50       12 if ($via) {
883 0 0       0 return sprintf(
    0          
884             'q[%s]->_factory(%s, \\(%s));',
885             $me,
886             ($name =~ /^\{/ ? "scalar(do $name)" : B::perlstring($name)),
887             ($via =~ /^\{/ ? "scalar(do $via)" : B::perlstring($via)),
888             );
889             }
890 2 50       6 if (!$has_sig) {
891 0         0 my $munged_code = sprintf('sub { my ($factory, $class) = (@_); do %s }', $code);
892 0 0       0 return sprintf(
    0          
893             'q[%s]->_factory(%s, { caller => __PACKAGE__, code => %s, optimize => %d });',
894             $me,
895             ($name =~ /^\{/ ? "scalar(do $name)" : B::perlstring($name)),
896             $optim ? B::perlstring($munged_code) : $munged_code,
897             !!$optim,
898             );
899             }
900 2         10 my ($signature_is_named, $signature_var_list, $type_params_stuff, $extra) = $me->_handle_signature_list($sig);
901 2         14 my $munged_code = sprintf('sub { my($factory,$class,%s)=(shift,shift,@_); %s; do %s }', $signature_var_list, $extra, $code);
902 2 50       33 sprintf(
    50          
903             'q[%s]->_factory(%s, { caller => __PACKAGE__, code => %s, named => %d, signature => %s, optimize => %d });',
904             $me,
905             ($name =~ /^\{/ ? "scalar(do $name)" : B::perlstring($name)),
906             $optim ? B::perlstring($munged_code) : $munged_code,
907             !!$signature_is_named,
908             $type_params_stuff,
909             !!$optim,
910             );
911             }
912              
913             sub _handle_method_keyword {
914 17     17   59 my $me = shift;
915 17         64 my ($name, $code, $has_sig, $sig, $attrs) = @_;
916            
917 17         69 my $optim;
918 17         84 for my $attr (@$attrs) {
919 1 50       12 $optim = 1 if $attr =~ /^:optimize\b/;
920             }
921            
922 17 100       78 if (defined $name) {
923 16 100       76 if ($has_sig) {
924 11         80 my ($signature_is_named, $signature_var_list, $type_params_stuff, $extra) = $me->_handle_signature_list($sig);
925 11         89 my $munged_code = sprintf('sub { my($self,%s)=(shift,@_); %s; my $class = ref($self)||$self; do %s }', $signature_var_list, $extra, $code);
926 11 50       321 return sprintf(
    100          
927             'q[%s]->_can(%s, { caller => __PACKAGE__, code => %s, named => %d, signature => %s, optimize => %d });',
928             $me,
929             ($name =~ /^\{/ ? "scalar(do $name)" : B::perlstring($name)),
930             $optim ? B::perlstring($munged_code) : $munged_code,
931             !!$signature_is_named,
932             $type_params_stuff,
933             !!$optim,
934             );
935             }
936             else {
937 5         32 my $munged_code = sprintf('sub { my $self = $_[0]; my $class = ref($self)||$self; do %s }', $code);
938 5 50       90 return sprintf(
    50          
939             'q[%s]->_can(%s, { caller => __PACKAGE__, code => %s, optimize => %d });',
940             $me,
941             ($name =~ /^\{/ ? "scalar(do $name)" : B::perlstring($name)),
942             $optim ? B::perlstring($munged_code) : $munged_code,
943             !!$optim,
944             );
945             }
946             }
947             else {
948 1 50       5 if ($has_sig) {
949 1         6 my ($signature_is_named, $signature_var_list, $type_params_stuff, $extra) = $me->_handle_signature_list($sig);
950 1         7 my $munged_code = sprintf('sub { my($self,%s)=(shift,@_); %s; my $class = ref($self)||$self; do %s }', $signature_var_list, $extra, $code);
951 1 50       29 return sprintf(
952             'q[%s]->wrap_coderef({ caller => __PACKAGE__, code => %s, named => %d, signature => %s, optimize => %d });',
953             'MooX::Press',
954             $optim ? B::perlstring($munged_code) : $munged_code,
955             !!$signature_is_named,
956             $type_params_stuff,
957             !!$optim,
958             );
959             }
960             else {
961 0         0 my $munged_code = sprintf('sub { my $self = $_[0]; my $class = ref($self)||$self; do %s }', $code);
962 0 0       0 return sprintf(
963             'q[%s]->wrap_coderef({ caller => __PACKAGE__, code => %s, optimize => %d });',
964             'MooX::Press',
965             $optim ? B::perlstring($munged_code) : $munged_code,
966             !!$optim,
967             );
968             }
969             }
970             }
971              
972             sub _handle_multimethod_keyword {
973 6     6   17 my $me = shift;
974 6         20 my ($name, $code, $has_sig, $sig, $attrs) = @_;
975            
976 6         13 my $optim;
977 6         15 my $extra_code = '';
978 6         27 for my $attr (@$attrs) {
979 1 50       7 $optim = 1 if $attr =~ /^:optimize\b/;
980 1 50       16 $extra_code .= sprintf('alias=>%s', B::perlstring($1)) if $attr =~ /^:alias\((.+)\)$/;
981             }
982            
983 6 50       19 if ($has_sig) {
984 6         26 my ($signature_is_named, $signature_var_list, $type_params_stuff, $extra) = $me->_handle_signature_list($sig);
985 6         42 my $munged_code = sprintf('sub { my($self,%s)=(shift,@_); %s; my $class = ref($self)||$self; do %s }', $signature_var_list, $extra, $code);
986 6 50       90 return sprintf(
987             'q[%s]->_multimethod(%s, { caller => __PACKAGE__, code => %s, named => %d, signature => %s, %s });',
988             $me,
989             ($name =~ /^\{/ ? "scalar(do $name)" : B::perlstring($name)),
990             $munged_code,
991             !!$signature_is_named,
992             $type_params_stuff,
993             $extra_code,
994             );
995             }
996             else {
997 0         0 my $munged_code = sprintf('sub { my $self = $_[0]; my $class = ref($self)||$self; do %s }', $code);
998 0 0       0 return sprintf(
999             'q[%s]->_multimethod(%s, { caller => __PACKAGE__, code => %s, named => 0, signature => sub { @_ }, %s });',
1000             $me,
1001             ($name =~ /^\{/ ? "scalar(do $name)" : B::perlstring($name)),
1002             $munged_code,
1003             $extra_code,
1004             );
1005             }
1006             }
1007              
1008             sub _handle_modifier_keyword {
1009 3     3   38 my ($me, $kind, $names, $code, $has_sig, $sig, $attrs) = @_;
1010              
1011 3         6 my $optim;
1012 3         14 for my $attr (@$attrs) {
1013 0 0       0 $optim = 1 if $attr =~ /^:optimize\b/;
1014             }
1015            
1016 3         27 my @names = $me->_handle_name_list($names);
1017            
1018             my $processed_names =
1019             join q[, ],
1020 3 50       18 map { /^\{/ ? "scalar(do $_)" : B::perlstring($_) } @names;
  4         81  
1021              
1022 3 100       30 if ($has_sig) {
    100          
1023 1         9 my ($signature_is_named, $signature_var_list, $type_params_stuff, $extra) = $me->_handle_signature_list($sig);
1024 1         4 my $munged_code;
1025 1 50       11 if ($kind eq 'around') {
1026 0         0 $munged_code = sprintf('sub { my($next,$self,%s)=(shift,shift,@_); %s; my $class = ref($self)||$self; do %s }', $signature_var_list, $extra, $code);
1027             }
1028             else {
1029 1         12 $munged_code = sprintf('sub { my($self,%s)=(shift,@_); %s; my $class = ref($self)||$self; do %s }', $signature_var_list, $extra, $code);
1030             }
1031 1 50       17 sprintf(
1032             'q[%s]->_modifier(q(%s), %s, { caller => __PACKAGE__, code => %s, named => %d, signature => %s, optimize => %d });',
1033             $me,
1034             $kind,
1035             $processed_names,
1036             $optim ? B::perlstring($munged_code) : $munged_code,
1037             !!$signature_is_named,
1038             $type_params_stuff,
1039             !!$optim,
1040             );
1041             }
1042             elsif ($kind eq 'around') {
1043 1         7 my $munged_code = sprintf('sub { my ($next, $self) = @_; my $class = ref($self)||$self; do %s }', $code);
1044 1 50       13 sprintf(
1045             'q[%s]->_modifier(q(%s), %s, { caller => __PACKAGE__, code => %s, optimize => %d });',
1046             $me,
1047             $kind,
1048             $processed_names,
1049             $optim ? B::perlstring($munged_code) : $munged_code,
1050             !!$optim,
1051             );
1052             }
1053             else {
1054 1         9 my $munged_code = sprintf('sub { my $self = $_[0]; my $class = ref($self)||$self; do %s }', $code);
1055 1 50       14 sprintf(
1056             'q[%s]->_modifier(q(%s), %s, { caller => __PACKAGE__, code => %s, optimize => %d });',
1057             $me,
1058             $kind,
1059             $processed_names,
1060             $optim ? B::perlstring($munged_code) : $munged_code,
1061             !!$optim,
1062             );
1063             }
1064             }
1065              
1066             sub _handle_package_keyword {
1067 72     72   309 my ($me, $kind, $name, $code, $has_sig, $sig, $plus, $opts) = @_;
1068            
1069 72 100       259 if ($kind eq 'abstract') {
1070 1         3 $kind = 'class';
1071 1         6 $code = "{ q[$me]->_abstract(1); $code }";
1072             }
1073            
1074 72 50       231 if ($kind eq 'interface') {
1075 0         0 $kind = 'role';
1076 0         0 $code = "{ q[$me]->_interface(1); $code }";
1077             }
1078            
1079 72 100 100     487 if ($name and $has_sig) {
    100          
    100          
1080 7         43 my ($signature_is_named, $signature_var_list, $type_params_stuff, $extra) = $me->_handle_signature_list($sig);
1081 7         70 my $munged_code = sprintf('sub { q(%s)->_package_callback(sub { my ($generator,%s)=(shift,@_); %s; do %s }, @_) }', $me, $signature_var_list, $extra, $code);
1082 7         156 sprintf(
1083             'use MooX::Pression::_Gather -parent => %s; use MooX::Pression::_Gather -gather, %s => { code => %s, named => %d, signature => %s }; use MooX::Pression::_Gather -unparent;',
1084             B::perlstring("$plus$name"),
1085             B::perlstring("$kind\_generator:$plus$name"),
1086             $munged_code,
1087             !!$signature_is_named,
1088             $type_params_stuff,
1089             );
1090             }
1091             elsif ($has_sig) {
1092 1         6 my ($signature_is_named, $signature_var_list, $type_params_stuff, $extra) = $me->_handle_signature_list($sig);
1093 1         11 my $munged_code = sprintf('sub { q(%s)->_package_callback(sub { my ($generator,%s)=(shift,@_); %s; do %s }, @_) }', $me, $signature_var_list, $extra, $code);
1094             sprintf(
1095             'q[%s]->anonymous_generator(%s => { code => %s, named => %d, signature => %s }, toolkit => %s, prefix => %s, factory_package => %s, type_library => %s)',
1096             $me,
1097             $kind,
1098             $munged_code,
1099             !!$signature_is_named,
1100             $type_params_stuff,
1101             B::perlstring($opts->{toolkit}||'Moo'),
1102             B::perlstring($opts->{prefix}),
1103             B::perlstring($opts->{factory_package}),
1104 1   50     37 B::perlstring($opts->{type_library}),
1105             );
1106             }
1107             elsif ($name) {
1108 60 50       1503 $code
1109             ? sprintf(
1110             'use MooX::Pression::_Gather -parent => %s; use MooX::Pression::_Gather -gather, %s => q[%s]->_package_callback(sub %s); use MooX::Pression::_Gather -unparent;',
1111             B::perlstring("$plus$name"),
1112             B::perlstring("$kind:$plus$name"),
1113             $me,
1114             $code,
1115             )
1116             : sprintf(
1117             'use MooX::Pression::_Gather -gather, %s => {};',
1118             B::perlstring("$kind:$plus$name"),
1119             );
1120             }
1121             else {
1122 4   50     13 $code ||= '{}';
1123             sprintf(
1124             'q[%s]->anonymous_package(%s => sub { do %s }, toolkit => %s, prefix => %s, factory_package => %s, type_library => %s)',
1125             $me,
1126             $kind,
1127             $code,
1128             B::perlstring($opts->{toolkit}||'Moo'),
1129             B::perlstring($opts->{prefix}),
1130             B::perlstring($opts->{factory_package}),
1131 4   50     89 B::perlstring($opts->{type_library}),
1132             );
1133             }
1134             }
1135              
1136             sub _handle_has_keyword {
1137 26     26   122 my ($me, $names, $rawspec, $default) = @_;
1138            
1139 26 100       115 $rawspec = '()' if !defined $rawspec;
1140            
1141 26 50 66     180 if (defined $default and $default =~ /\$self/) {
    100          
1142 0         0 $rawspec = "lazy => !!1, default => sub { my \$self = \$_[0]; $default }, $rawspec";
1143             }
1144             elsif (defined $default) {
1145 5         29 $rawspec = "default => sub { $default }, $rawspec";
1146             }
1147            
1148 26         132 my @names = $me->_handle_name_list($names);
1149            
1150 26         151 my @r;
1151 26         172 for my $name (@names) {
1152 28         151 $name =~ s/^\+\*/+/;
1153 28         99 $name =~ s/^\*//;
1154 28 100       597 push @r, sprintf(
1155             'q[%s]->_has(%s, %s)',
1156             $me,
1157             ($name =~ /^\{/) ? "scalar(do $name)" : B::perlstring($name),
1158             $rawspec,
1159             );
1160             }
1161 26         314 join ";", @r;
1162             }
1163              
1164             sub _handle_requires_keyword {
1165 3     3   12 my ($me, $name, $has_sig, $sig) = @_;
1166 3 50       28 my $r1 = sprintf(
1167             'q[%s]->_requires(%s);',
1168             $me,
1169             ($name =~ /^\{/ ? "scalar(do $name)" : B::perlstring($name)),
1170             );
1171 3         9 my $r2 = '';
1172 3 100       10 if (STRICT and $has_sig) {
1173 2         10 my ($signature_is_named, $signature_var_list, $type_params_stuff, $extra) = $me->_handle_signature_list($sig);
1174 2 50       30 $r2 = sprintf(
1175             'q[%s]->_modifier(q(around), %s, { caller => __PACKAGE__, code => %s, named => %d, signature => %s, optimize => %d });',
1176             $me,
1177             ($name =~ /^\{/ ? "scalar(do $name)" : B::perlstring($name)),
1178             'sub { my $next = shift; goto $next }',
1179             !!$signature_is_named,
1180             $type_params_stuff,
1181             1,
1182             );
1183             }
1184 3         21 "$r1$r2";
1185             }
1186              
1187             sub _syntax_error {
1188 0     0   0 require Carp;
1189 0 0       0 if (ref $_[-1]) {
1190 0         0 my $ref = pop;
1191 0         0 my ($me, $kind, @poss) = @_;
1192 0         0 Carp::croak(
1193             "Unexpected syntax in $kind.\n" .
1194             "Expected:\n" .
1195             join("", map "\t$_\n", @poss) .
1196             "Got:\n" .
1197             "\t" . substr($$ref, 0, 32)
1198             );
1199             }
1200             else {
1201 0         0 my ($me, $kind, $msg) = @_;
1202 0         0 Carp::croak("Unexpected syntax in $kind.\n" . $msg);
1203             }
1204             }
1205              
1206             my $owed = 0;
1207             sub _inject {
1208 156     156   638 my ($me, $ref, $trim_length, $new_code, $pad_at_end) = @_;
1209 156   100     840 $pad_at_end ||= 0;
1210            
1211 156         1215 my @orig_lines = split /\n/, substr($$ref, 0, $trim_length), -1;
1212 156         698 my @new_lines = split /\n/, $new_code, -1;
1213            
1214 156 100       760 if ($#orig_lines > $#new_lines) {
    100          
1215 38         115 my $diff = $#orig_lines - $#new_lines;
1216 38 100 100     254 if ($owed and $owed > $diff) {
    100          
1217 19         55 $owed -= $diff;
1218 19         42 $diff = 0;
1219             }
1220             elsif ($owed) {
1221 6         16 $diff -= $owed;
1222 6         15 $owed = 0;
1223             }
1224 38         128 my $prefix = "\n" x $diff;
1225 38 100       170 $new_code = $pad_at_end ? $new_code.$prefix : $prefix.$new_code;
1226             }
1227             elsif ($#orig_lines < $#new_lines) {
1228 61         179 $owed += ($#new_lines - $#orig_lines);
1229             }
1230            
1231 156         18135 substr $$ref, 0, $trim_length, $new_code;
1232             }
1233              
1234             #
1235             # KEYWORDS/UTILITIES
1236             #
1237              
1238             sub import {
1239 23     23   219 no warnings 'closure';
  23         63  
  23         23899  
1240 29     29   23485 my ($me, %opts) = (shift, @_);
1241 29   33     622 my $caller = ($opts{caller} ||= caller);
1242            
1243             # Need to reproduce this logic from MooX::Press to find out
1244             # the name of the type library.
1245             #
1246 29         291 require MooX::Press;
1247 29 100       193 $opts{prefix} = $opts{caller} unless exists $opts{prefix};
1248 29 50       291 $opts{factory_package} = $opts{prefix} unless exists $opts{factory_package};
1249 29 50       129 $opts{type_library} = 'Types' unless exists $opts{type_library};
1250 29         227 $opts{type_library} = 'MooX::Press'->qualify_name($opts{type_library}, $opts{prefix});
1251            
1252             # Optionally export wrapper subs for pre-declared types
1253             #
1254 29 50       866 if ($opts{declare}) {
1255 0         0 my $types = $opts{type_library};
1256 0         0 for my $name (@{ $opts{declare} }) {
  0         0  
1257 0 0       0 eval qq{
1258             sub $caller\::$name () { goto \\&$types\::$name }
1259             sub $caller\::is_$name (\$) { goto \\&$types\::is_$name }
1260             sub $caller\::assert_$name (\$) { goto \\&$types\::assert_$name }
1261             1;
1262             } or die($@);
1263             }
1264             }
1265            
1266             # Export utility stuff
1267             #
1268 29         373 MooX::Pression::_Gather->import::into($caller, -gather => %opts);
1269 29         506 MooX::Press::Keywords->import::into($caller, qw( -booleans -privacy -util )); # imports strict and warnings
1270 29         76993 Syntax::Keyword::Try->import::into($caller);
1271 29 50       6921 if ($] >= 5.018) {
    0          
1272 29         240 feature->import::into($caller, qw( say state unicode_strings unicode_eval evalbytes current_sub fc ));
1273             }
1274             elsif ($] >= 5.014) {
1275 0         0 feature->import::into($caller, qw( say state unicode_strings ));
1276             }
1277             $_->import::into($caller, qw( -types -is -assert ))
1278 29         9131 for qw(Types::Standard Types::Common::Numeric Types::Common::String);
1279            
1280             # `include` keyword
1281             #
1282             Keyword::Simple::define include => sub {
1283 2     2   8 my $ref = shift;
1284            
1285 2 50       17 $$ref =~ _fetch_re('MxpIncludeSyntax', anchor => 'start') or $me->_syntax_error(
1286             'include directive',
1287             'include <name>',
1288             $ref,
1289             );
1290            
1291 2         43 my ($pos, $name) = ($+[0], $+{name});
1292 2         33 my $qualified = 'MooX::Press'->qualify_name($name, $opts{prefix});
1293 2         68 $me->_inject($ref, $pos, sprintf('BEGIN { eval(q[%s]->_include(%s)) or die($@) };', $me, B::perlstring($qualified)));
1294 29         677130 };
1295              
1296             # `class` keyword
1297             #
1298             Keyword::Simple::define class => sub {
1299 61     61   8483 my $ref = shift;
1300            
1301 61 50       435 $$ref =~ _fetch_re('MxpClassSyntax', anchor => 'start') or $me->_syntax_error(
1302             'class declaration',
1303             'class <name> (<signature>) { <block> }',
1304             'class <name> { <block> }',
1305             'class <name>',
1306             'class (<signature>) { <block> }',
1307             'class { <block> }',
1308             'class;',
1309             $ref,
1310             );
1311            
1312 61         93901 my ($pos, $plus, $name, $sig, $block) = ($+[0], $+{plus}, $+{name}, $+{sig}, $+{block});
1313 61         458 my $has_sig = !!exists $+{sig};
1314 61   100     439 $plus ||= '';
1315 61   100     232 $block ||= '{}';
1316            
1317 61         441 $me->_inject($ref, $pos, "\n#\n#\n#\n#\n".$me->_handle_package_keyword(class => $name, $block, $has_sig, $sig, $plus, \%opts), 1);
1318 29         1041 };
1319              
1320             Keyword::Simple::define abstract => sub {
1321 1     1   424 my $ref = shift;
1322            
1323 1 50       15 $$ref =~ _fetch_re('MxpAbstractSyntax', anchor => 'start') or $me->_syntax_error(
1324             'abstract class declaration',
1325             'abstract class <name> (<signature>) { <block> }',
1326             'abstract class <name> { <block> }',
1327             'abstract class <name>',
1328             'abstract class (<signature>) { <block> }',
1329             'abstract class { <block> }',
1330             'abstract class;',
1331             $ref,
1332             );
1333            
1334 1         39 my ($pos, $plus, $name, $sig, $block) = ($+[0], $+{plus}, $+{name}, $+{sig}, $+{block});
1335 1         10 my $has_sig = !!exists $+{sig};
1336 1   50     9 $plus ||= '';
1337 1   50     6 $block ||= '{}';
1338            
1339 1         10 $me->_inject($ref, $pos, $me->_handle_package_keyword(abstract => $name, $block, $has_sig, $sig, $plus, \%opts), 1);
1340 29         699 };
1341              
1342 29         531 for my $kw (qw/ role interface /) {
1343             Keyword::Simple::define $kw => sub {
1344 10     10   1835 my $ref = shift;
1345            
1346 10 50       59 $$ref =~ _fetch_re('MxpRoleSyntax', anchor => 'start') or $me->_syntax_error(
1347             "$kw declaration",
1348             "$kw <name> (<signature>) { <block> }",
1349             "$kw <name> { <block> }",
1350             "$kw <name>",
1351             "$kw (<signature>) { <block> }",
1352             "$kw { <block> }",
1353             "$kw;",
1354             $ref,
1355             );
1356            
1357 10         11177 my ($pos, $name, $sig, $block) = ($+[0], $+{name}, $+{sig}, $+{block});
1358 10         100 my $has_sig = !!exists $+{sig};
1359 10   50     42 $block ||= '{}';
1360            
1361 10         70 $me->_inject($ref, $pos, $me->_handle_package_keyword($kw => $name, $block, $has_sig, $sig, '', \%opts), 1);
1362 58         870 };
1363             }
1364              
1365             Keyword::Simple::define toolkit => sub {
1366 0     0   0 my $ref = shift;
1367            
1368 0 0       0 $$ref =~ _fetch_re('MxpToolkitSyntax', anchor => 'start') or $me->_syntax_error(
1369             'toolkit declaration',
1370             'toolkit <toolkit> (<extensions>)',
1371             'toolkit <toolkit>;',
1372             $ref,
1373             );
1374            
1375 0         0 my ($pos, $name, $imports) = ($+[0], $+{name}, $+{imports});
1376            
1377 0 0       0 if ($imports) {
1378 0         0 my @imports = grep defined,
1379             ($imports =~ / ((?&PerlQualifiedIdentifier)|(?&PerlComma)) $GRAMMAR /xg);
1380 0         0 my @processed_imports;
1381 0         0 while (@imports) {
1382 23     23   208 no warnings 'uninitialized';
  23         70  
  23         91617  
1383 0         0 my $next = shift @imports;
1384 0 0       0 if ($next =~ /^::(.+)$/) {
    0          
1385 0         0 push @processed_imports, $1;
1386             }
1387             elsif ($next =~ /^[^\W0-9]/) {
1388 0         0 push @processed_imports, sprintf('%sX::%s', $name, $next);
1389             }
1390             else {
1391 0         0 die "Expected package name, got $next";
1392             }
1393 0 0       0 $imports[0] eq ',' and shift @imports;
1394             }
1395 0         0 $me->_inject($ref, $pos, sprintf('q[%s]->_toolkit(%s);', $me, join ",", map(B::perlstring($_), $name, @processed_imports)));
1396             }
1397            
1398             else {
1399 0         0 $me->_inject($ref, $pos, sprintf('q[%s]->_toolkit(%s);', $me, B::perlstring($name)));
1400             }
1401 29         726 };
1402              
1403             # `begin` and `end` keywords
1404             #
1405 29         535 for my $kw (qw/ begin end /) {
1406             Keyword::Simple::define $kw => sub {
1407 0     0   0 my $ref = shift;
1408            
1409 0 0       0 $$ref =~ _fetch_re('MxpHookSyntax', anchor => 'start') or $me->_syntax_error(
1410             "$kw hook",
1411             "$kw { <block> }",
1412             $ref,
1413             );
1414            
1415 0         0 my ($pos, $capture) = ($+[0], $+{hook});
1416 0         0 $me->_inject($ref, $pos, sprintf('q[%s]->_begin(sub { my ($package, $kind) = (shift, @_); do %s });', $me, $capture));
1417 58         755 };
1418             }
1419            
1420             # `type_name` keyword
1421             #
1422             Keyword::Simple::define type_name => sub {
1423 1     1   3 my $ref = shift;
1424            
1425 1 50       5 $$ref =~ _fetch_re('MxpTypeNameSyntax', anchor => 'start') or $me->_syntax_error(
1426             'type name declaration',
1427             'type_name <identifier>',
1428             $ref,
1429             );
1430            
1431 1         28 my ($pos, $capture) = ($+[0], $+{name});
1432 1         25 $me->_inject($ref, $pos, sprintf('q[%s]->_type_name(%s);', $me, B::perlstring($capture)));
1433 29         756 };
1434            
1435             # `extends` keyword
1436             #
1437             Keyword::Simple::define extends => sub {
1438 7     7   30 my $ref = shift;
1439            
1440 7 50       69 $$ref =~ _fetch_re('MxpExtendsSyntax', anchor => 'start') or $me->_syntax_error(
1441             'extends declaration',
1442             'extends <classes>',
1443             $ref,
1444             );
1445            
1446 7         370 my ($pos, $capture) = ($+[0], $+{list});
1447 7         92 $me->_inject($ref, $pos, sprintf('q[%s]->_extends(%s);', $me, $me->_handle_role_list($capture, 'class')));
1448 29         737 };
1449            
1450             # `with` keyword
1451             #
1452             Keyword::Simple::define with => sub {
1453 9     9   32 my $ref = shift;
1454            
1455 9 50       64 $$ref =~ _fetch_re('MxpWithSyntax', anchor => 'start') or $me->_syntax_error(
1456             'with declaration',
1457             'with <roles>',
1458             $ref,
1459             );
1460            
1461 9         260 my ($pos, $capture) = ($+[0], $+{list});
1462            
1463 9         130 $me->_inject($ref, $pos, sprintf('q[%s]->_with(%s);', $me, $me->_handle_role_list($capture, 'role')));
1464 29         696 };
1465            
1466             # `requires` keyword
1467             #
1468             Keyword::Simple::define requires => sub {
1469 3     3   11 my $ref = shift;
1470            
1471 3 50       14 $$ref =~ _fetch_re('MxpRequiresSyntax', anchor => 'start') or $me->_syntax_error(
1472             'requires declaration',
1473             'requires <name> (<signature>)',
1474             'requires <name>',
1475             $ref,
1476             );
1477            
1478 3         46 my ($pos, $name, $sig) = ($+[0], $+{name}, $+{sig});
1479 3         22 my $has_sig = !!exists $+{sig};
1480 3         25 $me->_inject($ref, $pos, $me->_handle_requires_keyword($name, $has_sig, $sig));
1481 29         681 };
1482            
1483             # `has` keyword
1484             #
1485             Keyword::Simple::define has => sub {
1486 26     26   134 my $ref = shift;
1487            
1488 26 50       126 $$ref =~ _fetch_re('MxpHasSyntax', anchor => 'start') or $me->_syntax_error(
1489             'attribute declaration',
1490             'has <name> (<spec>) = <default>',
1491             'has <name> (<spec>)',
1492             'has <name> = <default>',
1493             'has <name>',
1494             $ref,
1495             );
1496            
1497 26         1476 my ($pos, $name, $spec, $default) = ($+[0], $+{name}, $+{spec}, $+{default});
1498 26         200 my $has_spec = !!exists $+{spec};
1499 26         133 my $has_default = !!exists $+{default};
1500 26 100       364 $me->_inject($ref, $pos, $me->_handle_has_keyword($name, $has_spec ? $spec : undef, $has_default ? $default : undef));
    100          
1501 29         690 };
1502            
1503             # `constant` keyword
1504             #
1505             Keyword::Simple::define constant => sub {
1506 7     7   28 my $ref = shift;
1507            
1508 7 50       38 $$ref =~ _fetch_re('MxpConstantSyntax', anchor => 'start') or $me->_syntax_error(
1509             'constant declaration',
1510             'constant <name> = <value>',
1511             $ref,
1512             );
1513            
1514 7         195 my ($pos, $name, $expr) = ($+[0], $+{name}, $+{expr});
1515 7         118 $me->_inject($ref, $pos, sprintf('q[%s]->_constant(%s, %s);', $me, B::perlstring($name), $expr));
1516 29         754 };
1517            
1518             # `method` keyword
1519             #
1520             Keyword::Simple::define method => sub {
1521 17     17   74 my $ref = shift;
1522            
1523 17         72 state $re_attr = _fetch_re('MxpAttribute');
1524            
1525 17 50       191 $$ref =~ _fetch_re('MxpMethodSyntax', anchor => 'start') or $me->_syntax_error(
1526             'method declaration',
1527             'method <name> <attributes> (<signature>) { <block> }',
1528             'method <name> (<signature>) { <block> }',
1529             'method <name> <attributes> { <block> }',
1530             'method <name> { <block> }',
1531             'method <attributes> (<signature>) { <block> }',
1532             'method (<signature>) { <block> }',
1533             'method <attributes> { <block> }',
1534             'method { <block> }',
1535             $ref,
1536             );
1537            
1538 17         23460 my ($pos, $name, $attributes, $sig, $code) = ($+[0], $+{name}, $+{attributes}, $+{sig}, $+{code});
1539 17         145 my $has_sig = !!exists $+{sig};
1540 17 100       41826 my @attrs = $attributes ? grep(defined, ( ($attributes) =~ /($re_attr)/xg )) : ();
1541            
1542 17         472 $me->_inject($ref, $pos, $me->_handle_method_keyword($name, $code, $has_sig, $sig, \@attrs));
1543 29         726 };
1544              
1545             # `multi` keyword
1546             #
1547             Keyword::Simple::define multi => sub {
1548 6     6   24 my $ref = shift;
1549            
1550 6         17 state $re_attr = _fetch_re('MxpAttribute');
1551            
1552 6 50       28 $$ref =~ _fetch_re('MxpMultiSyntax', anchor => 'start') or $me->_syntax_error(
1553             'multimethod declaration',
1554             'multi method <name> <attributes> (<signature>) { <block> }',
1555             'multi method <name> (<signature>) { <block> }',
1556             'multi method <name> <attributes> { <block> }',
1557             'multi method <name> { <block> }',
1558             $ref,
1559             );
1560            
1561 6         2533 my ($pos, $name, $attributes, $sig, $code) = ($+[0], $+{name}, $+{attributes}, $+{sig}, $+{code});
1562 6         46 my $has_sig = !!exists $+{sig};
1563 6 100       39292 my @attrs = $attributes ? grep(defined, ( ($attributes) =~ /($re_attr)/xg )) : ();
1564            
1565 6         179 $me->_inject($ref, $pos, $me->_handle_multimethod_keyword($name, $code, $has_sig, $sig, \@attrs));
1566 29         800 };
1567              
1568             # `before`, `after`, and `around` keywords
1569             #
1570 29         699 for my $kw (qw( before after around )) {
1571             Keyword::Simple::define $kw => sub {
1572 3     3   18 my $ref = shift;
1573            
1574 3         15 state $re_attr = _fetch_re('MxpAttribute');
1575            
1576 3 50       13 $$ref =~ _fetch_re('MxpModifierSyntax', anchor => 'start') or $me->_syntax_error(
1577             "$kw method modifier declaration",
1578             "$kw <name> <attributes> (<signature>) { <block> }",
1579             "$kw <name> (<signature>) { <block> }",
1580             "$kw <name> <attributes> { <block> }",
1581             "$kw <name> { <block> }",
1582             $ref,
1583             );
1584            
1585 3         1766 my ($pos, $name, $attributes, $sig, $code) = ($+[0], $+{name}, $+{attributes}, $+{sig}, $+{code});
1586 3         25 my $has_sig = !!exists $+{sig};
1587 3 50       20 my @attrs = $attributes ? grep(defined, ( ($attributes) =~ /($re_attr)/xg )) : ();
1588            
1589 3         33 $me->_inject($ref, $pos, $me->_handle_modifier_keyword($kw, $name, $code, $has_sig, $sig, \@attrs));
1590 87         1596 };
1591             }
1592            
1593             Keyword::Simple::define factory => sub {
1594 2     2   10 my $ref = shift;
1595            
1596 2 50       11 if ( $$ref =~ _fetch_re('MxpFactorySyntax', anchor => 'start') ) {
1597 2         2844 state $re_attr = _fetch_re('MxpAttribute');
1598 2         56 my ($pos, $name, $attributes, $sig, $code) = ($+[0], $+{name}, $+{attributes}, $+{sig}, $+{code});
1599 2         18 my $has_sig = !!exists $+{sig};
1600 2 50       9 my @attrs = $attributes ? grep(defined, ( ($attributes) =~ /($re_attr)/xg )) : ();
1601 2         69 $me->_inject($ref, $pos, $me->_handle_factory_keyword($name, undef, $code, $has_sig, $sig, \@attrs));
1602 2         375 return;
1603             }
1604            
1605 0 0       0 $$ref =~ _fetch_re('MxpFactoryViaSyntax', anchor => 'start') or $me->_syntax_error(
1606             'factory method declaration',
1607             'factory <name> <attributes> (<signature>) { <block> }',
1608             'factory <name> (<signature>) { <block> }',
1609             'factory <name> <attributes> { <block> }',
1610             'factory <name> { <block> }',
1611             'factory <name> via <methodname>',
1612             'factory <name>',
1613             $ref,
1614             );
1615            
1616 0         0 my ($pos, $name, $via) = ($+[0], $+{name}, $+{via});
1617 0   0     0 $via ||= 'new';
1618 0         0 $me->_inject($ref, $pos, $me->_handle_factory_keyword($name, $via, undef, undef, undef, []));
1619 29         913 };
1620            
1621             Keyword::Simple::define coerce => sub {
1622 1     1   4 my $ref = shift;
1623            
1624 1 50       8 $$ref =~ _fetch_re('MxpCoerceSyntax', anchor => 'start') or $me->_syntax_error(
1625             'coercion declaration',
1626             'coerce from <type> via <method_name> { <block> }',
1627             'coerce from <type> via <method_name>',
1628             $ref,
1629             );
1630            
1631 1         1039 my ($pos, $from, $via, $code) = ($+[0], $+{from}, $+{via}, $+{code});
1632 1 50       14 if ($from =~ /^\{/) {
    50          
1633 0         0 $from = "scalar(do $from)"
1634             }
1635             elsif ($from !~ /^(q\b)|(qq\b)|"|'/) {
1636 1         6 $from = B::perlstring($from);
1637             }
1638 1 50       11 if ($via =~ /^\{/) {
    50          
1639 0         0 $via = "scalar(do $via)"
1640             }
1641             elsif ($via !~ /^(q\b)|(qq\b)|"|'/) {
1642 1         6 $via = B::perlstring($via);
1643             }
1644            
1645 1 50       17 $me->_inject($ref, $pos, sprintf('q[%s]->_coerce(%s, %s, %s);', $me, $from, $via, $code ? "sub { my \$class; local \$_; (\$class, \$_) = \@_; do $code }" : ''));
1646 29         803 };
1647            
1648             # Go!
1649             #
1650             on_scope_end {
1651 23 100   23   224 eval "package $caller; use MooX::Pression::_Gather -go; 1"
  23     29   56  
  23         156  
  29         3464  
1652             or Carp::croak($@);
1653 29         880 };
1654            
1655             # Need this to export `authority` and `version`...
1656 29         729 @_ = ($me);
1657 29         166 goto \&Exporter::Tiny::import;
1658             }
1659              
1660             our %OPTS;
1661              
1662             # `version` keyword
1663             #
1664             sub version {
1665 0     0 1 0 $OPTS{version} = shift;
1666             }
1667              
1668             # `authority` keyword
1669             #
1670             sub authority {
1671 0     0 1 0 $OPTS{authority} = shift;
1672             }
1673              
1674             # `overload` keyword
1675             #
1676             sub overload {
1677 1 50 33 1 1 19 if (@_ == 1 and ref($_[0]) eq 'HASH') {
    50 33        
1678 0   0     0 push @{ $OPTS{overload} ||= [] }, %{+shift};
  0         0  
  0         0  
1679             }
1680             elsif (@_ == 1 and ref($_[0]) eq 'ARRAY') {
1681 0   0     0 push @{ $OPTS{overload} ||= [] }, @{+shift};
  0         0  
  0         0  
1682             }
1683             else {
1684 1   50     3 push @{ $OPTS{overload} ||= [] }, @_;
  1         11  
1685             }
1686             }
1687              
1688             # `MooX::Pression::PACKAGE_SPEC` keyword
1689             #
1690 1     1 1 13 sub PACKAGE_SPEC { \%OPTS }
1691              
1692              
1693             #
1694             # CALLBACKS
1695             #
1696              
1697             sub _package_callback {
1698 73     73   237432 shift;
1699 73         179 my $cb = shift;
1700 73         333 local %OPTS = (in_package => 1);
1701 73         332 &$cb;
1702 73         262 delete $OPTS{in_package};
1703             # use Data::Dumper;
1704             # $Data::Dumper::Deparse = 1;
1705             # print "OPTS:".Dumper $cb, +{ %OPTS };
1706 73         829 return +{ %OPTS };
1707             }
1708             sub _has {
1709 31     31   251 my $me = shift;
1710 31 50       125 $OPTS{in_package} or $me->_syntax_error('attribute declaration', 'Not supported outside class or role');
1711 31         147 my ($attr, %spec) = @_;
1712 31         147 $OPTS{has}{$attr} = \%spec;
1713             }
1714             sub _extends {
1715 8     8   84 my $me = shift;
1716 8 50       46 $OPTS{in_package} or $me->_syntax_error('extends declaration', 'Not supported outside class');
1717 8   50     48 @{ $OPTS{extends}||=[] } = @_;
  8         76  
1718             }
1719             sub _type_name {
1720 1     1   7 my $me = shift;
1721 1 50       5 $OPTS{in_package} or $me->_syntax_error('extends declaration', 'Not supported outside class or role');
1722 1         4 $OPTS{type_name} = shift;
1723             }
1724             sub _begin {
1725 0     0   0 my $me = shift;
1726 0 0       0 $OPTS{in_package} or $me->_syntax_error('begin hook', 'Not supported outside class or role (use import option instead)');
1727 0         0 $OPTS{begin} = shift;
1728             }
1729             sub _end {
1730 0     0   0 my $me = shift;
1731 0 0       0 $OPTS{in_package} or $me->_syntax_error('end hook', 'Not supported outside class or role (use import option instead)');
1732 0         0 $OPTS{end} = shift;
1733             }
1734             sub _interface {
1735 0     0   0 shift;
1736 0         0 $OPTS{interface} = shift;
1737             }
1738             sub _abstract {
1739 1     1   6 shift;
1740 1         3 $OPTS{abstract} = shift;
1741             }
1742             sub _with {
1743 9     9   73 my $me = shift;
1744 9 50       46 $OPTS{in_package} or $me->_syntax_error('with declaration', 'Not supported outside class or role');
1745 9   50     21 push @{ $OPTS{with}||=[] }, @_;
  9         76  
1746             }
1747             sub _toolkit {
1748 0     0   0 my $me = shift;
1749 0 0       0 $OPTS{in_package} or $me->_syntax_error('toolkit declaration', 'Not supported outside class or role (use import option instead)');
1750 0         0 my ($toolkit, @imports) = @_;
1751 0         0 $OPTS{toolkit} = $toolkit;
1752 0 0 0     0 push @{ $OPTS{import}||=[] }, @imports if @imports;
  0         0  
1753             }
1754             sub _requires {
1755 3     3   20 my $me = shift;
1756 3 50       13 $OPTS{in_package} or $me->_syntax_error('requires declaration', 'Not supported outside role');
1757 3   100     6 push @{ $OPTS{requires}||=[] }, @_;
  3         23  
1758             }
1759             sub _coerce {
1760 1     1   12 my $me = shift;
1761 1 50       4 $OPTS{in_package} or $me->_syntax_error('coercion declaration', 'Not supported outside class');
1762 1   50     3 push @{ $OPTS{coerce}||=[] }, @_;
  1         14  
1763             }
1764             sub _factory {
1765 2     2   26 my $me = shift;
1766 2 50       7 $OPTS{in_package} or $me->_syntax_error('factory method declaration', 'Not supported outside class');
1767 2   100     6 push @{ $OPTS{factory}||=[] }, @_;
  2         14  
1768             }
1769             sub _constant {
1770 11     11   115 my $me = shift;
1771 11         34 my ($name, $value) = @_;
1772 11 100       36 if (! $OPTS{in_package}) {
1773 1         8 'MooX::Press'->install_constants(scalar(caller), { $name => $value });
1774 1         130 return;
1775             }
1776 10         41 $OPTS{constant}{$name} = $value;
1777             }
1778             sub _can {
1779 16     16   862 my $me = shift;
1780 16         53 my ($name, $code) = @_;
1781 16 100       94 if (! $OPTS{in_package}) {
1782 2         16 'MooX::Press'->install_methods(scalar(caller), { $name => $code });
1783 2         415 return;
1784             }
1785 14         67 $OPTS{can}{$name} = $code;
1786             }
1787             sub _multimethod {
1788 6     6   95 my $me = shift;
1789 6         18 my ($name, $spec) = @_;
1790 6 100       37 if (! $OPTS{in_package}) {
1791 2         13 'MooX::Press'->install_multimethod(scalar(caller), 'class', $name, $spec);
1792 2         46212 return;
1793             }
1794 4   50     35 push @{ $OPTS{multimethod} ||= [] }, $name => $spec;
  4         28  
1795             }
1796             sub _modifier {
1797 5     5   84 my $me = shift;
1798 5         21 my ($kind, @args) = @_;
1799 5 100       25 if (! $OPTS{in_package}) {
1800 1         3 my $codelike = pop @args;
1801 1         7 my $coderef = 'MooX::Press'->_prepare_method_modifier(scalar(caller), $kind, \@args, $codelike);
1802 1         27 require Class::Method::Modifiers;
1803 1         5 Class::Method::Modifiers::install_modifier(scalar(caller), $kind, @args, $coderef);
1804             }
1805 5   50     221 push @{ $OPTS{$kind} ||= [] }, @args;
  5         47  
1806             }
1807             sub _include {
1808 2     2   21 my $me = shift;
1809 2 50       12 $OPTS{in_package} and $me->_syntax_error('include directive', 'Not supported inside class or role');
1810            
1811 2         714 require Path::ScanINC;
1812 2         17121 my @chunks = split /::/, $_[0];
1813 2         9 $chunks[-1] .= '.pl';
1814 2         24 my $file = Path::ScanINC->new->first_file(@chunks);
1815            
1816 2 50       635 if (!$file) {
1817 0         0 require Carp;
1818 0         0 Carp::croak("No such file: " . join("/", @chunks));
1819             }
1820            
1821 2 50       49 ref $file eq 'ARRAY' and die "not supported yet";
1822 2         37 my $code = $file->slurp_utf8;
1823            
1824 2         1455 sprintf(
1825             "do {\n# line 1 %s\n%s\n};\n1;\n",
1826             B::perlstring($file),
1827             $code,
1828             );
1829             }
1830              
1831             #{
1832             # package MooX::Pression::Anonymous::Package;
1833             # our $AUTHORITY = 'cpan:TOBYINK';
1834             # our $VERSION = '0.303';
1835             # use overload q[""] => sub { ${$_[0]} }, fallback => 1;
1836             # sub DESTROY {}
1837             # sub AUTOLOAD {
1838             # my $me = shift;
1839             # (my $method = our $AUTOLOAD) =~ s/.*:://;
1840             # $$me->$method(@_);
1841             # }
1842             #
1843             # package MooX::Pression::Anonymous::Class;
1844             # our $AUTHORITY = 'cpan:TOBYINK';
1845             # our $VERSION = '0.303';
1846             # our @ISA = qw(MooX::Pression::Anonymous::Package);
1847             # sub new {
1848             # my $me = shift;
1849             # $$me->new(@_);
1850             # }
1851             # use overload q[&{}] => sub {
1852             # my $me = shift;
1853             # sub { $me->new(@_) }
1854             # };
1855             #
1856             # package MooX::Pression::Anonymous::Role;
1857             # our $AUTHORITY = 'cpan:TOBYINK';
1858             # our $VERSION = '0.303';
1859             # our @ISA = qw(MooX::Pression::Anonymous::Package);
1860             #
1861             # package MooX::Pression::Anonymous::ParameterizableClass;
1862             # our $AUTHORITY = 'cpan:TOBYINK';
1863             # our $VERSION = '0.303';
1864             # our @ISA = qw(MooX::Pression::Anonymous::Package);
1865             # sub generate_package {
1866             # my $me = shift;
1867             # my $gen = $$me->generate_package(@_);
1868             # bless \$gen, 'MooX::Pression::Anonymous::Class';
1869             # }
1870             # use overload q[&{}] => sub {
1871             # my $me = shift;
1872             # sub { $me->new_class(@_) }
1873             # };
1874             #
1875             # package MooX::Pression::Anonymous::ParameterizableRole;
1876             # our $AUTHORITY = 'cpan:TOBYINK';
1877             # our $VERSION = '0.303';
1878             # our @ISA = qw(MooX::Pression::Anonymous::Package);
1879             # sub generate_package {
1880             # my $me = shift;
1881             # my $gen = $$me->generate_package(@_);
1882             # bless \$gen, 'MooX::Pression::Anonymous::Class';
1883             # }
1884             # use overload q[&{}] => sub {
1885             # my $me = shift;
1886             # sub { $me->new_role(@_) }
1887             # };
1888             #}
1889              
1890             my $i = 0;
1891             sub anonymous_package {
1892 4     4 0 44012 my $me = shift;
1893 4         31 my ($kind, $callback, %opts) = @_;
1894 4         17 my $package_dfn = $me->_package_callback($callback);
1895            
1896 4         15 for my $forbidden (qw/ factory type_name coerce /) {
1897 12 50       31 die if exists $package_dfn->{$forbidden};
1898             }
1899 4         13 $package_dfn->{type_name} = undef;
1900 4         9 $package_dfn->{factory} = undef;
1901            
1902 4         24 my $qname = sprintf('%s::__ANON_%06d__', __PACKAGE__, ++$i);
1903            
1904 4         26 require MooX::Press;
1905 4         13 my $method = "make_$kind";
1906 4         40 MooX::Press->$method("::$qname", %opts, %$package_dfn);
1907            
1908 4         21771 require Module::Runtime;
1909 4         17 $INC{Module::Runtime::module_notional_filename($qname)} = __FILE__;
1910             #return bless(\$qname, "MooX::Pression::Anonymous::".ucfirst($kind));
1911 4         117 return $qname;
1912             }
1913              
1914             sub anonymous_generator {
1915 1     1 0 25 my $me = shift;
1916 1         9 my ($kind, $callback, %opts) = @_;
1917 1         6 my $qname = sprintf('%s::__ANON_%06d__', __PACKAGE__, ++$i);
1918            
1919 1         6 require MooX::Press;
1920 1         4 my $method = "make_$kind\_generator";
1921 1         10 MooX::Press->$method("::$qname", %opts, generator => $callback);
1922            
1923 1         560 require Module::Runtime;
1924 1         5 $INC{Module::Runtime::module_notional_filename($qname)} = __FILE__;
1925             #return bless(\$qname, "MooX::Pression::Anonymous::Parameterizable".ucfirst($kind));
1926 1         30 return $qname;
1927             }
1928              
1929             1;
1930              
1931             __END__
1932              
1933             =pod
1934              
1935             =encoding utf-8
1936              
1937             =head1 NAME
1938              
1939             MooX::Pression - express yourself through moo
1940              
1941             =head1 SYNOPSIS
1942              
1943             MyApp.pm
1944              
1945             use v5.18;
1946             use strict;
1947             use warnings;
1948            
1949             package MyApp {
1950             use MooX::Pression;
1951            
1952             class Person {
1953             has name ( type => Str, required => true );
1954             has gender ( type => Str );
1955            
1956             factory new_man (Str $name) {
1957             return $class->new(name => $name, gender => 'male');
1958             }
1959            
1960             factory new_woman (Str $name) {
1961             return $class->new(name => $name, gender => 'female');
1962             }
1963            
1964             method greet (Person *friend, Str *greeting = "Hello") {
1965             printf("%s, %s!\n", $arg->greeting, $arg->friend->name);
1966             }
1967            
1968             coerce from Str via from_string {
1969             return $class->new(name => $_);
1970             }
1971             }
1972             }
1973              
1974             my_script.pl
1975              
1976             use v5.18;
1977             use strict;
1978             use warnings;
1979             use MyApp;
1980             use MyApp::Types qw( is_Person );
1981            
1982             # Create a new MyApp::Person object.
1983             #
1984             my $alice = MyApp->new_woman("Alice");
1985             is_Person($alice) or die;
1986            
1987             # The string "Bob" will be coerced to a MyApp::Person.
1988             #
1989             $alice->greet(friend => "Bob", greeting => 'Hi');
1990              
1991             =head1 DESCRIPTION
1992              
1993             L<MooX::Pression> is kind of like L<Moops>; a marrying together of L<Moo>
1994             with L<Type::Tiny> and some keyword declaration magic. Instead of being
1995             built on L<Kavorka>, L<Parse::Keyword>, L<Keyword::Simple> and a whole
1996             heap of crack, it is built on L<MooX::Press>, L<Keyword::Simple>, and L<PPR>.
1997             I'm not saying there isn't some crazy stuff going on under the hood, but
1998             it ought to be a little more maintainable.
1999              
2000             Some of the insane features of Moops have been dialled back, and others
2001             have been amped up.
2002              
2003             It's more opinionated about API design and usage than Moops is, but in
2004             most cases, it should be fairly easy to port Moops code to MooX::Pression.
2005              
2006             MooX::Pression requires Perl 5.18.0 or above. It may work on Perl 5.14.x
2007             and Perl 5.16.x partly, but there are likely to be issues.
2008              
2009             L<MooX::Press> is a less magic version of MooX::Pression and only requires
2010             Perl 5.8.8 or above.
2011              
2012             =head2 Important Concepts
2013              
2014             =head3 The Factory Package and Prefix
2015              
2016             MooX::Pression assumes that all the classes and roles you are building
2017             with it will be defined under the same namespace B<prefix>. For example
2018             "MyApp::Person" and "MyApp::Company" are both defined under the common
2019             prefix of "MyApp".
2020              
2021             It also assumes there will be a B<< factory package >> that can be used
2022             to build new instances of your class. Rather than creating a new person
2023             object with C<< MyApp::Person->new() >>, you should create a new person
2024             object with C<< MyApp->new_person() >>. Calling C<< MyApp::Person->new() >>
2025             directly is only encouraged from within the "MyApp::Person" class itself,
2026             and from within the factory. Everywhere else, you should call
2027             C<< MyApp->new_person() >> instead.
2028              
2029             By default, the factory package and the prefix are the same: they are
2030             the caller that you imported MooX::Pression into. But they can be set
2031             to whatever:
2032              
2033             use MooX::Pression (
2034             prefix => 'MyApp::Objects',
2035             factory_package => 'MyApp::Makers',
2036             );
2037              
2038             MooX::Pression assumes that you are defining all the classes and roles
2039             within this namespace prefix in a single Perl module file. This Perl
2040             module file would normally be named based on the prefix, so in the
2041             example above, it would be "MyApp/Objects.pm" and in the example from
2042             the SYNOPSIS, it would be "MyApp.pm".
2043              
2044             But see also the documentation for C<include>.
2045              
2046             Of course, there is nothing to stop you from having multiple prefixes
2047             for different logical parts of a larger codebase, but MooX::Pression
2048             assumes that if it's been set up for a prefix, it owns that prefix and
2049             everything under it, and it's all defined in the same Perl module.
2050              
2051             Each object defined by MooX::Pression will have a C<FACTORY> method,
2052             so you can do:
2053              
2054             $person_object->FACTORY
2055              
2056             And it will return the string "MyApp". This allows for stuff like:
2057              
2058             class Person {
2059             method give_birth {
2060             return $self->FACTORY->new_person();
2061             }
2062             }
2063              
2064             =head3 The Type Library
2065              
2066             While building your classes and objects, MooX::Pression will also build
2067             type constraints for each of them. So for the "MyApp::Person" class
2068             above, it also builds a B<Person> type constraint. This can be used
2069             in Moo/Moose attribute definitions like:
2070              
2071             use MyApp;
2072             use MyApp::Types qw( Person );
2073            
2074             use Moose;
2075             has boss => (is => 'rw', isa => Person);
2076              
2077             And just anywhere a type constraint may be used generally. You should
2078             know this stuff by now.
2079              
2080             Note that we had to C<use MyApp> before we could C<use MyApp::Types>.
2081             This is because there isn't a physical "MyApp/Types.pm" file on disk;
2082             it is defined entirely by "MyApp.pm".
2083              
2084             Your type library will be the same as your namespace prefix, with
2085             "::Types" added at the end. But you can change that:
2086              
2087             use MooX::Pression (
2088             prefix => 'MyApp::Objects',
2089             factory_package => 'MyApp::Makers',
2090             type_library => 'MyApp::TypeLibrary',
2091             );
2092              
2093             It can sometimes be helpful to pre-warn MooX::Pression about the
2094             types you're going to define before you define them, just so it
2095             is able to allow them as barewords in some places...
2096              
2097             use MooX::Pression (
2098             prefix => 'MyApp::Objects',
2099             factory_package => 'MyApp::Makers',
2100             type_library => 'MyApp::TypeLibrary',
2101             declare => [qw( Person Company )],
2102             );
2103              
2104             See also L<Type::Tiny::Manual>.
2105              
2106             =head2 Keywords
2107              
2108             =head3 C<< class >>
2109              
2110             Define a very basic class:
2111              
2112             class Person;
2113              
2114             Define a more complicated class:
2115              
2116             class Person {
2117             ...;
2118             }
2119              
2120             Note that for the C<class> keyword without a block, it does I<not> act like
2121             the C<package> keyword by changing the "ambient" package. It just defines a
2122             totally empty class with no methods or attributes.
2123              
2124             The prefix will automatically be added to the class name, so if the prefix
2125             is MyApp, the above will create a class called MyApp::Person. It will also
2126             create a factory method C<< MyApp->new_person >>. (The name is generated by
2127             stripping the prefix from the class name, replacing any "::" with an
2128             underscore, lowercasing, and prefixing it with "new_".) And it will create
2129             a type called B<Person> in the type library. (Same rules to generate the
2130             name apart from lowercasing and adding "new_".)
2131              
2132             Classes can be given more complex names:
2133              
2134             class Person::Neanderthal {
2135             ...;
2136             }
2137              
2138             Will create "MyApp::Person::Neanderthal" class, a factory method called
2139             C<< MyApp->new_person_neanderthal >>, and a B<Person_Neanderthal> type.
2140              
2141             It is possible to create a class without the prefix:
2142              
2143             class ::Person {
2144             ...;
2145             }
2146              
2147             The class name will now be "Person" instead of "MyApp::Person"!
2148              
2149             =head4 Nested classes
2150              
2151             C<class> blocks can be nested. This establishes an inheritance heirarchy.
2152              
2153             class Animal {
2154             has name;
2155             class Mammal {
2156             class Primate {
2157             class Monkey;
2158             class Gorilla;
2159             class Human {
2160             class Superhuman;
2161             }
2162             }
2163             }
2164             class Bird;
2165             class Fish {
2166             class Shark;
2167             }
2168             }
2169            
2170             my $superman = MyApp->new_superhuman( name => 'Kal El' );
2171              
2172             See also C<extends> as an alternative way of declaring inheritance.
2173              
2174             It is possible to prefix a class name with a plus sign:
2175              
2176             package MyApp {
2177             use MooX::Pression;
2178             class Person {
2179             has name;
2180             class +Employee {
2181             has job_title;
2182             }
2183             }
2184             }
2185              
2186             Now the employee class will be named C<MyApp::Person::Employee> instead of
2187             the usual C<MyApp::Employee>.
2188              
2189             Classes can be declared as abstract:
2190              
2191             package MyApp {
2192             use MooX::Pression;
2193             abstract class Animal {
2194             class Cat;
2195             class Dog;
2196             }
2197             }
2198              
2199             For abstract classes, there is no constructor or factory, so you cannot create
2200             an Animal instance directly; but you can create instances of the subclasses.
2201             It is usually better to use roles than abstract classes, but sometimes the
2202             abstract class makes more intuitive sense.
2203              
2204             =head3 C<< role >>
2205              
2206             Define a very basic role:
2207              
2208             role Person;
2209              
2210             Define a more complicated role:
2211              
2212             role Person {
2213             ...;
2214             }
2215              
2216             This is just the same as C<class> but defines a role instead of a class.
2217              
2218             Roles cannot be nested within each other, nor can roles be nested in classes,
2219             nor classes in roles.
2220              
2221             =head3 C<< interface >>
2222              
2223             An interface is a lightweight role. It cannot define attributes, methods,
2224             multimethods, or method modifiers, but otherwise functions as a role.
2225             (It may have C<requires> statements and define constants.)
2226              
2227             package MyApp;
2228             use MooX::Pression;
2229            
2230             interface Serializer {
2231             requires serialize;
2232             }
2233            
2234             interface Deserializer {
2235             requires deserialize;
2236             }
2237            
2238             class MyJSON {
2239             with Serializer, Deserialize;
2240             method serialize ($value) { ... }
2241             method deserialize ($value) { ... }
2242             }
2243            
2244             my $obj = MyApp->new_myjson;
2245             $obj->does('MyApp::Serializer'); # true
2246              
2247             =head3 C<< toolkit >>
2248              
2249             Use a different toolkit instead of Moo.
2250              
2251             # use Mouse
2252             class Foo {
2253             toolkit Mouse;
2254             }
2255            
2256             # use Moose
2257             # use MooseX::Aliases
2258             # use MooseX::StrictConstructor
2259             class Bar {
2260             toolkit Moose ( Aliases, StrictConstructor );
2261             }
2262              
2263             You can of course specify you want to use Moo:
2264              
2265             class Baz {
2266             toolkit Moo;
2267             }
2268              
2269             Not all MooseX/MouseX/MooX packages will work, but *X::StrictConstructor will.
2270              
2271             Although it is not possible to use the C<toolkit> keyword outside of
2272             C<class>, C<abstract class>, C<role>, and C<interface> blocks, it is
2273             possible to specify a default toolkit when you import MooX::Pression.
2274              
2275             use MooX::Pression (
2276             ...,
2277             toolkit => 'Moose',
2278             );
2279              
2280             use MooX::Pression (
2281             ...,
2282             toolkit => 'Mouse',
2283             );
2284              
2285             =head3 C<< extends >>
2286              
2287             Defines a parent class. Only for use within C<class> and C<abstract class>
2288             blocks.
2289              
2290             class Person {
2291             extends Animal;
2292             }
2293              
2294             This works:
2295              
2296             class Person {
2297             extends ::Animal; # no prefix
2298             }
2299              
2300             =head3 C<< with >>
2301              
2302             Composes roles.
2303              
2304             class Person {
2305             with Employable, Consumer;
2306             }
2307            
2308             role Consumer;
2309            
2310             role Worker;
2311            
2312             role Payable;
2313            
2314             role Employable {
2315             with Worker, Payable;
2316             }
2317              
2318             Because roles are processed before classes, you can compose roles into classes
2319             where the role is defined later in the file. But if you compose one role into
2320             another, you must define them in a sensible order.
2321              
2322             It is possible to compose a role that does not exist by adding a question mark
2323             to the end of it:
2324              
2325             class Person {
2326             with Employable, Consumer?;
2327             }
2328            
2329             role Employable {
2330             with Worker?, Payable?;
2331             }
2332              
2333             This is equivalent to declaring an empty role.
2334              
2335             The C<with> keyword cannot be used outside of C<class>, C<abstract class>,
2336             C<role>, and C<interface> blocks.
2337              
2338             =head3 C<< begin >>
2339              
2340             This code gets run early on in the definition of a class or role.
2341              
2342             class Person {
2343             begin {
2344             say "Defining $package";
2345             }
2346             }
2347              
2348             At the time the code gets run, none of the class's attributes or methods will
2349             be defined yet.
2350              
2351             The lexical variables C<< $package >> and C<< $kind >> are defined within the
2352             block. C<< $kind >> will be either 'class' or 'role'.
2353              
2354             The C<begin> keyword cannot be used outside of C<class>, C<abstract class>,
2355             C<role>, and C<interface> blocks, though it is possible to define a global
2356             default for it:
2357              
2358             use MooX::Pression (
2359             ...,
2360             begin => sub {
2361             my ($package, $kind) = @_;
2362             ...;
2363             },
2364             );
2365              
2366             Per-package C<begin> overrides the global C<begin>.
2367              
2368             Unlike Perl's C<BEGIN> keyword, a package can only have one C<begin>.
2369              
2370             If C<class> definitions are nested, C<begin> blocks will be inherited by
2371             child classes. If a parent class is specified via C<extends>, C<begin>
2372             blocks will not be inherited.
2373              
2374             =head3 C<< end >>
2375              
2376             This code gets run late in the definition of a class or role.
2377              
2378             class Person {
2379             end {
2380             say "Finished defining $package";
2381             }
2382             }
2383              
2384             The lexical variables C<< $package >> and C<< $kind >> are defined within the
2385             block. C<< $kind >> will be either 'class' or 'role'.
2386              
2387             The C<end> keyword cannot be used outside of C<class>, C<abstract class>,
2388             C<role>, and C<interface> blocks, though it is possible to define a global
2389             default for it:
2390              
2391             use MooX::Pression (
2392             ...,
2393             end => sub {
2394             my ($package, $kind) = @_;
2395             ...;
2396             },
2397             );
2398              
2399             Per-package C<end> overrides the global C<end>.
2400              
2401             Unlike Perl's C<END> keyword, a package can only have one C<end>.
2402              
2403             If C<class> definitions are nested, C<end> blocks will be inherited by
2404             child classes. If a parent class is specified via C<extends>, C<end>
2405             blocks will not be inherited.
2406              
2407             =head3 C<< has >>
2408              
2409             Defines an attribute.
2410              
2411             class Person {
2412             has name;
2413             has age;
2414             }
2415            
2416             my $bob = MyApp->new_person(name => "Bob", age => 21);
2417              
2418             Cannot be used outside of C<class>, C<abstract class>, and C<role> blocks.
2419              
2420             Moo-style attribute specifications may be given:
2421              
2422             class Person {
2423             has name ( is => rw, type => Str, required => true );
2424             has age ( is => rw, type => Int );
2425             }
2426              
2427             Note there is no fat comma after the attribute name! It is a bareword.
2428              
2429             Use a plus sign before an attribute name to modify an attribute defined
2430             in a parent class.
2431              
2432             class Animal {
2433             has name ( type => Str, required => false );
2434            
2435             class Person {
2436             has +name ( required => true );
2437             }
2438             }
2439              
2440             C<rw>, C<rwp>, C<ro>, C<lazy>, C<bare>, C<true>, and C<false> are allowed as
2441             barewords for readability, but C<is> is optional, and defaults to C<rw>.
2442              
2443             Note C<type> instead of C<isa>. Any type constraints from L<Types::Standard>,
2444             L<Types::Common::Numeric>, and L<Types::Common::String> will be avaiable as
2445             barewords. Also, any pre-declared types can be used as barewords. It's
2446             possible to quote types as strings, in which case you don't need to have
2447             pre-declared them.
2448              
2449             class Person {
2450             has name ( type => Str, required => true );
2451             has age ( type => Int );
2452             has spouse ( type => 'Person' );
2453             has kids (
2454             is => lazy,
2455             type => 'ArrayRef[Person]',
2456             builder => sub { [] },
2457             );
2458             }
2459              
2460             Note that when C<type> is a string, MooX::Pression will consult your
2461             type library to figure out what it means.
2462              
2463             It is also possible to use C<< isa => 'SomeClass' >> or
2464             C<< does => 'SomeRole' >> to force strings to be treated as class names
2465             or role names instead of type names.
2466              
2467             class Person {
2468             has name ( type => Str, required => true );
2469             has age ( type => Int );
2470             has spouse ( isa => 'Person' );
2471             has pet ( isa => '::Animal' ); # no prefix
2472             }
2473              
2474             For enumerations, you can define them like this:
2475              
2476             class Person {
2477             ...;
2478             has status ( enum => ['alive', 'dead', 'undead'] );
2479             }
2480              
2481             MooX::Pression integrates support for L<MooX::Enumeration> (and
2482             L<MooseX::Enumeration>, but MouseX::Enumeration doesn't exist).
2483              
2484             class Person {
2485             ...;
2486             has status (
2487             enum => ['alive', 'dead', 'undead'],
2488             default => 'alive',
2489             handles => 1,
2490             );
2491             }
2492            
2493             my $bob = MyApp->new_person;
2494             if ( $bob->is_alive ) {
2495             ...;
2496             }
2497              
2498             C<< handles => 1 >> creates methods named C<is_alive>, C<is_dead>, and
2499             C<is_undead>, and C<< handles => 2 >> creates methods named
2500             C<status_is_alive>, C<status_is_dead>, and C<status_is_undead>.
2501              
2502             Checking C<< $bob->status eq 'alvie' >> is prone to typos, but
2503             C<< $bob->status_is_alvie >> will cause a runtime error because the
2504             method is not defined.
2505              
2506             MooX::Pression also integrates support for L<Sub::HandlesVia> allowing
2507             you to delegate certain methods to unblessed references and non-reference
2508             values. For example:
2509              
2510             class Person {
2511             has age (
2512             type => 'Int',
2513             default => 0,
2514             handles_via => 'Counter',
2515             handles => {
2516             birthday => 'inc', # increment age
2517             },
2518             );
2519             after birthday {
2520             if ($self->age < 30) {
2521             say "yay!";
2522             }
2523             else {
2524             say "urgh!";
2525             }
2526             }
2527             }
2528              
2529             A trailing C<< ! >> indicates a required attribute.
2530              
2531             class Person {
2532             has name!;
2533             }
2534              
2535             It is possible to give a default using an equals sign.
2536              
2537             class WidgetCollection {
2538             has name = "Widgets";
2539             has count (type => Num) = 0;
2540             }
2541              
2542             Note that the default comes after the spec, so in cases where the spec is
2543             long, it may be clearer to express the default inside the spec:
2544              
2545             class WidgetCollection {
2546             has name = "Widgets";
2547             has count (
2548             type => Num,
2549             lazy => true,
2550             required => false,
2551             default => 0,
2552             );
2553             }
2554              
2555             Defaults given this way will be eager (non-lazy), but can be made lazy using
2556             the spec:
2557              
2558             class WidgetCollection {
2559             has name = "Widgets";
2560             has count (is => lazy) = 0;
2561             }
2562              
2563             Defaults I<can> use the C<< $self >> object:
2564              
2565             class WidgetCollection {
2566             has name = "Widgets";
2567             has display_name = $self->name;
2568             }
2569              
2570             Any default that includes C<< $self >> will automatically be lazy, but can be
2571             made eager using the spec. (It is almost certainly a bad idea to do so though.)
2572              
2573             class WidgetCollection {
2574             has name = "Widgets";
2575             has display_name ( lazy => false ) = $self->name;
2576             }
2577              
2578             Commas may be used to separate multiple attributes:
2579              
2580             class WidgetCollection {
2581             has name, display_name ( type => Str );
2582             }
2583              
2584             The specification and defaults are applied to every attribute in the list.
2585              
2586             If you need to decide an attribute name on-the-fly, you can replace the
2587             name with a block that returns the name as a string.
2588              
2589             class Employee {
2590             extends Person;
2591             has {
2592             $ENV{LOCALE} eq 'GB'
2593             ? 'national_insurance_no'
2594             : 'social_security_no'
2595             } (type => Str)
2596             }
2597            
2598             my $bob = Employee->new(
2599             name => 'Bob',
2600             social_security_no => 1234,
2601             );
2602              
2603             You can think of the syntax as being kind of like C<print>.
2604              
2605             print BAREWORD_FILEHANDLE @strings;
2606             print { block_returning_filehandle(); } @strings;
2607              
2608             The block is called in scalar context, so you'll need a loop to define a list
2609             like this:
2610              
2611             class Person {
2612             my @attrs = qw( name age );
2613            
2614             # this does not work
2615             has {@attrs} ( required => true );
2616            
2617             # this works
2618             for my $attr (@attrs) {
2619             has {$attr} ( required => true );
2620             }
2621             }
2622              
2623             The names of attributes can start with an asterisk:
2624              
2625             has *foo;
2626              
2627             This adds no extra meaning, but is supported for consistency with the syntax
2628             of named parameters in method signatures. (Depending on your text editor, it
2629             may also improve syntax highlighting.)
2630              
2631             =head3 C<< constant >>
2632              
2633             Defines a constant.
2634              
2635             class Person {
2636             extends Animal;
2637             constant latin_name = 'Homo sapiens';
2638             }
2639              
2640             C<< MyApp::Person->latin_name >>, C<< MyApp::Person::latin_name >>, and
2641             C<< $person_object->latin_name >> will return 'Homo sapiens'.
2642              
2643             Outside of C<class>, C<abstract class>, C<role>, and C<interface> blocks,
2644             will define a constant in the caller package. (That is, usually the factory.)
2645              
2646             =head3 C<< method >>
2647              
2648             Defines a method.
2649              
2650             class Person {
2651             has spouse;
2652            
2653             method marry {
2654             my ($self, $partner) = @_;
2655             $self->spouse($partner);
2656             $partner->spouse($self);
2657             return $self;
2658             }
2659             }
2660              
2661             C<< sub { ... } >> will not work as a way to define methods within the
2662             class. Use C<< method { ... } >> instead.
2663              
2664             Outside of C<class>, C<abstract class>, C<role>, and C<interface> blocks,
2665             C<method> will define a method in the caller package. (Usually the factory.)
2666              
2667             The variables C<< $self >> and C<< $class >> will be automatically defined
2668             within all methods. C<< $self >> is set to C<< $_[0] >> (though the invocant
2669             is not shifted off C<< @_ >>). C<< $class >> is set to C<< ref($self)||$self >>.
2670             If the method is called as a class method, both C<< $self >> and C<< $class >>
2671             will be the same thing: the full class name as a string. If the method is
2672             called as an object method, C<< $self >> is the object and C<< $class >> is
2673             its class.
2674              
2675             Like with C<has>, you may use a block that returns a string instead of a
2676             bareword name for the method.
2677              
2678             method {"ma"."rry"} {
2679             ...;
2680             }
2681              
2682             MooX::Pression supports method signatures for named arguments and
2683             positional arguments. A mixture of named and positional arguments
2684             is allowed, with some limitations. For anything more complicates,
2685             you should define the method with no signature at all, and unpack
2686             C<< @_ >> within the body of the method.
2687              
2688             =head4 Signatures for Named Arguments
2689              
2690             class Person {
2691             has spouse;
2692            
2693             method marry ( Person *partner, Object *date = DateTime->now ) {
2694             $self->spouse( $arg->partner );
2695             $arg->partner->spouse( $self );
2696             return $self;
2697             }
2698             }
2699              
2700             The syntax for each named argument is:
2701              
2702             Type *name = default
2703              
2704             The type is a type name, which will be parsed using L<Type::Parser>.
2705             (So it can include the C<< ~ >>, C<< | >>, and C<< & >>, operators,
2706             and can include parameters in C<< [ ] >> brackets. Type::Parser can
2707             handle whitespace in the type, but not comments.
2708              
2709             Alternatively, you can provide a block which returns a type name as a string
2710             or returns a blessed Type::Tiny object. For very complex types, where you're
2711             expressing additional coercions or value constraints, this is probably what
2712             you want.
2713              
2714             The asterisk indicates that the argument is named, not positional.
2715              
2716             The name may be followed by a question mark to indicate an optional
2717             argument.
2718              
2719             method marry ( Person *partner, Object *date? ) {
2720             ...;
2721             }
2722              
2723             Or it may be followed by an equals sign to set a default value.
2724              
2725             Comments may be included in the signature, but not in the middle of
2726             a type constraint.
2727              
2728             method marry (
2729             # comment here is okay
2730             Person
2731             # comment here is fine too
2732             *partner
2733             # and here
2734             ) { ... }
2735              
2736             method marry (
2737             Person # comment here is not okay!
2738             | Horse
2739             *partner
2740             ) { ... }
2741              
2742             As with signature-free methods, C<< $self >> and C<< $class >> wll be
2743             defined for you in the body of the method. However, when a signature
2744             has been used C<< $self >> I<is> shifted off C<< @_ >>.
2745              
2746             Also within the body of the method, a variable called C<< $arg >>
2747             is provided. This is a hashref of the named arguments. So you can
2748             access the partner argument in the above example like this:
2749              
2750             $arg->{partner}
2751              
2752             But because C<< $arg >> is blessed, you can also do:
2753              
2754             $arg->partner
2755              
2756             The latter style is encouraged as it looks neater, plus it helps
2757             catch typos. (C<< $ars->{pratner} >> for example!) However, accessing
2758             it as a plain hashref is supported and shouldn't be considered to be
2759             breaking encapsulation.
2760              
2761             For optional arguments you can check:
2762              
2763             exists($arg->{date})
2764              
2765             Or:
2766              
2767             $arg->has_date
2768              
2769             For types which have a coercion defined, the value will be automatically
2770             coerced.
2771              
2772             Methods with named arguments can be called with a hash or hashref.
2773              
2774             $alice->marry( partner => $bob ); # okay
2775             $alice->marry({ partner => $bob }); # also okay
2776              
2777             =head4 Signatures for Positional Arguments
2778              
2779             method marry ( Person $partner, Object $date? ) {
2780             $self->spouse( $partner );
2781             $partner->spouse( $self );
2782             return $self;
2783             }
2784              
2785             The dollar sign is used instead of an asterisk to indicate a positional
2786             argument.
2787              
2788             As with named arguments, C<< $self >> is automatically shifted off C<< @_ >>
2789             and C<< $class >> exists. Unlike named arguments, there is no C<< $arg >>
2790             variable, and instead a scalar variable is defined for each named argument.
2791              
2792             Optional arguments and defaults are supported in the same way as named
2793             arguments.
2794              
2795             It is possible to include a slurpy hash or array at the end of the list
2796             of positional arguments.
2797              
2798             method marry ( $partner, $date, @vows ) {
2799             ...;
2800             }
2801              
2802             If you need to perform a type check on the slurpy parameter, you should
2803             pretend it is a hashref or arrayref.
2804              
2805             method marry ( $partner, $date, ArrayRef[Str] @vows ) {
2806             ...;
2807             }
2808              
2809             =head4 Signatures with Mixed Arguments
2810              
2811             Since MooX::Pression 0.200, you may mix named and positional arguments
2812             with the following limitations:
2813              
2814             =over
2815              
2816             =item *
2817              
2818             Positional arguments must appear at the beginning and/or end of the list.
2819             They cannot be surrounded by named arguments.
2820              
2821             =item *
2822              
2823             Positional arguments cannot be optional and cannot have a default. They
2824             must be required. (Named arguments can be optional and have defaults.)
2825              
2826             =item *
2827              
2828             No slurpies!
2829              
2830             =back
2831              
2832             method print_html ($tag, Str $text, *htmlver?, *xml?, $fh) {
2833            
2834             confess "update your HTML" if $arg->htmlver < 5;
2835            
2836             if (length $text) {
2837             print $fh "<tag>$text</tag>";
2838             }
2839             elsif ($arg->xml) {
2840             print $fh "<tag />";
2841             }
2842             else {
2843             print $fh "<tag></tag>";
2844             }
2845             }
2846            
2847             $obj->print_html('h1', 'Hello World', { xml => true }, \*STDOUT);
2848             $obj->print_html('h1', 'Hello World', xml => true , \*STDOUT);
2849             $obj->print_html('h1', 'Hello World', \*STDOUT);
2850              
2851             Mixed signatures are basically implemented like named signatures, but
2852             prior to interpreting C<< @_ >> as a hash, some parameters are spliced
2853             off the head and tail. We need to know how many elements to splice off
2854             each end, so that is why there are restrictions on slurpies and optional
2855             parameters.
2856              
2857             =head4 Empty Signatures
2858              
2859             There is a difference between the following two methods:
2860              
2861             method foo {
2862             ...;
2863             }
2864            
2865             method foo () {
2866             ...;
2867             }
2868              
2869             In the first, you have not provided a signature and are expected to
2870             deal with C<< @_ >> in the body of the method. In the second, there
2871             is a signature, but it is a signature showing that the method expects
2872             no arguments (other than the invocant of course).
2873              
2874             =head4 Optimizing Methods
2875              
2876             For a slight compiled-time penalty, you can improve the speed which
2877             methods run at using the C<< :optimize >> attribute:
2878              
2879             method foo :optimize (...) {
2880             ...;
2881             }
2882              
2883             Optimized methods must not close over any lexical (C<my> or C<our>)
2884             variables; they can only access the variables declared in their,
2885             signature, C<< $self >>, C<< $class >>, C<< @_ >>, and globals.
2886              
2887             =head4 Anonymous Methods
2888              
2889             It I<is> possible to use C<method> without a name to return an
2890             anonymous method (coderef):
2891              
2892             use MooX::Pression prefix => 'MyApp';
2893            
2894             class MyClass {
2895             method get_method ($foo) {
2896             method ($bar) {
2897             return $foo . $bar;
2898             }
2899             }
2900             }
2901            
2902             my $obj = MyApp->new_myclass;
2903             my $anon = $obj->get_method("FOO");
2904             say ref($anon); # CODE
2905             say $obj->$anon("BAR"); # FOOBAR
2906              
2907             Note that while C<< $anon >> is a coderef, it is still a method, and
2908             still expects to be passed an object as C<< $self >>.
2909              
2910             Due to limitations with L<Keyword::Simple>, keywords are always
2911             complete statements, so C<< method ... >> has an implicit semicolon
2912             before and after it. This means that this won't work:
2913              
2914             my $x = method { ... };
2915              
2916             Because it gets treated as:
2917              
2918             my $x = ;
2919             method { ... };
2920              
2921             A workaround is to wrap it in a C<< do { ... } >> block.
2922              
2923             my $x = do { method { ... } };
2924              
2925             =head4 Multimethods
2926              
2927             Multi methods should I<< Just Work [tm] >> if you prefix them with the
2928             keyword C<multi>
2929              
2930             use MooX::Pression prefix => 'MyApp';
2931            
2932             class Widget {
2933             multi method foo :alias(quux) (Any $x) {
2934             say "Buzz";
2935             }
2936             multi method foo (HashRef $h) {
2937             say "Fizz";
2938             }
2939             }
2940            
2941             my $thing = MyApp->new_widget;
2942             $thing->foo( {} ); # Fizz
2943             $thing->foo( 42 ); # Buzz
2944            
2945             $thing->quux( {} ); # Buzz
2946              
2947             This feature requires L<MooX::Press> 0.035 and L<Sub::MultiMethod> to be
2948             installed.
2949              
2950             Outside of C<class>, C<abstract class>, C<role>, and C<interface> blocks,
2951             C<multi method> will define a multi method in the caller package. (That is,
2952             usually the factory.)
2953              
2954             =head3 C<< requires >>
2955              
2956             Indicates that a role requires classes to fulfil certain methods.
2957              
2958             role Payable {
2959             requires account;
2960             requires deposit (Num $amount);
2961             }
2962            
2963             class Employee {
2964             extends Person;
2965             with Payable;
2966             has account!;
2967             method deposit (Num $amount) {
2968             ...;
2969             }
2970             }
2971              
2972             Required methods have an optional signature; this is usually ignored, but
2973             if L<Devel::StrictMode> determines that strict behaviour is being used,
2974             the signature will be applied to the method via an C<around> modifier.
2975              
2976             Or to put it another way, this:
2977              
2978             role Payable {
2979             requires account;
2980             requires deposit (Num $amount);
2981             }
2982              
2983             Is a shorthand for this:
2984              
2985             role Payable {
2986             requires account;
2987             requires deposit;
2988            
2989             use Devel::StrictMode 'STRICT';
2990             if (STRICT) {
2991             around deposit (Num $amount) {
2992             $self->$next(@_);
2993             }
2994             }
2995             }
2996              
2997             Can only be used in C<role> and C<interface> blocks.
2998              
2999             =head3 C<< before >>
3000              
3001             before marry {
3002             say "Speak now or forever hold your peace!";
3003             }
3004              
3005             As with C<method>, C<< $self >> and C<< $class >> are defined.
3006              
3007             As with C<method>, you can provide a signature:
3008              
3009             before marry ( Person $partner, Object $date? ) {
3010             say "Speak now or forever hold your peace!";
3011             }
3012              
3013             Note that this will result in the argument types being checked/coerced twice;
3014             once by the before method modifier and once by the method itself. Sometimes
3015             this may be desirable, but at other times your before method modifier might
3016             not care about the types of the arguments, so can omit checking them.
3017              
3018             before marry ( $partner, $date? ) {
3019             say "Speak now or forever hold your peace!";
3020             }
3021              
3022             Commas may be used to modify multiple methods:
3023              
3024             before marry, sky_dive (@args) {
3025             say "wish me luck!";
3026             }
3027              
3028             The C<< :optimize >> attribute is supported for C<before>.
3029              
3030             Method modifiers do work outside of C<class>, C<abstract class>, C<role>,
3031             and C<interface> blocks, modifying methods in the caller package, which is
3032             usually the factory package.
3033              
3034             =head3 C<< after >>
3035              
3036             There's not much to say about C<after>. It's just like C<before>.
3037              
3038             after marry {
3039             say "You may kiss the bride!";
3040             }
3041            
3042             after marry ( Person $partner, Object $date? ) {
3043             say "You may kiss the bride!";
3044             }
3045            
3046             after marry ( $partner, $date? ) {
3047             say "You may kiss the bride!";
3048             }
3049              
3050             Commas may be used to modify multiple methods:
3051              
3052             after marry, finished_school_year (@args) {
3053             $self->go_on_holiday();
3054             }
3055              
3056             The C<< :optimize >> attribute is supported for C<after>.
3057              
3058             Method modifiers do work outside of C<class>, C<abstract class>, C<role>,
3059             and C<interface> blocks, modifying methods in the caller package, which is
3060             usually the factory package.
3061              
3062             =head3 C<< around >>
3063              
3064             The C<around> method modifier is somewhat more interesting.
3065              
3066             around marry ( Person $partner, Object $date? ) {
3067             say "Speak now or forever hold your peace!";
3068             my $return = $self->$next(@_);
3069             say "You may kiss the bride!";
3070             return $return;
3071             }
3072              
3073             The C<< $next >> variable holds a coderef pointing to the "original" method
3074             that is being modified. This gives your method modifier the ability to munge
3075             the arguments seen by the "original" method, and munge any return values.
3076             (I say "original" in quote marks because it may not really be the original
3077             method but another wrapper!)
3078              
3079             C<< $next >> and C<< $self >> are both shifted off C<< @_ >>.
3080              
3081             If you use the signature-free version then C<< $next >> and C<< $self >>
3082             are not shifted off C<< @_ >> for you, but the variables are still defined.
3083              
3084             around marry {
3085             say "Speak now or forever hold your peace!";
3086             my $return = $self->$next($_[2], $_[3]);
3087             say "You may kiss the bride!";
3088             return $return;
3089             }
3090              
3091             Commas may be used to modify multiple methods:
3092              
3093             around insert, update ($dbh, @args) {
3094             $dbh->begin_transaction;
3095             my $return = $self->$next(@_);
3096             $dbh->commit_transaction;
3097             return $return;
3098             }
3099              
3100             The C<< :optimize >> attribute is supported for C<around>.
3101              
3102             Note that C<< SUPER:: >> won't work as expected in MooX::Pression, so
3103             C<around> should be used instead.
3104              
3105             Method modifiers do work outside of C<class>, C<abstract class>, C<role>,
3106             and C<interface> blocks, modifying methods in the caller package, which is
3107             usually the factory package.
3108              
3109             =head3 C<< factory >>
3110              
3111             The C<factory> keyword is used to define alternative constructors for
3112             your class.
3113              
3114             class Person {
3115             has name ( type => Str, required => true );
3116             has gender ( type => Str );
3117            
3118             factory new_man (Str $name) {
3119             return $class->new(name => $name, gender => 'male');
3120             }
3121            
3122             factory new_woman (Str $name) {
3123             return $class->new(name => $name, gender => 'female');
3124             }
3125             }
3126              
3127             But here's the twist. These methods are defined within the factory
3128             package, not within the class.
3129              
3130             So you can call:
3131              
3132             MyApp->new_man("Bob") # yes
3133              
3134             But not:
3135              
3136             MyApp::Person->new_man("Bob") # no
3137              
3138             Note that if your class defines I<any> factory methods like this, then the
3139             default factory method (in this case C<< MyApp->new_person >> will no longer
3140             be automatically created. But you can create the default one easily:
3141              
3142             class Person {
3143             has name ( type => Str, required => true );
3144             has gender ( type => Str );
3145            
3146             factory new_man (Str $name) { ... }
3147             factory new_woman (Str $name) { ... }
3148             factory new_person; # no method signature or body!
3149             }
3150              
3151             Within a factory method body, the variable C<< $class >> is defined, just
3152             like normal methods, but C<< $self >> is not defined. There is also a
3153             variable C<< $factory >> which is a string containing the factory
3154             package name. This is because you sometimes need to create more than
3155             just one object in a factory method.
3156              
3157             class Wheel;
3158            
3159             class Car {
3160             has wheels = [];
3161            
3162             factory new_three_wheeler () {
3163             return $class->new(
3164             wheels => [
3165             $factory->new_wheel,
3166             $factory->new_wheel,
3167             $factory->new_wheel,
3168             ]
3169             );
3170             }
3171            
3172             factory new_four_wheeler () {
3173             return $class->new(
3174             wheels => [
3175             $factory->new_wheel,
3176             $factory->new_wheel,
3177             $factory->new_wheel,
3178             $factory->new_wheel,
3179             ]
3180             );
3181             }
3182             }
3183              
3184             As with C<method> and the method modifiers, if you provide a signature,
3185             C<< $factory >> and C<< $class >> will be shifted off C<< @_ >>. If you
3186             don't provide a signature, the variables will be defined, but not shifted
3187             off C<< @_ >>.
3188              
3189             An alternative way to provide additional constructors is with C<method>
3190             and then use C<factory> to proxy them.
3191              
3192             class Person {
3193             has name ( type => Str, required => true );
3194             has gender ( type => Str );
3195            
3196             method new_guy (Str $name) { ... }
3197             method new_gal (Str $name) { ... }
3198            
3199             factory new_person;
3200             factory new_man via new_guy;
3201             factory new_woman via new_gal;
3202             }
3203              
3204             Now C<< MyApp->new_man >> will call C<< MyApp::Person->new_guy >>.
3205              
3206             C<< factory new_person >> with no C<via> or method body is basically
3207             like saying C<< via new >>.
3208              
3209             The C<< :optimize >> attribute is supported for C<factory>.
3210              
3211             The C<factory> keyword can only be used inside C<class> blocks.
3212              
3213             =head4 Implementing a singleton
3214              
3215             Factories make it pretty easy to implement a singleton.
3216              
3217             class AppConfig {
3218             ...;
3219            
3220             factory get_appconfig () {
3221             state $config = $class->new();
3222             }
3223             }
3224              
3225             Now C<< MyApp->get_appconfig >> will always return the same AppConfig object.
3226             Because any explicit use of the C<factory> keyword in a class definition
3227             suppresses the automatic creation of a factory method for the class, there
3228             will be no C<< MyApp->new_appconfig >> method for creating new objects
3229             of that class.
3230              
3231             (People can still manually call C<< MyApp::AppConfig->new >> to get a new
3232             AppConfig object, but remember MooX::Pression discourages calling constructors
3233             directly, and encourages you to use the factory package for instantiating
3234             objects!)
3235              
3236             =head3 C<< type_name >>
3237              
3238             class Homo::Sapiens {
3239             type_name Human;
3240             }
3241              
3242             The class will still be called L<MyApp::Homo::Sapiens> but the type in the
3243             type library will be called B<Human> instead of B<Homo_Sapiens>.
3244              
3245             Can only be used in C<class>, C<abstract class>, C<role>, and C<interface>
3246             blocks.
3247              
3248             =head3 C<< coerce >>
3249              
3250             class Person {
3251             has name ( type => Str, required => true );
3252             has gender ( type => Str );
3253            
3254             coerce from Str via from_string {
3255             $class->new(name => $_);
3256             }
3257             }
3258            
3259             class Company {
3260             has owner ( type => 'Person', required => true );
3261             }
3262            
3263             my $acme = MyApp->new_company( owner => "Bob" );
3264              
3265             Note that the company owner is supposed to be a person object, not a string,
3266             but the Person class knows how create a person object from a string.
3267              
3268             Coercions are automatically enabled in a lot of places for types that have
3269             a coercion. For example, types in signatures, and types in attribute
3270             definitions.
3271              
3272             Note that the coercion body doesn't allow signatures, and the value being
3273             coerced will be found in C<< $_ >>. If you want to have signatures, you
3274             can define a coercion as a normal method first:
3275              
3276             class Person {
3277             has name ( type => Str, required => true );
3278             has gender ( type => Str );
3279            
3280             method from_string ( Str $name ) {
3281             $class->new(name => $name);
3282             }
3283            
3284             coerce from Str via from_string;
3285             }
3286              
3287             In both cases, a C<< MyApp::Person->from_string >> method is generated
3288             which can be called to manually coerce a string into a person object.
3289              
3290             They keyword C<< from >> is technically optional, but does make the
3291             statement more readable.
3292              
3293             coerce Str via from_string { # this works
3294             $class->new(name => $_);
3295             }
3296              
3297             The C<< :optimize >> attribute is not currently supported for C<coerce>.
3298              
3299             Can only be used in C<class> blocks.
3300              
3301             =head3 C<< overload >>
3302              
3303             class Collection {
3304             has items = [];
3305             overload '@{}' => sub { shift->list };
3306             }
3307              
3308             The list passed to C<overload> is passed to L<overload> with no other
3309             processing.
3310              
3311             Can only be used in C<class> blocks.
3312              
3313             =head3 C<< version >>
3314              
3315             class Person {
3316             version 1.0;
3317             }
3318              
3319             This just sets C<< $MyApp::Person::VERSION >>.
3320              
3321             Can only be used in C<class>, C<abstract class>, C<role>, and C<interface>
3322             blocks.
3323              
3324             You can set a default version for all packages like this:
3325              
3326             use MooX::Pression (
3327             ...,
3328             version => 1.0,
3329             );
3330              
3331             If C<class> definitions are nested, C<version> will be inherited by
3332             child classes. If a parent class is specified via C<extends>, C<version>
3333             will not be inherited.
3334              
3335             =head3 C<< authority >>
3336              
3337             class Person {
3338             authority 'cpan:TOBYINK';
3339             }
3340              
3341             This just sets C<< $MyApp::Person::AUTHORITY >>.
3342              
3343             It is used to indicate who is the maintainer of the package.
3344              
3345             Can only be used in C<class>, C<abstract class>, C<role>, and C<interface>
3346             blocks.
3347              
3348             use MooX::Pression (
3349             ...,
3350             version => 1.0,
3351             authority => 'cpan:TOBYINK',
3352             );
3353              
3354             If C<class> definitions are nested, C<authority> will be inherited by
3355             child classes. If a parent class is specified via C<extends>, C<authority>
3356             will not be inherited.
3357              
3358             =head3 C<< include >>
3359              
3360             C<include> is the MooX::Pression equivalent of Perl's C<require>.
3361              
3362             package MyApp {
3363             use MooX::Pression;
3364             include Database;
3365             include Classes;
3366             include Roles;
3367             }
3368              
3369             It works somewhat more crudely than C<require> and C<use>, evaluating
3370             the included file pretty much as if it had been copy and pasted into the
3371             file that included it.
3372              
3373             The names of the files to load are processsed using the same rules for
3374             prefixes as classes and roles (so MyApp::Database, etc in the example),
3375             and C<< @INC >> is searched just like C<require> and C<use> do, but
3376             instead of looking for a file called "MyApp/Database.pm", MooX::Pression
3377             will look for "MyApp/Database.pl" (yes, ".pl"). This naming convention
3378             ensures people won't accidentally load MyApp::Database using C<use>
3379             or C<require> because it isn't intended to be loaded outside the context
3380             of the MyApp package.
3381              
3382             The file "MyApp/Database.pl" might look something like this:
3383              
3384             class Database {
3385             has dbh = DBI->connect(...);
3386            
3387             factory get_db {
3388             state $instance = $class->new;
3389             }
3390             }
3391              
3392             Note that it doesn't start with a C<package> statement, nor
3393             C<use MooX::Pression>. It's just straight on to the definitions.
3394             There's no C<< 1; >> needed at the end.
3395              
3396             C<< use strict >> and C<< use warnings >> are safe to put in the
3397             file if you need them to satisfy linters, but they're not necessary
3398             because the contents of the file are evaluated as if they had been
3399             copied and pasted into the main MyApp module.
3400              
3401             There are I<no> checks to prevent a file from being included more than
3402             once, and there are I<no> checks to deal with cyclical inclusions.
3403              
3404             Inclusions are currently only supported at the top level, and not within
3405             class and role definitions.
3406              
3407             =head3 C<< MooX::Pression::PACKAGE_SPEC() >>
3408              
3409             This function can be used while a class or role is being compiled to
3410             tweak the specification for the class/role.
3411              
3412             class Foo {
3413             has foo;
3414             MooX::Pression::PACKAGE_SPEC->{has}{foo}{type} = Int;
3415             }
3416              
3417             It returns a hashref of attributes, methods, etc. L<MooX::Press> should
3418             give you an idea about how the hashref is structured, but MooX::Pression
3419             only supports a subset of what MooX::Press supports. For example, MooX::Press
3420             allows C<has> to be an arrayref or a hashref, but MooX::Pression only supports
3421             a hashref. The exact subset that MooX::Pression supports is subject to change
3422             without notice.
3423              
3424             This can be used to access MooX::Press features that MooX::Pression doesn't
3425             expose.
3426              
3427             =head2 Helper Subs
3428              
3429             Earlier it was stated that C<sub> cannot be used to define methods in
3430             classes and roles. This is true, but that doesn't mean that it has no
3431             use.
3432              
3433             package MyApp {
3434             use MooX::Pression;
3435            
3436             sub helper_function { ... }
3437            
3438             class Foo {
3439             method foo {
3440             ...;
3441             helper_function(...);
3442             ...;
3443             }
3444             }
3445            
3446             class Bar {
3447             sub other_helper { ... }
3448             method bar {
3449             ...;
3450             helper_function(...);
3451             other_helper(...);
3452             ...;
3453             }
3454             }
3455             }
3456              
3457             The subs defined by C<sub> end up in the "MyApp" package, not
3458             "MyApp::Foo" or "MyApp::Bar". They can be called by any of the classes
3459             and roles defined in MyApp. This makes them suitable for helper subs
3460             like logging, L<List::Util>/L<Scalar::Util> sorts of functions, and
3461             so on.
3462              
3463             package MyApp {
3464             use MooX::Pression;
3465            
3466             use List::Util qw( any all first reduce );
3467             # the above functions are now available within
3468             # all of MyApp's classes and roles, but won't
3469             # pollute any of their namespaces.
3470            
3471             use namespace::clean;
3472             # And now they won't even pollute MyApp's namespace.
3473             # Though I'm pretty sure this will also stop them
3474             # from working in any methods that used ":optimize".
3475            
3476             class Foo { ... }
3477             role Bar { ... }
3478             role Baz { ... }
3479             }
3480              
3481             C<sub> is also usually your best option for those tiny little
3482             coderefs that need to be defined here and there:
3483              
3484             has foo (
3485             is => lazy,
3486             type => ArrayRef[Str],
3487             builder => sub { [] },
3488             );
3489              
3490             Though consider using L<Sub::Quote> if you're using Moo.
3491              
3492             =head2 Utilities
3493              
3494             MooX::Pression also exports constants C<true> and C<false> into your
3495             namespace. These show clearer boolean intent in code than using 1 and 0.
3496              
3497             MooX::Pression exports C<rw>, C<ro>, C<rwp>, and C<lazy> constants
3498             which make your attribute specs a little cleaner looking.
3499              
3500             MooX::Pression exports C<blessed> from L<Scalar::Util> because that can
3501             be handy to have, and C<confess> from L<Carp>. MooX::Pression's copy
3502             of C<confess> is super-powered and runs its arguments through C<sprintf>.
3503              
3504             before vote {
3505             if ($self->age < 18) {
3506             confess("Can't vote, only %d", $self->age);
3507             }
3508             }
3509              
3510             MooX::Pression turns on strict, warnings, and the following modern Perl
3511             features:
3512              
3513             # Perl 5.14 and Perl 5.16
3514             say state unicode_strings
3515            
3516             # Perl 5.18 or above
3517             say state unicode_strings unicode_eval evalbytes current_sub fc
3518              
3519             If you're wondering why not other features, it's because I didn't want to
3520             enable any that are currently classed as experimental, nor any that require
3521             a version of Perl above 5.18. The C<switch> feature is mostly seen as a
3522             failed experiment these days, and C<lexical_subs> cannot be called as methods
3523             so are less useful in object-oriented code.
3524              
3525             You can, of course, turn on extra features yourself.
3526              
3527             package MyApp {
3528             use MooX::Pression;
3529             use feature qw( lexical_subs postderef );
3530            
3531             ...;
3532             }
3533              
3534             (The C<current_sub> feature is unlikely to work fully unless you
3535             have C<:optimize> switched on for that method, or the method does not
3536             include a signature. For non-optimized methods with a signature, a
3537             wrapper is installed that handles checks, coercions, and defaults.
3538             C<< __SUB__ >> will point to the "inner" sub, minus the wrapper.)
3539              
3540             MooX::Pression exports L<Syntax::Keyword::Try> for you. Useful to have.
3541              
3542             And last but not least, it exports all the types, C<< is_* >> functions,
3543             and C<< assert_* >> functions from L<Types::Standard>,
3544             L<Types::Common::String>, and L<Types::Common::Numeric>.
3545              
3546             =head2 Anonymous Classes and Roles
3547              
3548             =head3 Anonymous classes
3549              
3550             It is possible to make anonymous classes:
3551              
3552             my $class = do { class; };
3553             my $object = $class->new;
3554              
3555             The C<< do { ... } >> block is necessary because of a limitation in
3556             L<Keyword::Simple>, where any keywords it defines must be complete
3557             statements.
3558              
3559             Anonymous classes can have methods and attributes and so on:
3560              
3561             my $class = do { class {
3562             has foo (type => Int);
3563             has bar (type => Int);
3564             }};
3565            
3566             my $object = $class->new(foo => 1, bar => 2);
3567              
3568             Anonymous classes I<do not> implicitly inherit from their parent like
3569             named nested classes do. Named classes nested inside anonymous classes
3570             I<do not> implicitly inherit from the anonymous class.
3571              
3572             Having one anonymous class inherit from another can be done though:
3573              
3574             my $base = do { class; }
3575             my $derived = do { class {
3576             extends {"::$k1"};
3577             }};
3578              
3579             This works because C<extends> accepts a block which returns a string for
3580             the package name, and the string needs to begin with "::" to avoid the
3581             auto prefix mechanism.
3582              
3583             =head3 Anonymous roles
3584              
3585             Anonymous roles work in much the same way.
3586              
3587             =head2 Parameterizable Classes and Roles
3588              
3589             =head3 Parameterizable classes
3590              
3591             package MyApp {
3592             use MooX::Pression;
3593            
3594             class Animal {
3595             has name;
3596             }
3597            
3598             class Species ( Str $common_name, Str $binomial ) {
3599             extends Animal;
3600             constant common_name = $common_name;
3601             constant binomial = $binomial;
3602             }
3603            
3604             class Dog {
3605             extends Species('dog', 'Canis familiaris');
3606             method bark () {
3607             say "woof!";
3608             }
3609             }
3610             }
3611              
3612             Here, "MyApp::Species" isn't a class in the usual sense; you cannot create
3613             instances of it. It's like a template for generating classes. Then
3614             "MyApp::Dog" generates a class from the template and inherits from that.
3615              
3616             my $Cat = MyApp->generate_species('cat', 'Felis catus');
3617             my $mog = $Cat->new(name => 'Mog');
3618            
3619             $mog->isa('MyApp::Animal'); # true
3620             $mog->isa('MyApp::Species'); # false!!!
3621             $mog->isa($Cat); # true
3622              
3623             Because there are never any instances of "MyApp::Species", it doesn't
3624             make sense to have a B<Species> type constraint. Instead there are
3625             B<SpeciesClass> and B<SpeciesInstance> type constraints.
3626              
3627             use MyApp::Types -is;
3628            
3629             my $lassie = MyApp->new_dog;
3630            
3631             is_Animal( $lassie ); # true
3632             is_Dog( $lassie ); # true
3633             is_SpeciesInstance( $lassie ); # true
3634             is_SpeciesClass( ref($lassie) ); # true
3635              
3636             Subclasses cannot be nested inside parameterizable classes, but
3637             parameterizable classes can be nested inside regular classes, in
3638             which case the classes they generate will inherit from the outer
3639             class.
3640              
3641             package MyApp {
3642             use MooX::Pression;
3643            
3644             class Animal {
3645             has name;
3646             class Species ( Str $common_name, Str $binomial ) {
3647             constant common_name = $common_name;
3648             constant binomial = $binomial;
3649             }
3650             }
3651            
3652             class Dog {
3653             extends Species('dog', 'Canis familiaris');
3654             method bark () {
3655             say "woof!";
3656             }
3657             }
3658             }
3659              
3660             Anonymous parameterizable classes are possible:
3661              
3662             my $generator = do { class ($footype, $bartype) {
3663             has foo (type => $footype);
3664             has bar (type => $bartype);
3665             };
3666            
3667             my $class = $generator->generate_package(Int, Num);
3668            
3669             my $object = $class->new(foo => 42, bar => 4.2);
3670              
3671             =head3 Parameterizable roles
3672              
3673             Often it makes more sense to parameterize roles than classes.
3674              
3675             package MyApp {
3676             use MooX::Pression;
3677            
3678             class Animal {
3679             has name;
3680             }
3681            
3682             role Species ( Str $common_name, Str $binomial ) {
3683             constant common_name = $common_name;
3684             constant binomial = $binomial;
3685             }
3686            
3687             class Dog {
3688             extends Animal;
3689             with Species('dog', 'Canis familiaris'), GoodBoi?;
3690             method bark () {
3691             say "woof!";
3692             }
3693             }
3694             }
3695              
3696             Anonymous parameterizable roles are possible.
3697              
3698             =head2 MooX::Pression vs Moops
3699              
3700             MooX::Pression has fewer dependencies than Moops, and crucially doesn't
3701             rely on L<Package::Keyword> and L<Devel::CallParser> which have... issues.
3702             MooX::Pression uses Damian Conway's excellent L<PPR> to handle most parsing
3703             needs, so parsing should be more predictable.
3704              
3705             Moops is faster though.
3706              
3707             Here are a few key syntax and feature differences.
3708              
3709             =head3 Declaring a class
3710              
3711             Moops:
3712              
3713             class Foo::Bar 1.0 extends Foo with Bar {
3714             ...;
3715             }
3716              
3717             MooX::Pression:
3718              
3719             class Foo::Bar {
3720             version 1.0;
3721             extends Foo;
3722             with Bar;
3723             }
3724              
3725             Moops and MooX::Pression use different logic for determining whether a class
3726             name is "absolute" or "relative". In Moops, classes containing a "::" are seen
3727             as absolute class names; in MooX::Pression, only classes I<starting with> "::"
3728             are taken to be absolute; all others are given the prefix.
3729              
3730             Moops:
3731              
3732             package MyApp {
3733             use Moops;
3734             class Foo {
3735             class Bar {
3736             class Baz {
3737             # Nesting class blocks establishes a naming
3738             # heirarchy so this is MyApp::Foo::Bar::Baz!
3739             }
3740             }
3741             }
3742             }
3743              
3744             MooX::Pression:
3745              
3746             package MyApp {
3747             use MooX::Pression;
3748             class Foo {
3749             class Bar {
3750             class Baz {
3751             # This is only MyApp::Baz, but nesting
3752             # establishes an @ISA chain instead.
3753             }
3754             }
3755             }
3756             }
3757              
3758             =head3 How namespacing works
3759              
3760             Moops:
3761              
3762             use feature 'say';
3763             package MyApp {
3764             use Moops;
3765             use List::Util qw(uniq);
3766             class Foo {
3767             say __PACKAGE__; # MyApp::Foo
3768             say for uniq(1,2,1,3); # ERROR!
3769             sub foo { ... } # MyApp::Foo::foo()
3770             }
3771             }
3772              
3773             MooX::Pression:
3774              
3775             use feature 'say';
3776             package MyApp {
3777             use MooX::Pression;
3778             use List::Util qw(uniq);
3779             class Foo {
3780             say __PACKAGE__; # MyApp
3781             say for uniq(1,2,1,3); # this works fine
3782             sub foo { ... } # MyApp::foo()
3783             }
3784             }
3785              
3786             This is why you can't use C<sub> to define methods in MooX::Pression.
3787             You need to use the C<method> keyword. In MooX::Pression, all the code
3788             in the class definition block is still executing in the parent
3789             package's namespace!
3790              
3791             =head3 Multimethods
3792              
3793             Moops/Kavorka multimethods are faster, but MooX::Pression is smarter at
3794             picking the best candidate to dispatch to, and intelligently selecting
3795             candidates across inheritance hierarchies and role compositions.
3796              
3797             =head3 Other crazy Kavorka features
3798              
3799             Kavorka allows you to mark certain parameters as read-only or aliases,
3800             allows you to specify multiple names for named parameters, allows you
3801             to rename the invocant, allows you to give methods and parameters
3802             attributes, allows you to specify a method's return type, etc, etc.
3803              
3804             MooX::Pression's C<method> keyword is unlikely to ever offer as many
3805             features as that. It is unlikely to offer many more features than it
3806             currently offers.
3807              
3808             If you need fine-grained control over how C<< @_ >> is handled, just
3809             don't use a signature and unpack C<< @_ >> inside your method body
3810             however you need to.
3811              
3812             =head3 Lexical accessors
3813              
3814             Moops automatically imported C<lexical_has> from L<Lexical::Accessor>
3815             into each class. MooX::Pression does not, but thanks to how namespacing
3816             works, it only needs to be imported once if you want to use it.
3817              
3818             package MyApp {
3819             use MooX::Pression;
3820             use Lexical::Accessor;
3821            
3822             class Foo {
3823             my $identifier = lexical_has identifier => (
3824             is => rw,
3825             isa => Int,
3826             default => sub { 0 },
3827             );
3828            
3829             method some_method () {
3830             $self->$identifier( 123 ); # set identifier
3831             ...;
3832             return $self->$identifier; # get identifier
3833             }
3834             }
3835             }
3836              
3837             Lexical accessors give you true private object attributes.
3838              
3839             =head3 Factories
3840              
3841             MooX::Pression puts an emphasis on having a factory package for instantiating
3842             objects. Moops didn't have anything similar.
3843              
3844             =head3 C<augment> and C<override>
3845              
3846             These are L<Moose> method modifiers that are not implemented by L<Moo>.
3847             Moops allows you to use these in Moose and Mouse classes, but not Moo
3848             classes. MooX::Pression simply doesn't support them.
3849              
3850             =head3 Type Libraries
3851              
3852             Moops allowed you to declare multiple type libraries, define type
3853             constraints in each, and specify for each class and role which type
3854             libraries you want it to use.
3855              
3856             MooX::Pression automatically creates a single type library for all
3857             your classes and roles within a module to use, and automatically
3858             populates it with the types it thinks you might want.
3859              
3860             If you need to use other type constraints:
3861              
3862             package MyApp {
3863             use MooX::Pression;
3864             # Just import types into the factory package!
3865             use Types::Path::Tiny qw( Path );
3866            
3867             class DataSource {
3868             has file => ( type => Path );
3869            
3870             method set_file ( Path $file ) {
3871             $self->file( $file );
3872             }
3873             }
3874             }
3875            
3876             my $ds = MyApp->new_datasource;
3877             $ds->set_file('blah.txt'); # coerce Str to Path
3878             print $ds->file->slurp_utf8;
3879              
3880             =head3 Constants
3881              
3882             Moops:
3883              
3884             class Foo {
3885             define PI = 3.2;
3886             }
3887              
3888             MooX::Pression:
3889              
3890             class Foo {
3891             constant PI = 3.2;
3892             }
3893              
3894             =head3 Parameterizable classes and roles
3895              
3896             These were always on my todo list for Moops; I doubt they'll ever be done.
3897             They work nicely in MooX::Pression though.
3898              
3899             =head1 BUGS
3900              
3901             Please report any bugs to
3902             L<http://rt.cpan.org/Dist/Display.html?Queue=MooX-Pression>.
3903              
3904             =head1 TODO
3905              
3906             =head2 Plugin system
3907              
3908             MooX::Pression can often load MooX/MouseX/MooseX plugins and work
3909             fine with them, but some things won't work, like plugins that rely on
3910             being able to wrap C<has>. So it would be nice to have a plugin system
3911             that extensions can hook into.
3912              
3913             If you're interested in extending MooX::Pression, file a bug report about
3914             it and let's have a conversation about the best way for that to happen.
3915              
3916             =head1 SEE ALSO
3917              
3918             Less magic version:
3919             L<MooX::Press>, L<portable::loader>.
3920              
3921             Important underlying technologies:
3922             L<Moo>, L<Type::Tiny::Manual>.
3923              
3924             Similar modules:
3925             L<Moops>, L<Kavorka>, L<Dios>, L<MooseX::Declare>.
3926              
3927             =head1 AUTHOR
3928              
3929             Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
3930              
3931             =head1 COPYRIGHT AND LICENCE
3932              
3933             This software is copyright (c) 2020 by Toby Inkster.
3934              
3935             This is free software; you can redistribute it and/or modify it under
3936             the same terms as the Perl 5 programming language system itself.
3937              
3938             =head1 DISCLAIMER OF WARRANTIES
3939              
3940             THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
3941             WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
3942             MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
3943