line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Keyword::Declare; |
2
|
|
|
|
|
|
|
our $VERSION = '0.001017'; |
3
|
|
|
|
|
|
|
|
4
|
19
|
|
|
19
|
|
1227551
|
use 5.012; # required for pluggable keywords plus /.../r |
|
19
|
|
|
|
|
214
|
|
5
|
19
|
|
|
19
|
|
107
|
use warnings; |
|
19
|
|
|
|
|
39
|
|
|
19
|
|
|
|
|
569
|
|
6
|
19
|
|
|
19
|
|
102
|
use Carp; |
|
19
|
|
|
|
|
37
|
|
|
19
|
|
|
|
|
1658
|
|
7
|
19
|
|
|
19
|
|
144
|
use List::Util 1.45 'max', 'uniqstr'; |
|
19
|
|
|
|
|
440
|
|
|
19
|
|
|
|
|
2231
|
|
8
|
|
|
|
|
|
|
|
9
|
19
|
|
|
19
|
|
6891
|
use Keyword::Simple; |
|
19
|
|
|
|
|
355744
|
|
|
19
|
|
|
|
|
686
|
|
10
|
19
|
|
|
19
|
|
13883
|
use PPR; |
|
19
|
|
|
|
|
773446
|
|
|
19
|
|
|
|
|
5083
|
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
my $NESTING_THRESHOLD = 100; # How many nested keyword expansions is probably too many? |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
my $TYPE_JUNCTION = qr{ [^\W\d] \w*+ (?: [|] [^\W\d] \w*+ )*+ }x; # How to match a TypeA|TypeB type |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
my @keyword_impls; # Tracks all keyword information in every scope |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
sub import { |
19
|
19
|
|
|
19
|
|
299
|
my (undef, $opt_ref) = @_; |
20
|
19
|
|
50
|
|
|
211
|
$opt_ref //= {}; |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
# Don't allow bad arguments to be passed when the module is loaded... |
23
|
19
|
|
|
|
|
67
|
my $arg_type = ref($opt_ref); |
24
|
19
|
50
|
33
|
|
|
196
|
if (@_ > 2 || $arg_type ne 'HASH') { |
25
|
0
|
|
0
|
|
|
0
|
$arg_type ||= $opt_ref; |
26
|
0
|
|
|
|
|
0
|
croak "Invalid option for: use Keyword::Declare.\n", |
27
|
|
|
|
|
|
|
"Expected single hash reference, but found $arg_type instead.\n", |
28
|
|
|
|
|
|
|
"Error detected"; |
29
|
|
|
|
|
|
|
} |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# If debugging requested, set in on for the caller's lexical scope... |
32
|
19
|
50
|
|
|
|
93
|
if ($opt_ref->{debug}) { |
33
|
0
|
|
|
|
|
0
|
${^H}{'Keyword::Declare debug'} = !!$opt_ref->{debug}; |
34
|
|
|
|
|
|
|
} |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
# Install replacement __DATA__ handler... |
37
|
|
|
|
|
|
|
# [REMOVE IF UPSTREAM MODULE (Keyword::Simple) FIXED] |
38
|
19
|
|
|
|
|
84
|
_install_data_handler(); |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
# Install the 'keytype' (meta-)keyword... |
41
|
|
|
|
|
|
|
Keyword::Simple::define 'keytype', sub { |
42
|
|
|
|
|
|
|
# Unpack trailing code... |
43
|
10
|
|
|
10
|
|
711
|
my ($src_ref) = @_; |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
# Where was this keyword declared??? |
46
|
10
|
|
|
|
|
62
|
my ($file, $line) = (caller)[1,2]; |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
# These track error messages and help decompose the parameter list... |
49
|
|
|
|
|
|
|
# (they have to be package vars, so they're visible to in-regex code blocks in older Perls) |
50
|
10
|
|
|
|
|
78
|
our ($expected, $failed_at, $block_start, @params) = ('new type name', 0, 0); |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
# Match and extract the keyword definition... |
53
|
19
|
|
|
19
|
|
403
|
use re 'eval'; |
|
19
|
|
|
|
|
57
|
|
|
19
|
|
|
|
|
11820
|
|
54
|
10
|
50
|
|
|
|
357024
|
$$src_ref =~ s{ |
55
|
|
|
|
|
|
|
\A |
56
|
|
|
|
|
|
|
(? |
57
|
|
|
|
|
|
|
(?&PerlNWS) |
58
|
10
|
|
|
|
|
66
|
(?{ $expected = "new type name"; $failed_at = pos() }) |
|
10
|
|
|
|
|
203
|
|
59
|
|
|
|
|
|
|
(? \$?+ ) |
60
|
|
|
|
|
|
|
(? (?&PerlIdentifier) ) |
61
|
|
|
|
|
|
|
(?&PerlOWS) |
62
|
10
|
|
|
|
|
32
|
(?{ $expected = "'is '"; $failed_at = pos() }) |
|
10
|
|
|
|
|
100
|
|
63
|
|
|
|
|
|
|
is |
64
|
|
|
|
|
|
|
(?&PerlOWS) |
65
|
10
|
|
|
|
|
21
|
(?{ $expected = "existing typename or literal string or regex after 'is'"; $failed_at = pos() }) |
|
10
|
|
|
|
|
542
|
|
66
|
|
|
|
|
|
|
(? |
67
|
|
|
|
|
|
|
(? (?&PerlMatch) ) |
68
|
|
|
|
|
|
|
| |
69
|
|
|
|
|
|
|
(? (?&PerlString) ) |
70
|
|
|
|
|
|
|
| |
71
|
|
|
|
|
|
|
(? $TYPE_JUNCTION ) |
72
|
|
|
|
|
|
|
) |
73
|
|
|
|
|
|
|
) |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
$PPR::GRAMMAR |
76
|
|
|
|
|
|
|
}{}xms |
77
|
|
|
|
|
|
|
or croak "Invalid keytype definition. Expected $expected\nbut found: ", |
78
|
|
|
|
|
|
|
substr($$src_ref, $failed_at) =~ /(\S+)/; |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
# Save the information from the keyword definition... |
81
|
10
|
|
|
|
|
3646
|
my %keytype_info = ( %+, location => "$file line $line", hashline => "$line $file" ); |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
# Set up the sigil... |
84
|
10
|
|
|
|
|
55
|
my $sigil_decl = q{}; |
85
|
10
|
100
|
|
|
|
49
|
if ($keytype_info{typesigil}) { |
86
|
3
|
|
|
|
|
14
|
my $var = qq{$keytype_info{typesigil}$keytype_info{newtype}}; |
87
|
3
|
100
|
|
|
|
19
|
if ($keytype_info{oldtyperegex}) { |
|
|
50
|
|
|
|
|
|
88
|
2
|
|
|
|
|
12
|
$keytype_info{oldtyperegex} =~ s{^m}{}; |
89
|
2
|
100
|
|
|
|
18
|
if ($keytype_info{oldtyperegex} =~ /\(\?\&Perl[A-Z]/) { |
90
|
1
|
|
|
|
|
11
|
$keytype_info{oldtyperegex} =~ s{^\s*(\S)}{$1\$PPR::GRAMMAR}; |
91
|
|
|
|
|
|
|
} |
92
|
2
|
|
|
|
|
14
|
$sigil_decl = qq{my $var; BEGIN { $var = qr$keytype_info{oldtyperegex} }} |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
elsif ($keytype_info{oldtypestring}) { |
95
|
1
|
|
|
|
|
6
|
$sigil_decl = qq{my $var; BEGIN { $var = $keytype_info{oldtypestring} }} |
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
else { |
98
|
0
|
|
|
|
|
0
|
croak "Invalid keytype definition. Can only specify a sigil on new typename ($keytype_info{typesigil}$keytype_info{newtype}) if type is specified as a string or regex"; |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
# Debug, if requested... |
103
|
10
|
50
|
|
|
|
49
|
if (${^H}{"Keyword::Declare debug"}) { |
104
|
0
|
|
|
|
|
0
|
my $msg = ("#" x 50) . "\n" |
105
|
|
|
|
|
|
|
. " Installed keytype at $keytype_info{location}:\n\n$keytype_info{syntax}\n\n" |
106
|
|
|
|
|
|
|
. ("#" x 50) . "\n"; |
107
|
0
|
|
|
|
|
0
|
$msg =~ s{^}{###}gm; |
108
|
0
|
|
|
|
|
0
|
warn $msg; |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
# Install the lexical type definition... |
112
|
10
|
|
|
|
|
1397
|
$$src_ref |
113
|
|
|
|
|
|
|
= qq{BEGIN{\$^H{q{Keyword::Declare keytype:$keytype_info{newtype}=$keytype_info{oldtype}}} = 1;}} |
114
|
|
|
|
|
|
|
. $sigil_decl |
115
|
|
|
|
|
|
|
. $$src_ref; |
116
|
19
|
|
|
|
|
220
|
}; |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
# Install the 'keyword' (meta-)keyword... |
119
|
|
|
|
|
|
|
Keyword::Simple::define 'keyword', sub { |
120
|
|
|
|
|
|
|
# Unpack trailing code... |
121
|
157
|
|
|
157
|
|
36753
|
my ($src_ref) = @_; |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
# Where was this keyword declared??? |
124
|
157
|
|
|
|
|
758
|
my ($file, $line) = (caller)[1,2]; |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
# Which keywords are allowed in nested code at this point... |
127
|
157
|
|
|
|
|
1412
|
my @active_IDs = @^H{ grep { m{^ Keyword::Declare \s+ active:}xms } keys %^H }; |
|
5832
|
|
|
|
|
14238
|
|
128
|
|
|
|
|
|
|
my $lexical_keywords |
129
|
157
|
100
|
|
|
|
837
|
= @active_IDs ? join '|', reverse sort map { $keyword_impls[$_]{skip_matcher} } @active_IDs |
|
5642
|
|
|
|
|
12561
|
|
130
|
|
|
|
|
|
|
: '(?!)'; |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
# These track error messages and help decompose the parameter list... |
133
|
|
|
|
|
|
|
# (they have to be package vars, so they're visible to in-regex code blocks in older Perls) |
134
|
157
|
|
|
|
|
726
|
our ($expected, $failed_at, $block_start, @params) = ('keyword name', 0, 0); |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
# Match and extract the keyword definition... |
137
|
19
|
|
|
19
|
|
160
|
use re 'eval'; |
|
19
|
|
|
|
|
45
|
|
|
19
|
|
|
|
|
14160
|
|
138
|
157
|
50
|
|
|
|
5909440
|
$$src_ref =~ s{ |
139
|
|
|
|
|
|
|
\A |
140
|
|
|
|
|
|
|
(?<____K_D___KeywordDeclaration> |
141
|
|
|
|
|
|
|
(?&PerlNWS) |
142
|
|
|
|
|
|
|
(?<____K_D___keyword> (?&PerlIdentifier) ) |
143
|
|
|
|
|
|
|
(?&PerlOWS) |
144
|
157
|
|
|
|
|
1103
|
(?{ $expected = "keyword parameters or block, or 'from' specifier"; $failed_at = pos() }) |
|
157
|
|
|
|
|
1852
|
|
145
|
|
|
|
|
|
|
(?<____K_D___params> (?&____K_D___ParamList) ) |
146
|
|
|
|
|
|
|
(?&PerlOWS) |
147
|
157
|
|
|
|
|
753
|
(?{ $expected = 'keyword block or attribute'; $failed_at = pos() }) |
|
157
|
|
|
|
|
1584
|
|
148
|
|
|
|
|
|
|
(?<____K_D___attrs> (?&PerlAttributes)?+ ) |
149
|
|
|
|
|
|
|
(?&PerlOWS) |
150
|
157
|
|
|
|
|
272
|
(?{ $expected = 'keyword block'; $failed_at = $block_start = pos() }) |
|
157
|
|
|
|
|
16361
|
|
151
|
|
|
|
|
|
|
(?<____K_D___block> \{\{\{ .*? \}\}\} | (?&PerlBlock) ) |
152
|
|
|
|
|
|
|
) |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
(?(DEFINE) |
155
|
|
|
|
|
|
|
(?<____K_D___ParamList> |
156
|
|
|
|
|
|
|
\( |
157
|
|
|
|
|
|
|
(?&____K_D___ParamSet)?+ |
158
|
|
|
|
|
|
|
(?: |
159
|
|
|
|
|
|
|
(?&PerlOWS) \) (?&PerlOWS) :then\( |
160
|
1
|
|
|
|
|
13
|
(?{ push @Keyword::Declare::params, undef; }) |
161
|
|
|
|
|
|
|
(?&____K_D___ParamSet) |
162
|
|
|
|
|
|
|
)?+ |
163
|
|
|
|
|
|
|
\) |
164
|
|
|
|
|
|
|
| |
165
|
|
|
|
|
|
|
# Nothing |
166
|
|
|
|
|
|
|
) |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
(?<____K_D___ParamSet> |
169
|
|
|
|
|
|
|
(?&PerlOWS) (?&____K_D___Param) |
170
|
|
|
|
|
|
|
(?: (?&PerlOWS) , (?&PerlOWS) (?&____K_D___Param) )*+ |
171
|
|
|
|
|
|
|
,?+ (?&PerlOWS) |
172
|
|
|
|
|
|
|
) |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
(?<____K_D___Param> |
175
|
180
|
|
|
|
|
406
|
(?{ $expected = 'keyword parameter type'; $failed_at = pos() }) |
|
180
|
|
|
|
|
1925
|
|
176
|
|
|
|
|
|
|
(?<____K_D___type> (?&PerlMatch) | (?&PerlString) | $TYPE_JUNCTION ) |
177
|
|
|
|
|
|
|
|
178
|
176
|
|
|
|
|
355
|
(?{ $expected = 'keyword parameter quantifier or variable'; $failed_at = pos() }) |
|
176
|
|
|
|
|
2745
|
|
179
|
|
|
|
|
|
|
(?: (?&PerlOWS) (?<____K_D___quantifier> [?*+][?+]?+ ) )?+ |
180
|
|
|
|
|
|
|
|
181
|
176
|
|
|
|
|
332
|
(?{ $expected = 'keyword parameter variable'; $failed_at = pos() }) |
|
176
|
|
|
|
|
4633
|
|
182
|
|
|
|
|
|
|
(?: (?&PerlOWS) (?<____K_D___sigil> [\$\@] ) |
183
|
|
|
|
|
|
|
(?<____K_D___name> (?&PerlIdentifier) ) )?+ |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
(?: (?&PerlOWS) :sep \( |
186
|
2
|
|
|
|
|
4
|
(?{ $expected = 'keyword parameter separator :sep'; $failed_at = pos() }) |
|
2
|
|
|
|
|
68
|
|
187
|
|
|
|
|
|
|
(?&PerlOWS) (?<____K_D___sep> (?&PerlMatch) | (?&PerlString) | $TYPE_JUNCTION ) |
188
|
|
|
|
|
|
|
(?&PerlOWS) \) |
189
|
|
|
|
|
|
|
)?+ |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
(?: (?&PerlOWS) = |
192
|
0
|
|
|
|
|
0
|
(?{ $expected = 'keyword parameter default string after ='; $failed_at = pos() }) |
|
0
|
|
|
|
|
0
|
|
193
|
|
|
|
|
|
|
(?&PerlOWS) (?<____K_D___default> (?&PerlQuotelikeQ) ) )?+ |
194
|
|
|
|
|
|
|
|
195
|
176
|
|
|
|
|
13400
|
(?{ push @Keyword::Declare::params, { %+ } }) |
196
|
|
|
|
|
|
|
) |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
(? |
200
|
|
|
|
|
|
|
keyword (?&____K_D___KeywordDeclaration) |
201
|
|
|
|
|
|
|
| |
202
|
|
|
|
|
|
|
$lexical_keywords |
203
|
|
|
|
|
|
|
) |
204
|
|
|
|
|
|
|
) |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
$PPR::GRAMMAR |
207
|
|
|
|
|
|
|
}{}xms |
208
|
|
|
|
|
|
|
or croak "Invalid keyword definition. Expected $expected\nbut found: ", |
209
|
|
|
|
|
|
|
substr($$src_ref, $failed_at) =~ /(\S+)/; |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
# Save the information from the keyword definition.. |
212
|
157
|
|
|
|
|
41931
|
@Keyword::Declare::params = map { _deprefix($_) } @Keyword::Declare::params; |
|
177
|
|
|
|
|
783
|
|
213
|
157
|
|
|
|
|
4387
|
my %keyword_info = %+; |
214
|
157
|
|
|
|
|
544
|
%keyword_info = ( %{ _deprefix(\%keyword_info) }, |
215
|
|
|
|
|
|
|
desc => $keyword_info{____K_D___keyword}, |
216
|
157
|
|
|
|
|
732
|
param_list => [ @Keyword::Declare::params], |
217
|
|
|
|
|
|
|
location => "$file line $line", |
218
|
|
|
|
|
|
|
hashline => "$line $file", |
219
|
|
|
|
|
|
|
); |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
# Check for excessive meta-ness... |
222
|
157
|
50
|
|
|
|
935
|
if ($keyword_info{keyword} =~ /^(?:keyword|keytype)$/) { |
223
|
0
|
|
|
|
|
0
|
croak "Can't redefine '$keyword_info{keyword}' keyword"; |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
# Remember where the block started... |
227
|
|
|
|
|
|
|
my $block_location |
228
|
157
|
|
|
|
|
989
|
= ($line + substr($keyword_info{KeywordDeclaration}, 0, $block_start) =~ tr/\n//) . " $file"; |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
# Convert any {{{...}}} block... |
231
|
157
|
100
|
|
|
|
543
|
if ($keyword_info{block} =~ m{ \A \{\{\{ }xms) { |
232
|
23
|
|
|
|
|
109
|
$keyword_info{block} = _convert_triple_block(\%keyword_info); |
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
# Extract and verify any attributes... |
236
|
157
|
|
|
|
|
605
|
_unpack_attrs(\%keyword_info); |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
# Extract various useful components from the parameter list... |
239
|
157
|
|
|
|
|
555
|
_unpack_signature(\%keyword_info); |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
# Prepare for a trailing #line directive to keep trailing line numbers straight... |
242
|
157
|
|
|
|
|
534
|
$line += $keyword_info{KeywordDeclaration} =~ tr/\n//; |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
# Record the keyword definition... |
245
|
157
|
|
|
|
|
478
|
my $keyword_ID = $keyword_info{ID} = @keyword_impls; |
246
|
157
|
|
|
|
|
370
|
push @keyword_impls, \%keyword_info; |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
# Create the keyword dispatching function... |
249
|
157
|
|
|
|
|
481
|
my $keyword_defn = _build_keyword_code(\%keyword_info); |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
# Report installation of keyword if requested... |
252
|
157
|
50
|
|
|
|
523
|
if (${^H}{"Keyword::Declare debug"}) { |
253
|
0
|
|
|
|
|
0
|
my $msg = ("#" x 50) . "\n" |
254
|
|
|
|
|
|
|
. " Installed keyword macro at $keyword_info{location}:\n\n$keyword_info{syntax}\n\n" |
255
|
|
|
|
|
|
|
. ("#" x 50) . "\n"; |
256
|
0
|
|
|
|
|
0
|
$msg =~ s{^}{###}gm; |
257
|
0
|
|
|
|
|
0
|
warn $msg; |
258
|
|
|
|
|
|
|
} |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
# Install the keyword, exporting it as well if it's in an import() or unimport() sub... |
261
|
157
|
|
|
|
|
1618
|
$$src_ref = qq{ if (((caller 0)[3]//q{}) =~ /\\b(?:un)?import\\Z/) { $keyword_defn } } |
262
|
|
|
|
|
|
|
. q{ Keyword::Declare::_install_data_handler(); } |
263
|
|
|
|
|
|
|
. qq{ BEGIN{ $keyword_defn } } |
264
|
|
|
|
|
|
|
. "\n#line $line $file\n" |
265
|
|
|
|
|
|
|
. $$src_ref; |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
# Pre-empt addition of extraneous trailing newline by Keyword::Simple... |
268
|
|
|
|
|
|
|
# [REMOVE IF UPSTREAM MODULE (Keyword::Simple) IS FIXED] |
269
|
157
|
|
|
|
|
87311
|
$$src_ref =~ s{\n\z}{}; |
270
|
19
|
|
|
|
|
670
|
}; |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
# Install the 'unkeyword' (anti-meta-)keyword... |
273
|
|
|
|
|
|
|
Keyword::Simple::define 'unkeyword', sub { |
274
|
|
|
|
|
|
|
# Unpack trailing code... |
275
|
1
|
|
|
1
|
|
7
|
my ($src_ref) = @_; |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
# Where was this keyword declared??? |
278
|
1
|
|
|
|
|
9
|
my ($file, $line) = (caller)[1,2]; |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
# Match and extract the keyword definition... |
281
|
19
|
|
|
19
|
|
173
|
use re 'eval'; |
|
19
|
|
|
|
|
56
|
|
|
19
|
|
|
|
|
9553
|
|
282
|
1
|
|
|
|
|
34241
|
$$src_ref =~ s{ |
283
|
|
|
|
|
|
|
\A |
284
|
|
|
|
|
|
|
(? (?&PerlNWS) ) |
285
|
|
|
|
|
|
|
(?: |
286
|
|
|
|
|
|
|
(? (?&PerlIdentifier) ) |
287
|
|
|
|
|
|
|
| |
288
|
|
|
|
|
|
|
(? \S+ ) |
289
|
|
|
|
|
|
|
) |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
$PPR::GRAMMAR |
292
|
|
|
|
|
|
|
}{}xms; |
293
|
|
|
|
|
|
|
|
294
|
1
|
|
|
|
|
107
|
my %keyword_info = %+; |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
croak "Invalid unkeyword definition. Expected keyword name (identifier)\n" |
297
|
|
|
|
|
|
|
. " but found: $keyword_info{unexpected}" |
298
|
1
|
50
|
|
|
|
8
|
if defined $keyword_info{unexpected}; |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
# Check for excessive meta-ness... |
301
|
1
|
50
|
|
|
|
7
|
if ($keyword_info{keyword} =~ /^(?:keyword|keytype)$/) { |
302
|
0
|
|
|
|
|
0
|
croak "Can't undefine '$keyword_info{keyword}' keyword"; |
303
|
|
|
|
|
|
|
} |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
# Report installation of keyword if requested... |
306
|
1
|
50
|
|
|
|
6
|
if (${^H}{"Keyword::Declare debug"}) { |
307
|
0
|
|
|
|
|
0
|
my $msg = ("#" x 50) . "\n" |
308
|
|
|
|
|
|
|
. " Uninstalled keyword macro: $keyword_info{keyword}(...)\n" |
309
|
|
|
|
|
|
|
. " at $file line $line\n" |
310
|
|
|
|
|
|
|
. ("#" x 50) . "\n"; |
311
|
0
|
|
|
|
|
0
|
$msg =~ s{^}{###}gm; |
312
|
0
|
|
|
|
|
0
|
warn $msg; |
313
|
|
|
|
|
|
|
} |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
# How to remove the Keyword::Simple keyword (with workaround for earlier versions)... |
316
|
1
|
|
|
|
|
3
|
my $keyword_defn = q{Keyword::Simple::undefine( 'KEYWORD' );}; |
317
|
1
|
50
|
|
|
|
5
|
if ($Keyword::Simple::VERSION < 0.04) { |
318
|
0
|
|
|
|
|
0
|
$keyword_defn .= "\$^H{'Keyword::Simple/keywords'} =~ s{ KEYWORD:-?\\d*}{}g;" ; |
319
|
|
|
|
|
|
|
} |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
# How to remove the Keyword::Declare keywords... |
322
|
1
|
|
|
|
|
5
|
$keyword_defn .= q{ |
323
|
|
|
|
|
|
|
delete @^H{ grep m{^ Keyword::Declare \s+ active:KEYWORD:}xms, keys %^H }; |
324
|
|
|
|
|
|
|
}; |
325
|
1
|
|
|
|
|
10
|
$keyword_defn =~ s{KEYWORD}{$keyword_info{keyword}}g; |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
# Uninstall the keyword, exporting it as well if it's in an import() or unimport() sub... |
328
|
1
|
|
|
|
|
316
|
$$src_ref = qq{ if (((caller 0)[3]//q{}) =~ /\\b(?:un)?import\\Z/) { $keyword_defn } } |
329
|
|
|
|
|
|
|
. qq{ BEGIN{ $keyword_defn } } |
330
|
|
|
|
|
|
|
. "\n#line $line $file\n" |
331
|
|
|
|
|
|
|
. $$src_ref; |
332
|
19
|
|
|
|
|
498
|
}; |
333
|
|
|
|
|
|
|
} |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
# Keyword::Simple::define() has a bug: it can't define keywords starting with _ |
336
|
|
|
|
|
|
|
# [REMOVE WHEN UPSTREAM MODULE (Keyword::Simple) IS FIXED] |
337
|
|
|
|
|
|
|
sub _replacement_define { |
338
|
|
|
|
|
|
|
package Keyword::Simple; |
339
|
|
|
|
|
|
|
|
340
|
334
|
|
|
334
|
|
796
|
my ($kw, $sub) = @_; |
341
|
334
|
50
|
|
|
|
1799
|
$kw =~ /^[^\W\d]\w*\z/ or croak "'$kw' doesn't look like an identifier"; |
342
|
334
|
50
|
|
|
|
1027
|
ref($sub) eq 'CODE' or croak "'$sub' doesn't look like a coderef"; |
343
|
|
|
|
|
|
|
|
344
|
334
|
50
|
|
|
|
983
|
if ($Keyword::Simple::VERSION < 0.04) { |
345
|
0
|
|
|
|
|
0
|
our @meta; |
346
|
0
|
|
|
|
|
0
|
my $n = @meta; |
347
|
0
|
|
|
|
|
0
|
push @meta, $sub; |
348
|
|
|
|
|
|
|
|
349
|
0
|
|
|
|
|
0
|
$^H{+HINTK_KEYWORDS} .= " $kw:$n"; |
350
|
19
|
|
|
19
|
|
9620
|
use B::Hooks::EndOfScope; |
|
19
|
|
|
|
|
207307
|
|
|
19
|
|
|
|
|
136
|
|
351
|
|
|
|
|
|
|
on_scope_end { |
352
|
0
|
|
|
0
|
|
0
|
delete $meta[$n]; |
353
|
0
|
|
|
|
|
0
|
}; |
354
|
|
|
|
|
|
|
} |
355
|
|
|
|
|
|
|
else { |
356
|
334
|
|
100
|
|
|
493
|
my %keywords = %{$^H{+HINTK_KEYWORDS} // {}}; |
|
334
|
|
|
|
|
1928
|
|
357
|
334
|
|
|
|
|
886
|
$keywords{$kw} = $sub; |
358
|
334
|
|
|
|
|
8356
|
$^H{+HINTK_KEYWORDS} = \%keywords; |
359
|
|
|
|
|
|
|
} |
360
|
|
|
|
|
|
|
} |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
# Install a __DATA__ keyword to overcome bug in Keyword::Simple... |
363
|
|
|
|
|
|
|
# [REMOVE WHEN UPSTREAM MODULE (Keyword::Simple) IS FIXED] |
364
|
|
|
|
|
|
|
sub _install_data_handler { |
365
|
|
|
|
|
|
|
my $DATA_HANDLER = sub { |
366
|
|
|
|
|
|
|
# Unpack trailing code... |
367
|
1
|
|
|
1
|
|
6
|
my ($src_ref) = @_; |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
# Convert to data handle... |
370
|
1
|
|
|
|
|
3
|
my $data = $$src_ref; |
371
|
1
|
|
|
|
|
14
|
$data =~ s{ \A [^\n]* \n }{}xms; |
372
|
1
|
50
|
|
|
|
8
|
$data .= "\n" unless substr($data,-1) eq "\n"; |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
# Create end-of-__DATA__ marker unlikely to be in the data... |
375
|
1
|
|
|
|
|
4
|
my $END_DATA = "\3" x 253; # \3 is ASCII END-OF-TEXT, 253 is max ident length |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
# Replace trailing code with code that opens a local *DATA handle... |
378
|
1
|
|
|
|
|
52
|
$$src_ref = qq{BEGIN {open *DATA, '<', \\<<'$END_DATA'\n$data$END_DATA\n} 1; }; |
379
|
176
|
|
|
176
|
|
25743
|
}; |
380
|
176
|
|
|
|
|
437
|
_replacement_define('__DATA__', $DATA_HANDLER); |
381
|
|
|
|
|
|
|
} |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
# Remove special prefix on names of internal named captures... |
385
|
|
|
|
|
|
|
sub _deprefix { |
386
|
334
|
|
|
334
|
|
748
|
my ($hash_ref) = @_; |
387
|
|
|
|
|
|
|
|
388
|
334
|
100
|
|
|
|
849
|
return undef if !defined $hash_ref; |
389
|
1488
|
|
|
|
|
2530
|
return { map { my $key = $_; $key =~ s{^____K_D___}{}; $key => $hash_ref->{$_} } |
|
1488
|
|
|
|
|
4621
|
|
|
1488
|
|
|
|
|
9549
|
|
390
|
333
|
|
|
|
|
464
|
keys %{$hash_ref} }; |
|
333
|
|
|
|
|
1311
|
|
391
|
|
|
|
|
|
|
} |
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
# Generate the source code that actually installs a keyword... |
395
|
|
|
|
|
|
|
sub _build_keyword_code { |
396
|
|
|
|
|
|
|
my ($keyword_name, $keyword_sig, $keyword_ID, $keyword_block, $block_location, $block_hashline, $prefix_var) |
397
|
157
|
|
|
157
|
|
297
|
= @{shift()}{qw< keyword sig_desc ID block location hashline prefix >}; |
|
157
|
|
|
|
|
779
|
|
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
# Generate the keyword definition and set up its unique lexical ID... |
400
|
157
|
|
|
|
|
1258
|
return qq{ |
401
|
|
|
|
|
|
|
\$^H{"Keyword::Declare active:$keyword_name:\Q$keyword_sig\E"} = $keyword_ID; |
402
|
|
|
|
|
|
|
Keyword::Declare::_replacement_define('$keyword_name', Keyword::Declare::_get_dispatcher_for('$keyword_name', |
403
|
|
|
|
|
|
|
$keyword_ID, sub |
404
|
|
|
|
|
|
|
#line $block_hashline |
405
|
|
|
|
|
|
|
{ $keyword_impls[$keyword_ID]{sig_vars_unpack} do $keyword_block })); |
406
|
|
|
|
|
|
|
}; |
407
|
|
|
|
|
|
|
} |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
# Locate prefix code for keyword... |
410
|
|
|
|
|
|
|
sub _get_prefix { |
411
|
0
|
|
|
0
|
|
0
|
state $source_cache = {}; |
412
|
|
|
|
|
|
|
|
413
|
0
|
|
|
|
|
0
|
my ($trail_ref, $keyword) = @_; |
414
|
|
|
|
|
|
|
|
415
|
0
|
|
|
|
|
0
|
my $filename = (caller 2)[1]; |
416
|
0
|
|
0
|
|
|
0
|
my $source = $source_cache->{$filename} //= do { local (*ARGV, $/); @ARGV=$filename; <> }; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
417
|
|
|
|
|
|
|
|
418
|
0
|
|
|
|
|
0
|
my $trailing = $$trail_ref; |
419
|
0
|
|
|
|
|
0
|
$trailing =~ s/\s+\z//; |
420
|
0
|
|
|
|
|
0
|
$source =~ s{\b$keyword\s*\Q$trailing\E\s*\z}{}; |
421
|
|
|
|
|
|
|
|
422
|
0
|
|
|
|
|
0
|
return 'qq{' . quotemeta($source) . '}'; |
423
|
|
|
|
|
|
|
} |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
# Install keyword's source-code generator, and return a dispatcher sub for that keyword |
427
|
|
|
|
|
|
|
# (building a closure for it, if necessary)... |
428
|
|
|
|
|
|
|
sub _get_dispatcher_for { |
429
|
158
|
|
|
158
|
|
2500
|
my ($keyword_name, $keyword_ID, $keyword_generator) = @_; |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
# Install the keyword generator sub... |
432
|
158
|
|
|
|
|
496
|
$keyword_impls[$keyword_ID]{generator} = $keyword_generator; |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
# This will dispatch any keyword of the specified name... |
435
|
158
|
|
|
|
|
259
|
state %dispatcher_for; |
436
|
|
|
|
|
|
|
return $dispatcher_for{$keyword_name} //= sub { |
437
|
76
|
|
|
76
|
|
576
|
my ($src_ref) = @_; |
438
|
76
|
|
|
|
|
405
|
my ($package, $file, $line) = caller; |
439
|
76
|
|
|
|
|
213
|
local $PPR::ERROR; |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
# Which variants of this keyword are currently in scope??? |
442
|
76
|
|
|
|
|
402
|
my @candidate_IDs = @^H{ grep { m{^ Keyword::Declare \s+ active:$keyword_name:}xms } keys %^H }; |
|
409
|
|
|
|
|
2450
|
|
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
# Which keywords are allowed in nested code at this point... |
445
|
76
|
|
|
|
|
326
|
my @active_IDs = @^H{ grep { m{^ Keyword::Declare \s+ active:}xms } keys %^H }; |
|
409
|
|
|
|
|
1327
|
|
446
|
|
|
|
|
|
|
my $lexical_keywords |
447
|
76
|
50
|
|
|
|
386
|
= @active_IDs ? join '|', reverse sort map { $keyword_impls[$_]{skip_matcher} } @active_IDs |
|
297
|
|
|
|
|
1356
|
|
448
|
|
|
|
|
|
|
: '(?!)'; |
449
|
76
|
|
|
|
|
353
|
$lexical_keywords = "(?(DEFINE) (? $lexical_keywords ) )"; |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
# Which of them match the keyword's actual arguments??? |
452
|
|
|
|
|
|
|
my @viable_IDs |
453
|
76
|
|
|
|
|
193
|
= grep { $$src_ref =~ m{ \A $keyword_impls[$_]{sig_matcher} $lexical_keywords $PPR::GRAMMAR }xms } |
|
143
|
|
|
|
|
4979123
|
|
454
|
|
|
|
|
|
|
@candidate_IDs; |
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
# If none of them match...game over!!! |
458
|
76
|
50
|
|
|
|
14411
|
if (!@viable_IDs) { |
459
|
|
|
|
|
|
|
my $error = eval "no strict;sub{\n" . ($PPR::ERROR//q{}) . '}' |
460
|
|
|
|
|
|
|
? " $keyword_name " |
461
|
0
|
|
|
|
|
0
|
. do{ my $src = $$src_ref; |
462
|
0
|
|
|
|
|
0
|
$src =~ s{ \A \s*+ (\S++ [^\n]*+) \n .* }{$1}xs; |
463
|
0
|
|
|
|
|
0
|
$src; |
464
|
|
|
|
|
|
|
} |
465
|
0
|
0
|
0
|
|
|
0
|
: do{ my $err = $@; |
|
0
|
|
|
|
|
0
|
|
466
|
0
|
|
|
|
|
0
|
$err =~ s{^}{ }gm; |
467
|
0
|
|
|
|
|
0
|
$err =~ s{\(eval \d++\) line \d++} |
|
0
|
|
|
|
|
0
|
|
468
|
0
|
|
|
|
|
0
|
{ "$file line " . $PPR::ERROR->line($line) }eg; |
469
|
|
|
|
|
|
|
$err |
470
|
|
|
|
|
|
|
}; |
471
|
0
|
|
|
|
|
0
|
croak "Invalid " |
472
|
|
|
|
|
|
|
. join(" or ", uniqstr map { $keyword_impls[$_]{desc} } @candidate_IDs) |
473
|
0
|
|
|
|
|
0
|
. " at $file line $line.\nExpected:" |
|
0
|
|
|
|
|
0
|
|
474
|
|
|
|
|
|
|
. join("\n ", q{}, uniqstr map { $keyword_impls[$_]{syntax} } @candidate_IDs) |
475
|
|
|
|
|
|
|
. "\nbut found:\n$error" |
476
|
|
|
|
|
|
|
. "\nCompilation failed"; |
477
|
|
|
|
|
|
|
} |
478
|
|
|
|
|
|
|
|
479
|
76
|
100
|
|
|
|
394
|
# If too many of them match...see if we can reduce it to a single match... |
480
|
|
|
|
|
|
|
if (@viable_IDs > 1) { |
481
|
23
|
|
|
|
|
106
|
# Only keep those with the most parameters... |
|
58
|
|
|
|
|
327
|
|
482
|
23
|
|
|
|
|
79
|
my $max_sig_len = max map { $keyword_impls[$_]{sig_len} } @viable_IDs; |
|
58
|
|
|
|
|
197
|
|
483
|
|
|
|
|
|
|
@viable_IDs = grep { $keyword_impls[$_]{sig_len} == $max_sig_len } @viable_IDs; |
484
|
|
|
|
|
|
|
|
485
|
23
|
100
|
|
|
|
90
|
# Resolve ambiguous matches, if possible... |
486
|
3
|
|
|
|
|
21
|
if (@viable_IDs > 1) { |
487
|
|
|
|
|
|
|
@viable_IDs = _resolve_matches(@viable_IDs); |
488
|
|
|
|
|
|
|
} |
489
|
|
|
|
|
|
|
|
490
|
23
|
100
|
|
|
|
92
|
# If still too many, see if one is marked :prefer... |
491
|
1
|
50
|
|
|
|
3
|
if (@viable_IDs > 1) { |
|
3
|
|
|
|
|
11
|
|
492
|
1
|
|
|
|
|
3
|
if (my @preferred_IDs = grep { $keyword_impls[$_]{prefer} } @viable_IDs) { |
493
|
|
|
|
|
|
|
@viable_IDs = @preferred_IDs; |
494
|
|
|
|
|
|
|
} |
495
|
|
|
|
|
|
|
} |
496
|
|
|
|
|
|
|
|
497
|
23
|
50
|
|
|
|
93
|
# If still too many, give up and report the ambiguity... |
498
|
|
|
|
|
|
|
if (@viable_IDs > 1) { |
499
|
0
|
|
|
|
|
0
|
croak "Ambiguous " |
500
|
|
|
|
|
|
|
. join(" or ", uniqstr map { $keyword_impls[$_]{desc} } @viable_IDs) |
501
|
0
|
|
|
|
|
0
|
. " at $file line $line:\n $keyword_name " |
502
|
0
|
|
|
|
|
0
|
. do{ my $src = $$src_ref; |
503
|
0
|
|
|
|
|
0
|
$src =~ s{ \A \s*+ ( \S++ [^\n]*+) \n .* }{$1}xs; |
504
|
|
|
|
|
|
|
$src; |
505
|
|
|
|
|
|
|
} |
506
|
0
|
|
|
|
|
0
|
. "\nCould be:\n" |
|
0
|
|
|
|
|
0
|
|
507
|
|
|
|
|
|
|
. join("\n", map { " $keyword_impls[$_]{syntax}" } @viable_IDs) |
508
|
|
|
|
|
|
|
. "\nCompilation failed"; |
509
|
|
|
|
|
|
|
} |
510
|
|
|
|
|
|
|
} |
511
|
|
|
|
|
|
|
|
512
|
76
|
|
|
|
|
328
|
# If we get here, we have a unique best candidate, so install it... |
513
|
|
|
|
|
|
|
my ($ID) = @viable_IDs; |
514
|
|
|
|
|
|
|
|
515
|
76
|
|
|
|
|
440
|
# Add in the replacement code... |
516
|
|
|
|
|
|
|
_insert_replacement_code($src_ref, $ID, $file, $line, $lexical_keywords); |
517
|
158
|
|
100
|
|
|
1336
|
} |
518
|
|
|
|
|
|
|
} |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
# These help unpack /.../ type specifiers... |
521
|
|
|
|
|
|
|
my $REGEX_TYPE = qr{ \A (?&PerlMatch) \z $PPR::GRAMMAR }x; |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
my $REGEX_PAT = qr{ |
524
|
|
|
|
|
|
|
\A |
525
|
|
|
|
|
|
|
(?: (? / ) | m \s* (? \S )) |
526
|
|
|
|
|
|
|
(? .* ) |
527
|
|
|
|
|
|
|
(?: \k | [])>\}] ) |
528
|
|
|
|
|
|
|
(? [imnsxadlup]*+ ) |
529
|
|
|
|
|
|
|
\z |
530
|
|
|
|
|
|
|
}xs; |
531
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
my %ACTUAL_TYPE_OF = ( |
533
|
|
|
|
|
|
|
# Specified type... # Translated to... |
534
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
# Autogenerated type translations (from bin/gen_types.pl)... |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
'ArrayIndexer' => '/(?&PerlArrayIndexer)/', |
539
|
|
|
|
|
|
|
'AssignmentOperator' => '/(?&PerlAssignmentOperator)/', |
540
|
|
|
|
|
|
|
'Attributes' => '/(?&PerlAttributes)/', |
541
|
|
|
|
|
|
|
'Comma' => '/(?&PerlComma)/', |
542
|
|
|
|
|
|
|
'Document' => '/(?&PerlDocument)/', |
543
|
|
|
|
|
|
|
'HashIndexer' => '/(?&PerlHashIndexer)/', |
544
|
|
|
|
|
|
|
'InfixBinaryOperator' => '/(?&PerlInfixBinaryOperator)/', |
545
|
|
|
|
|
|
|
'LowPrecedenceInfixOperator' => '/(?&PerlLowPrecedenceInfixOperator)/', |
546
|
|
|
|
|
|
|
'OWS' => '/(?&PerlOWS)/', |
547
|
|
|
|
|
|
|
'PostfixUnaryOperator' => '/(?&PerlPostfixUnaryOperator)/', |
548
|
|
|
|
|
|
|
'PrefixUnaryOperator' => '/(?&PerlPrefixUnaryOperator)/', |
549
|
|
|
|
|
|
|
'StatementModifier' => '/(?&PerlStatementModifier)/', |
550
|
|
|
|
|
|
|
'NWS' => '/(?&PerlNWS)/', |
551
|
|
|
|
|
|
|
'Whitespace' => '/(?&PerlNWS)/', |
552
|
|
|
|
|
|
|
'Statement' => '/(?&PerlStatement)/', |
553
|
|
|
|
|
|
|
'Block' => '/(?&PerlBlock)/', |
554
|
|
|
|
|
|
|
'Comment' => '/(?&PerlComment)/', |
555
|
|
|
|
|
|
|
'ControlBlock' => '/(?&PerlControlBlock)/', |
556
|
|
|
|
|
|
|
'Expression' => '/(?&PerlExpression)/', |
557
|
|
|
|
|
|
|
'Expr' => '/(?&PerlExpression)/', |
558
|
|
|
|
|
|
|
'Format' => '/(?&PerlFormat)/', |
559
|
|
|
|
|
|
|
'Keyword' => '/(?&PerlKeyword)/', |
560
|
|
|
|
|
|
|
'Label' => '/(?&PerlLabel)/', |
561
|
|
|
|
|
|
|
'PackageDeclaration' => '/(?&PerlPackageDeclaration)/', |
562
|
|
|
|
|
|
|
'Pod' => '/(?&PerlPod)/', |
563
|
|
|
|
|
|
|
'SubroutineDeclaration' => '/(?&PerlSubroutineDeclaration)/', |
564
|
|
|
|
|
|
|
'UseStatement' => '/(?&PerlUseStatement)/', |
565
|
|
|
|
|
|
|
'LowPrecedenceNotExpression' => '/(?&PerlLowPrecedenceNotExpression)/', |
566
|
|
|
|
|
|
|
'List' => '/(?&PerlList)/', |
567
|
|
|
|
|
|
|
'CommaList' => '/(?&PerlCommaList)/', |
568
|
|
|
|
|
|
|
'Assignment' => '/(?&PerlAssignment)/', |
569
|
|
|
|
|
|
|
'ConditionalExpression' => '/(?&PerlConditionalExpression)/', |
570
|
|
|
|
|
|
|
'Ternary' => '/(?&PerlConditionalExpression)/', |
571
|
|
|
|
|
|
|
'ListElem' => '/(?&PerlConditionalExpression)/', |
572
|
|
|
|
|
|
|
'BinaryExpression' => '/(?&PerlBinaryExpression)/', |
573
|
|
|
|
|
|
|
'PrefixPostfixTerm' => '/(?&PerlPrefixPostfixTerm)/', |
574
|
|
|
|
|
|
|
'Term' => '/(?&PerlTerm)/', |
575
|
|
|
|
|
|
|
'AnonymousArray' => '/(?&PerlAnonymousArray)/', |
576
|
|
|
|
|
|
|
'AnonArray' => '/(?&PerlAnonymousArray)/', |
577
|
|
|
|
|
|
|
'AnonymousHash' => '/(?&PerlAnonymousHash)/', |
578
|
|
|
|
|
|
|
'AnonHash' => '/(?&PerlAnonymousHash)/', |
579
|
|
|
|
|
|
|
'AnonymousSubroutine' => '/(?&PerlAnonymousSubroutine)/', |
580
|
|
|
|
|
|
|
'Call' => '/(?&PerlCall)/', |
581
|
|
|
|
|
|
|
'DiamondOperator' => '/(?&PerlDiamondOperator)/', |
582
|
|
|
|
|
|
|
'DoBlock' => '/(?&PerlDoBlock)/', |
583
|
|
|
|
|
|
|
'EvalBlock' => '/(?&PerlEvalBlock)/', |
584
|
|
|
|
|
|
|
'Literal' => '/(?&PerlLiteral)/', |
585
|
|
|
|
|
|
|
'Lvalue' => '/(?&PerlLvalue)/', |
586
|
|
|
|
|
|
|
'ParenthesesList' => '/(?&PerlParenthesesList)/', |
587
|
|
|
|
|
|
|
'ParensList' => '/(?&PerlParenthesesList)/', |
588
|
|
|
|
|
|
|
'Quotelike' => '/(?&PerlQuotelike)/', |
589
|
|
|
|
|
|
|
'ReturnStatement' => '/(?&PerlReturnStatement)/', |
590
|
|
|
|
|
|
|
'Typeglob' => '/(?&PerlTypeglob)/', |
591
|
|
|
|
|
|
|
'VariableDeclaration' => '/(?&PerlVariableDeclaration)/', |
592
|
|
|
|
|
|
|
'VarDecl' => '/(?&PerlVariableDeclaration)/', |
593
|
|
|
|
|
|
|
'Variable' => '/(?&PerlVariable)/', |
594
|
|
|
|
|
|
|
'Var' => '/(?&PerlVariable)/', |
595
|
|
|
|
|
|
|
'ArrayAccess' => '/(?&PerlArrayAccess)/', |
596
|
|
|
|
|
|
|
'Bareword' => '/(?&PerlBareword)/', |
597
|
|
|
|
|
|
|
'BuiltinFunction' => '/(?&PerlBuiltinFunction)/', |
598
|
|
|
|
|
|
|
'HashAccess' => '/(?&PerlHashAccess)/', |
599
|
|
|
|
|
|
|
'Number' => '/(?&PerlNumber)/', |
600
|
|
|
|
|
|
|
'Num' => '/(?&PerlNumber)/', |
601
|
|
|
|
|
|
|
'QuotelikeQW' => '/(?&PerlQuotelikeQW)/', |
602
|
|
|
|
|
|
|
'QuotelikeQX' => '/(?&PerlQuotelikeQX)/', |
603
|
|
|
|
|
|
|
'Regex' => '/(?&PerlRegex)/', |
604
|
|
|
|
|
|
|
'Regexp' => '/(?&PerlRegex)/', |
605
|
|
|
|
|
|
|
'ScalarAccess' => '/(?&PerlScalarAccess)/', |
606
|
|
|
|
|
|
|
'String' => '/(?&PerlString)/', |
607
|
|
|
|
|
|
|
'Str' => '/(?&PerlString)/', |
608
|
|
|
|
|
|
|
'Substitution' => '/(?&PerlSubstitution)/', |
609
|
|
|
|
|
|
|
'QuotelikeS' => '/(?&PerlSubstitution)/', |
610
|
|
|
|
|
|
|
'Transliteration' => '/(?&PerlTransliteration)/', |
611
|
|
|
|
|
|
|
'QuotelikeTR' => '/(?&PerlTransliteration)/', |
612
|
|
|
|
|
|
|
'ContextualRegex' => '/(?&PerlContextualRegex)/', |
613
|
|
|
|
|
|
|
'Heredoc' => '/(?&PerlHeredoc)/', |
614
|
|
|
|
|
|
|
'Integer' => '/(?&PerlInteger)/', |
615
|
|
|
|
|
|
|
'Int' => '/(?&PerlInteger)/', |
616
|
|
|
|
|
|
|
'Match' => '/(?&PerlMatch)/', |
617
|
|
|
|
|
|
|
'QuotelikeM' => '/(?&PerlMatch)/', |
618
|
|
|
|
|
|
|
'NullaryBuiltinFunction' => '/(?&PerlNullaryBuiltinFunction)/', |
619
|
|
|
|
|
|
|
'OldQualifiedIdentifier' => '/(?&PerlOldQualifiedIdentifier)/', |
620
|
|
|
|
|
|
|
'QuotelikeQ' => '/(?&PerlQuotelikeQ)/', |
621
|
|
|
|
|
|
|
'QuotelikeQQ' => '/(?&PerlQuotelikeQQ)/', |
622
|
|
|
|
|
|
|
'QuotelikeQR' => '/(?&PerlQuotelikeQR)/', |
623
|
|
|
|
|
|
|
'VString' => '/(?&PerlVString)/', |
624
|
|
|
|
|
|
|
'VariableArray' => '/(?&PerlVariableArray)/', |
625
|
|
|
|
|
|
|
'VarArray' => '/(?&PerlVariableArray)/', |
626
|
|
|
|
|
|
|
'ArrayVar' => '/(?&PerlVariableArray)/', |
627
|
|
|
|
|
|
|
'VariableHash' => '/(?&PerlVariableHash)/', |
628
|
|
|
|
|
|
|
'VarHash' => '/(?&PerlVariableHash)/', |
629
|
|
|
|
|
|
|
'HashVar' => '/(?&PerlVariableHash)/', |
630
|
|
|
|
|
|
|
'VariableScalar' => '/(?&PerlVariableScalar)/', |
631
|
|
|
|
|
|
|
'VarScalar' => '/(?&PerlVariableScalar)/', |
632
|
|
|
|
|
|
|
'ScalarVar' => '/(?&PerlVariableScalar)/', |
633
|
|
|
|
|
|
|
'VersionNumber' => '/(?&PerlVersionNumber)/', |
634
|
|
|
|
|
|
|
'ContextualMatch' => '/(?&PerlContextualMatch)/', |
635
|
|
|
|
|
|
|
'ContextualQuotelikeM' => '/(?&PerlContextualMatch)/', |
636
|
|
|
|
|
|
|
'PositiveInteger' => '/(?&PerlPositiveInteger)/', |
637
|
|
|
|
|
|
|
'PosInt' => '/(?&PerlPositiveInteger)/', |
638
|
|
|
|
|
|
|
'QualifiedIdentifier' => '/(?&PerlQualifiedIdentifier)/', |
639
|
|
|
|
|
|
|
'QualIdent' => '/(?&PerlQualifiedIdentifier)/', |
640
|
|
|
|
|
|
|
'QuotelikeQR' => '/(?&PerlQuotelikeQR)/', |
641
|
|
|
|
|
|
|
'VString' => '/(?&PerlVString)/', |
642
|
|
|
|
|
|
|
'Identifier' => '/(?&PerlIdentifier)/', |
643
|
|
|
|
|
|
|
'Ident' => '/(?&PerlIdentifier)/', |
644
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
# End of autogenerated type translations |
646
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
'Integer' => '/(?:[+-]?+(?&PPR_digit_seq)(?!\.))/', |
648
|
|
|
|
|
|
|
'Int' => '/(?:[+-]?+(?&PPR_digit_seq)(?!\.))/', |
649
|
|
|
|
|
|
|
'PositiveInteger' => '/(?:[+]?+(?&PPR_digit_seq)(?!\.))/', |
650
|
|
|
|
|
|
|
'PosInt' => '/(?:[+]?+(?&PPR_digit_seq)(?!\.))/', |
651
|
|
|
|
|
|
|
'Comment' => '/\#[^\n]*\n/', |
652
|
|
|
|
|
|
|
); |
653
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
our %isa = ( |
655
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
# Autogenerated type ISA hierarchy (from bin/gen_types.pl)... |
657
|
|
|
|
|
|
|
|
658
|
|
|
|
|
|
|
"AnonArray\34Assignment"=>1,"AnonArray\34BinaryExpression"=>1,"AnonArray\34CommaList"=>1,"AnonArray\34ConditionalExpression"=>1,"AnonArray\34Document"=>1,"AnonArray\34Expr"=>1,"AnonArray\34Expression"=>1,"AnonArray\34List"=>1,"AnonArray\34ListElem"=>1,"AnonArray\34LowPrecedenceNotExpression"=>1,"AnonArray\34PrefixPostfixTerm"=>1,"AnonArray\34Statement"=>1,"AnonArray\34Term"=>1,"AnonArray\34Ternary"=>1,"AnonHash\34Assignment"=>1,"AnonHash\34BinaryExpression"=>1,"AnonHash\34CommaList"=>1,"AnonHash\34ConditionalExpression"=>1,"AnonHash\34Document"=>1,"AnonHash\34Expr"=>1,"AnonHash\34Expression"=>1,"AnonHash\34List"=>1,"AnonHash\34ListElem"=>1,"AnonHash\34LowPrecedenceNotExpression"=>1,"AnonHash\34PrefixPostfixTerm"=>1,"AnonHash\34Statement"=>1,"AnonHash\34Term"=>1,"AnonHash\34Ternary"=>1,"AnonymousArray\34Assignment"=>1,"AnonymousArray\34BinaryExpression"=>1,"AnonymousArray\34CommaList"=>1,"AnonymousArray\34ConditionalExpression"=>1,"AnonymousArray\34Document"=>1,"AnonymousArray\34Expr"=>1,"AnonymousArray\34Expression"=>1,"AnonymousArray\34List"=>1,"AnonymousArray\34ListElem"=>1,"AnonymousArray\34LowPrecedenceNotExpression"=>1,"AnonymousArray\34PrefixPostfixTerm"=>1,"AnonymousArray\34Statement"=>1,"AnonymousArray\34Term"=>1,"AnonymousArray\34Ternary"=>1,"AnonymousHash\34Assignment"=>1,"AnonymousHash\34BinaryExpression"=>1,"AnonymousHash\34CommaList"=>1,"AnonymousHash\34ConditionalExpression"=>1,"AnonymousHash\34Document"=>1,"AnonymousHash\34Expr"=>1,"AnonymousHash\34Expression"=>1,"AnonymousHash\34List"=>1,"AnonymousHash\34ListElem"=>1,"AnonymousHash\34LowPrecedenceNotExpression"=>1,"AnonymousHash\34PrefixPostfixTerm"=>1,"AnonymousHash\34Statement"=>1,"AnonymousHash\34Term"=>1,"AnonymousHash\34Ternary"=>1,"AnonymousSubroutine\34Assignment"=>1,"AnonymousSubroutine\34BinaryExpression"=>1,"AnonymousSubroutine\34CommaList"=>1,"AnonymousSubroutine\34ConditionalExpression"=>1,"AnonymousSubroutine\34Document"=>1,"AnonymousSubroutine\34Expr"=>1,"AnonymousSubroutine\34Expression"=>1,"AnonymousSubroutine\34List"=>1,"AnonymousSubroutine\34ListElem"=>1,"AnonymousSubroutine\34LowPrecedenceNotExpression"=>1,"AnonymousSubroutine\34PrefixPostfixTerm"=>1,"AnonymousSubroutine\34Statement"=>1,"AnonymousSubroutine\34Term"=>1,"AnonymousSubroutine\34Ternary"=>1,"ArrayAccess\34Assignment"=>1,"ArrayAccess\34BinaryExpression"=>1,"ArrayAccess\34CommaList"=>1,"ArrayAccess\34ConditionalExpression"=>1,"ArrayAccess\34Document"=>1,"ArrayAccess\34Expr"=>1,"ArrayAccess\34Expression"=>1,"ArrayAccess\34List"=>1,"ArrayAccess\34ListElem"=>1,"ArrayAccess\34LowPrecedenceNotExpression"=>1,"ArrayAccess\34PrefixPostfixTerm"=>1,"ArrayAccess\34Statement"=>1,"ArrayAccess\34Term"=>1,"ArrayAccess\34Ternary"=>1,"ArrayAccess\34Var"=>1,"ArrayAccess\34Variable"=>1,"ArrayVar\34ArrayAccess"=>1,"ArrayVar\34Assignment"=>1,"ArrayVar\34BinaryExpression"=>1,"ArrayVar\34CommaList"=>1,"ArrayVar\34ConditionalExpression"=>1,"ArrayVar\34Document"=>1,"ArrayVar\34Expr"=>1,"ArrayVar\34Expression"=>1,"ArrayVar\34List"=>1,"ArrayVar\34ListElem"=>1,"ArrayVar\34LowPrecedenceNotExpression"=>1,"ArrayVar\34PrefixPostfixTerm"=>1,"ArrayVar\34Statement"=>1,"ArrayVar\34Term"=>1,"ArrayVar\34Ternary"=>1,"ArrayVar\34Var"=>1,"ArrayVar\34Variable"=>1,"Assignment\34CommaList"=>1,"Assignment\34Document"=>1,"Assignment\34Expr"=>1,"Assignment\34Expression"=>1,"Assignment\34List"=>1,"Assignment\34LowPrecedenceNotExpression"=>1,"Assignment\34Statement"=>1,"Bareword\34Assignment"=>1,"Bareword\34BinaryExpression"=>1,"Bareword\34CommaList"=>1,"Bareword\34ConditionalExpression"=>1,"Bareword\34Document"=>1,"Bareword\34Expr"=>1,"Bareword\34Expression"=>1,"Bareword\34List"=>1,"Bareword\34ListElem"=>1,"Bareword\34Literal"=>1,"Bareword\34LowPrecedenceNotExpression"=>1,"Bareword\34PrefixPostfixTerm"=>1,"Bareword\34Statement"=>1,"Bareword\34Term"=>1,"Bareword\34Ternary"=>1,"BinaryExpression\34Assignment"=>1,"BinaryExpression\34CommaList"=>1,"BinaryExpression\34ConditionalExpression"=>1,"BinaryExpression\34Document"=>1,"BinaryExpression\34Expr"=>1,"BinaryExpression\34Expression"=>1,"BinaryExpression\34List"=>1,"BinaryExpression\34ListElem"=>1,"BinaryExpression\34LowPrecedenceNotExpression"=>1,"BinaryExpression\34Statement"=>1,"BinaryExpression\34Ternary"=>1,"Block\34Document"=>1,"Block\34Statement"=>1,"BuiltinFunction\34Assignment"=>1,"BuiltinFunction\34BinaryExpression"=>1,"BuiltinFunction\34Call"=>1,"BuiltinFunction\34CommaList"=>1,"BuiltinFunction\34ConditionalExpression"=>1,"BuiltinFunction\34Document"=>1,"BuiltinFunction\34Expr"=>1,"BuiltinFunction\34Expression"=>1,"BuiltinFunction\34List"=>1,"BuiltinFunction\34ListElem"=>1,"BuiltinFunction\34LowPrecedenceNotExpression"=>1,"BuiltinFunction\34PrefixPostfixTerm"=>1,"BuiltinFunction\34Statement"=>1,"BuiltinFunction\34Term"=>1,"BuiltinFunction\34Ternary"=>1,"Call\34Assignment"=>1,"Call\34BinaryExpression"=>1,"Call\34CommaList"=>1,"Call\34ConditionalExpression"=>1,"Call\34Document"=>1,"Call\34Expr"=>1,"Call\34Expression"=>1,"Call\34List"=>1,"Call\34ListElem"=>1,"Call\34LowPrecedenceNotExpression"=>1,"Call\34PrefixPostfixTerm"=>1,"Call\34Statement"=>1,"Call\34Term"=>1,"Call\34Ternary"=>1,"CommaList\34Document"=>1,"CommaList\34Expr"=>1,"CommaList\34Expression"=>1,"CommaList\34List"=>1,"CommaList\34LowPrecedenceNotExpression"=>1,"CommaList\34Statement"=>1,"Comment\34NWS"=>1,"Comment\34OWS"=>1,"Comment\34Whitespace"=>1,"ConditionalExpression\34Assignment"=>1,"ConditionalExpression\34CommaList"=>1,"ConditionalExpression\34Document"=>1,"ConditionalExpression\34Expr"=>1,"ConditionalExpression\34Expression"=>1,"ConditionalExpression\34List"=>1,"ConditionalExpression\34LowPrecedenceNotExpression"=>1,"ConditionalExpression\34Statement"=>1,"ContextualMatch\34Assignment"=>1,"ContextualMatch\34BinaryExpression"=>1,"ContextualMatch\34CommaList"=>1,"ContextualMatch\34ConditionalExpression"=>1,"ContextualMatch\34ContextualRegex"=>1,"ContextualMatch\34Document"=>1,"ContextualMatch\34Expr"=>1,"ContextualMatch\34Expression"=>1,"ContextualMatch\34List"=>1,"ContextualMatch\34ListElem"=>1,"ContextualMatch\34LowPrecedenceNotExpression"=>1,"ContextualMatch\34Match"=>1,"ContextualMatch\34PrefixPostfixTerm"=>1,"ContextualMatch\34Quotelike"=>1,"ContextualMatch\34QuotelikeM"=>1,"ContextualMatch\34Regex"=>1,"ContextualMatch\34Regexp"=>1,"ContextualMatch\34Statement"=>1,"ContextualMatch\34Term"=>1,"ContextualMatch\34Ternary"=>1,"ContextualQuotelikeM\34Assignment"=>1,"ContextualQuotelikeM\34BinaryExpression"=>1,"ContextualQuotelikeM\34CommaList"=>1,"ContextualQuotelikeM\34ConditionalExpression"=>1,"ContextualQuotelikeM\34ContextualRegex"=>1,"ContextualQuotelikeM\34Document"=>1,"ContextualQuotelikeM\34Expr"=>1,"ContextualQuotelikeM\34Expression"=>1,"ContextualQuotelikeM\34List"=>1,"ContextualQuotelikeM\34ListElem"=>1,"ContextualQuotelikeM\34LowPrecedenceNotExpression"=>1,"ContextualQuotelikeM\34Match"=>1,"ContextualQuotelikeM\34PrefixPostfixTerm"=>1,"ContextualQuotelikeM\34Quotelike"=>1,"ContextualQuotelikeM\34QuotelikeM"=>1,"ContextualQuotelikeM\34Regex"=>1,"ContextualQuotelikeM\34Regexp"=>1,"ContextualQuotelikeM\34Statement"=>1,"ContextualQuotelikeM\34Term"=>1,"ContextualQuotelikeM\34Ternary"=>1,"ContextualRegex\34Assignment"=>1,"ContextualRegex\34BinaryExpression"=>1,"ContextualRegex\34CommaList"=>1,"ContextualRegex\34ConditionalExpression"=>1,"ContextualRegex\34Document"=>1,"ContextualRegex\34Expr"=>1,"ContextualRegex\34Expression"=>1,"ContextualRegex\34List"=>1,"ContextualRegex\34ListElem"=>1,"ContextualRegex\34LowPrecedenceNotExpression"=>1,"ContextualRegex\34PrefixPostfixTerm"=>1,"ContextualRegex\34Quotelike"=>1,"ContextualRegex\34Regex"=>1,"ContextualRegex\34Regexp"=>1,"ContextualRegex\34Statement"=>1,"ContextualRegex\34Term"=>1,"ContextualRegex\34Ternary"=>1,"ControlBlock\34Document"=>1,"ControlBlock\34Statement"=>1,"DiamondOperator\34Assignment"=>1,"DiamondOperator\34BinaryExpression"=>1,"DiamondOperator\34CommaList"=>1,"DiamondOperator\34ConditionalExpression"=>1,"DiamondOperator\34Document"=>1,"DiamondOperator\34Expr"=>1,"DiamondOperator\34Expression"=>1,"DiamondOperator\34List"=>1,"DiamondOperator\34ListElem"=>1,"DiamondOperator\34LowPrecedenceNotExpression"=>1,"DiamondOperator\34PrefixPostfixTerm"=>1,"DiamondOperator\34Statement"=>1,"DiamondOperator\34Term"=>1,"DiamondOperator\34Ternary"=>1,"DoBlock\34Assignment"=>1,"DoBlock\34BinaryExpression"=>1,"DoBlock\34CommaList"=>1,"DoBlock\34ConditionalExpression"=>1,"DoBlock\34Document"=>1,"DoBlock\34Expr"=>1,"DoBlock\34Expression"=>1,"DoBlock\34List"=>1,"DoBlock\34ListElem"=>1,"DoBlock\34LowPrecedenceNotExpression"=>1,"DoBlock\34PrefixPostfixTerm"=>1,"DoBlock\34Statement"=>1,"DoBlock\34Term"=>1,"DoBlock\34Ternary"=>1,"EvalBlock\34Assignment"=>1,"EvalBlock\34BinaryExpression"=>1,"EvalBlock\34CommaList"=>1,"EvalBlock\34ConditionalExpression"=>1,"EvalBlock\34Document"=>1,"EvalBlock\34Expr"=>1,"EvalBlock\34Expression"=>1,"EvalBlock\34List"=>1,"EvalBlock\34ListElem"=>1,"EvalBlock\34LowPrecedenceNotExpression"=>1,"EvalBlock\34PrefixPostfixTerm"=>1,"EvalBlock\34Statement"=>1,"EvalBlock\34Term"=>1,"EvalBlock\34Ternary"=>1,"Expr\34Document"=>1,"Expr\34Statement"=>1,"Expression\34Document"=>1,"Expression\34Statement"=>1,"Format\34Document"=>1,"Format\34Statement"=>1,"HashAccess\34Assignment"=>1,"HashAccess\34BinaryExpression"=>1,"HashAccess\34CommaList"=>1,"HashAccess\34ConditionalExpression"=>1,"HashAccess\34Document"=>1,"HashAccess\34Expr"=>1,"HashAccess\34Expression"=>1,"HashAccess\34List"=>1,"HashAccess\34ListElem"=>1,"HashAccess\34LowPrecedenceNotExpression"=>1,"HashAccess\34PrefixPostfixTerm"=>1,"HashAccess\34Statement"=>1,"HashAccess\34Term"=>1,"HashAccess\34Ternary"=>1,"HashAccess\34Var"=>1,"HashAccess\34Variable"=>1,"HashVar\34Assignment"=>1,"HashVar\34BinaryExpression"=>1,"HashVar\34CommaList"=>1,"HashVar\34ConditionalExpression"=>1,"HashVar\34Document"=>1,"HashVar\34Expr"=>1,"HashVar\34Expression"=>1,"HashVar\34HashAccess"=>1,"HashVar\34List"=>1,"HashVar\34ListElem"=>1,"HashVar\34LowPrecedenceNotExpression"=>1,"HashVar\34PrefixPostfixTerm"=>1,"HashVar\34Statement"=>1,"HashVar\34Term"=>1,"HashVar\34Ternary"=>1,"HashVar\34Var"=>1,"HashVar\34Variable"=>1,"Heredoc\34Assignment"=>1,"Heredoc\34BinaryExpression"=>1,"Heredoc\34CommaList"=>1,"Heredoc\34ConditionalExpression"=>1,"Heredoc\34Document"=>1,"Heredoc\34Expr"=>1,"Heredoc\34Expression"=>1,"Heredoc\34List"=>1,"Heredoc\34ListElem"=>1,"Heredoc\34Literal"=>1,"Heredoc\34LowPrecedenceNotExpression"=>1,"Heredoc\34PrefixPostfixTerm"=>1,"Heredoc\34Statement"=>1,"Heredoc\34Str"=>1,"Heredoc\34String"=>1,"Heredoc\34Term"=>1,"Heredoc\34Ternary"=>1,"Ident\34Assignment"=>1,"Ident\34Bareword"=>1,"Ident\34BinaryExpression"=>1,"Ident\34CommaList"=>1,"Ident\34ConditionalExpression"=>1,"Ident\34Document"=>1,"Ident\34Expr"=>1,"Ident\34Expression"=>1,"Ident\34List"=>1,"Ident\34ListElem"=>1,"Ident\34Literal"=>1,"Ident\34LowPrecedenceNotExpression"=>1,"Ident\34OldQualifiedIdentifier"=>1,"Ident\34PrefixPostfixTerm"=>1,"Ident\34QualIdent"=>1,"Ident\34QualifiedIdentifier"=>1,"Ident\34Statement"=>1,"Ident\34Term"=>1,"Ident\34Ternary"=>1,"Identifier\34Assignment"=>1,"Identifier\34Bareword"=>1,"Identifier\34BinaryExpression"=>1,"Identifier\34CommaList"=>1,"Identifier\34ConditionalExpression"=>1,"Identifier\34Document"=>1,"Identifier\34Expr"=>1,"Identifier\34Expression"=>1,"Identifier\34List"=>1,"Identifier\34ListElem"=>1,"Identifier\34Literal"=>1,"Identifier\34LowPrecedenceNotExpression"=>1,"Identifier\34OldQualifiedIdentifier"=>1,"Identifier\34PrefixPostfixTerm"=>1,"Identifier\34QualIdent"=>1,"Identifier\34QualifiedIdentifier"=>1,"Identifier\34Statement"=>1,"Identifier\34Term"=>1,"Identifier\34Ternary"=>1,"Int\34Assignment"=>1,"Int\34BinaryExpression"=>1,"Int\34CommaList"=>1,"Int\34ConditionalExpression"=>1,"Int\34Document"=>1,"Int\34Expr"=>1,"Int\34Expression"=>1,"Int\34List"=>1,"Int\34ListElem"=>1,"Int\34Literal"=>1,"Int\34LowPrecedenceNotExpression"=>1,"Int\34Num"=>1,"Int\34Number"=>1,"Int\34PrefixPostfixTerm"=>1,"Int\34Statement"=>1,"Int\34Term"=>1,"Int\34Ternary"=>1,"Integer\34Assignment"=>1,"Integer\34BinaryExpression"=>1,"Integer\34CommaList"=>1,"Integer\34ConditionalExpression"=>1,"Integer\34Document"=>1,"Integer\34Expr"=>1,"Integer\34Expression"=>1,"Integer\34List"=>1,"Integer\34ListElem"=>1,"Integer\34Literal"=>1,"Integer\34LowPrecedenceNotExpression"=>1,"Integer\34Num"=>1,"Integer\34Number"=>1,"Integer\34PrefixPostfixTerm"=>1,"Integer\34Statement"=>1,"Integer\34Term"=>1,"Integer\34Ternary"=>1,"Keyword\34Document"=>1,"Keyword\34Statement"=>1,"Label\34Document"=>1,"Label\34Statement"=>1,"List\34Document"=>1,"List\34Expr"=>1,"List\34Expression"=>1,"List\34LowPrecedenceNotExpression"=>1,"List\34Statement"=>1,"ListElem\34Assignment"=>1,"ListElem\34CommaList"=>1,"ListElem\34Document"=>1,"ListElem\34Expr"=>1,"ListElem\34Expression"=>1,"ListElem\34List"=>1,"ListElem\34LowPrecedenceNotExpression"=>1,"ListElem\34Statement"=>1,"Literal\34Assignment"=>1,"Literal\34BinaryExpression"=>1,"Literal\34CommaList"=>1,"Literal\34ConditionalExpression"=>1,"Literal\34Document"=>1,"Literal\34Expr"=>1,"Literal\34Expression"=>1,"Literal\34List"=>1,"Literal\34ListElem"=>1,"Literal\34LowPrecedenceNotExpression"=>1,"Literal\34PrefixPostfixTerm"=>1,"Literal\34Statement"=>1,"Literal\34Term"=>1,"Literal\34Ternary"=>1,"LowPrecedenceNotExpression\34Document"=>1,"LowPrecedenceNotExpression\34Expr"=>1,"LowPrecedenceNotExpression\34Expression"=>1,"LowPrecedenceNotExpression\34Statement"=>1,"Lvalue\34Assignment"=>1,"Lvalue\34BinaryExpression"=>1,"Lvalue\34CommaList"=>1,"Lvalue\34ConditionalExpression"=>1,"Lvalue\34Document"=>1,"Lvalue\34Expr"=>1,"Lvalue\34Expression"=>1,"Lvalue\34List"=>1,"Lvalue\34ListElem"=>1,"Lvalue\34LowPrecedenceNotExpression"=>1,"Lvalue\34PrefixPostfixTerm"=>1,"Lvalue\34Statement"=>1,"Lvalue\34Term"=>1,"Lvalue\34Ternary"=>1,"Match\34Assignment"=>1,"Match\34BinaryExpression"=>1,"Match\34CommaList"=>1,"Match\34ConditionalExpression"=>1,"Match\34Document"=>1,"Match\34Expr"=>1,"Match\34Expression"=>1,"Match\34List"=>1,"Match\34ListElem"=>1,"Match\34LowPrecedenceNotExpression"=>1,"Match\34PrefixPostfixTerm"=>1,"Match\34Quotelike"=>1,"Match\34Regex"=>1,"Match\34Regexp"=>1,"Match\34Statement"=>1,"Match\34Term"=>1,"Match\34Ternary"=>1,"NullaryBuiltinFunction\34Assignment"=>1,"NullaryBuiltinFunction\34BinaryExpression"=>1,"NullaryBuiltinFunction\34BuiltinFunction"=>1,"NullaryBuiltinFunction\34Call"=>1,"NullaryBuiltinFunction\34CommaList"=>1,"NullaryBuiltinFunction\34ConditionalExpression"=>1,"NullaryBuiltinFunction\34Document"=>1,"NullaryBuiltinFunction\34Expr"=>1,"NullaryBuiltinFunction\34Expression"=>1,"NullaryBuiltinFunction\34List"=>1,"NullaryBuiltinFunction\34ListElem"=>1,"NullaryBuiltinFunction\34LowPrecedenceNotExpression"=>1,"NullaryBuiltinFunction\34PrefixPostfixTerm"=>1,"NullaryBuiltinFunction\34Statement"=>1,"NullaryBuiltinFunction\34Term"=>1,"NullaryBuiltinFunction\34Ternary"=>1,"Num\34Assignment"=>1,"Num\34BinaryExpression"=>1,"Num\34CommaList"=>1,"Num\34ConditionalExpression"=>1,"Num\34Document"=>1,"Num\34Expr"=>1,"Num\34Expression"=>1,"Num\34List"=>1,"Num\34ListElem"=>1,"Num\34Literal"=>1,"Num\34LowPrecedenceNotExpression"=>1,"Num\34PrefixPostfixTerm"=>1,"Num\34Statement"=>1,"Num\34Term"=>1,"Num\34Ternary"=>1,"Number\34Assignment"=>1,"Number\34BinaryExpression"=>1,"Number\34CommaList"=>1,"Number\34ConditionalExpression"=>1,"Number\34Document"=>1,"Number\34Expr"=>1,"Number\34Expression"=>1,"Number\34List"=>1,"Number\34ListElem"=>1,"Number\34Literal"=>1,"Number\34LowPrecedenceNotExpression"=>1,"Number\34PrefixPostfixTerm"=>1,"Number\34Statement"=>1,"Number\34Term"=>1,"Number\34Ternary"=>1,"NWS\34OWS"=>1,"OldQualifiedIdentifier\34Assignment"=>1,"OldQualifiedIdentifier\34Bareword"=>1,"OldQualifiedIdentifier\34BinaryExpression"=>1,"OldQualifiedIdentifier\34CommaList"=>1,"OldQualifiedIdentifier\34ConditionalExpression"=>1,"OldQualifiedIdentifier\34Document"=>1,"OldQualifiedIdentifier\34Expr"=>1,"OldQualifiedIdentifier\34Expression"=>1,"OldQualifiedIdentifier\34List"=>1,"OldQualifiedIdentifier\34ListElem"=>1,"OldQualifiedIdentifier\34Literal"=>1,"OldQualifiedIdentifier\34LowPrecedenceNotExpression"=>1,"OldQualifiedIdentifier\34PrefixPostfixTerm"=>1,"OldQualifiedIdentifier\34Statement"=>1,"OldQualifiedIdentifier\34Term"=>1,"OldQualifiedIdentifier\34Ternary"=>1,"PackageDeclaration\34Document"=>1,"PackageDeclaration\34Statement"=>1,"ParensList\34Assignment"=>1,"ParensList\34BinaryExpression"=>1,"ParensList\34CommaList"=>1,"ParensList\34ConditionalExpression"=>1,"ParensList\34Document"=>1,"ParensList\34Expr"=>1,"ParensList\34Expression"=>1,"ParensList\34List"=>1,"ParensList\34ListElem"=>1,"ParensList\34LowPrecedenceNotExpression"=>1,"ParensList\34PrefixPostfixTerm"=>1,"ParensList\34Statement"=>1,"ParensList\34Term"=>1,"ParensList\34Ternary"=>1,"ParenthesesList\34Assignment"=>1,"ParenthesesList\34BinaryExpression"=>1,"ParenthesesList\34CommaList"=>1,"ParenthesesList\34ConditionalExpression"=>1,"ParenthesesList\34Document"=>1,"ParenthesesList\34Expr"=>1,"ParenthesesList\34Expression"=>1,"ParenthesesList\34List"=>1,"ParenthesesList\34ListElem"=>1,"ParenthesesList\34LowPrecedenceNotExpression"=>1,"ParenthesesList\34PrefixPostfixTerm"=>1,"ParenthesesList\34Statement"=>1,"ParenthesesList\34Term"=>1,"ParenthesesList\34Ternary"=>1,"Pod\34NWS"=>1,"Pod\34OWS"=>1,"Pod\34Whitespace"=>1,"PosInt\34Assignment"=>1,"PosInt\34BinaryExpression"=>1,"PosInt\34CommaList"=>1,"PosInt\34ConditionalExpression"=>1,"PosInt\34Document"=>1,"PosInt\34Expr"=>1,"PosInt\34Expression"=>1,"PosInt\34Int"=>1,"PosInt\34Integer"=>1,"PosInt\34List"=>1,"PosInt\34ListElem"=>1,"PosInt\34Literal"=>1,"PosInt\34LowPrecedenceNotExpression"=>1,"PosInt\34Num"=>1,"PosInt\34Number"=>1,"PosInt\34PrefixPostfixTerm"=>1,"PosInt\34Statement"=>1,"PosInt\34Term"=>1,"PosInt\34Ternary"=>1,"PositiveInteger\34Assignment"=>1,"PositiveInteger\34BinaryExpression"=>1,"PositiveInteger\34CommaList"=>1,"PositiveInteger\34ConditionalExpression"=>1,"PositiveInteger\34Document"=>1,"PositiveInteger\34Expr"=>1,"PositiveInteger\34Expression"=>1,"PositiveInteger\34Int"=>1,"PositiveInteger\34Integer"=>1,"PositiveInteger\34List"=>1,"PositiveInteger\34ListElem"=>1,"PositiveInteger\34Literal"=>1,"PositiveInteger\34LowPrecedenceNotExpression"=>1,"PositiveInteger\34Num"=>1,"PositiveInteger\34Number"=>1,"PositiveInteger\34PrefixPostfixTerm"=>1,"PositiveInteger\34Statement"=>1,"PositiveInteger\34Term"=>1,"PositiveInteger\34Ternary"=>1,"PrefixPostfixTerm\34Assignment"=>1,"PrefixPostfixTerm\34BinaryExpression"=>1,"PrefixPostfixTerm\34CommaList"=>1,"PrefixPostfixTerm\34ConditionalExpression"=>1,"PrefixPostfixTerm\34Document"=>1,"PrefixPostfixTerm\34Expr"=>1,"PrefixPostfixTerm\34Expression"=>1,"PrefixPostfixTerm\34List"=>1,"PrefixPostfixTerm\34ListElem"=>1,"PrefixPostfixTerm\34LowPrecedenceNotExpression"=>1,"PrefixPostfixTerm\34Statement"=>1,"PrefixPostfixTerm\34Ternary"=>1,"QualIdent\34Assignment"=>1,"QualIdent\34Bareword"=>1,"QualIdent\34BinaryExpression"=>1,"QualIdent\34CommaList"=>1,"QualIdent\34ConditionalExpression"=>1,"QualIdent\34Document"=>1,"QualIdent\34Expr"=>1,"QualIdent\34Expression"=>1,"QualIdent\34List"=>1,"QualIdent\34ListElem"=>1,"QualIdent\34Literal"=>1,"QualIdent\34LowPrecedenceNotExpression"=>1,"QualIdent\34OldQualifiedIdentifier"=>1,"QualIdent\34PrefixPostfixTerm"=>1,"QualIdent\34Statement"=>1,"QualIdent\34Term"=>1,"QualIdent\34Ternary"=>1,"QualifiedIdentifier\34Assignment"=>1,"QualifiedIdentifier\34Bareword"=>1,"QualifiedIdentifier\34BinaryExpression"=>1,"QualifiedIdentifier\34CommaList"=>1,"QualifiedIdentifier\34ConditionalExpression"=>1,"QualifiedIdentifier\34Document"=>1,"QualifiedIdentifier\34Expr"=>1,"QualifiedIdentifier\34Expression"=>1,"QualifiedIdentifier\34List"=>1,"QualifiedIdentifier\34ListElem"=>1,"QualifiedIdentifier\34Literal"=>1,"QualifiedIdentifier\34LowPrecedenceNotExpression"=>1,"QualifiedIdentifier\34OldQualifiedIdentifier"=>1,"QualifiedIdentifier\34PrefixPostfixTerm"=>1,"QualifiedIdentifier\34Statement"=>1,"QualifiedIdentifier\34Term"=>1,"QualifiedIdentifier\34Ternary"=>1,"Quotelike\34Assignment"=>1,"Quotelike\34BinaryExpression"=>1,"Quotelike\34CommaList"=>1,"Quotelike\34ConditionalExpression"=>1,"Quotelike\34Document"=>1,"Quotelike\34Expr"=>1,"Quotelike\34Expression"=>1,"Quotelike\34List"=>1,"Quotelike\34ListElem"=>1,"Quotelike\34LowPrecedenceNotExpression"=>1,"Quotelike\34PrefixPostfixTerm"=>1,"Quotelike\34Statement"=>1,"Quotelike\34Term"=>1,"Quotelike\34Ternary"=>1,"QuotelikeM\34Assignment"=>1,"QuotelikeM\34BinaryExpression"=>1,"QuotelikeM\34CommaList"=>1,"QuotelikeM\34ConditionalExpression"=>1,"QuotelikeM\34Document"=>1,"QuotelikeM\34Expr"=>1,"QuotelikeM\34Expression"=>1,"QuotelikeM\34List"=>1,"QuotelikeM\34ListElem"=>1,"QuotelikeM\34LowPrecedenceNotExpression"=>1,"QuotelikeM\34PrefixPostfixTerm"=>1,"QuotelikeM\34Quotelike"=>1,"QuotelikeM\34Regex"=>1,"QuotelikeM\34Regexp"=>1,"QuotelikeM\34Statement"=>1,"QuotelikeM\34Term"=>1,"QuotelikeM\34Ternary"=>1,"QuotelikeQ\34Assignment"=>1,"QuotelikeQ\34BinaryExpression"=>1,"QuotelikeQ\34CommaList"=>1,"QuotelikeQ\34ConditionalExpression"=>1,"QuotelikeQ\34Document"=>1,"QuotelikeQ\34Expr"=>1,"QuotelikeQ\34Expression"=>1,"QuotelikeQ\34List"=>1,"QuotelikeQ\34ListElem"=>1,"QuotelikeQ\34Literal"=>1,"QuotelikeQ\34LowPrecedenceNotExpression"=>1,"QuotelikeQ\34PrefixPostfixTerm"=>1,"QuotelikeQ\34Quotelike"=>1,"QuotelikeQ\34Statement"=>1,"QuotelikeQ\34Str"=>1,"QuotelikeQ\34String"=>1,"QuotelikeQ\34Term"=>1,"QuotelikeQ\34Ternary"=>1,"QuotelikeQQ\34Assignment"=>1,"QuotelikeQQ\34BinaryExpression"=>1,"QuotelikeQQ\34CommaList"=>1,"QuotelikeQQ\34ConditionalExpression"=>1,"QuotelikeQQ\34Document"=>1,"QuotelikeQQ\34Expr"=>1,"QuotelikeQQ\34Expression"=>1,"QuotelikeQQ\34List"=>1,"QuotelikeQQ\34ListElem"=>1,"QuotelikeQQ\34Literal"=>1,"QuotelikeQQ\34LowPrecedenceNotExpression"=>1,"QuotelikeQQ\34PrefixPostfixTerm"=>1,"QuotelikeQQ\34Quotelike"=>1,"QuotelikeQQ\34Statement"=>1,"QuotelikeQQ\34Str"=>1,"QuotelikeQQ\34String"=>1,"QuotelikeQQ\34Term"=>1,"QuotelikeQQ\34Ternary"=>1,"QuotelikeQR\34Assignment"=>1,"QuotelikeQR\34BinaryExpression"=>1,"QuotelikeQR\34CommaList"=>1,"QuotelikeQR\34ConditionalExpression"=>1,"QuotelikeQR\34ContextualRegex"=>1,"QuotelikeQR\34Document"=>1,"QuotelikeQR\34Expr"=>1,"QuotelikeQR\34Expression"=>1,"QuotelikeQR\34List"=>1,"QuotelikeQR\34ListElem"=>1,"QuotelikeQR\34LowPrecedenceNotExpression"=>1,"QuotelikeQR\34PrefixPostfixTerm"=>1,"QuotelikeQR\34Quotelike"=>1,"QuotelikeQR\34Regex"=>1,"QuotelikeQR\34Regexp"=>1,"QuotelikeQR\34Statement"=>1,"QuotelikeQR\34Term"=>1,"QuotelikeQR\34Ternary"=>1,"QuotelikeQW\34Assignment"=>1,"QuotelikeQW\34BinaryExpression"=>1,"QuotelikeQW\34CommaList"=>1,"QuotelikeQW\34ConditionalExpression"=>1,"QuotelikeQW\34Document"=>1,"QuotelikeQW\34Expr"=>1,"QuotelikeQW\34Expression"=>1,"QuotelikeQW\34List"=>1,"QuotelikeQW\34ListElem"=>1,"QuotelikeQW\34LowPrecedenceNotExpression"=>1,"QuotelikeQW\34PrefixPostfixTerm"=>1,"QuotelikeQW\34Quotelike"=>1,"QuotelikeQW\34Statement"=>1,"QuotelikeQW\34Term"=>1,"QuotelikeQW\34Ternary"=>1,"QuotelikeQX\34Assignment"=>1,"QuotelikeQX\34BinaryExpression"=>1,"QuotelikeQX\34CommaList"=>1,"QuotelikeQX\34ConditionalExpression"=>1,"QuotelikeQX\34Document"=>1,"QuotelikeQX\34Expr"=>1,"QuotelikeQX\34Expression"=>1,"QuotelikeQX\34List"=>1,"QuotelikeQX\34ListElem"=>1,"QuotelikeQX\34LowPrecedenceNotExpression"=>1,"QuotelikeQX\34PrefixPostfixTerm"=>1,"QuotelikeQX\34Quotelike"=>1,"QuotelikeQX\34Statement"=>1,"QuotelikeQX\34Term"=>1,"QuotelikeQX\34Ternary"=>1,"QuotelikeS\34Assignment"=>1,"QuotelikeS\34BinaryExpression"=>1,"QuotelikeS\34CommaList"=>1,"QuotelikeS\34ConditionalExpression"=>1,"QuotelikeS\34Document"=>1,"QuotelikeS\34Expr"=>1,"QuotelikeS\34Expression"=>1,"QuotelikeS\34List"=>1,"QuotelikeS\34ListElem"=>1,"QuotelikeS\34LowPrecedenceNotExpression"=>1,"QuotelikeS\34PrefixPostfixTerm"=>1,"QuotelikeS\34Quotelike"=>1,"QuotelikeS\34Statement"=>1,"QuotelikeS\34Term"=>1,"QuotelikeS\34Ternary"=>1,"QuotelikeTR\34Assignment"=>1,"QuotelikeTR\34BinaryExpression"=>1,"QuotelikeTR\34CommaList"=>1,"QuotelikeTR\34ConditionalExpression"=>1,"QuotelikeTR\34Document"=>1,"QuotelikeTR\34Expr"=>1,"QuotelikeTR\34Expression"=>1,"QuotelikeTR\34List"=>1,"QuotelikeTR\34ListElem"=>1,"QuotelikeTR\34LowPrecedenceNotExpression"=>1,"QuotelikeTR\34PrefixPostfixTerm"=>1,"QuotelikeTR\34Quotelike"=>1,"QuotelikeTR\34Statement"=>1,"QuotelikeTR\34Term"=>1,"QuotelikeTR\34Ternary"=>1,"Regex\34Assignment"=>1,"Regex\34BinaryExpression"=>1,"Regex\34CommaList"=>1,"Regex\34ConditionalExpression"=>1,"Regex\34Document"=>1,"Regex\34Expr"=>1,"Regex\34Expression"=>1,"Regex\34List"=>1,"Regex\34ListElem"=>1,"Regex\34LowPrecedenceNotExpression"=>1,"Regex\34PrefixPostfixTerm"=>1,"Regex\34Quotelike"=>1,"Regex\34Statement"=>1,"Regex\34Term"=>1,"Regex\34Ternary"=>1,"Regexp\34Assignment"=>1,"Regexp\34BinaryExpression"=>1,"Regexp\34CommaList"=>1,"Regexp\34ConditionalExpression"=>1,"Regexp\34Document"=>1,"Regexp\34Expr"=>1,"Regexp\34Expression"=>1,"Regexp\34List"=>1,"Regexp\34ListElem"=>1,"Regexp\34LowPrecedenceNotExpression"=>1,"Regexp\34PrefixPostfixTerm"=>1,"Regexp\34Quotelike"=>1,"Regexp\34Statement"=>1,"Regexp\34Term"=>1,"Regexp\34Ternary"=>1,"ReturnStatement\34Assignment"=>1,"ReturnStatement\34BinaryExpression"=>1,"ReturnStatement\34CommaList"=>1,"ReturnStatement\34ConditionalExpression"=>1,"ReturnStatement\34Document"=>1,"ReturnStatement\34Expr"=>1,"ReturnStatement\34Expression"=>1,"ReturnStatement\34List"=>1,"ReturnStatement\34ListElem"=>1,"ReturnStatement\34LowPrecedenceNotExpression"=>1,"ReturnStatement\34PrefixPostfixTerm"=>1,"ReturnStatement\34Statement"=>1,"ReturnStatement\34Term"=>1,"ReturnStatement\34Ternary"=>1,"ScalarAccess\34Assignment"=>1,"ScalarAccess\34BinaryExpression"=>1,"ScalarAccess\34CommaList"=>1,"ScalarAccess\34ConditionalExpression"=>1,"ScalarAccess\34Document"=>1,"ScalarAccess\34Expr"=>1,"ScalarAccess\34Expression"=>1,"ScalarAccess\34List"=>1,"ScalarAccess\34ListElem"=>1,"ScalarAccess\34LowPrecedenceNotExpression"=>1,"ScalarAccess\34PrefixPostfixTerm"=>1,"ScalarAccess\34Statement"=>1,"ScalarAccess\34Term"=>1,"ScalarAccess\34Ternary"=>1,"ScalarAccess\34Var"=>1,"ScalarAccess\34Variable"=>1,"ScalarVar\34Assignment"=>1,"ScalarVar\34BinaryExpression"=>1,"ScalarVar\34CommaList"=>1,"ScalarVar\34ConditionalExpression"=>1,"ScalarVar\34Document"=>1,"ScalarVar\34Expr"=>1,"ScalarVar\34Expression"=>1,"ScalarVar\34List"=>1,"ScalarVar\34ListElem"=>1,"ScalarVar\34LowPrecedenceNotExpression"=>1,"ScalarVar\34PrefixPostfixTerm"=>1,"ScalarVar\34ScalarAccess"=>1,"ScalarVar\34Statement"=>1,"ScalarVar\34Term"=>1,"ScalarVar\34Ternary"=>1,"ScalarVar\34Var"=>1,"ScalarVar\34Variable"=>1,"Statement\34Document"=>1,"Str\34Assignment"=>1,"Str\34BinaryExpression"=>1,"Str\34CommaList"=>1,"Str\34ConditionalExpression"=>1,"Str\34Document"=>1,"Str\34Expr"=>1,"Str\34Expression"=>1,"Str\34List"=>1,"Str\34ListElem"=>1,"Str\34Literal"=>1,"Str\34LowPrecedenceNotExpression"=>1,"Str\34PrefixPostfixTerm"=>1,"Str\34Quotelike"=>1,"Str\34Statement"=>1,"Str\34Term"=>1,"Str\34Ternary"=>1,"String\34Assignment"=>1,"String\34BinaryExpression"=>1,"String\34CommaList"=>1,"String\34ConditionalExpression"=>1,"String\34Document"=>1,"String\34Expr"=>1,"String\34Expression"=>1,"String\34List"=>1,"String\34ListElem"=>1,"String\34Literal"=>1,"String\34LowPrecedenceNotExpression"=>1,"String\34PrefixPostfixTerm"=>1,"String\34Quotelike"=>1,"String\34Statement"=>1,"String\34Term"=>1,"String\34Ternary"=>1,"SubroutineDeclaration\34Document"=>1,"SubroutineDeclaration\34Statement"=>1,"Substitution\34Assignment"=>1,"Substitution\34BinaryExpression"=>1,"Substitution\34CommaList"=>1,"Substitution\34ConditionalExpression"=>1,"Substitution\34Document"=>1,"Substitution\34Expr"=>1,"Substitution\34Expression"=>1,"Substitution\34List"=>1,"Substitution\34ListElem"=>1,"Substitution\34LowPrecedenceNotExpression"=>1,"Substitution\34PrefixPostfixTerm"=>1,"Substitution\34Quotelike"=>1,"Substitution\34Statement"=>1,"Substitution\34Term"=>1,"Substitution\34Ternary"=>1,"Term\34Assignment"=>1,"Term\34BinaryExpression"=>1,"Term\34CommaList"=>1,"Term\34ConditionalExpression"=>1,"Term\34Document"=>1,"Term\34Expr"=>1,"Term\34Expression"=>1,"Term\34List"=>1,"Term\34ListElem"=>1,"Term\34LowPrecedenceNotExpression"=>1,"Term\34PrefixPostfixTerm"=>1,"Term\34Statement"=>1,"Term\34Ternary"=>1,"Ternary\34Assignment"=>1,"Ternary\34CommaList"=>1,"Ternary\34Document"=>1,"Ternary\34Expr"=>1,"Ternary\34Expression"=>1,"Ternary\34List"=>1,"Ternary\34LowPrecedenceNotExpression"=>1,"Ternary\34Statement"=>1,"Transliteration\34Assignment"=>1,"Transliteration\34BinaryExpression"=>1,"Transliteration\34CommaList"=>1,"Transliteration\34ConditionalExpression"=>1,"Transliteration\34Document"=>1,"Transliteration\34Expr"=>1,"Transliteration\34Expression"=>1,"Transliteration\34List"=>1,"Transliteration\34ListElem"=>1,"Transliteration\34LowPrecedenceNotExpression"=>1,"Transliteration\34PrefixPostfixTerm"=>1,"Transliteration\34Quotelike"=>1,"Transliteration\34Statement"=>1,"Transliteration\34Term"=>1,"Transliteration\34Ternary"=>1,"Typeglob\34Assignment"=>1,"Typeglob\34BinaryExpression"=>1,"Typeglob\34CommaList"=>1,"Typeglob\34ConditionalExpression"=>1,"Typeglob\34Document"=>1,"Typeglob\34Expr"=>1,"Typeglob\34Expression"=>1,"Typeglob\34List"=>1,"Typeglob\34ListElem"=>1,"Typeglob\34LowPrecedenceNotExpression"=>1,"Typeglob\34PrefixPostfixTerm"=>1,"Typeglob\34Statement"=>1,"Typeglob\34Term"=>1,"Typeglob\34Ternary"=>1,"UseStatement\34Document"=>1,"UseStatement\34Statement"=>1,"Var\34Assignment"=>1,"Var\34BinaryExpression"=>1,"Var\34CommaList"=>1,"Var\34ConditionalExpression"=>1,"Var\34Document"=>1,"Var\34Expr"=>1,"Var\34Expression"=>1,"Var\34List"=>1,"Var\34ListElem"=>1,"Var\34LowPrecedenceNotExpression"=>1,"Var\34PrefixPostfixTerm"=>1,"Var\34Statement"=>1,"Var\34Term"=>1,"Var\34Ternary"=>1,"VarArray\34ArrayAccess"=>1,"VarArray\34Assignment"=>1,"VarArray\34BinaryExpression"=>1,"VarArray\34CommaList"=>1,"VarArray\34ConditionalExpression"=>1,"VarArray\34Document"=>1,"VarArray\34Expr"=>1,"VarArray\34Expression"=>1,"VarArray\34List"=>1,"VarArray\34ListElem"=>1,"VarArray\34LowPrecedenceNotExpression"=>1,"VarArray\34PrefixPostfixTerm"=>1,"VarArray\34Statement"=>1,"VarArray\34Term"=>1,"VarArray\34Ternary"=>1,"VarArray\34Var"=>1,"VarArray\34Variable"=>1,"VarDecl\34Assignment"=>1,"VarDecl\34BinaryExpression"=>1,"VarDecl\34CommaList"=>1,"VarDecl\34ConditionalExpression"=>1,"VarDecl\34Document"=>1,"VarDecl\34Expr"=>1,"VarDecl\34Expression"=>1,"VarDecl\34List"=>1,"VarDecl\34ListElem"=>1,"VarDecl\34LowPrecedenceNotExpression"=>1,"VarDecl\34PrefixPostfixTerm"=>1,"VarDecl\34Statement"=>1,"VarDecl\34Term"=>1,"VarDecl\34Ternary"=>1,"VarHash\34Assignment"=>1,"VarHash\34BinaryExpression"=>1,"VarHash\34CommaList"=>1,"VarHash\34ConditionalExpression"=>1,"VarHash\34Document"=>1,"VarHash\34Expr"=>1,"VarHash\34Expression"=>1,"VarHash\34HashAccess"=>1,"VarHash\34List"=>1,"VarHash\34ListElem"=>1,"VarHash\34LowPrecedenceNotExpression"=>1,"VarHash\34PrefixPostfixTerm"=>1,"VarHash\34Statement"=>1,"VarHash\34Term"=>1,"VarHash\34Ternary"=>1,"VarHash\34Var"=>1,"VarHash\34Variable"=>1,"Variable\34Assignment"=>1,"Variable\34BinaryExpression"=>1,"Variable\34CommaList"=>1,"Variable\34ConditionalExpression"=>1,"Variable\34Document"=>1,"Variable\34Expr"=>1,"Variable\34Expression"=>1,"Variable\34List"=>1,"Variable\34ListElem"=>1,"Variable\34LowPrecedenceNotExpression"=>1,"Variable\34PrefixPostfixTerm"=>1,"Variable\34Statement"=>1,"Variable\34Term"=>1,"Variable\34Ternary"=>1,"VariableArray\34ArrayAccess"=>1,"VariableArray\34Assignment"=>1,"VariableArray\34BinaryExpression"=>1,"VariableArray\34CommaList"=>1,"VariableArray\34ConditionalExpression"=>1,"VariableArray\34Document"=>1,"VariableArray\34Expr"=>1,"VariableArray\34Expression"=>1,"VariableArray\34List"=>1,"VariableArray\34ListElem"=>1,"VariableArray\34LowPrecedenceNotExpression"=>1,"VariableArray\34PrefixPostfixTerm"=>1,"VariableArray\34Statement"=>1,"VariableArray\34Term"=>1,"VariableArray\34Ternary"=>1,"VariableArray\34Var"=>1,"VariableArray\34Variable"=>1,"VariableDeclaration\34Assignment"=>1,"VariableDeclaration\34BinaryExpression"=>1,"VariableDeclaration\34CommaList"=>1,"VariableDeclaration\34ConditionalExpression"=>1,"VariableDeclaration\34Document"=>1,"VariableDeclaration\34Expr"=>1,"VariableDeclaration\34Expression"=>1,"VariableDeclaration\34List"=>1,"VariableDeclaration\34ListElem"=>1,"VariableDeclaration\34LowPrecedenceNotExpression"=>1,"VariableDeclaration\34PrefixPostfixTerm"=>1,"VariableDeclaration\34Statement"=>1,"VariableDeclaration\34Term"=>1,"VariableDeclaration\34Ternary"=>1,"VariableHash\34Assignment"=>1,"VariableHash\34BinaryExpression"=>1,"VariableHash\34CommaList"=>1,"VariableHash\34ConditionalExpression"=>1,"VariableHash\34Document"=>1,"VariableHash\34Expr"=>1,"VariableHash\34Expression"=>1,"VariableHash\34HashAccess"=>1,"VariableHash\34List"=>1,"VariableHash\34ListElem"=>1,"VariableHash\34LowPrecedenceNotExpression"=>1,"VariableHash\34PrefixPostfixTerm"=>1,"VariableHash\34Statement"=>1,"VariableHash\34Term"=>1,"VariableHash\34Ternary"=>1,"VariableHash\34Var"=>1,"VariableHash\34Variable"=>1,"VariableScalar\34Assignment"=>1,"VariableScalar\34BinaryExpression"=>1,"VariableScalar\34CommaList"=>1,"VariableScalar\34ConditionalExpression"=>1,"VariableScalar\34Document"=>1,"VariableScalar\34Expr"=>1,"VariableScalar\34Expression"=>1,"VariableScalar\34List"=>1,"VariableScalar\34ListElem"=>1,"VariableScalar\34LowPrecedenceNotExpression"=>1,"VariableScalar\34PrefixPostfixTerm"=>1,"VariableScalar\34ScalarAccess"=>1,"VariableScalar\34Statement"=>1,"VariableScalar\34Term"=>1,"VariableScalar\34Ternary"=>1,"VariableScalar\34Var"=>1,"VariableScalar\34Variable"=>1,"VarScalar\34Assignment"=>1,"VarScalar\34BinaryExpression"=>1,"VarScalar\34CommaList"=>1,"VarScalar\34ConditionalExpression"=>1,"VarScalar\34Document"=>1,"VarScalar\34Expr"=>1,"VarScalar\34Expression"=>1,"VarScalar\34List"=>1,"VarScalar\34ListElem"=>1,"VarScalar\34LowPrecedenceNotExpression"=>1,"VarScalar\34PrefixPostfixTerm"=>1,"VarScalar\34ScalarAccess"=>1,"VarScalar\34Statement"=>1,"VarScalar\34Term"=>1,"VarScalar\34Ternary"=>1,"VarScalar\34Var"=>1,"VarScalar\34Variable"=>1,"VersionNumber\34Assignment"=>1,"VersionNumber\34BinaryExpression"=>1,"VersionNumber\34CommaList"=>1,"VersionNumber\34ConditionalExpression"=>1,"VersionNumber\34Document"=>1,"VersionNumber\34Expr"=>1,"VersionNumber\34Expression"=>1,"VersionNumber\34List"=>1,"VersionNumber\34ListElem"=>1,"VersionNumber\34Literal"=>1,"VersionNumber\34LowPrecedenceNotExpression"=>1,"VersionNumber\34Num"=>1,"VersionNumber\34Number"=>1,"VersionNumber\34PrefixPostfixTerm"=>1,"VersionNumber\34Statement"=>1,"VersionNumber\34Term"=>1,"VersionNumber\34Ternary"=>1,"VString\34Assignment"=>1,"VString\34BinaryExpression"=>1,"VString\34CommaList"=>1,"VString\34ConditionalExpression"=>1,"VString\34Document"=>1,"VString\34Expr"=>1,"VString\34Expression"=>1,"VString\34List"=>1,"VString\34ListElem"=>1,"VString\34Literal"=>1,"VString\34LowPrecedenceNotExpression"=>1,"VString\34Num"=>1,"VString\34Number"=>1,"VString\34PrefixPostfixTerm"=>1,"VString\34Statement"=>1,"VString\34Str"=>1,"VString\34String"=>1,"VString\34Term"=>1,"VString\34Ternary"=>1,"VString\34VersionNumber"=>1,"Whitespace\34OWS"=>1, |
659
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
# End of autogenerated type ISA hierarchy |
661
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
); |
663
|
|
|
|
|
|
|
|
664
|
|
|
|
|
|
|
# Convert type aliases into standard PPR types... |
665
|
168
|
|
|
168
|
|
395
|
sub _resolve_type { |
666
|
|
|
|
|
|
|
my ($type, $user_defined_type_for) = @_; |
667
|
|
|
|
|
|
|
|
668
|
168
|
|
100
|
|
|
1714
|
# Identify valid user-defined types in the current calling scope... |
|
5883
|
|
|
|
|
9869
|
|
669
|
|
|
|
|
|
|
$user_defined_type_for //= { map { m{ \A Keyword::Declare \s* keytype: (\w+) = (.*) }xms } keys %^H }; |
670
|
168
|
|
|
|
|
956
|
|
671
|
|
|
|
|
|
|
while ($type =~ /\A \w++ \Z/x) { |
672
|
|
|
|
|
|
|
$type = $user_defined_type_for->{$type} |
673
|
|
|
|
|
|
|
// $ACTUAL_TYPE_OF{$type} |
674
|
171
|
|
66
|
|
|
1339
|
// croak "Unknown type ($type) for keyword parameter.\nDid you mean: ", |
|
0
|
|
33
|
|
|
0
|
|
675
|
|
|
|
|
|
|
join(' or ', grep { lc substr($_,0,1) eq lc substr($type,0,1) } keys %ACTUAL_TYPE_OF); |
676
|
|
|
|
|
|
|
} |
677
|
168
|
100
|
|
|
|
14709
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
678
|
1
|
|
|
|
|
11
|
if ($type =~ m{\A (?: q\s*\S | ' ) (.*) \S \z }x) { |
679
|
|
|
|
|
|
|
return quotemeta $1 |
680
|
|
|
|
|
|
|
} |
681
|
166
|
50
|
|
|
|
3514
|
elsif ($type =~ $REGEX_TYPE ) { |
682
|
166
|
|
|
|
|
1289
|
$type =~ $REGEX_PAT or die "Keyword::Declare internal error: weird regex"; |
683
|
166
|
|
|
|
|
797
|
my $pat = $+{pattern}; |
684
|
166
|
|
|
|
|
531
|
my $mods = $+{modifiers}; |
685
|
166
|
|
|
|
|
1328
|
$pat =~ s{(?
|
686
|
|
|
|
|
|
|
return "(?$mods:$pat)"; |
687
|
|
|
|
|
|
|
} |
688
|
1
|
|
|
|
|
6
|
elsif ($type =~ $TYPE_JUNCTION) { |
|
2
|
|
|
|
|
9
|
|
689
|
|
|
|
|
|
|
return join '|', map { _resolve_type($_, $user_defined_type_for) } split /[|]/, $type; |
690
|
|
|
|
|
|
|
} |
691
|
0
|
|
|
|
|
0
|
else { |
692
|
|
|
|
|
|
|
die 'Keyword::Declare internal error: incomprehensible type: [$type]'; |
693
|
|
|
|
|
|
|
} |
694
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
} |
696
|
|
|
|
|
|
|
|
697
|
|
|
|
|
|
|
# Convert named types and explicit regexes or strings to matcher regex... |
698
|
178
|
|
|
178
|
|
341
|
sub _convert_type_to_matcher { |
699
|
|
|
|
|
|
|
my ($param) = @_; |
700
|
178
|
|
|
|
|
259
|
|
701
|
|
|
|
|
|
|
my $matcher; |
702
|
|
|
|
|
|
|
|
703
|
|
|
|
|
|
|
# Convert type specification to PPR subrule invocations and build a description... |
704
|
178
|
|
|
|
|
390
|
# ...for named types... |
705
|
178
|
100
|
|
|
|
1045
|
my $type = $param->{type}; |
706
|
|
|
|
|
|
|
if ($type =~ m{\A \w++ (?: [|] \w++ )* \Z}x) { |
707
|
163
|
|
|
|
|
687
|
# Extract component types... |
708
|
|
|
|
|
|
|
my @types = split /[|]/, $type; |
709
|
|
|
|
|
|
|
|
710
|
163
|
|
|
|
|
382
|
# First set up pseudo-inheritance... |
711
|
166
|
|
|
|
|
881
|
for my $component_type (@types) { |
712
|
|
|
|
|
|
|
$isa{$component_type, $type} = 1; |
713
|
|
|
|
|
|
|
} |
714
|
|
|
|
|
|
|
|
715
|
163
|
|
33
|
|
|
820
|
# Convert component types to regexes... |
716
|
163
|
100
|
|
|
|
621
|
$param->{desc} //= do { |
717
|
163
|
|
|
|
|
335
|
my $desc = $param->{name} ? "<$param->{name}>" : '<'.join(' or ', @types).'>'; |
718
|
163
|
|
|
|
|
662
|
$desc =~ tr/_/ /; |
719
|
|
|
|
|
|
|
$desc; |
720
|
163
|
|
|
|
|
381
|
}; |
|
166
|
|
|
|
|
405
|
|
721
|
|
|
|
|
|
|
$type = '/' . join('|', map { _resolve_type( $_ ) } @types) . '/'; |
722
|
|
|
|
|
|
|
|
723
|
|
|
|
|
|
|
} |
724
|
|
|
|
|
|
|
|
725
|
178
|
100
|
|
|
|
7957
|
# ...for literal string types... |
|
|
50
|
|
|
|
|
|
726
|
|
|
|
|
|
|
if ($type =~ m{\A (?: q\s*\S | ' ) (.*) \S \z }x) { |
727
|
|
|
|
|
|
|
$param->{desc} |
728
|
7
|
100
|
33
|
|
|
46
|
//= ($param->{name} |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
11
|
|
729
|
|
|
|
|
|
|
? do{ my $name = "<$param->{name}>"; $name =~ tr/_/ /; $name } |
730
|
|
|
|
|
|
|
: $1 |
731
|
7
|
|
|
|
|
20
|
); |
732
|
|
|
|
|
|
|
$matcher = '(?:' . quotemeta($1) . ')'; |
733
|
|
|
|
|
|
|
} |
734
|
|
|
|
|
|
|
|
735
|
|
|
|
|
|
|
# ...for regex types... |
736
|
171
|
50
|
|
|
|
4039
|
elsif ($type =~ $REGEX_TYPE ) { |
737
|
171
|
|
|
|
|
2250
|
$type =~ $REGEX_PAT or die "Keyword::Declare internal error: weird regex"; |
738
|
171
|
|
|
|
|
732
|
my %match = %+; |
739
|
|
|
|
|
|
|
$match{pattern} =~ s{(?
|
740
|
|
|
|
|
|
|
$param->{desc} |
741
|
171
|
100
|
66
|
|
|
513
|
//= ($param->{name} |
|
7
|
|
|
|
|
26
|
|
|
7
|
|
|
|
|
16
|
|
|
7
|
|
|
|
|
30
|
|
742
|
|
|
|
|
|
|
? do{ my $name = "<$param->{name}>"; $name =~ tr/_/ /; $name } |
743
|
|
|
|
|
|
|
: "/$match{pattern}/$match{modifiers}" |
744
|
171
|
|
|
|
|
699
|
); |
745
|
|
|
|
|
|
|
$matcher = "(?$match{modifiers}:$match{pattern})"; |
746
|
|
|
|
|
|
|
} |
747
|
|
|
|
|
|
|
|
748
|
|
|
|
|
|
|
# Incomprehensible types... |
749
|
0
|
|
|
|
|
0
|
else { |
750
|
|
|
|
|
|
|
die "Keyword::Declare internal error: incomprehensible type: [$type]" |
751
|
|
|
|
|
|
|
} |
752
|
178
|
|
|
|
|
533
|
|
753
|
|
|
|
|
|
|
return $matcher; |
754
|
|
|
|
|
|
|
} |
755
|
|
|
|
|
|
|
|
756
|
|
|
|
|
|
|
# This class allows captures from type-regexes to be preserved and accessed... |
757
|
|
|
|
|
|
|
{ |
758
|
|
|
|
|
|
|
package Keyword::Declare::Arg; |
759
|
117
|
|
|
117
|
|
319375
|
use overload |
760
|
19
|
|
|
|
|
271
|
'""' => sub { $_[0]{""} }, |
761
|
19
|
|
|
19
|
|
146555
|
fallback => 1 |
|
19
|
|
|
|
|
77
|
|
762
|
|
|
|
|
|
|
} |
763
|
|
|
|
|
|
|
|
764
|
|
|
|
|
|
|
# Extract a string or a Keyword::Declare::Arg object from the most recent match... |
765
|
128
|
|
|
128
|
|
1287801
|
sub _objectify { |
766
|
|
|
|
|
|
|
my ($match_str, $captures_ref) = @_; |
767
|
|
|
|
|
|
|
|
768
|
128
|
|
|
|
|
795
|
# Trim any leading Perlish whitespace from the match... |
769
|
|
|
|
|
|
|
$match_str =~ s{^(?: \s*+ (?: [#].*\n \s*+)*+)}{}x; |
770
|
|
|
|
|
|
|
|
771
|
128
|
100
|
|
|
|
304
|
# Just return the match if there were no captures... |
|
128
|
|
|
|
|
35289
|
|
772
|
|
|
|
|
|
|
return $match_str if !keys %{$captures_ref}; |
773
|
92
|
|
|
|
|
282
|
|
|
92
|
|
|
|
|
583
|
|
774
|
92
|
|
100
|
|
|
698
|
my $obj = { q{}=>$match_str, %{$captures_ref} }; |
775
|
92
|
|
|
|
|
860
|
$obj->{':sep'} = delete( $obj->{____KD___sep} ) // q{}; |
776
|
|
|
|
|
|
|
return bless $obj, 'Keyword::Declare::Arg'; |
777
|
|
|
|
|
|
|
} |
778
|
|
|
|
|
|
|
|
779
|
|
|
|
|
|
|
# Convert the keyword's parameter list to various useful representations... |
780
|
157
|
|
|
157
|
|
285
|
sub _unpack_signature { |
781
|
|
|
|
|
|
|
my ($keyword_info_ref) = @_; |
782
|
|
|
|
|
|
|
|
783
|
157
|
|
|
|
|
324
|
# We're setting up all these entries... |
784
|
157
|
|
|
|
|
429
|
my $sig_vars = ""; # List of variables into which keyword args are unpacked |
785
|
157
|
|
|
|
|
363
|
$keyword_info_ref->{sig_vars_unpack} = ""; # Statements that unpack keyword args |
786
|
157
|
|
|
|
|
313
|
$keyword_info_ref->{sig_matcher} = ""; # Pattern that matches entire arg list |
787
|
157
|
|
|
|
|
344
|
$keyword_info_ref->{sig_skip_matcher} = ""; # Pattern that matches entire arg list without captures |
788
|
157
|
|
|
|
|
310
|
$keyword_info_ref->{sig} = []; # Array of parameter types |
789
|
157
|
|
|
|
|
315
|
$keyword_info_ref->{sig_quantified} = []; # Array of quantified parameter types |
790
|
157
|
|
|
|
|
546
|
$keyword_info_ref->{sig_names} = []; # Names of each parameter ("" if no unnamed) |
791
|
|
|
|
|
|
|
$keyword_info_ref->{sig_defaults} = {}; # Defaults for any parameter that has them |
792
|
|
|
|
|
|
|
|
793
|
157
|
|
|
|
|
288
|
# Walk through the parameters... |
794
|
157
|
|
|
|
|
241
|
my $not_post = 1; |
|
157
|
|
|
|
|
561
|
|
795
|
177
|
100
|
|
|
|
458
|
for my $param (@{$keyword_info_ref->{param_list}}) { |
796
|
1
|
|
|
|
|
2
|
if (!defined($param)) { |
797
|
1
|
|
|
|
|
3
|
$not_post = 0; |
798
|
|
|
|
|
|
|
next; |
799
|
|
|
|
|
|
|
} |
800
|
|
|
|
|
|
|
|
801
|
176
|
|
|
|
|
439
|
# Generate a regex to match this parameter (note: modifies $param!)... |
802
|
|
|
|
|
|
|
my $matcher = _convert_type_to_matcher($param); |
803
|
|
|
|
|
|
|
|
804
|
176
|
|
|
|
|
333
|
# Generate a regex to match the separator (if any)... |
805
|
176
|
100
|
|
|
|
484
|
my $sep; |
806
|
2
|
|
|
|
|
10
|
if ($param->{sep}) { |
807
|
|
|
|
|
|
|
$sep = _convert_type_to_matcher({name=>':sep', type=>$param->{sep}}); |
808
|
|
|
|
|
|
|
} |
809
|
|
|
|
|
|
|
|
810
|
176
|
50
|
|
|
|
442
|
# Resolve implicit quantification (and any default value)... |
811
|
0
|
|
|
|
|
0
|
if (exists $param->{default}) { |
812
|
0
|
|
|
|
|
0
|
my $def = $param->{default}; |
813
|
0
|
|
|
|
|
0
|
$def =~ s{\A (?: qq? \s* \S | ["']) (.*) \S \Z }{$1}gx; |
814
|
0
|
0
|
0
|
|
|
0
|
$keyword_info_ref->{sig_defaults}{$param->{name}} = $def; |
|
|
|
0
|
|
|
|
|
815
|
|
|
|
|
|
|
$param->{quantifier} //= $param->{sigil} && $param->{sigil} eq '@' ? '*' : '?'; |
816
|
|
|
|
|
|
|
} |
817
|
176
|
100
|
100
|
|
|
1195
|
else { |
|
|
|
100
|
|
|
|
|
818
|
|
|
|
|
|
|
$param->{quantifier} //= $param->{sigil} && $param->{sigil} eq '@' ? '+' : ''; |
819
|
|
|
|
|
|
|
} |
820
|
|
|
|
|
|
|
|
821
|
|
|
|
|
|
|
# Matchers handle leading whitespace (unless they ARE whitespace)... |
822
|
176
|
50
|
|
|
|
686
|
$matcher = "(?:(?&PerlOWS)$matcher)" |
823
|
|
|
|
|
|
|
if $param->{type} !~ m{^/\(\?\&Perl[ON]WS\)/$}; |
824
|
|
|
|
|
|
|
|
825
|
176
|
|
|
|
|
360
|
# Quantified parameters are repeatable... |
826
|
176
|
100
|
|
|
|
446
|
my $single_matcher = $matcher; |
827
|
|
|
|
|
|
|
if ($param->{quantifier}) { |
828
|
22
|
100
|
|
|
|
56
|
# Unseparated parameters are easy... |
829
|
20
|
|
|
|
|
72
|
if (!$sep) { |
830
|
|
|
|
|
|
|
$matcher = "(?:$matcher$param->{quantifier})"; |
831
|
|
|
|
|
|
|
} |
832
|
|
|
|
|
|
|
# Separated parameters are more complex... |
833
|
2
|
|
|
|
|
9
|
else { |
834
|
2
|
100
|
|
|
|
8
|
$matcher = "(?:$matcher(?:(?&PerlOWS)$sep(?&PerlOWS)$matcher)*)"; |
835
|
2
|
|
|
|
|
7
|
$matcher .= '?' if $param->{quantifier} eq '*'; |
836
|
|
|
|
|
|
|
$single_matcher .= "(?=(?<____KD___sep>$sep))?"; |
837
|
|
|
|
|
|
|
} |
838
|
|
|
|
|
|
|
} |
839
|
|
|
|
|
|
|
|
840
|
|
|
|
|
|
|
|
841
|
176
|
|
|
|
|
322
|
# Named parameters have to be named captured... |
842
|
176
|
100
|
|
|
|
441
|
my $skip_matcher = $matcher; |
843
|
165
|
|
|
|
|
455
|
if ($param->{name}) { |
844
|
|
|
|
|
|
|
$matcher = "(?<$param->{name}>$matcher)"; |
845
|
|
|
|
|
|
|
} |
846
|
|
|
|
|
|
|
|
847
|
176
|
|
|
|
|
446
|
# Accumulate the signature matching pattern... |
848
|
176
|
100
|
|
|
|
511
|
$keyword_info_ref->{sig_matcher} .= $matcher; |
849
|
|
|
|
|
|
|
$keyword_info_ref->{sig_skip_matcher} .= $skip_matcher |
850
|
|
|
|
|
|
|
if $not_post; |
851
|
|
|
|
|
|
|
|
852
|
176
|
|
|
|
|
294
|
# Accumulate signature types and names (if any)... |
|
176
|
|
|
|
|
501
|
|
853
|
176
|
|
|
|
|
276
|
push @{ $keyword_info_ref->{sig} }, $param->{type}; |
|
176
|
|
|
|
|
504
|
|
854
|
176
|
|
100
|
|
|
274
|
push @{ $keyword_info_ref->{sig_quantified} }, $param->{type}.$param->{quantifier}; |
|
176
|
|
|
|
|
534
|
|
855
|
|
|
|
|
|
|
push @{ $keyword_info_ref->{sig_names} }, $param->{name} // q{}; |
856
|
|
|
|
|
|
|
|
857
|
176
|
100
|
|
|
|
440
|
# Accumulate variable list into which parameters will be unpacked... |
858
|
165
|
100
|
100
|
|
|
876
|
if ($param->{name}) { |
859
|
|
|
|
|
|
|
my $match_once = $param->{sigil} ne '$' || $single_matcher =~ /\(\? |
860
|
|
|
|
|
|
|
? "m{$single_matcher\$PPR::GRAMMAR}" |
861
|
|
|
|
|
|
|
: "m{}"; |
862
|
165
|
|
|
|
|
426
|
|
863
|
|
|
|
|
|
|
$sig_vars .= "$param->{sigil}$param->{name},"; |
864
|
165
|
100
|
|
|
|
1062
|
$keyword_info_ref->{sig_vars_unpack} .= "$param->{sigil}$param->{name} = " |
865
|
|
|
|
|
|
|
. ( $param->{sigil} eq '$' |
866
|
|
|
|
|
|
|
? qq{do { my \$arg = shift(); |
867
|
|
|
|
|
|
|
\$arg =~ $match_once; |
868
|
|
|
|
|
|
|
Keyword::Declare::_objectify(\$arg,{%+}); |
869
|
|
|
|
|
|
|
}; |
870
|
|
|
|
|
|
|
} |
871
|
|
|
|
|
|
|
: qq{do { my \@data; |
872
|
|
|
|
|
|
|
my \$arg = shift(); |
873
|
|
|
|
|
|
|
while (\$arg =~ /\\S/ && \$arg =~ ${match_once}g) { |
874
|
|
|
|
|
|
|
push \@data, |
875
|
|
|
|
|
|
|
Keyword::Declare::_objectify(\$&,{%+}); |
876
|
|
|
|
|
|
|
} |
877
|
|
|
|
|
|
|
\@data; |
878
|
|
|
|
|
|
|
}; |
879
|
|
|
|
|
|
|
} |
880
|
|
|
|
|
|
|
) |
881
|
|
|
|
|
|
|
} |
882
|
11
|
|
|
|
|
37
|
else { |
883
|
|
|
|
|
|
|
$keyword_info_ref->{sig_vars_unpack} .= 'shift();'; |
884
|
|
|
|
|
|
|
} |
885
|
|
|
|
|
|
|
} |
886
|
|
|
|
|
|
|
|
887
|
|
|
|
|
|
|
# use Data::Show; show $keyword_info_ref->{sig_vars_unpack}; |
888
|
|
|
|
|
|
|
|
889
|
157
|
|
|
|
|
319
|
# Build a human readable version of the signature... |
|
157
|
|
|
|
|
571
|
|
890
|
|
|
|
|
|
|
$keyword_info_ref->{sig_desc} = '(' . join(',', @{$keyword_info_ref->{sig_quantified}}) . ')'; |
891
|
|
|
|
|
|
|
|
892
|
|
|
|
|
|
|
# Build a pretty description for debugging and error messages... |
893
|
157
|
|
|
|
|
556
|
$keyword_info_ref->{syntax} = "$keyword_info_ref->{keyword} " |
|
176
|
|
|
|
|
612
|
|
|
177
|
|
|
|
|
549
|
|
894
|
|
|
|
|
|
|
. join(" ", map { $_->{desc} } grep {defined} @Keyword::Declare::params); |
895
|
|
|
|
|
|
|
|
896
|
157
|
|
|
|
|
511
|
# Build a regex that matches the keyword plus its arguments... |
897
|
157
|
|
|
|
|
443
|
$keyword_info_ref->{matcher} = "$keyword_info_ref->{keyword}$keyword_info_ref->{sig_matcher}"; |
898
|
|
|
|
|
|
|
$keyword_info_ref->{skip_matcher} = "$keyword_info_ref->{keyword}$keyword_info_ref->{sig_skip_matcher}"; |
899
|
|
|
|
|
|
|
|
900
|
157
|
|
|
|
|
245
|
# Precompute the length of the signature (for multiple-dispatch tie-breaking)... |
|
157
|
|
|
|
|
360
|
|
901
|
|
|
|
|
|
|
$keyword_info_ref->{sig_len} = scalar @{ $keyword_info_ref->{sig} }; |
902
|
|
|
|
|
|
|
|
903
|
|
|
|
|
|
|
# Consolidate the signature-unpacking code... |
904
|
157
|
100
|
|
|
|
701
|
$keyword_info_ref->{sig_vars_unpack} = |
905
|
|
|
|
|
|
|
$sig_vars ? "my ($sig_vars); $keyword_info_ref->{sig_vars_unpack}" : q{}; |
906
|
|
|
|
|
|
|
} |
907
|
|
|
|
|
|
|
|
908
|
|
|
|
|
|
|
|
909
|
|
|
|
|
|
|
# Extract and verify any attrs specified on the keyword... |
910
|
157
|
|
|
157
|
|
342
|
sub _unpack_attrs { |
911
|
|
|
|
|
|
|
my ($keyword_info_ref) = @_; |
912
|
|
|
|
|
|
|
|
913
|
157
|
100
|
|
|
|
518
|
# Are there any keyword attrs to unpack??? |
914
|
|
|
|
|
|
|
if ($keyword_info_ref->{attrs}) { |
915
|
|
|
|
|
|
|
# Extract any :prefer or :keepspace attr... |
916
|
3
|
|
|
|
|
30
|
$keyword_info_ref->{prefer} |
917
|
|
|
|
|
|
|
= $keyword_info_ref->{attrs} =~ s{\bprefer\b}{}xms; |
918
|
3
|
|
|
|
|
16
|
$keyword_info_ref->{keepspace} |
919
|
|
|
|
|
|
|
= $keyword_info_ref->{attrs} =~ s{\bkeepspace\b}{}xms; |
920
|
|
|
|
|
|
|
|
921
|
3
|
50
|
|
|
|
85
|
# Extract any :desc(...) attr... |
922
|
0
|
|
|
|
|
0
|
if ($keyword_info_ref->{attrs} =~ s{\bdesc\( (.*?) \)}{}xms) { |
923
|
|
|
|
|
|
|
$keyword_info_ref->{desc} = $1; |
924
|
|
|
|
|
|
|
} |
925
|
3
|
|
|
|
|
19
|
else { |
926
|
|
|
|
|
|
|
$keyword_info_ref->{desc} = $keyword_info_ref->{keyword}; |
927
|
|
|
|
|
|
|
} |
928
|
|
|
|
|
|
|
|
929
|
3
|
50
|
|
|
|
19
|
# Extract any :prefix(...) attr... |
930
|
0
|
|
|
|
|
0
|
if ($keyword_info_ref->{attrs} =~ s{\bprefix\( \s* (\$[^\W\d]\w*) \s* \)}{}xms) { |
931
|
|
|
|
|
|
|
$keyword_info_ref->{prefix} = $1; |
932
|
|
|
|
|
|
|
} |
933
|
|
|
|
|
|
|
|
934
|
|
|
|
|
|
|
# Complain about anything else... |
935
|
3
|
50
|
|
|
|
13
|
croak ":then attribute specified too late (must come immediately after parameter list)" |
936
|
|
|
|
|
|
|
if $keyword_info_ref->{attrs} =~ s{\bthen\b}{}xms; |
937
|
3
|
50
|
|
|
|
19
|
croak "Invalid attribute: $keyword_info_ref->{attrs}" |
938
|
|
|
|
|
|
|
if $keyword_info_ref->{attrs} =~ /[^\s:]/; |
939
|
|
|
|
|
|
|
} |
940
|
|
|
|
|
|
|
} |
941
|
|
|
|
|
|
|
|
942
|
|
|
|
|
|
|
|
943
|
|
|
|
|
|
|
# Convert a {{{...}}} interpolated keyword body to a normal body... |
944
|
23
|
|
|
23
|
|
62
|
sub _convert_triple_block { |
|
23
|
|
|
|
|
116
|
|
945
|
|
|
|
|
|
|
my ($block, $keyword) = @{shift()}{qw< block keyword >}; |
946
|
|
|
|
|
|
|
|
947
|
23
|
|
|
|
|
81
|
# Peel off extra curlies... |
948
|
|
|
|
|
|
|
$block = substr($block, 3, -3); |
949
|
|
|
|
|
|
|
|
950
|
23
|
100
|
|
|
|
143
|
# Report unclosed «...}> interpolations... |
951
|
6
|
|
|
|
|
74
|
if ($block =~ m{ <\{ (? (? \s* \S*) .*? ) (?: <\{ | « | \Z ) }xms) { |
952
|
|
|
|
|
|
|
my %match = %+; |
953
|
|
|
|
|
|
|
croak qq[Missing }> on interpolation <{$match{leader}...\n] |
954
|
6
|
50
|
|
|
|
55
|
. qq[in string-style block of keyword $keyword\ndefined] |
955
|
|
|
|
|
|
|
if $match{interpolation} !~ m{ \}> }xms; |
956
|
23
|
100
|
|
|
|
153
|
} |
957
|
10
|
|
|
|
|
138
|
if ($block =~ m{ « (? (? \s* \S*) .*? ) (?: <\{ | « | \Z ) }xms) { |
958
|
|
|
|
|
|
|
my %match = %+; |
959
|
|
|
|
|
|
|
croak qq[Missing » on interpolation «$match{leader}...\n] |
960
|
10
|
50
|
|
|
|
78
|
. qq[in string-style block of keyword $keyword\ndefined] |
961
|
|
|
|
|
|
|
if $match{interpolation} !~ m{ » }xms; |
962
|
|
|
|
|
|
|
} |
963
|
|
|
|
|
|
|
|
964
|
23
|
|
|
|
|
237
|
# Convert the inter polated text to code that does the interpolations... |
965
|
|
|
|
|
|
|
$block =~ s{ |
966
|
|
|
|
|
|
|
« (? .*? ) » |
967
|
|
|
|
|
|
|
| |
968
|
|
|
|
|
|
|
<\{ (? .*? ) \}> |
969
|
|
|
|
|
|
|
| |
970
|
|
|
|
|
|
|
(? .+? ) (?= <\{ | « | \z ) |
971
|
65
|
100
|
|
|
|
427
|
}{ |
|
43
|
50
|
|
|
|
358
|
|
972
|
22
|
|
|
|
|
194
|
if (exists $+{literal_code} ) { 'qq{' . quotemeta($+{literal_code}) . '},'; } |
973
|
0
|
|
|
|
|
0
|
elsif (exists $+{interpolation}) { qq{ do{$+{interpolation}}, }; } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
974
|
|
|
|
|
|
|
else { say {*STDERR} 'Keyword::Declare internal error in {{{...}}} block'; exit; } |
975
|
|
|
|
|
|
|
}gexms; |
976
|
|
|
|
|
|
|
|
977
|
23
|
|
|
|
|
136
|
# Build and return the block's new source code... |
978
|
|
|
|
|
|
|
return "{ return join '', $block; }"; |
979
|
|
|
|
|
|
|
} |
980
|
|
|
|
|
|
|
|
981
|
|
|
|
|
|
|
|
982
|
|
|
|
|
|
|
# Transform a keyword invocation into the code generated by the keyword's body... |
983
|
76
|
|
|
76
|
|
422
|
sub _insert_replacement_code { |
984
|
|
|
|
|
|
|
my ($src_ref, $ID, $file, $line, $active_keywords) = @_; |
985
|
|
|
|
|
|
|
|
986
|
76
|
|
|
|
|
263
|
# Unpack keyword information... |
987
|
|
|
|
|
|
|
my $keyword = $keyword_impls[$ID]; |
988
|
|
|
|
|
|
|
|
989
|
76
|
|
|
|
|
2637484
|
# Remove the arguments from the source code... |
990
|
76
|
|
|
|
|
29067
|
$$src_ref =~ s{ \A ($keyword->{sig_matcher}) $active_keywords $PPR::GRAMMAR }{}xms; |
991
|
76
|
|
|
|
|
602
|
my %args = %+; |
992
|
|
|
|
|
|
|
for my $argname (keys %args) { |
993
|
118
|
100
|
50
|
|
|
740
|
$args{$argname} = $keyword->{sig_defaults}{$argname} // q{} |
994
|
|
|
|
|
|
|
if $args{$argname} eq q{}; |
995
|
76
|
|
|
|
|
385
|
} |
996
|
76
|
|
|
|
|
207
|
my $arg_list = $1; |
|
76
|
|
|
|
|
653
|
|
997
|
|
|
|
|
|
|
my @args = @args{ @{$keyword_impls[$ID]{sig_names}} }; |
998
|
|
|
|
|
|
|
|
999
|
|
|
|
|
|
|
# Tidy them, if requested... |
1000
|
|
|
|
|
|
|
@args = map { |
1001
|
130
|
100
|
|
|
|
964
|
!defined($_) ? undef |
|
91
|
100
|
|
|
|
199
|
|
1002
|
91
|
|
|
|
|
432
|
: m{\S} ? do { my $arg = $_; |
1003
|
91
|
|
|
|
|
914
|
$arg =~ s{\A\s*+(?:\#.*\n\s*+)*+}{}; |
1004
|
91
|
|
|
|
|
364
|
$arg =~ s{\s*+(?:\#.*\n\s*+)*+\z}{}; |
1005
|
|
|
|
|
|
|
$arg; |
1006
|
|
|
|
|
|
|
} |
1007
|
|
|
|
|
|
|
: $_ |
1008
|
76
|
50
|
|
|
|
488
|
} @args |
1009
|
|
|
|
|
|
|
if !$keyword->{keepspace}; |
1010
|
|
|
|
|
|
|
|
1011
|
76
|
|
|
|
|
340
|
# Adjust the line number so trailing code stays correct... |
1012
|
|
|
|
|
|
|
$line += $arg_list =~ tr/\n//; |
1013
|
|
|
|
|
|
|
|
1014
|
76
|
|
50
|
|
|
538
|
# Generate replacement code... |
1015
|
|
|
|
|
|
|
my $replacement_code = $keyword->{generator}->(@args) // q{}; |
1016
|
|
|
|
|
|
|
|
1017
|
76
|
50
|
|
|
|
50555
|
# If debugging requested, provide a summary of the substitution... |
1018
|
0
|
|
|
|
|
0
|
if (${^H}{"Keyword::Declare debug"}) { |
1019
|
0
|
|
|
|
|
0
|
my $keyword = " $keyword_impls[$ID]{syntax}"; |
1020
|
0
|
|
|
|
|
0
|
my $from = " $keyword_impls[$ID]{keyword} $arg_list"; |
1021
|
0
|
|
|
|
|
0
|
my $to = $replacement_code; |
1022
|
0
|
|
|
|
|
0
|
$to =~ s{\A\s*\n|\n\s*\Z}{}gm; |
1023
|
0
|
|
|
|
|
0
|
$to =~ s{\h+}{ }g; |
1024
|
|
|
|
|
|
|
$to =~ s{^}{ }gm; |
1025
|
0
|
|
|
|
|
0
|
|
1026
|
|
|
|
|
|
|
my $msg |
1027
|
|
|
|
|
|
|
= ("#" x 50) . "\n" |
1028
|
|
|
|
|
|
|
. " Keyword macro defined at $keyword_impls[$ID]{location}:\n\n$keyword\n\n" |
1029
|
|
|
|
|
|
|
. " Converted code at $file line $line:" . "\n\n$from\n\n" |
1030
|
|
|
|
|
|
|
. " Into:" . "\n\n$to\n\n" |
1031
|
0
|
|
|
|
|
0
|
. ("#" x 50) . "\n"; |
1032
|
0
|
|
|
|
|
0
|
$msg =~ s{^}{###}gm; |
1033
|
|
|
|
|
|
|
warn $msg; |
1034
|
|
|
|
|
|
|
} |
1035
|
|
|
|
|
|
|
|
1036
|
76
|
|
|
|
|
411
|
# Track possible cycles... |
|
4
|
|
|
|
|
30
|
|
1037
|
4
|
50
|
33
|
|
|
29
|
$$src_ref =~ s{^(\#KDCT:_:_:)(\d+)([^\n]*)} |
1038
|
|
|
|
|
|
|
{ my ($comment, $count, $trace) = ($1, $2, $3); |
1039
|
4
|
|
|
|
|
38
|
croak "Likely keyword substitution cycle:\n $trace\nCompilation abandoned", |
1040
|
|
|
|
|
|
|
if $count > $NESTING_THRESHOLD && $trace =~ m{(\w++) --> .+ --> \1}; |
1041
|
|
|
|
|
|
|
$comment.($count+1).$trace." --> $keyword->{keyword}"; |
1042
|
|
|
|
|
|
|
}gexms; |
1043
|
76
|
|
|
|
|
690
|
|
1044
|
|
|
|
|
|
|
# Install the replacement code... |
1045
|
|
|
|
|
|
|
$$src_ref = "$replacement_code\n#KDCT:_:_:1 $keyword->{keyword}\n#line $line $file\n" . $$src_ref; |
1046
|
|
|
|
|
|
|
|
1047
|
76
|
|
|
|
|
35085
|
# Pre-empt addition of extraneous trailing newline by Keyword::Simple... |
1048
|
|
|
|
|
|
|
# [REMOVE WHEN UPSTREAM MODULE (Keyword::Simple) IS FIXED] |
1049
|
|
|
|
|
|
|
$$src_ref =~ s{\n\z}{}; |
1050
|
|
|
|
|
|
|
} |
1051
|
|
|
|
|
|
|
|
1052
|
8
|
|
|
8
|
|
25
|
# Compare two types... |
1053
|
|
|
|
|
|
|
sub _is_narrower { |
1054
|
|
|
|
|
|
|
my ($type_a, $type_b) = @_; |
1055
|
8
|
100
|
|
|
|
26
|
|
1056
|
|
|
|
|
|
|
# Short-circuit on identity... |
1057
|
|
|
|
|
|
|
return 0 if $type_a eq $type_b; |
1058
|
7
|
100
|
|
|
|
51
|
|
|
|
50
|
|
|
|
|
|
1059
|
7
|
100
|
|
|
|
40
|
# Otherwise, work out the metatypes of the types... |
|
|
50
|
|
|
|
|
|
1060
|
|
|
|
|
|
|
my $kind_a = $type_a =~ /\A'|\Aq\W/ ? 'literal' : $type_a =~ m{\A/|\Am\W}xms ? 'pattern' : 'typename'; |
1061
|
|
|
|
|
|
|
my $kind_b = $type_b =~ /\A'|\Aq\W/ ? 'literal' : $type_b =~ m{\A/|\Am\W}xms ? 'pattern' : 'typename'; |
1062
|
7
|
100
|
100
|
|
|
39
|
|
1063
|
5
|
100
|
|
|
|
22
|
# If both are named types, try the standard inheritance hierarchy rules... |
1064
|
2
|
50
|
|
|
|
9
|
if ($kind_a eq 'typename' && $kind_b eq 'typename') { |
1065
|
|
|
|
|
|
|
return +1 if $isa{$type_a,$type_b}; |
1066
|
|
|
|
|
|
|
return -1 if $isa{$type_b,$type_a}; |
1067
|
|
|
|
|
|
|
} |
1068
|
2
|
|
|
|
|
10
|
|
1069
|
|
|
|
|
|
|
# Otherwise, the metatype names "just happen" to be in narrowness order ;-)... |
1070
|
|
|
|
|
|
|
return $kind_a cmp $kind_b; |
1071
|
|
|
|
|
|
|
} |
1072
|
|
|
|
|
|
|
|
1073
|
5
|
|
|
5
|
|
16
|
# Compare two type signatures (of equal length)... |
1074
|
|
|
|
|
|
|
sub _cmp_signatures { |
1075
|
|
|
|
|
|
|
my ($sig_a, $sig_b) = @_; |
1076
|
5
|
|
|
|
|
9
|
|
1077
|
5
|
|
|
|
|
17
|
# Track relative ordering parameter-by-parameter... |
1078
|
|
|
|
|
|
|
my $partial_ordering = 0; |
1079
|
8
|
|
|
|
|
29
|
for my $n (0 .. $#$sig_a) { |
1080
|
|
|
|
|
|
|
# Find the ordering of the next pair from the two lists... |
1081
|
|
|
|
|
|
|
my $is_narrower = _is_narrower($sig_a->[$n], $sig_b->[$n]); |
1082
|
8
|
100
|
100
|
|
|
46
|
|
1083
|
|
|
|
|
|
|
# If this pair's ordering contradicts the ordering so far, there is no ordering... |
1084
|
|
|
|
|
|
|
return 0 if $is_narrower && $is_narrower == -$partial_ordering; |
1085
|
6
|
|
66
|
|
|
35
|
|
1086
|
|
|
|
|
|
|
# Otherwise if there's an ordering, it becomes the "ordering so far"... |
1087
|
|
|
|
|
|
|
$partial_ordering ||= $is_narrower; |
1088
|
|
|
|
|
|
|
} |
1089
|
3
|
|
|
|
|
10
|
|
1090
|
|
|
|
|
|
|
# If we make it through the entire list, return the resulting ordering... |
1091
|
|
|
|
|
|
|
return $partial_ordering; |
1092
|
|
|
|
|
|
|
} |
1093
|
|
|
|
|
|
|
|
1094
|
3
|
|
|
3
|
|
30
|
# Resolve ambiguous argument lists using Perl6-ish multiple dispatch rules... |
1095
|
|
|
|
|
|
|
sub _resolve_matches { |
1096
|
|
|
|
|
|
|
my @IDs = @_; |
1097
|
3
|
|
|
|
|
27
|
|
|
14
|
|
|
|
|
49
|
|
1098
|
14
|
50
|
|
|
|
35
|
# Extend type hierarchy... |
1099
|
0
|
|
|
|
|
0
|
my @keytype_isa = map { my ($derived, $base) = m{ \A Keyword::Declare \s+ keytype:(\w+)=(\w+) \z}xms; |
1100
|
0
|
|
|
|
|
0
|
if ($derived) { |
1101
|
0
|
|
|
|
|
0
|
my @ancestors = map { my $anc = $_; |
1102
|
|
|
|
|
|
|
$anc =~ s{ \A $base $; } |
1103
|
0
|
|
|
|
|
0
|
{$derived$;}xms; |
|
0
|
|
|
|
|
0
|
|
1104
|
|
|
|
|
|
|
$anc => 1 |
1105
|
0
|
|
|
|
|
0
|
} |
1106
|
|
|
|
|
|
|
grep { m{ \A $base $; }xms } |
1107
|
|
|
|
|
|
|
keys %isa; |
1108
|
14
|
|
|
|
|
33
|
$derived.$;.$base => 1, @ancestors; |
1109
|
|
|
|
|
|
|
} |
1110
|
|
|
|
|
|
|
else { |
1111
|
3
|
|
|
|
|
2180
|
(); |
1112
|
|
|
|
|
|
|
} |
1113
|
|
|
|
|
|
|
} keys %^H; |
1114
|
3
|
|
|
|
|
145
|
local %isa = ( %isa, @keytype_isa ); |
|
7
|
|
|
|
|
36
|
|
1115
|
|
|
|
|
|
|
|
1116
|
|
|
|
|
|
|
# Track narrownesses... |
1117
|
3
|
|
|
|
|
28
|
my %narrower = map { $_ => [] } 0..$#IDs; |
1118
|
7
|
|
|
|
|
29
|
|
1119
|
|
|
|
|
|
|
# Compare all signatures, recording definitive differences in narrowness... |
1120
|
5
|
|
|
|
|
29
|
for my $index_1 (0 .. $#IDs) { |
1121
|
|
|
|
|
|
|
for my $index_2 ($index_1+1 .. $#IDs) { |
1122
|
5
|
100
|
|
|
|
25
|
my $narrowness = _cmp_signatures($keyword_impls[$IDs[$index_1]]{sig}, |
|
2
|
100
|
|
|
|
5
|
|
|
2
|
|
|
|
|
10
|
|
1123
|
1
|
|
|
|
|
2
|
$keyword_impls[$IDs[$index_2]]{sig}); |
|
1
|
|
|
|
|
6
|
|
1124
|
|
|
|
|
|
|
|
1125
|
|
|
|
|
|
|
if ($narrowness > 0) { push @{$narrower{$index_1}}, $index_2; } |
1126
|
|
|
|
|
|
|
elsif ($narrowness < 0) { push @{$narrower{$index_2}}, $index_1; } |
1127
|
|
|
|
|
|
|
} |
1128
|
3
|
|
|
|
|
13
|
} |
|
7
|
|
|
|
|
11
|
|
|
7
|
|
|
|
|
25
|
|
1129
|
3
|
|
|
|
|
11
|
|
1130
|
|
|
|
|
|
|
# Was there a signature narrower than all the others??? |
1131
|
|
|
|
|
|
|
my $max_narrower = max map { scalar @{$_} } values %narrower; |
1132
|
3
|
100
|
|
|
|
80
|
my $unique_narrowest = $max_narrower == $#IDs; |
1133
|
|
|
|
|
|
|
|
1134
|
|
|
|
|
|
|
# If not, return the entire set... |
1135
|
2
|
|
|
|
|
9
|
return @IDs if !$unique_narrowest; |
|
4
|
|
|
|
|
6
|
|
|
4
|
|
|
|
|
135
|
|
1136
|
|
|
|
|
|
|
|
1137
|
|
|
|
|
|
|
# Otherwise, return the narrowest... |
1138
|
|
|
|
|
|
|
return @IDs[ grep { @{$narrower{$_}} >= $max_narrower } keys %narrower ]; |
1139
|
|
|
|
|
|
|
} |
1140
|
|
|
|
|
|
|
|
1141
|
|
|
|
|
|
|
1; # Magic true value required at end of module |
1142
|
|
|
|
|
|
|
__END__ |