| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Switch::Right; |
|
2
|
|
|
|
|
|
|
|
|
3
|
7
|
|
|
7
|
|
1497299
|
use 5.036; |
|
|
7
|
|
|
|
|
26
|
|
|
4
|
|
|
|
|
|
|
our $VERSION = '0.000006'; |
|
5
|
|
|
|
|
|
|
|
|
6
|
7
|
|
|
7
|
|
2530
|
use experimental qw< builtin refaliasing try >; |
|
|
7
|
|
|
|
|
20289
|
|
|
|
7
|
|
|
|
|
52
|
|
|
7
|
7
|
|
|
7
|
|
4587
|
use builtin qw< true false is_bool blessed created_as_number reftype >; |
|
|
7
|
|
|
|
|
567
|
|
|
|
7
|
|
|
|
|
445
|
|
|
8
|
7
|
|
|
7
|
|
45
|
use Scalar::Util qw < looks_like_number >; |
|
|
7
|
|
|
|
|
17
|
|
|
|
7
|
|
|
|
|
426
|
|
|
9
|
7
|
|
|
7
|
|
80
|
use overload; |
|
|
7
|
|
|
|
|
15
|
|
|
|
7
|
|
|
|
|
56
|
|
|
10
|
|
|
|
|
|
|
|
|
11
|
7
|
|
|
7
|
|
10228
|
use Multi::Dispatch; |
|
|
7
|
|
|
|
|
4714247
|
|
|
|
7
|
|
|
|
|
115
|
|
|
12
|
7
|
|
|
7
|
|
3572
|
use PPR::X; |
|
|
7
|
|
|
|
|
27
|
|
|
|
7
|
|
|
|
|
253
|
|
|
13
|
7
|
|
|
7
|
|
53
|
use Carp qw< croak carp >; |
|
|
7
|
|
|
|
|
16
|
|
|
|
7
|
|
|
|
|
1080
|
|
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
# Useful patterns... |
|
16
|
7
|
|
|
7
|
|
558
|
my $OWS; BEGIN { $OWS = q{(?>(?&PerlOWS))}; } |
|
17
|
|
|
|
|
|
|
my $CONTAINER_VARIABLE; |
|
18
|
7
|
|
|
7
|
|
451165
|
BEGIN { $CONTAINER_VARIABLE |
|
19
|
|
|
|
|
|
|
= qr{ \A (?> (?&PerlVariableArray) | (?&PerlVariableHash) |
|
20
|
|
|
|
|
|
|
| my $OWS (?> (?&PerlVariableArray) | (?&PerlVariableHash) ) $OWS = .* |
|
21
|
|
|
|
|
|
|
) |
|
22
|
|
|
|
|
|
|
\z $PPR::GRAMMAR |
|
23
|
|
|
|
|
|
|
}xms; |
|
24
|
|
|
|
|
|
|
} |
|
25
|
|
|
|
|
|
|
my $ARRAY_SLICE; |
|
26
|
7
|
|
|
7
|
|
429565
|
BEGIN { $ARRAY_SLICE |
|
27
|
|
|
|
|
|
|
= qr{ \A (?> (?&PerlArrayAccess) |
|
28
|
|
|
|
|
|
|
| my $OWS (?&PerlArrayAccess) $OWS = .* |
|
29
|
|
|
|
|
|
|
) |
|
30
|
|
|
|
|
|
|
\z $PPR::GRAMMAR |
|
31
|
|
|
|
|
|
|
}xms; |
|
32
|
|
|
|
|
|
|
} |
|
33
|
|
|
|
|
|
|
my $HASH_SLICE; |
|
34
|
7
|
|
|
7
|
|
367309
|
BEGIN { $HASH_SLICE |
|
35
|
|
|
|
|
|
|
= qr{ \A (?> (?&PerlHashAccess) |
|
36
|
|
|
|
|
|
|
| my $OWS (?&PerlHashAccess) $OWS = .* |
|
37
|
|
|
|
|
|
|
) |
|
38
|
|
|
|
|
|
|
\z $PPR::GRAMMAR |
|
39
|
|
|
|
|
|
|
}xms; |
|
40
|
|
|
|
|
|
|
} |
|
41
|
|
|
|
|
|
|
my $FLIP_FLOP; |
|
42
|
7
|
|
|
7
|
|
510035
|
BEGIN { $FLIP_FLOP |
|
43
|
|
|
|
|
|
|
= qr{ \A (?&FlipFlop) \z |
|
44
|
|
|
|
|
|
|
(?(DEFINE) |
|
45
|
|
|
|
|
|
|
(? |
|
46
|
|
|
|
|
|
|
\( (?>(?&PerlOWS)) (?&FlipFlop) (?>(?&PerlOWS)) \) |
|
47
|
|
|
|
|
|
|
| |
|
48
|
|
|
|
|
|
|
(?>(?&PerlBinaryExpression)) (?>(?&PerlOWS)) |
|
49
|
|
|
|
|
|
|
\.\.\.? (?>(?&PerlOWS)) |
|
50
|
|
|
|
|
|
|
(?>(?&PerlBinaryExpression)) |
|
51
|
|
|
|
|
|
|
) |
|
52
|
|
|
|
|
|
|
(? |
|
53
|
|
|
|
|
|
|
(?> [=!][~=] | <= >?+ | >= |
|
54
|
|
|
|
|
|
|
| cmp | [lg][te] | eq | ne |
|
55
|
|
|
|
|
|
|
| [+] (?! [+=] ) |
|
56
|
|
|
|
|
|
|
| - (?! [-=] ) |
|
57
|
|
|
|
|
|
|
| [.%x] (?! [=] ) |
|
58
|
|
|
|
|
|
|
| [&|^][.] (?! [=] ) |
|
59
|
|
|
|
|
|
|
| [<>*&|/]{1,2}+ (?! [=] ) |
|
60
|
|
|
|
|
|
|
| \^ (?! [=] ) |
|
61
|
|
|
|
|
|
|
| ~~ | isa |
|
62
|
|
|
|
|
|
|
) |
|
63
|
|
|
|
|
|
|
) |
|
64
|
|
|
|
|
|
|
) |
|
65
|
|
|
|
|
|
|
$PPR::GRAMMAR |
|
66
|
|
|
|
|
|
|
}xms; |
|
67
|
|
|
|
|
|
|
} |
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
# Install the new keywords, functions, and smartmatching... |
|
70
|
|
|
|
|
|
|
sub import { |
|
71
|
|
|
|
|
|
|
# Export replacement keywords... |
|
72
|
7
|
|
|
7
|
|
117
|
use Keyword::Simple; |
|
|
7
|
|
|
|
|
26
|
|
|
|
7
|
|
|
|
|
734
|
|
|
73
|
7
|
|
|
7
|
|
244
|
Keyword::Simple::define given => \&_given_impl; |
|
74
|
7
|
|
|
|
|
271
|
Keyword::Simple::define when => \&_when_impl; |
|
75
|
7
|
|
|
|
|
267
|
Keyword::Simple::define default => \&_default_impl; |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
# Outside a given a 'break' is an error; outside a when a 'continue' is too... |
|
78
|
|
|
|
|
|
|
{ |
|
79
|
7
|
|
|
7
|
|
41
|
no strict 'refs'; |
|
|
7
|
|
|
|
|
12
|
|
|
|
7
|
|
|
|
|
374
|
|
|
|
7
|
|
|
|
|
123
|
|
|
80
|
7
|
|
|
7
|
|
35
|
no warnings qw< redefine >; |
|
|
7
|
|
|
|
|
13
|
|
|
|
7
|
|
|
|
|
1802
|
|
|
81
|
7
|
|
|
|
|
20
|
*{caller.'::break'} = \&break; |
|
|
7
|
|
|
|
|
71
|
|
|
82
|
7
|
|
|
|
|
20
|
*{caller.'::continue'} = \&continue; |
|
|
7
|
|
|
|
|
78
|
|
|
83
|
|
|
|
|
|
|
} |
|
84
|
|
|
|
|
|
|
|
|
85
|
7
|
|
|
|
|
17
|
# Export smartmatch()... |
|
86
|
7
|
0
|
0
|
7
|
|
1015379
|
multi smartmatch :export; |
|
|
7
|
0
|
50
|
7
|
|
18
|
|
|
|
7
|
0
|
|
1173
|
|
2799
|
|
|
|
7
|
0
|
|
|
|
53
|
|
|
|
7
|
0
|
|
|
|
33
|
|
|
|
7
|
50
|
|
|
|
8533
|
|
|
|
7
|
100
|
|
|
|
15
|
|
|
|
7
|
100
|
|
|
|
19
|
|
|
|
7
|
100
|
|
|
|
15
|
|
|
|
7
|
50
|
|
|
|
74
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
7
|
|
|
|
|
19
|
|
|
|
7
|
|
|
|
|
47
|
|
|
|
7
|
|
|
|
|
62
|
|
|
|
1173
|
|
|
|
|
2637126
|
|
|
|
1173
|
|
|
|
|
8093
|
|
|
|
1173
|
|
|
|
|
4038
|
|
|
|
4090
|
|
|
|
|
10321
|
|
|
|
2474
|
|
|
|
|
5950
|
|
|
|
1616
|
|
|
|
|
4281
|
|
|
|
93
|
|
|
|
|
306
|
|
|
|
1523
|
|
|
|
|
2169
|
|
|
|
1523
|
|
|
|
|
5788
|
|
|
|
1523
|
|
|
|
|
8186
|
|
|
|
1173
|
|
|
|
|
2651
|
|
|
|
1173
|
|
|
|
|
1601
|
|
|
|
1173
|
|
|
|
|
4697
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
7
|
|
|
|
|
16
|
|
|
|
7
|
|
|
|
|
27
|
|
|
|
7
|
|
|
|
|
53
|
|
|
|
7
|
|
|
|
|
18
|
|
|
|
7
|
|
|
|
|
5034
|
|
|
|
7
|
|
|
|
|
29
|
|
|
|
7
|
|
|
|
|
38
|
|
|
87
|
|
|
|
|
|
|
} |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
# Error messages shared by *_given_impl()... |
|
90
|
|
|
|
|
|
|
my $WHENTRUEMSG = q{BEGIN{warn q{"when (true) {...}" better written as "default {...}"}}}; |
|
91
|
|
|
|
|
|
|
my $WHENFALSEMSG = q{BEGIN{warn q{Useless use of "when (false)"}}}; |
|
92
|
|
|
|
|
|
|
|
|
93
|
0
|
|
|
0
|
|
|
sub _pure_given_impl { my ($source) = @_; |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
# Recognize a valid "pure" given block (i.e. containing only when and default blocks)... |
|
96
|
0
|
|
|
|
|
|
state @pure_statements; |
|
97
|
0
|
|
|
|
|
|
@pure_statements = (); |
|
98
|
|
|
|
|
|
|
state $VALIDATE_PURE_GIVEN = qr{ |
|
99
|
|
|
|
|
|
|
\A given (? (? $OWS ) \( |
|
100
|
|
|
|
|
|
|
(? (?: $OWS (?> any | all | none ) $OWS => )?+ ) |
|
101
|
|
|
|
|
|
|
(? $OWS ) (?>(? (?&PerlExpression))) |
|
102
|
|
|
|
|
|
|
(? $OWS ) \) |
|
103
|
|
|
|
|
|
|
(? $OWS \{ $OWS ) (?>(? (?&PureBlock) )) \} |
|
104
|
|
|
|
|
|
|
) |
|
105
|
|
|
|
|
|
|
(?>(? .* )) |
|
106
|
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
(?(DEFINE) |
|
108
|
|
|
|
|
|
|
(? # Distinguish "when", "default", and "given" from other statements... |
|
109
|
|
|
|
|
|
|
(?: |
|
110
|
|
|
|
|
|
|
when (? $OWS \( $OWS ) |
|
111
|
|
|
|
|
|
|
(?> |
|
112
|
|
|
|
|
|
|
(? (? true ) |
|
113
|
|
|
|
|
|
|
| (? false ) |
|
114
|
|
|
|
|
|
|
) \b |
|
115
|
|
|
|
|
|
|
| |
|
116
|
|
|
|
|
|
|
(? (?: (?> any | all | none ) $OWS => $OWS )?+ ) |
|
117
|
|
|
|
|
|
|
(? (?>(?&PerlExpression))) |
|
118
|
|
|
|
|
|
|
) |
|
119
|
|
|
|
|
|
|
(? $OWS \) $OWS ) |
|
120
|
|
|
|
|
|
|
(?>(? (?&PerlBlock) )) |
|
121
|
|
|
|
|
|
|
(? $OWS ) |
|
122
|
0
|
|
|
|
|
|
(?{ push @pure_statements, { TYPE => 'when', %+ }; }) |
|
123
|
|
|
|
|
|
|
| |
|
124
|
|
|
|
|
|
|
default (? $OWS ) |
|
125
|
|
|
|
|
|
|
(?>(? (?&PerlBlock) )) |
|
126
|
|
|
|
|
|
|
(? $OWS ) |
|
127
|
0
|
|
|
|
|
|
(?{ push @pure_statements, { TYPE => 'default', %+ }; }) |
|
128
|
|
|
|
|
|
|
| |
|
129
|
|
|
|
|
|
|
(? |
|
130
|
|
|
|
|
|
|
given \b $OWS \( |
|
131
|
|
|
|
|
|
|
(?: $OWS (?> any | all | none ) $OWS => )?+ |
|
132
|
|
|
|
|
|
|
$OWS (?>(? (?>(?&PerlExpression)))) |
|
133
|
|
|
|
|
|
|
$OWS \) |
|
134
|
|
|
|
|
|
|
$OWS (?>(? (?&NestedPureBlock) )) $OWS |
|
135
|
|
|
|
|
|
|
) |
|
136
|
0
|
|
|
|
|
|
(?{ push @pure_statements, { TYPE => 'given', %+ }; }) |
|
137
|
|
|
|
|
|
|
| |
|
138
|
|
|
|
|
|
|
(?! $OWS (?> when | default ) \b ) |
|
139
|
|
|
|
|
|
|
(?>(? (?&PerlStatement) $OWS )) |
|
140
|
0
|
|
|
|
|
|
(?{ push @pure_statements, { TYPE => 'other', %+ }; }) |
|
141
|
|
|
|
|
|
|
)*+ |
|
142
|
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
# Possible trailing whitespace at the end of the block... |
|
144
|
|
|
|
|
|
|
( (?>(? (?&PerlNWS) )) |
|
145
|
0
|
|
|
|
|
|
(?{ push @pure_statements, { TYPE => 'other', %+ }; }) |
|
146
|
|
|
|
|
|
|
)?+ |
|
147
|
|
|
|
|
|
|
) |
|
148
|
|
|
|
|
|
|
(? # Non-capturing version of the above |
|
149
|
|
|
|
|
|
|
\{ $OWS |
|
150
|
|
|
|
|
|
|
(?: |
|
151
|
|
|
|
|
|
|
when $OWS \( (?: $OWS (?> any | all | none ) $OWS => )?+ |
|
152
|
|
|
|
|
|
|
$OWS (?>(?&PerlExpression)) |
|
153
|
|
|
|
|
|
|
$OWS \) $OWS (?>(?&PerlBlock)) $OWS |
|
154
|
|
|
|
|
|
|
| |
|
155
|
|
|
|
|
|
|
default $OWS (?>(?&PerlBlock)) $OWS |
|
156
|
|
|
|
|
|
|
| |
|
157
|
|
|
|
|
|
|
given \b $OWS \( (?: $OWS (?> any | all | none ) $OWS => )?+ |
|
158
|
|
|
|
|
|
|
$OWS (?>(?&PerlExpression)) |
|
159
|
|
|
|
|
|
|
$OWS \) |
|
160
|
|
|
|
|
|
|
$OWS (?>(?&NestedPureBlock)) $OWS |
|
161
|
|
|
|
|
|
|
| |
|
162
|
|
|
|
|
|
|
(?! when \b | default | given \b ) (?>(?&PerlStatement)) $OWS |
|
163
|
|
|
|
|
|
|
)*+ |
|
164
|
|
|
|
|
|
|
\} |
|
165
|
|
|
|
|
|
|
) |
|
166
|
|
|
|
|
|
|
(? |
|
167
|
|
|
|
|
|
|
# Pure given can't have a continue or break or goto in it... |
|
168
|
|
|
|
|
|
|
(?: continue | break | goto ) \b (*COMMIT)(*FAIL) |
|
169
|
|
|
|
|
|
|
| |
|
170
|
|
|
|
|
|
|
(?&PerlStdBuiltinFunction) |
|
171
|
|
|
|
|
|
|
) |
|
172
|
|
|
|
|
|
|
(? |
|
173
|
|
|
|
|
|
|
# "Pure" given can't have a postfix "when" modifier in it... |
|
174
|
|
|
|
|
|
|
(?> if | for(?:each)?+ | while | unless | until | when (*COMMIT)(*FAIL) ) |
|
175
|
|
|
|
|
|
|
\b |
|
176
|
|
|
|
|
|
|
(?>(?&PerlOWS)) |
|
177
|
|
|
|
|
|
|
(?&PerlExpression) |
|
178
|
|
|
|
|
|
|
) # End of rule (?) |
|
179
|
|
|
|
|
|
|
) |
|
180
|
|
|
|
|
|
|
$PPR::X::GRAMMAR |
|
181
|
0
|
|
|
|
|
|
}xms; |
|
182
|
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
# Generate an optimized given/when implementation if the given is "pure"... |
|
184
|
7
|
|
|
7
|
|
71
|
no warnings 'once'; |
|
|
7
|
|
|
|
|
12
|
|
|
|
7
|
|
|
|
|
16433
|
|
|
185
|
0
|
0
|
|
|
|
|
if ($source =~ $VALIDATE_PURE_GIVEN) { |
|
186
|
0
|
|
|
|
|
|
my %matched = %+; |
|
187
|
0
|
|
|
|
|
|
my $nesting_depth = 0; |
|
188
|
0
|
|
|
|
|
|
my $after_a_statement = 0; |
|
189
|
0
|
|
|
|
|
|
my $GIVEN_EXPR = _apply_term_magic($matched{EXPR}); |
|
190
|
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
return |
|
192
|
|
|
|
|
|
|
"if (1) $matched{ws_post_kw} { local *_ = $matched{ws_pre_expr} \\scalar($GIVEN_EXPR); $matched{ws_pre_close} if(0) $matched{ws_pre_block} }" |
|
193
|
|
|
|
|
|
|
. join("", map { |
|
194
|
0
|
0
|
|
|
|
|
my $PREFIX = $after_a_statement ? 'if(0){}' : q{}; |
|
195
|
0
|
0
|
|
|
|
|
if ($_->{TYPE} eq 'when') { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
196
|
0
|
|
|
|
|
|
my $BLOCK = $_->{WHENBLOCK}; |
|
197
|
0
|
0
|
|
|
|
|
if ($_->{WHENTRUE}) { substr($BLOCK,1,0) = $WHENTRUEMSG; } |
|
|
0
|
0
|
|
|
|
|
|
|
198
|
0
|
|
|
|
|
|
elsif ($_->{WHENFALSE}) { substr($BLOCK,1,0) = $WHENFALSEMSG; } |
|
199
|
0
|
|
0
|
|
|
|
my $JUNC = $_->{WHENJUNC} // q{}; |
|
200
|
0
|
|
|
|
|
|
$after_a_statement = 0; |
|
201
|
|
|
|
|
|
|
"$PREFIX elsif $_->{WHENOPEN} smartmatch($matched{JUNC} \$_, $JUNC scalar(" |
|
202
|
0
|
|
|
|
|
|
. _apply_term_magic($_->{WHENEXPR}) . ")) $_->{WHENCLOSE} $BLOCK $_->{WHENPOST}" |
|
203
|
|
|
|
|
|
|
} |
|
204
|
|
|
|
|
|
|
elsif ($_->{TYPE} eq 'default') { |
|
205
|
0
|
|
|
|
|
|
$after_a_statement = 0; |
|
206
|
0
|
|
|
|
|
|
"$PREFIX elsif (1) $_->{DEFPRE} $_->{DEFBLOCK} $_->{DEFPOST}" |
|
207
|
|
|
|
|
|
|
} |
|
208
|
|
|
|
|
|
|
elsif ($_->{TYPE} eq 'given') { |
|
209
|
0
|
|
|
|
|
|
my $nested = _pure_given_impl($_->{NESTEDGIVEN}); |
|
210
|
0
|
0
|
|
|
|
|
if ($after_a_statement) { |
|
211
|
0
|
|
|
|
|
|
$nested; |
|
212
|
|
|
|
|
|
|
} |
|
213
|
|
|
|
|
|
|
else { |
|
214
|
0
|
|
|
|
|
|
$after_a_statement = 1; |
|
215
|
0
|
|
|
|
|
|
$nesting_depth++; |
|
216
|
0
|
|
|
|
|
|
"else { $nested "; |
|
217
|
|
|
|
|
|
|
} |
|
218
|
|
|
|
|
|
|
} |
|
219
|
|
|
|
|
|
|
else { # Must be a regular statement... |
|
220
|
0
|
0
|
|
|
|
|
if ($after_a_statement) { |
|
221
|
0
|
|
|
|
|
|
$_->{STATEMENT}; |
|
222
|
|
|
|
|
|
|
} |
|
223
|
|
|
|
|
|
|
else { |
|
224
|
0
|
|
|
|
|
|
$after_a_statement = 1; |
|
225
|
0
|
|
|
|
|
|
$nesting_depth++; |
|
226
|
0
|
|
|
|
|
|
"else { $_->{STATEMENT}"; |
|
227
|
|
|
|
|
|
|
} |
|
228
|
|
|
|
|
|
|
} |
|
229
|
0
|
0
|
|
|
|
|
} @{[@pure_statements]} ) |
|
|
0
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
. (!$after_a_statement ? "else{}" : q{}) |
|
231
|
|
|
|
|
|
|
. ('}' x $nesting_depth) |
|
232
|
|
|
|
|
|
|
. "}$matched{TRAILING_CODE}"; |
|
233
|
|
|
|
|
|
|
} |
|
234
|
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
# Otherwise, fail... |
|
236
|
0
|
|
|
|
|
|
return; |
|
237
|
|
|
|
|
|
|
} |
|
238
|
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
# Implement "given" keyword... |
|
240
|
0
|
|
|
0
|
|
|
sub _given_impl { my ($source_ref) = @_; # Has to be this way because of code blocks in regex |
|
241
|
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
# First try the "pure" approach (only works on a limited selection of "given" blocks)... |
|
243
|
0
|
|
|
|
|
|
my $REPLACEMENT_CODE = _pure_given_impl('given ' . ${$source_ref}); |
|
|
0
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
# Otherwise recognize a valid general-purpose given block (with a single scalar argument)... |
|
246
|
0
|
0
|
|
|
|
|
if (!defined $REPLACEMENT_CODE) { |
|
247
|
0
|
|
|
|
|
|
state $VALIDATE_GIVEN = qr{ |
|
248
|
|
|
|
|
|
|
\A (? |
|
249
|
|
|
|
|
|
|
$OWS \( |
|
250
|
|
|
|
|
|
|
(? (?: $OWS (?> any | all | none ) $OWS => )?+ ) |
|
251
|
|
|
|
|
|
|
$OWS (?>(? (?&PerlExpression))) |
|
252
|
|
|
|
|
|
|
$OWS \) |
|
253
|
|
|
|
|
|
|
(?> |
|
254
|
|
|
|
|
|
|
$OWS (?>(? (?&PerlBlock) )) |
|
255
|
|
|
|
|
|
|
| |
|
256
|
|
|
|
|
|
|
(?) |
|
257
|
|
|
|
|
|
|
) |
|
258
|
|
|
|
|
|
|
) |
|
259
|
|
|
|
|
|
|
(?>(? .* )) |
|
260
|
|
|
|
|
|
|
$PPR::GRAMMAR |
|
261
|
|
|
|
|
|
|
}xms; |
|
262
|
0
|
|
|
|
|
|
${$source_ref} =~ $VALIDATE_GIVEN; |
|
|
0
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
# Extract components... |
|
265
|
0
|
|
|
|
|
|
my %result = %+; |
|
266
|
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
# It's a valid "given"... |
|
268
|
0
|
0
|
|
|
|
|
if (exists $result{BLOCK}) { |
|
|
|
0
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
my ($GIVEN, $JUNC, $EXPR, $BLOCK, $TRAILING_CODE) |
|
270
|
0
|
|
|
|
|
|
= @result{qw< GIVEN JUNC EXPR BLOCK TRAILING_CODE >}; |
|
271
|
0
|
|
0
|
|
|
|
$JUNC //= q{}; |
|
272
|
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
# Augment the block with control flow and other necessary components... |
|
274
|
0
|
|
|
|
|
|
$BLOCK = _augment_block(given => "$BLOCK", $JUNC); |
|
275
|
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
# Topicalize the "given" argument... |
|
277
|
0
|
|
|
|
|
|
$EXPR = _apply_term_magic($EXPR); |
|
278
|
0
|
|
|
|
|
|
substr($BLOCK, 1, 0) = qq{local *_ = \\($EXPR);}; |
|
279
|
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
# Implement "given" as a (trivial) "if" block... |
|
281
|
0
|
|
|
|
|
|
$REPLACEMENT_CODE = qq{ if (1) $BLOCK }; |
|
282
|
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
# At what line should the "given" end??? |
|
284
|
0
|
|
|
|
|
|
my $end_line = (caller)[2] + $GIVEN =~ tr/\n//; |
|
285
|
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
# Append the trailing code (at the right line number)... |
|
287
|
0
|
|
|
|
|
|
$REPLACEMENT_CODE .= "\n#line $end_line\n$TRAILING_CODE"; |
|
288
|
|
|
|
|
|
|
} |
|
289
|
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
# Otherwise, report the error in context... |
|
291
|
|
|
|
|
|
|
elsif (exists $result{EXPR}) { |
|
292
|
0
|
|
|
|
|
|
$REPLACEMENT_CODE = q{ BEGIN { warn q{Invalid code somewhere in "given" block starting} } } |
|
293
|
|
|
|
|
|
|
. q{ BEGIN { warn qq{(Note: the error reported below may be misleading)\\n}}} |
|
294
|
0
|
|
|
|
|
|
. qq{ if ${$source_ref} }; |
|
295
|
|
|
|
|
|
|
} |
|
296
|
|
|
|
|
|
|
} |
|
297
|
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
# Install standard code in place of keyword... |
|
299
|
0
|
|
|
|
|
|
${$source_ref} = $REPLACEMENT_CODE; |
|
|
0
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
} |
|
301
|
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
# Implementation of "when" keyword... |
|
305
|
0
|
|
|
0
|
|
|
sub _when_impl ($source_ref) { |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
306
|
0
|
|
|
|
|
|
my ($REPLACEMENT_CODE, $TRAILING_CODE); |
|
307
|
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
# What various kinds of "when" look like... |
|
309
|
0
|
|
|
|
|
|
state $WHEN_CLASSIFIER = qr{ |
|
310
|
|
|
|
|
|
|
\A (? $OWS |
|
311
|
|
|
|
|
|
|
( \( |
|
312
|
|
|
|
|
|
|
(?: |
|
313
|
|
|
|
|
|
|
$OWS (? (? true ) |
|
314
|
|
|
|
|
|
|
| (? false ) |
|
315
|
|
|
|
|
|
|
) \b |
|
316
|
|
|
|
|
|
|
| |
|
317
|
|
|
|
|
|
|
(? (?: $OWS (?> any | all | none ) $OWS => )?+ ) |
|
318
|
|
|
|
|
|
|
$OWS (? (?&PerlExpression)) |
|
319
|
|
|
|
|
|
|
) |
|
320
|
|
|
|
|
|
|
$OWS \) |
|
321
|
|
|
|
|
|
|
$OWS (?>(? (?&PerlBlock) ) |
|
322
|
|
|
|
|
|
|
| (?) |
|
323
|
|
|
|
|
|
|
) |
|
324
|
|
|
|
|
|
|
| |
|
325
|
|
|
|
|
|
|
(?>(? (?&PerlCommaList))) |
|
326
|
|
|
|
|
|
|
(?>(?&PerlOWSOrEND)) (?> ; | (?= \} | \z )) |
|
327
|
|
|
|
|
|
|
| |
|
328
|
|
|
|
|
|
|
(? \N{0,20} ) |
|
329
|
|
|
|
|
|
|
) |
|
330
|
|
|
|
|
|
|
) |
|
331
|
|
|
|
|
|
|
(? .* ) |
|
332
|
|
|
|
|
|
|
$PPR::GRAMMAR |
|
333
|
|
|
|
|
|
|
}xms; |
|
334
|
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
# Classify the type of "when" we're processing... |
|
336
|
0
|
|
|
|
|
|
${$source_ref} =~ $WHEN_CLASSIFIER; |
|
|
0
|
|
|
|
|
|
|
|
337
|
0
|
|
|
|
|
|
my %matched = %+; |
|
338
|
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
# Handle a valid when block (with a list of scalar arguments)... |
|
340
|
0
|
0
|
0
|
|
|
|
if (defined $matched{BLOCK} && defined $matched{EXPR}) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
my ($WHEN, $JUNC, $EXPR, $WHENTRUE, $WHENFALSE, $BLOCK, $TRAILING_CODE) |
|
342
|
0
|
|
|
|
|
|
= @matched{qw< WHEN JUNC EXPR WHENTRUE WHENFALSE BLOCK TRAILING_CODE>}; |
|
343
|
0
|
|
0
|
|
|
|
$JUNC //= q{}; |
|
344
|
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
# Adjust when's expression appropriately... |
|
346
|
0
|
|
|
|
|
|
$EXPR = _apply_term_magic($EXPR); |
|
347
|
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
# Augment the block with control flow and other necessary components... |
|
349
|
0
|
|
|
|
|
|
$BLOCK = _augment_block(when => "$BLOCK"); |
|
350
|
0
|
0
|
|
|
|
|
if ($WHENTRUE) { substr($BLOCK, 1, 0) = $WHENTRUEMSG; } |
|
|
0
|
0
|
|
|
|
|
|
|
351
|
0
|
|
|
|
|
|
elsif ($WHENFALSE) { substr($BLOCK, 1, 0) = $WHENFALSEMSG; } |
|
352
|
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
# Is the current "given" junctive??? |
|
354
|
0
|
|
0
|
|
|
|
my $given_junc = $^H{'Switch::Right/GivenJunctive'} // q{}; |
|
355
|
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
# Implement the "when" as an "if"... |
|
357
|
0
|
|
|
|
|
|
$REPLACEMENT_CODE = qq{if(1)\{local \$Switch::Right::when_value = } |
|
358
|
|
|
|
|
|
|
. qq{smartmatch($given_junc \$_, $JUNC scalar($EXPR));} |
|
359
|
|
|
|
|
|
|
. qq{if(1){if (\$Switch::Right::when_value) $BLOCK }\}}; |
|
360
|
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
# At what line should the "when" end??? |
|
362
|
0
|
|
|
|
|
|
my $end_line = (caller)[2] + $WHEN =~ tr/\n//; |
|
363
|
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
# Append the trailing code (at the right line number)... |
|
365
|
0
|
|
|
|
|
|
$REPLACEMENT_CODE .= "\n#line $end_line\n$TRAILING_CODE"; |
|
366
|
|
|
|
|
|
|
} |
|
367
|
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
# Otherwise, reject the "when" with extreme prejudice... |
|
369
|
|
|
|
|
|
|
elsif (defined $matched{MODIFIER}) { |
|
370
|
0
|
|
|
|
|
|
$REPLACEMENT_CODE = qq{ BEGIN { die q{Can't specify postfix "when" modifier outside a "given"} } }; |
|
371
|
|
|
|
|
|
|
} |
|
372
|
|
|
|
|
|
|
elsif (exists $matched{INVALID_BLOCK}) { |
|
373
|
0
|
|
|
|
|
|
$REPLACEMENT_CODE = qq{ BEGIN { warn q{Invalid code block in "when"} } } |
|
374
|
|
|
|
|
|
|
. qq{ BEGIN { warn qq{(Note: the error reported below may be misleading)\\n} } } |
|
375
|
0
|
|
|
|
|
|
. qq{ if ${$source_ref} }; |
|
376
|
|
|
|
|
|
|
} |
|
377
|
|
|
|
|
|
|
else { |
|
378
|
0
|
|
|
|
|
|
$REPLACEMENT_CODE = qq{ BEGIN { die q{Incomprehensible "when" (near: $matched{INCOMPREHENSIBLE})} } }; |
|
379
|
|
|
|
|
|
|
} |
|
380
|
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
# Install code implementing keyword behaviour... |
|
382
|
0
|
|
|
|
|
|
${$source_ref} = $REPLACEMENT_CODE; |
|
|
0
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
} |
|
384
|
|
|
|
|
|
|
|
|
385
|
0
|
|
|
0
|
|
|
sub _default_impl ($source_ref) { |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
386
|
0
|
|
|
|
|
|
state $DEFAULT_CLASSIFIER = qr{ |
|
387
|
|
|
|
|
|
|
(? $OWS (?>(? (?&PerlBlock) )) ) |
|
388
|
|
|
|
|
|
|
(? .* ) |
|
389
|
|
|
|
|
|
|
$PPR::GRAMMAR |
|
390
|
|
|
|
|
|
|
}xms; |
|
391
|
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
# Verify that we match the syntax for a "default" block... |
|
393
|
0
|
|
|
|
|
|
${$source_ref} =~ $DEFAULT_CLASSIFIER; |
|
|
0
|
|
|
|
|
|
|
|
394
|
0
|
|
|
|
|
|
my %matched = %+; |
|
395
|
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
# Implement the "default" block... |
|
397
|
0
|
0
|
|
|
|
|
if (defined $matched{BLOCK}) { |
|
398
|
|
|
|
|
|
|
# Install the necessary extras... |
|
399
|
0
|
|
|
|
|
|
my $BLOCK = _augment_block(default => $matched{BLOCK}); |
|
400
|
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
# Build the implementation of the "default"... |
|
402
|
0
|
|
|
|
|
|
my $REPLACEMENT_CODE = qq{ if (1) $BLOCK }; |
|
403
|
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
# At what line should the "default" end??? |
|
405
|
0
|
|
|
|
|
|
my $end_line = (caller)[2] + $matched{DEFAULT} =~ tr/\n//; |
|
406
|
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
# Append the trailing code (at the right line number)... |
|
408
|
0
|
|
|
|
|
|
${$source_ref} = "$REPLACEMENT_CODE\n#line $end_line\n$matched{TRAILING_CODE}"; |
|
|
0
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
} |
|
410
|
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
# Report the error... |
|
412
|
|
|
|
|
|
|
else { |
|
413
|
0
|
|
|
|
|
|
${$source_ref} |
|
|
0
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
= qq{ BEGIN { die q{Incomprehensible "default" (near: $matched{INCOMPREHENSIBLE})} } }; |
|
415
|
|
|
|
|
|
|
} |
|
416
|
|
|
|
|
|
|
} |
|
417
|
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
# Implement the "continue" command... |
|
419
|
0
|
|
|
0
|
0
|
|
sub continue () { |
|
|
0
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
# Which "when" block are we in??? |
|
421
|
0
|
|
|
|
|
|
my $AFTERWHEN = (caller 0)[10]{'Switch::Right/Afterwhen'}; |
|
422
|
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
# Jump out of it, if possible... |
|
424
|
7
|
|
|
7
|
|
60
|
no warnings; |
|
|
7
|
|
|
|
|
14
|
|
|
|
7
|
|
|
|
|
1082
|
|
|
425
|
0
|
|
|
|
|
|
eval { goto $AFTERWHEN }; |
|
|
0
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
# If not possible, that's fatal... |
|
428
|
0
|
|
|
|
|
|
croak q{Can't "continue" outside a "when" or "default"}; |
|
429
|
|
|
|
|
|
|
} |
|
430
|
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
# Implement the "break" command... |
|
432
|
0
|
|
|
0
|
0
|
|
sub break () { |
|
|
0
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
# Which "given" block are we in??? |
|
434
|
0
|
|
|
|
|
|
my $AFTERGIVEN = (caller 0)[10]{'Switch::Right/Aftergiven'}; |
|
435
|
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
# Jump out of it, if possible... |
|
437
|
7
|
|
|
7
|
|
64
|
no warnings; |
|
|
7
|
|
|
|
|
12
|
|
|
|
7
|
|
|
|
|
9513
|
|
|
438
|
0
|
|
|
|
|
|
eval { goto $AFTERGIVEN }; |
|
|
0
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
# If we weren't in a "given", can we jump out of a surrounding loop??? |
|
441
|
0
|
|
|
|
|
|
eval { next }; |
|
|
0
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
# Otherwise, the "break" was illegal and must be punished... |
|
444
|
0
|
|
|
|
|
|
croak q{Can't "break" outside a "given"}; |
|
445
|
|
|
|
|
|
|
} |
|
446
|
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
# Insert unique identifying information into a "given"/"when"/"default" source code block... |
|
449
|
0
|
|
|
0
|
|
|
sub _augment_block ($TYPE, $BLOCK, $JUNC = q{}) { |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
# Unique identifiers for each type of block... |
|
451
|
0
|
|
|
|
|
|
state %ID; |
|
452
|
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
# Who and what is this block??? |
|
454
|
0
|
0
|
|
|
|
|
my $KIND = $TYPE eq 'default' ? "when" : $TYPE; |
|
455
|
0
|
|
|
|
|
|
my $NAME = "After$KIND"; |
|
456
|
0
|
|
|
|
|
|
my $ID = $NAME . ++$ID{$KIND}; |
|
457
|
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
# Give each block a unique name (uses refaliasing to create a lexical constant)... |
|
459
|
0
|
|
|
|
|
|
substr($BLOCK, 1,0) |
|
460
|
|
|
|
|
|
|
= qq{ BEGIN { \$^H{'Switch::Right/$NAME'} = '$ID'; } }; |
|
461
|
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
# A when block auto-breaks at the end of its block... |
|
463
|
0
|
0
|
|
|
|
|
if ($KIND eq 'when') { |
|
|
|
0
|
|
|
|
|
|
|
464
|
0
|
|
|
|
|
|
my $AFTERGIVEN = $^H{'Switch::Right/Aftergiven'}; |
|
465
|
0
|
0
|
|
|
|
|
substr($BLOCK,-1,0) |
|
466
|
|
|
|
|
|
|
= ';' |
|
467
|
|
|
|
|
|
|
. (defined($AFTERGIVEN) ? qq{eval { no warnings; goto $AFTERGIVEN } || } : q{}) |
|
468
|
|
|
|
|
|
|
. qq{eval { no warnings; next } || die q{Can't "$TYPE" outside a topicalizer} }; |
|
469
|
|
|
|
|
|
|
} |
|
470
|
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
elsif ($KIND eq 'given') { |
|
472
|
|
|
|
|
|
|
# Remember whether (and how) given was junctive... |
|
473
|
0
|
|
|
|
|
|
substr($BLOCK, 1,0) = qq{ BEGIN { \$^H{'Switch::Right/GivenJunctive'} = '$JUNC'; } }; |
|
474
|
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
# Given blocks must to pre-convert postfix "when" modifiers (which can't be keyworded)... |
|
476
|
0
|
|
|
|
|
|
$BLOCK = _convert_postfix_whens($BLOCK); |
|
477
|
|
|
|
|
|
|
} |
|
478
|
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
# Return identified block... |
|
480
|
0
|
|
|
|
|
|
return "$BLOCK $ID:;"; |
|
481
|
|
|
|
|
|
|
} |
|
482
|
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
# Identify and pre-convert "EXPR when EXPR" syntax... |
|
484
|
0
|
|
|
0
|
|
|
sub _convert_postfix_whens ($BLOCK) { |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
# Track locations of "when" modifiers in the block's source... |
|
486
|
0
|
|
|
|
|
|
my @target_pos; |
|
487
|
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
# Extract those locations, whenever a statement has a "when" modifier... |
|
489
|
0
|
|
|
|
|
|
$BLOCK =~ m{ |
|
490
|
|
|
|
|
|
|
\{ (?&PerlStatementSequence) \} |
|
491
|
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
(?(DEFINE) |
|
493
|
|
|
|
|
|
|
(? |
|
494
|
|
|
|
|
|
|
(?> |
|
495
|
|
|
|
|
|
|
(?>(?&PerlPodSequence)) |
|
496
|
|
|
|
|
|
|
(?: (?>(?&PerlLabel)) (?&PerlOWSOrEND) )?+ |
|
497
|
|
|
|
|
|
|
(?>(?&PerlPodSequence)) |
|
498
|
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
(?> (?&PerlKeyword) |
|
500
|
|
|
|
|
|
|
| (?&PerlSubroutineDeclaration) |
|
501
|
|
|
|
|
|
|
| (?&PerlMethodDeclaration) |
|
502
|
|
|
|
|
|
|
| (?&PerlUseStatement) |
|
503
|
|
|
|
|
|
|
| (?&PerlPackageDeclaration) |
|
504
|
|
|
|
|
|
|
| (?&PerlClassDeclaration) |
|
505
|
|
|
|
|
|
|
| (?&PerlFieldDeclaration) |
|
506
|
|
|
|
|
|
|
| (?&PerlControlBlock) |
|
507
|
|
|
|
|
|
|
| (?&PerlFormat) |
|
508
|
|
|
|
|
|
|
| |
|
509
|
|
|
|
|
|
|
# POSTFIX when HAS TO BE REWRITTEN BEFORE OTHER POSTFIX MODIFIERS ARE MATCHED... |
|
510
|
|
|
|
|
|
|
(? |
|
511
|
|
|
|
|
|
|
(? (?>(?&PerlExpression)) (?>(?&PerlOWS)) ) |
|
512
|
|
|
|
|
|
|
(?= when \b ) |
|
513
|
|
|
|
|
|
|
(? (?&PerlStatementModifier) (?>(?&PerlOWSOrEND)) ) |
|
514
|
|
|
|
|
|
|
(? (?> ; | (?= \} | \z )) ) |
|
515
|
|
|
|
|
|
|
) |
|
516
|
0
|
|
|
|
|
|
(?{ my $len = length($+{MATCH}); |
|
517
|
|
|
|
|
|
|
unshift @target_pos, { |
|
518
|
|
|
|
|
|
|
expr => $+{EXPR}, |
|
519
|
|
|
|
|
|
|
mod => substr($+{MOD},4), |
|
520
|
|
|
|
|
|
|
end => $+{END}, |
|
521
|
0
|
|
|
|
|
|
from => pos() - $len, |
|
522
|
|
|
|
|
|
|
len => $len, |
|
523
|
|
|
|
|
|
|
} |
|
524
|
|
|
|
|
|
|
}) |
|
525
|
|
|
|
|
|
|
| |
|
526
|
|
|
|
|
|
|
(?>(?&PerlExpression)) (?>(?&PerlOWS)) |
|
527
|
|
|
|
|
|
|
(?&PerlStatementModifier)?+ (?>(?&PerlOWSOrEND)) |
|
528
|
|
|
|
|
|
|
(?> ; | (?= \} | \z )) |
|
529
|
|
|
|
|
|
|
| (?&PerlBlock) |
|
530
|
|
|
|
|
|
|
| ; |
|
531
|
|
|
|
|
|
|
) |
|
532
|
|
|
|
|
|
|
| # A yada-yada... |
|
533
|
|
|
|
|
|
|
\.\.\. (?>(?&PerlOWSOrEND)) |
|
534
|
|
|
|
|
|
|
(?> ; | (?= \} | \z )) |
|
535
|
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
| # Just a label... |
|
537
|
|
|
|
|
|
|
(?>(?&PerlLabel)) (?>(?&PerlOWSOrEND)) |
|
538
|
|
|
|
|
|
|
(?> ; | (?= \} | \z )) |
|
539
|
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
| # Just an empty statement... |
|
541
|
|
|
|
|
|
|
(?>(?&PerlOWS)) ; |
|
542
|
|
|
|
|
|
|
) |
|
543
|
|
|
|
|
|
|
) |
|
544
|
|
|
|
|
|
|
) |
|
545
|
|
|
|
|
|
|
$PPR::X::GRAMMAR |
|
546
|
|
|
|
|
|
|
}xms; |
|
547
|
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
# Replace each postfix "when"... |
|
549
|
0
|
|
|
|
|
|
for my $pos (@target_pos) { |
|
550
|
|
|
|
|
|
|
# Unique ID for the "when" (needed by continue())... |
|
551
|
0
|
|
|
|
|
|
state $ID; $ID++; |
|
|
0
|
|
|
|
|
|
|
|
552
|
0
|
|
|
|
|
|
state $JUNCTIVE_EXPR = qr{ |
|
553
|
|
|
|
|
|
|
$OWS (?>(? (?: any | all | none ) $OWS => $OWS | )) (? .* ) |
|
554
|
|
|
|
|
|
|
$PPR::GRAMMAR |
|
555
|
|
|
|
|
|
|
}xms; |
|
556
|
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
# Unpack and enchant the "when" expression... |
|
558
|
0
|
|
|
|
|
|
my ($JUNCTIVE, $MOD_EXPR) = (q{}, $pos->{mod}); |
|
559
|
0
|
0
|
|
|
|
|
if ($MOD_EXPR =~ $JUNCTIVE_EXPR) { |
|
560
|
0
|
|
|
|
|
|
($JUNCTIVE, $MOD_EXPR) = ( $+{JUNC}, _apply_term_magic($+{EXPR}) ); |
|
561
|
|
|
|
|
|
|
} |
|
562
|
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
# Convert postfix "when" to a postfix "if" (preserving Afterwhen info for continue())... |
|
564
|
|
|
|
|
|
|
substr($BLOCK, $pos->{from}, $pos->{len}) |
|
565
|
|
|
|
|
|
|
= "BEGIN { \$^H{'Switch::Right/Afterwhenprev'} = \$^H{'Switch::Right/Afterwhen'};" |
|
566
|
|
|
|
|
|
|
. " \$^H{'Switch::Right/Afterwhen'} = 'Afterpostfixwhen$ID'; }" |
|
567
|
|
|
|
|
|
|
. "$pos->{expr}, break if smartmatch(\$_, $JUNCTIVE scalar($MOD_EXPR))" |
|
568
|
|
|
|
|
|
|
. ";Afterpostfixwhen$ID:" |
|
569
|
|
|
|
|
|
|
. "BEGIN { \$^H{'Switch::Right/Afterwhen'} = \$^H{'Switch::Right/Afterwhenprev'}; }" |
|
570
|
0
|
|
|
|
|
|
. $pos->{end}; |
|
571
|
|
|
|
|
|
|
} |
|
572
|
|
|
|
|
|
|
|
|
573
|
0
|
|
|
|
|
|
return $BLOCK; |
|
574
|
|
|
|
|
|
|
} |
|
575
|
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
# Change the target expression of a "when" to implement all the magic behaviours... |
|
577
|
0
|
|
|
0
|
|
|
sub _apply_term_magic ($EXPR) { |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
578
|
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
# Apply compile-time expression folding... |
|
580
|
0
|
|
|
|
|
|
$EXPR = _simplify_expr($EXPR); |
|
581
|
|
|
|
|
|
|
|
|
582
|
|
|
|
|
|
|
# Adjust flip..flips to canonical booleans... |
|
583
|
0
|
0
|
0
|
|
|
|
if ($EXPR =~ /\.\./ && $EXPR =~ $FLIP_FLOP) { |
|
584
|
0
|
|
|
|
|
|
return "!!($EXPR)"; |
|
585
|
|
|
|
|
|
|
} |
|
586
|
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
# An @array or %hash gets enreferenced and then smartmatched. |
|
588
|
|
|
|
|
|
|
# An @array[@slice] or %kv[@slice] gets appropriately wrapped and then smartmatched. |
|
589
|
|
|
|
|
|
|
# Anything else is evaluated as-is... |
|
590
|
0
|
0
|
0
|
|
|
|
return ($EXPR =~ /[\@%]/ && $EXPR =~ $CONTAINER_VARIABLE) ? "\\$EXPR" |
|
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
591
|
|
|
|
|
|
|
: ($EXPR =~ /[\@]/ && $EXPR =~ $ARRAY_SLICE) ? "[$EXPR]" |
|
592
|
|
|
|
|
|
|
: ($EXPR =~ /[\%]/ && $EXPR =~ $HASH_SLICE) ? "{$EXPR}" |
|
593
|
|
|
|
|
|
|
: $EXPR; |
|
594
|
|
|
|
|
|
|
} |
|
595
|
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
# Reduce a compile-time expression to what the compiler actually sees... |
|
598
|
|
|
|
|
|
|
# (Essential because that's what when() actually sees and how it decides |
|
599
|
|
|
|
|
|
|
# whether or not smartmatch is magically distributive over a boolean expression)... |
|
600
|
0
|
|
|
0
|
|
|
sub _simplify_expr ($code) { |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
601
|
7
|
|
|
7
|
|
63
|
no warnings; |
|
|
7
|
|
|
|
|
14
|
|
|
|
7
|
|
|
|
|
342
|
|
|
602
|
7
|
|
|
7
|
|
45
|
use B::Deparse; |
|
|
7
|
|
|
|
|
194
|
|
|
|
7
|
|
|
|
|
487
|
|
|
603
|
7
|
|
|
7
|
|
42
|
use builtin qw; |
|
|
7
|
|
|
|
|
11
|
|
|
|
7
|
|
|
|
|
1550
|
|
|
604
|
0
|
|
|
|
|
|
state $deparse = B::Deparse->new; |
|
605
|
0
|
|
|
|
|
|
return $deparse->coderef2text(eval qq{no strict; sub{ANSWER( scalar($code) );DONE()}}) |
|
606
|
|
|
|
|
|
|
=~ s{.* ANSWER \( \s* scalar \s* (.*) \) \s* ; \s* DONE() .* \z}{$1}gxmsr; |
|
607
|
|
|
|
|
|
|
} |
|
608
|
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
# Implement the new simpler, but shinier smartmatch operator... |
|
611
|
|
|
|
|
|
|
# (Every one of the following four variants could each have been a set of multiple variants, |
|
612
|
|
|
|
|
|
|
# but this way is currently still significantly faster)... |
|
613
|
|
|
|
|
|
|
|
|
614
|
7
|
0
|
0
|
7
|
|
1742653
|
multi smartmatch ($left, $right) { |
|
|
7
|
50
|
50
|
7
|
|
28
|
|
|
|
7
|
0
|
|
7
|
|
3504
|
|
|
|
7
|
0
|
|
7
|
|
55
|
|
|
|
7
|
0
|
|
7
|
|
14
|
|
|
|
7
|
0
|
|
7
|
|
4216
|
|
|
|
7
|
0
|
|
201244
|
|
72
|
|
|
|
7
|
50
|
|
|
|
13
|
|
|
|
7
|
100
|
|
|
|
645
|
|
|
|
7
|
50
|
|
|
|
43
|
|
|
|
7
|
50
|
|
|
|
11
|
|
|
|
7
|
50
|
|
|
|
396
|
|
|
|
7
|
|
|
|
|
33
|
|
|
|
7
|
|
|
|
|
10
|
|
|
|
7
|
|
|
|
|
4662
|
|
|
|
7
|
|
|
|
|
6672
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
7
|
|
|
|
|
22
|
|
|
|
7
|
|
|
|
|
12
|
|
|
|
7
|
|
|
|
|
98
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
7
|
|
|
|
|
37
|
|
|
|
7
|
|
|
|
|
46
|
|
|
|
7
|
|
|
|
|
64
|
|
|
|
201244
|
|
|
|
|
294904
|
|
|
|
201244
|
|
|
|
|
700098
|
|
|
|
201244
|
|
|
|
|
477389
|
|
|
|
804976
|
|
|
|
|
1609189
|
|
|
|
603732
|
|
|
|
|
1308771
|
|
|
|
201244
|
|
|
|
|
406970
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
201244
|
|
|
|
|
280973
|
|
|
|
201244
|
|
|
|
|
426197
|
|
|
|
201244
|
|
|
|
|
433303
|
|
|
|
201244
|
|
|
|
|
364800
|
|
|
|
201244
|
|
|
|
|
276895
|
|
|
|
201244
|
|
|
|
|
496876
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
7
|
|
|
|
|
29
|
|
|
|
7
|
|
|
|
|
48
|
|
|
|
7
|
|
|
|
|
1048
|
|
|
|
7
|
|
|
|
|
30
|
|
|
|
7
|
|
|
|
|
136
|
|
|
|
201939
|
|
|
|
|
320010
|
|
|
|
201939
|
|
|
|
|
265514
|
|
|
|
201939
|
|
|
|
|
482782
|
|
|
|
201939
|
|
|
|
|
473387
|
|
|
|
201939
|
|
|
|
|
371287
|
|
|
|
201939
|
|
|
|
|
433853
|
|
|
615
|
|
|
|
|
|
|
# The standard error message for args that are objects (and which shouldn't be)... |
|
616
|
201939
|
100
|
|
|
|
291872
|
state $OBJ_ARG = "Smartmatching an object breaks encapsulation"; |
|
|
201939
|
|
|
|
|
335635
|
|
|
|
201939
|
|
|
|
|
424366
|
|
|
617
|
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
# Track "use integer" status in original caller (passing it down to nested smartmatches)... |
|
619
|
201939
|
|
66
|
|
|
425651
|
local $Switch::Right::_use_integer = $Switch::Right::_use_integer // (caller 0)[8] & 0x1; |
|
620
|
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
# RHS undef only matches LHS undef... |
|
622
|
201939
|
100
|
|
|
|
400084
|
return !defined $left if !defined $right; |
|
623
|
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
# RHS distinguished boolean always returns RHS value... |
|
625
|
201786
|
100
|
|
|
|
423857
|
return $right if is_bool($right); |
|
626
|
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
# RHS objects use their SMARTMATCH method (if they have one)... |
|
628
|
200365
|
|
100
|
|
|
630813
|
my $right_type = reftype($right) // 'VAL'; |
|
629
|
200365
|
100
|
100
|
|
|
633162
|
if ($right_type ne 'REGEXP' && blessed $right) { |
|
630
|
98
|
|
|
|
|
161
|
try { return $right->SMARTMATCH($left) } |
|
|
98
|
|
|
|
|
1890
|
|
|
631
|
92
|
|
|
|
|
14018
|
catch ($ERR) { croak "$OBJ_ARG ($ERR)" } |
|
632
|
|
|
|
|
|
|
} |
|
633
|
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
# Otherwise, branch to the appropriate comparator (if any)... |
|
635
|
200267
|
|
100
|
|
|
562422
|
my $left_type = reftype($left) // 'VAL'; |
|
636
|
200267
|
|
100
|
|
|
535610
|
my $left_is_obj = $left_type ne 'REGEXP' && blessed($left); |
|
637
|
200267
|
100
|
|
|
|
312521
|
eval { goto ($left_is_obj ? 'OBJECT' : $left_type) . $right_type }; |
|
|
200267
|
|
|
|
|
785721
|
|
|
638
|
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
# Otherwise, a RHS subref (with any non-subref LHS) acts like a boolean-returning test... |
|
640
|
542
|
100
|
|
|
|
5145
|
return $right->($left) if $right_type eq 'CODE'; |
|
641
|
|
|
|
|
|
|
|
|
642
|
|
|
|
|
|
|
# At thi spoint, no other combination of arguments will ever match... |
|
643
|
281
|
|
|
|
|
8615
|
return false; |
|
644
|
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
# Objects can be used as LHS when matching an RHS value, but must be preprocessed... |
|
646
|
|
|
|
|
|
|
OBJECTVAL: |
|
647
|
4
|
50
|
|
|
|
19
|
if (created_as_number($right) ) { |
|
648
|
0
|
0
|
|
|
|
0
|
croak $OBJ_ARG if !overload::Method($left, '0+'); |
|
649
|
0
|
|
|
|
|
0
|
$left = 0+$left; |
|
650
|
|
|
|
|
|
|
} |
|
651
|
|
|
|
|
|
|
else { |
|
652
|
4
|
50
|
|
|
|
29
|
croak $OBJ_ARG if !overload::Method($left, q{""}); |
|
653
|
4
|
|
|
|
|
378
|
$left = "$left"; |
|
654
|
|
|
|
|
|
|
} |
|
655
|
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
# Compare two scalar values (or a suitably overloaded LHS object and an RHS value)... |
|
657
|
199374
|
100
|
|
|
|
407345
|
VALVAL: |
|
658
|
|
|
|
|
|
|
# 1. undef doesn't match a number or a string... |
|
659
|
|
|
|
|
|
|
return false if !defined $left; |
|
660
|
|
|
|
|
|
|
|
|
661
|
|
|
|
|
|
|
# 2. Match primordial RHS numbers using == (respecting any ambient "use integer")... |
|
662
|
199289
|
100
|
|
|
|
469094
|
if (created_as_number($right) ) { |
|
663
|
778
|
100
|
|
|
|
3388
|
if (!looks_like_number($left)) { return false; } |
|
|
14
|
50
|
|
|
|
308
|
|
|
664
|
7
|
|
|
7
|
|
4798
|
elsif ($Switch::Right::_use_integer) { use integer; return $left == $right; } |
|
|
7
|
|
|
|
|
124
|
|
|
|
7
|
|
|
|
|
44
|
|
|
|
0
|
|
|
|
|
0
|
|
|
665
|
764
|
|
|
|
|
16157
|
else { return $left == $right; } |
|
666
|
|
|
|
|
|
|
} |
|
667
|
|
|
|
|
|
|
|
|
668
|
|
|
|
|
|
|
# 3. Otherwise just use string equality... |
|
669
|
198511
|
|
|
|
|
2726181
|
return $left eq $right; |
|
670
|
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
# RHS regexes match any defined non-ref value via =~ pattern-matching... |
|
672
|
95
|
|
66
|
|
|
3047
|
VALREGEXP: |
|
673
|
|
|
|
|
|
|
return defined($left) && $left =~ $right; |
|
674
|
|
|
|
|
|
|
|
|
675
|
|
|
|
|
|
|
# Compare two refs of the same type... |
|
676
|
12
|
|
|
|
|
332
|
CODECODE: |
|
677
|
|
|
|
|
|
|
return $left == $right; |
|
678
|
|
|
|
|
|
|
|
|
679
|
2
|
|
66
|
|
|
143
|
REGEXPREGEXP: |
|
680
|
|
|
|
|
|
|
return $left == $right || $left eq $right; |
|
681
|
|
|
|
|
|
|
|
|
682
|
133
|
100
|
|
|
|
597
|
ARRAYARRAY: |
|
683
|
|
|
|
|
|
|
return true if $left == $right; # ...they're the same array |
|
684
|
122
|
100
|
|
|
|
185
|
return false if @{$left} != @{$right}; # ...different lengths so their contents can't match |
|
|
122
|
|
|
|
|
295
|
|
|
|
122
|
|
|
|
|
757
|
|
|
685
|
|
|
|
|
|
|
|
|
686
|
|
|
|
|
|
|
# Handle non-identical self-referential structures... |
|
687
|
108
|
|
|
|
|
349
|
local %Sm4r7m4tCh::seen = %Sm4r7m4tCh::seen; |
|
688
|
108
|
100
|
66
|
|
|
1314
|
return false if $Sm4r7m4tCh::seen{"L$left"}++ || $Sm4r7m4tCh::seen{"R$right"}++; |
|
689
|
|
|
|
|
|
|
|
|
690
|
|
|
|
|
|
|
# Otherwise, corresponding pairs of array elements must all smartmatch... |
|
691
|
105
|
|
|
|
|
157
|
for my $n (keys @{$right}) { |
|
|
105
|
|
|
|
|
321
|
|
|
692
|
447
|
100
|
|
|
|
1578
|
return false if !smartmatch($left->[$n], $right->[$n]); |
|
693
|
|
|
|
|
|
|
} |
|
694
|
76
|
|
|
|
|
1994
|
return true; |
|
695
|
|
|
|
|
|
|
|
|
696
|
100
|
100
|
|
|
|
756
|
HASHHASH: |
|
697
|
|
|
|
|
|
|
return true if $left == $right; # ...they're the same hash |
|
698
|
80
|
100
|
|
|
|
124
|
return false if keys %{$left} != keys %{$right}; # ...different numbers of keys, can't match |
|
|
80
|
|
|
|
|
213
|
|
|
|
80
|
|
|
|
|
990
|
|
|
699
|
|
|
|
|
|
|
|
|
700
|
|
|
|
|
|
|
# Handle non-identical self-referential structures... |
|
701
|
58
|
|
|
|
|
429
|
local %Sm4r7m4tCh::seen = %Sm4r7m4tCh::seen; |
|
702
|
58
|
50
|
33
|
|
|
600
|
return false if $Sm4r7m4tCh::seen{"L$left"}++ || $Sm4r7m4tCh::seen{"R$right"}++; |
|
703
|
|
|
|
|
|
|
|
|
704
|
|
|
|
|
|
|
# Otherwise, are they identical is structure??? |
|
705
|
58
|
|
|
|
|
96
|
for my $key (keys %{$left}) { |
|
|
58
|
|
|
|
|
719
|
|
|
706
|
|
|
|
|
|
|
return false if !exists $right->{$key} # ...must have same keys |
|
707
|
1408
|
100
|
100
|
|
|
5046
|
|| !smartmatch($left->{$key}, $right->{$key}); # ...every value must match |
|
708
|
|
|
|
|
|
|
} |
|
709
|
43
|
|
|
|
|
1705
|
return true; |
|
710
|
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
# Every other REF/REF comparison, just checks for the same address.. |
|
712
|
4
|
|
|
|
|
4
|
FORMATFORMAT:; |
|
713
|
4
|
|
|
|
|
4
|
IOIO:; |
|
714
|
6
|
|
|
|
|
5
|
SCALARSCALAR:; |
|
715
|
8
|
|
|
|
|
7
|
VSTRINGVSTRING:; |
|
716
|
11
|
|
|
|
|
8
|
REFREF:; |
|
717
|
13
|
|
|
|
|
13
|
GLOBGLOB:; |
|
718
|
15
|
|
|
|
|
12
|
LVALUELVALUE:; |
|
719
|
15
|
|
|
|
|
274
|
return $left == $right; |
|
720
|
7
|
|
|
|
|
13
|
} |
|
|
201939
|
|
|
|
|
1014832
|
|
|
721
|
|
|
|
|
|
|
|
|
722
|
|
|
|
|
|
|
# Junctive smartmatching of the RHS list... |
|
723
|
7
|
0
|
0
|
7
|
|
763764
|
multi smartmatch ($left, $junction =~ /^(?:any|all|none)$/, \@right) { |
|
|
7
|
50
|
0
|
7
|
|
39
|
|
|
|
7
|
0
|
100
|
7
|
|
3709
|
|
|
|
7
|
0
|
66
|
7
|
|
60
|
|
|
|
7
|
50
|
|
7
|
|
17
|
|
|
|
7
|
50
|
|
7
|
|
4830
|
|
|
|
7
|
50
|
|
7
|
|
71
|
|
|
|
7
|
50
|
|
|
|
14
|
|
|
|
7
|
0
|
|
|
|
689
|
|
|
|
7
|
0
|
|
|
|
55
|
|
|
|
7
|
0
|
|
|
|
17
|
|
|
|
7
|
50
|
|
|
|
511
|
|
|
|
7
|
100
|
|
|
|
67
|
|
|
|
7
|
100
|
|
|
|
17
|
|
|
|
7
|
|
|
|
|
1200
|
|
|
|
7
|
|
|
|
|
53
|
|
|
|
7
|
|
|
|
|
18
|
|
|
|
7
|
|
|
|
|
4405
|
|
|
|
7
|
|
|
|
|
77
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
7
|
|
|
|
|
23
|
|
|
|
7
|
|
|
|
|
17
|
|
|
|
7
|
|
|
|
|
56
|
|
|
|
7
|
|
|
|
|
50
|
|
|
|
7
|
|
|
|
|
72
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
7
|
|
|
|
|
26
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
7
|
|
|
|
|
1847
|
|
|
|
7
|
|
|
|
|
34
|
|
|
|
7
|
|
|
|
|
159
|
|
|
|
389
|
|
|
|
|
904
|
|
|
|
389
|
|
|
|
|
2806
|
|
|
|
318
|
|
|
|
|
593
|
|
|
|
318
|
|
|
|
|
451
|
|
|
|
318
|
|
|
|
|
1642
|
|
|
|
318
|
|
|
|
|
568
|
|
|
|
318
|
|
|
|
|
2000
|
|
|
|
300
|
|
|
|
|
1184
|
|
|
|
300
|
|
|
|
|
652
|
|
|
|
300
|
|
|
|
|
876
|
|
|
724
|
|
|
|
|
|
|
|
|
725
|
|
|
|
|
|
|
# Track "use integer" status in original caller (passing it down to nested smartmatches)... |
|
726
|
300
|
|
33
|
|
|
411
|
local $Switch::Right::_use_integer = $Switch::Right::_use_integer // (caller 0)[8] & 0x1; |
|
|
300
|
|
|
|
|
2514
|
|
|
727
|
|
|
|
|
|
|
|
|
728
|
|
|
|
|
|
|
# Select junctive behaviour... |
|
729
|
300
|
|
|
|
|
1238
|
goto $junction; |
|
730
|
|
|
|
|
|
|
|
|
731
|
|
|
|
|
|
|
# Disjunction... |
|
732
|
146
|
|
|
|
|
304
|
any: for my $rval (@right) { |
|
733
|
238
|
100
|
|
|
|
581
|
return true if smartmatch($left, $rval); |
|
734
|
|
|
|
|
|
|
} |
|
735
|
56
|
|
|
|
|
1570
|
return false; |
|
736
|
|
|
|
|
|
|
|
|
737
|
|
|
|
|
|
|
# Conjunction... |
|
738
|
89
|
|
|
|
|
199
|
all: for my $rval (@right) { |
|
739
|
153
|
100
|
|
|
|
312
|
return false if !smartmatch($left, $rval); |
|
740
|
|
|
|
|
|
|
} |
|
741
|
41
|
|
|
|
|
1312
|
return true; |
|
742
|
|
|
|
|
|
|
|
|
743
|
|
|
|
|
|
|
# Injunction... |
|
744
|
65
|
|
|
|
|
148
|
none: for my $rval (@right) { |
|
745
|
133
|
100
|
|
|
|
356
|
return false if smartmatch($left, $rval); |
|
746
|
|
|
|
|
|
|
} |
|
747
|
62
|
|
|
|
|
1332
|
return true; |
|
748
|
7
|
|
|
|
|
18
|
} |
|
|
300
|
|
|
|
|
2202
|
|
|
749
|
|
|
|
|
|
|
|
|
750
|
|
|
|
|
|
|
# Junctive smartmatching of the LHS list... |
|
751
|
7
|
0
|
0
|
7
|
|
701367
|
multi smartmatch ($junction =~ /^(?:any|all|none)$/, \@left, $right) { |
|
|
7
|
50
|
0
|
7
|
|
17
|
|
|
|
7
|
0
|
50
|
7
|
|
3099
|
|
|
|
7
|
0
|
33
|
7
|
|
70
|
|
|
|
7
|
50
|
|
7
|
|
11
|
|
|
|
7
|
50
|
|
7
|
|
4522
|
|
|
|
7
|
50
|
|
7
|
|
54
|
|
|
|
7
|
50
|
|
|
|
12
|
|
|
|
7
|
0
|
|
|
|
550
|
|
|
|
7
|
0
|
|
|
|
37
|
|
|
|
7
|
0
|
|
|
|
12
|
|
|
|
7
|
50
|
|
|
|
305
|
|
|
|
7
|
50
|
|
|
|
38
|
|
|
|
7
|
50
|
|
|
|
34
|
|
|
|
7
|
|
|
|
|
1139
|
|
|
|
7
|
|
|
|
|
44
|
|
|
|
7
|
|
|
|
|
10
|
|
|
|
7
|
|
|
|
|
4110
|
|
|
|
7
|
|
|
|
|
57
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
7
|
|
|
|
|
21
|
|
|
|
7
|
|
|
|
|
14
|
|
|
|
7
|
|
|
|
|
31
|
|
|
|
7
|
|
|
|
|
29
|
|
|
|
7
|
|
|
|
|
93
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
7
|
|
|
|
|
26
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
7
|
|
|
|
|
2392
|
|
|
|
7
|
|
|
|
|
70
|
|
|
|
7
|
|
|
|
|
199
|
|
|
|
89
|
|
|
|
|
167
|
|
|
|
89
|
|
|
|
|
544
|
|
|
|
89
|
|
|
|
|
177
|
|
|
|
89
|
|
|
|
|
132
|
|
|
|
89
|
|
|
|
|
404
|
|
|
|
89
|
|
|
|
|
261
|
|
|
|
89
|
|
|
|
|
656
|
|
|
|
89
|
|
|
|
|
344
|
|
|
|
89
|
|
|
|
|
230
|
|
|
|
89
|
|
|
|
|
283
|
|
|
752
|
|
|
|
|
|
|
# Track "use integer" status in original caller (passing it down to nested smartmatches)... |
|
753
|
89
|
|
33
|
|
|
133
|
local $Switch::Right::_use_integer = $Switch::Right::_use_integer // (caller 0)[8] & 0x1; |
|
|
89
|
|
|
|
|
797
|
|
|
754
|
|
|
|
|
|
|
|
|
755
|
|
|
|
|
|
|
# Dispatch on junctive type... |
|
756
|
89
|
|
|
|
|
450
|
goto $junction; |
|
757
|
|
|
|
|
|
|
|
|
758
|
|
|
|
|
|
|
# Disjunction... |
|
759
|
24
|
|
|
|
|
85
|
any: for my $lval (@left) { |
|
760
|
58
|
100
|
|
|
|
157
|
return true if smartmatch($lval, $right); |
|
761
|
|
|
|
|
|
|
} |
|
762
|
8
|
|
|
|
|
147
|
return false; |
|
763
|
|
|
|
|
|
|
|
|
764
|
|
|
|
|
|
|
# Conjunction... |
|
765
|
31
|
|
|
|
|
71
|
all: for my $lval (@left) { |
|
766
|
57
|
100
|
|
|
|
759
|
return false if !smartmatch($lval, $right); |
|
767
|
|
|
|
|
|
|
} |
|
768
|
19
|
|
|
|
|
603
|
return true; |
|
769
|
|
|
|
|
|
|
|
|
770
|
|
|
|
|
|
|
# Injunction: |
|
771
|
34
|
|
|
|
|
81
|
none: for my $lval (@left) { |
|
772
|
57
|
100
|
|
|
|
145
|
return false if smartmatch($lval, $right); |
|
773
|
|
|
|
|
|
|
} |
|
774
|
31
|
|
|
|
|
575
|
return true; |
|
775
|
7
|
|
|
|
|
12
|
} |
|
|
89
|
|
|
|
|
658
|
|
|
776
|
|
|
|
|
|
|
|
|
777
|
|
|
|
|
|
|
|
|
778
|
|
|
|
|
|
|
# Junctive smartmatching of both LHS and RHS lists... |
|
779
|
7
|
0
|
0
|
7
|
|
863843
|
multi smartmatch ( |
|
|
7
|
50
|
0
|
7
|
|
17
|
|
|
|
7
|
0
|
50
|
7
|
|
3557
|
|
|
|
7
|
0
|
33
|
7
|
|
59
|
|
|
|
7
|
50
|
50
|
7
|
|
14
|
|
|
|
7
|
50
|
33
|
7
|
|
4342
|
|
|
|
7
|
50
|
|
7
|
|
54
|
|
|
|
7
|
50
|
|
7
|
|
15
|
|
|
|
7
|
0
|
|
|
|
580
|
|
|
|
7
|
0
|
|
|
|
43
|
|
|
|
7
|
0
|
|
|
|
14
|
|
|
|
7
|
50
|
|
|
|
373
|
|
|
|
7
|
50
|
|
|
|
40
|
|
|
|
7
|
50
|
|
|
|
13
|
|
|
|
7
|
50
|
|
|
|
1038
|
|
|
|
7
|
50
|
|
|
|
41
|
|
|
|
7
|
|
|
|
|
13
|
|
|
|
7
|
|
|
|
|
947
|
|
|
|
7
|
|
|
|
|
126
|
|
|
|
7
|
|
|
|
|
55
|
|
|
|
7
|
|
|
|
|
8310
|
|
|
|
7
|
|
|
|
|
131
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
7
|
|
|
|
|
42
|
|
|
|
7
|
|
|
|
|
95
|
|
|
|
7
|
|
|
|
|
56
|
|
|
|
7
|
|
|
|
|
29
|
|
|
|
7
|
|
|
|
|
65
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
7
|
|
|
|
|
20
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
7
|
|
|
|
|
2914
|
|
|
|
7
|
|
|
|
|
30
|
|
|
|
7
|
|
|
|
|
163
|
|
|
|
78
|
|
|
|
|
137
|
|
|
|
78
|
|
|
|
|
789
|
|
|
|
78
|
|
|
|
|
145
|
|
|
|
78
|
|
|
|
|
440
|
|
|
|
78
|
|
|
|
|
189
|
|
|
|
78
|
|
|
|
|
112
|
|
|
|
78
|
|
|
|
|
478
|
|
|
|
78
|
|
|
|
|
321
|
|
|
|
78
|
|
|
|
|
588
|
|
|
|
78
|
|
|
|
|
138
|
|
|
|
78
|
|
|
|
|
337
|
|
|
|
78
|
|
|
|
|
360
|
|
|
|
78
|
|
|
|
|
273
|
|
|
|
78
|
|
|
|
|
292
|
|
|
780
|
|
|
|
|
|
|
$ljunction =~ m/^(?:any|all|none)$/, \@left, |
|
781
|
78
|
|
33
|
|
|
126
|
$rjunction =~ m/^(?:any|all|none)$/, \@right |
|
|
78
|
|
|
|
|
715
|
|
|
782
|
|
|
|
|
|
|
) { |
|
783
|
|
|
|
|
|
|
# Track "use integer" status in original caller (passing it down to nested smartmatches)... |
|
784
|
78
|
|
|
|
|
477
|
local $Switch::Right::_use_integer = $Switch::Right::_use_integer // (caller 0)[8] & 0x1; |
|
785
|
|
|
|
|
|
|
|
|
786
|
|
|
|
|
|
|
# Dispatch according to the combination of junctive types... |
|
787
|
25
|
|
|
|
|
62
|
goto "$ljunction$rjunction"; |
|
788
|
256
|
|
|
|
|
532
|
|
|
789
|
573
|
100
|
|
|
|
1287
|
# The nine combinations... |
|
790
|
|
|
|
|
|
|
anyany: for my $lval (@left) { |
|
791
|
6
|
|
|
|
|
442
|
for my $rval (@right) { |
|
792
|
|
|
|
|
|
|
return true if smartmatch($lval, $rval); # ...because any match is sufficient |
|
793
|
7
|
|
|
|
|
20
|
}} |
|
794
|
16
|
|
|
|
|
33
|
return false; # ...because no LHS value matched any RHS value |
|
795
|
25
|
100
|
|
|
|
185
|
|
|
796
|
|
|
|
|
|
|
anyall: for my $lval (@left) { |
|
797
|
5
|
|
|
|
|
157
|
for my $rval (@right) { |
|
798
|
|
|
|
|
|
|
next anyall if !smartmatch($lval, $rval); # ...because not all RHS vals match LHS |
|
799
|
2
|
|
|
|
|
40
|
} |
|
800
|
|
|
|
|
|
|
return true; # ...because all RHS values have matched some LHS value |
|
801
|
3
|
|
|
|
|
6
|
} |
|
802
|
|
|
|
|
|
|
return false; # ...because no LHS value matched all RHS values |
|
803
|
|
|
|
|
|
|
|
|
804
|
|
|
|
|
|
|
nonenone:; # This one's tricky: it means there isn't an LHS elem that matches no RHS elem, |
|
805
|
17
|
|
|
|
|
47
|
# which is the same as all LHS elems matching at least one (i.e. any) RHS elem |
|
806
|
922
|
|
|
|
|
2485
|
# so we just fall through to... |
|
807
|
197991
|
100
|
|
|
|
465145
|
|
|
808
|
|
|
|
|
|
|
allany: for my $lval (@left) { |
|
809
|
2
|
|
|
|
|
109
|
for my $rval (@right) { |
|
810
|
|
|
|
|
|
|
next allany if smartmatch($lval, $rval); # ...because at least 1 RHS value matched |
|
811
|
15
|
|
|
|
|
966
|
} |
|
812
|
|
|
|
|
|
|
return false; # ...because no RHS value matched the current LHS value |
|
813
|
7
|
|
|
|
|
21
|
} |
|
814
|
13
|
|
|
|
|
97
|
return true; # ...because every RHS value matched at least one RHS value |
|
815
|
28
|
100
|
|
|
|
77
|
|
|
816
|
|
|
|
|
|
|
allall: for my $lval (@left) { |
|
817
|
5
|
|
|
|
|
168
|
for my $rval (@right) { |
|
818
|
|
|
|
|
|
|
return false if !smartmatch($lval, $rval); # ...because a single mismatch is failure |
|
819
|
4
|
|
|
|
|
11
|
}} |
|
820
|
6
|
|
|
|
|
12
|
return true; # ...because every possible LHS/RHS combination matched |
|
821
|
16
|
100
|
|
|
|
40
|
|
|
822
|
|
|
|
|
|
|
noneany: for my $lval (@left) { |
|
823
|
1
|
|
|
|
|
22
|
for my $rval (@right) { |
|
824
|
|
|
|
|
|
|
return false if smartmatch($lval, $rval); # ...because a single match is failure |
|
825
|
5
|
|
|
|
|
15
|
}} |
|
826
|
13
|
|
|
|
|
28
|
return true; # ...because every LHS value failed to match any RHS value |
|
827
|
|
|
|
|
|
|
|
|
828
|
22
|
100
|
|
|
|
142
|
noneall: for my $lval (@left) { |
|
829
|
|
|
|
|
|
|
for my $rval (@right) { |
|
830
|
|
|
|
|
|
|
# This left elem is okay if it doesn't match at least one right elem... |
|
831
|
2
|
|
|
|
|
39
|
next noneall if !smartmatch($lval, $rval); |
|
832
|
|
|
|
|
|
|
# ...because every LHS value must mismatch at least one RHS value |
|
833
|
3
|
|
|
|
|
120
|
} |
|
834
|
|
|
|
|
|
|
return false; # ...because an LHS value did match all RHS values |
|
835
|
8
|
|
|
|
|
22
|
} |
|
836
|
13
|
|
|
|
|
122
|
return true; # ...because every LHS value failed to match at least one RHS value |
|
837
|
24
|
100
|
|
|
|
118
|
|
|
838
|
|
|
|
|
|
|
anynone: for my $lval (@left) { |
|
839
|
|
|
|
|
|
|
for my $rval (@right) { |
|
840
|
6
|
|
|
|
|
265
|
next anynone if smartmatch($lval, $rval); |
|
841
|
|
|
|
|
|
|
# ...because this left elem matched an RHS value, so it can't be the chosen one |
|
842
|
2
|
|
|
|
|
45
|
} |
|
843
|
|
|
|
|
|
|
return true; # ...because an LHS did match none of the RHS values |
|
844
|
5
|
|
|
|
|
14
|
} |
|
845
|
11
|
|
|
|
|
25
|
return false; # ...because we didn''t find an LHS value that matched no RHS value |
|
846
|
21
|
100
|
|
|
|
82
|
|
|
847
|
|
|
|
|
|
|
allnone: for my $lval (@left) { |
|
848
|
3
|
|
|
|
|
59
|
for my $rval (@right) { |
|
849
|
7
|
|
|
|
|
13
|
return false if smartmatch($lval, $rval); # ...because any match is disqualifying |
|
|
78
|
|
|
|
|
815
|
|
|
850
|
|
|
|
|
|
|
}} |
|
851
|
|
|
|
|
|
|
return true; # ...because every LHS/RHS combination has now failed to match |
|
852
|
|
|
|
|
|
|
} |
|
853
|
|
|
|
|
|
|
|
|
854
|
|
|
|
|
|
|
1; # Magic true value required at end of module |
|
855
|
|
|
|
|
|
|
__END__ |