| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
# Common routines used by PP Functions |
|
2
|
|
|
|
|
|
|
# Copyright (c) 2015-2018 Rocky Bernstein |
|
3
|
|
|
|
|
|
|
# Copyright (c) 1998-2000, 2002, 2003, 2004, 2005, 2006 Stephen McCamant. |
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
# All rights reserved. |
|
6
|
|
|
|
|
|
|
# This module is free software; you can redistribute and/or modify |
|
7
|
|
|
|
|
|
|
# it under the same terms as Perl itself. |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
# This is based on the module B::Deparse by Stephen McCamant. |
|
10
|
|
|
|
|
|
|
# It has been extended save tree structure, and is addressible |
|
11
|
|
|
|
|
|
|
# by opcode address. |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
# B::Parse in turn is based on the module of the same name by Malcolm Beattie, |
|
14
|
|
|
|
|
|
|
# but essentially none of his code remains. |
|
15
|
8
|
|
|
8
|
|
50
|
use strict; use warnings; |
|
|
8
|
|
|
8
|
|
15
|
|
|
|
8
|
|
|
|
|
241
|
|
|
|
8
|
|
|
|
|
37
|
|
|
|
8
|
|
|
|
|
191
|
|
|
|
8
|
|
|
|
|
299
|
|
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
package B::DeparseTree::PPfns; |
|
18
|
8
|
|
|
8
|
|
68
|
use Carp; |
|
|
8
|
|
|
|
|
15
|
|
|
|
8
|
|
|
|
|
538
|
|
|
19
|
8
|
|
|
|
|
513
|
use B qw( |
|
20
|
|
|
|
|
|
|
OPf_STACKED |
|
21
|
|
|
|
|
|
|
OPf_SPECIAL |
|
22
|
|
|
|
|
|
|
OPpCONST_BARE |
|
23
|
|
|
|
|
|
|
OPpLVAL_INTRO |
|
24
|
|
|
|
|
|
|
OPpREPEAT_DOLIST |
|
25
|
|
|
|
|
|
|
OPpSORT_INTEGER |
|
26
|
|
|
|
|
|
|
OPpSORT_NUMERIC |
|
27
|
|
|
|
|
|
|
OPpSORT_REVERSE |
|
28
|
|
|
|
|
|
|
opnumber |
|
29
|
8
|
|
|
8
|
|
51
|
); |
|
|
8
|
|
|
|
|
14
|
|
|
30
|
|
|
|
|
|
|
|
|
31
|
8
|
|
|
8
|
|
51
|
use B::Deparse; |
|
|
8
|
|
|
|
|
12
|
|
|
|
8
|
|
|
|
|
159
|
|
|
32
|
8
|
|
|
8
|
|
37
|
use B::DeparseTree::OPflags; |
|
|
8
|
|
|
|
|
27
|
|
|
|
8
|
|
|
|
|
561
|
|
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# Copied from B/const-xs.inc. Perl 5.16 doesn't have this |
|
35
|
8
|
|
|
8
|
|
50
|
use constant SVpad_STATE => 11; |
|
|
8
|
|
|
|
|
15
|
|
|
|
8
|
|
|
|
|
1476
|
|
|
36
|
8
|
|
|
8
|
|
56
|
use constant SVpad_TYPED => 8; |
|
|
8
|
|
|
|
|
15
|
|
|
|
8
|
|
|
|
|
518
|
|
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
# FIXME: DRY $is_cperl |
|
39
|
|
|
|
|
|
|
# Version specific modification are next... |
|
40
|
8
|
|
|
8
|
|
57
|
use Config; |
|
|
8
|
|
|
|
|
17
|
|
|
|
8
|
|
|
|
|
852
|
|
|
41
|
|
|
|
|
|
|
my $is_cperl = $Config::Config{usecperl}; |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
# Copy unchanged functions from B::Deparse |
|
44
|
|
|
|
|
|
|
*balanced_delim = *B::Deparse::balanced_delim; |
|
45
|
|
|
|
|
|
|
*double_delim = *B::Deparse::double_delim; |
|
46
|
|
|
|
|
|
|
*escape_extended_re = *B::Deparse::escape_extended_re; |
|
47
|
|
|
|
|
|
|
|
|
48
|
8
|
|
|
8
|
|
50
|
use B::DeparseTree::SyntaxTree; |
|
|
8
|
|
|
|
|
14
|
|
|
|
8
|
|
|
|
|
1785
|
|
|
49
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
our($VERSION, @EXPORT, @ISA); |
|
51
|
|
|
|
|
|
|
$VERSION = '3.2.0'; |
|
52
|
|
|
|
|
|
|
@ISA = qw(Exporter); |
|
53
|
|
|
|
|
|
|
@EXPORT = qw( |
|
54
|
|
|
|
|
|
|
%strict_bits |
|
55
|
|
|
|
|
|
|
ambient_pragmas |
|
56
|
|
|
|
|
|
|
anon_hash_or_list |
|
57
|
|
|
|
|
|
|
baseop |
|
58
|
|
|
|
|
|
|
binop |
|
59
|
|
|
|
|
|
|
code_list |
|
60
|
|
|
|
|
|
|
concat |
|
61
|
|
|
|
|
|
|
cops |
|
62
|
|
|
|
|
|
|
dedup_func_parens |
|
63
|
|
|
|
|
|
|
dedup_parens_func |
|
64
|
|
|
|
|
|
|
deparse_binop_left |
|
65
|
|
|
|
|
|
|
deparse_binop_right |
|
66
|
|
|
|
|
|
|
deparse_format |
|
67
|
|
|
|
|
|
|
deparse_op_siblings |
|
68
|
|
|
|
|
|
|
double_delim |
|
69
|
|
|
|
|
|
|
dq |
|
70
|
|
|
|
|
|
|
dq_unop |
|
71
|
|
|
|
|
|
|
dquote |
|
72
|
|
|
|
|
|
|
e_anoncode |
|
73
|
|
|
|
|
|
|
e_method |
|
74
|
|
|
|
|
|
|
elem |
|
75
|
|
|
|
|
|
|
filetest |
|
76
|
|
|
|
|
|
|
for_loop |
|
77
|
|
|
|
|
|
|
func_needs_parens |
|
78
|
|
|
|
|
|
|
givwhen |
|
79
|
|
|
|
|
|
|
indirop |
|
80
|
|
|
|
|
|
|
is_lexical_subs |
|
81
|
|
|
|
|
|
|
is_list_newer |
|
82
|
|
|
|
|
|
|
is_list_older |
|
83
|
|
|
|
|
|
|
listop |
|
84
|
|
|
|
|
|
|
logassignop |
|
85
|
|
|
|
|
|
|
logop |
|
86
|
|
|
|
|
|
|
loop_common |
|
87
|
|
|
|
|
|
|
loopex |
|
88
|
|
|
|
|
|
|
map_texts |
|
89
|
|
|
|
|
|
|
mapop |
|
90
|
|
|
|
|
|
|
matchop |
|
91
|
|
|
|
|
|
|
maybe_local |
|
92
|
|
|
|
|
|
|
maybe_local_str |
|
93
|
|
|
|
|
|
|
maybe_my |
|
94
|
|
|
|
|
|
|
maybe_parens |
|
95
|
|
|
|
|
|
|
maybe_parens_func |
|
96
|
|
|
|
|
|
|
maybe_parens_unop |
|
97
|
|
|
|
|
|
|
maybe_qualify |
|
98
|
|
|
|
|
|
|
maybe_targmy |
|
99
|
|
|
|
|
|
|
_method |
|
100
|
|
|
|
|
|
|
null_newer |
|
101
|
|
|
|
|
|
|
null_older |
|
102
|
|
|
|
|
|
|
pfixop |
|
103
|
|
|
|
|
|
|
pp_padsv |
|
104
|
|
|
|
|
|
|
range |
|
105
|
|
|
|
|
|
|
repeat |
|
106
|
|
|
|
|
|
|
rv2x |
|
107
|
|
|
|
|
|
|
scopeop |
|
108
|
|
|
|
|
|
|
single_delim |
|
109
|
|
|
|
|
|
|
slice |
|
110
|
|
|
|
|
|
|
split |
|
111
|
|
|
|
|
|
|
stringify_newer |
|
112
|
|
|
|
|
|
|
stringify_older |
|
113
|
|
|
|
|
|
|
subst_newer |
|
114
|
|
|
|
|
|
|
subst_older |
|
115
|
|
|
|
|
|
|
unop |
|
116
|
|
|
|
|
|
|
); |
|
117
|
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
# The BEGIN {} is used here because otherwise this code isn't executed |
|
120
|
|
|
|
|
|
|
# when you run B::Deparse on itself. |
|
121
|
|
|
|
|
|
|
my %globalnames; |
|
122
|
8
|
|
|
8
|
|
636
|
BEGIN { map($globalnames{$_}++, "SIG", "STDIN", "STDOUT", "STDERR", "INC", |
|
123
|
|
|
|
|
|
|
"ENV", "ARGV", "ARGVOUT", "_"); } |
|
124
|
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
BEGIN { |
|
126
|
|
|
|
|
|
|
# List version-specific constants here. |
|
127
|
|
|
|
|
|
|
# Easiest way to keep this code portable between version looks to |
|
128
|
|
|
|
|
|
|
# be to fake up a dummy constant that will never actually be true. |
|
129
|
8
|
|
|
8
|
|
40
|
foreach (qw( |
|
130
|
|
|
|
|
|
|
CVf_LOCKED |
|
131
|
|
|
|
|
|
|
OPpCONST_ARYBASE |
|
132
|
|
|
|
|
|
|
OPpCONST_NOVER |
|
133
|
|
|
|
|
|
|
OPpEVAL_BYTES |
|
134
|
|
|
|
|
|
|
OPpITER_REVERSED |
|
135
|
|
|
|
|
|
|
OPpOUR_INTRO |
|
136
|
|
|
|
|
|
|
OPpPAD_STATE |
|
137
|
|
|
|
|
|
|
OPpREVERSE_INPLACE |
|
138
|
|
|
|
|
|
|
OPpSORT_DESCEND |
|
139
|
|
|
|
|
|
|
OPpSORT_INPLACE |
|
140
|
|
|
|
|
|
|
OPpTARGET_MY |
|
141
|
|
|
|
|
|
|
OPpSUBSTR_REPL_FIRST |
|
142
|
|
|
|
|
|
|
PMf_EVAL PMf_EXTENDED |
|
143
|
|
|
|
|
|
|
PMf_NONDESTRUCT |
|
144
|
|
|
|
|
|
|
PMf_SKIPWHITE |
|
145
|
|
|
|
|
|
|
RXf_PMf_CHARSET |
|
146
|
|
|
|
|
|
|
RXf_PMf_KEEPCOPY |
|
147
|
|
|
|
|
|
|
RXf_SKIPWHITE |
|
148
|
|
|
|
|
|
|
)) { |
|
149
|
152
|
|
|
|
|
225
|
eval { import B $_ }; |
|
|
152
|
|
|
|
|
8765
|
|
|
150
|
8
|
|
|
8
|
|
46
|
no strict 'refs'; |
|
|
8
|
|
|
|
|
14
|
|
|
|
8
|
|
|
|
|
615
|
|
|
151
|
152
|
100
|
|
|
|
266
|
*{$_} = sub () {0} unless *{$_}{CODE}; |
|
|
24
|
|
|
|
|
70
|
|
|
|
152
|
|
|
|
|
1440
|
|
|
152
|
|
|
|
|
|
|
} |
|
153
|
|
|
|
|
|
|
} |
|
154
|
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
my %strict_bits = do { |
|
156
|
|
|
|
|
|
|
local $^H; |
|
157
|
|
|
|
|
|
|
map +($_ => strict::bits($_)), qw/refs subs vars/ |
|
158
|
|
|
|
|
|
|
}; |
|
159
|
|
|
|
|
|
|
|
|
160
|
8
|
|
|
8
|
|
29
|
BEGIN { for (qw[ pushmark ]) { |
|
161
|
8
|
|
|
|
|
701
|
eval "sub OP_\U$_ () { " . opnumber($_) . "}" |
|
162
|
|
|
|
|
|
|
}} |
|
163
|
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
{ |
|
165
|
|
|
|
|
|
|
# Mask out the bits that L uses |
|
166
|
|
|
|
|
|
|
my $WARN_MASK; |
|
167
|
|
|
|
|
|
|
BEGIN { |
|
168
|
8
|
|
|
8
|
|
10750
|
$WARN_MASK = $warnings::Bits{all} | $warnings::DeadBits{all}; |
|
169
|
|
|
|
|
|
|
} |
|
170
|
|
|
|
|
|
|
sub WARN_MASK () { |
|
171
|
200
|
|
|
200
|
0
|
554
|
return $WARN_MASK; |
|
172
|
|
|
|
|
|
|
} |
|
173
|
|
|
|
|
|
|
} |
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
my(%left, %right); |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
sub ambient_pragmas { |
|
178
|
61
|
|
|
61
|
0
|
90527
|
my $self = shift; |
|
179
|
61
|
|
|
|
|
239
|
my ($arybase, $hint_bits, $warning_bits, $hinthash) = (0, 0); |
|
180
|
|
|
|
|
|
|
|
|
181
|
61
|
|
|
|
|
261
|
while (@_ > 1) { |
|
182
|
183
|
|
|
|
|
275
|
my $name = shift(); |
|
183
|
183
|
|
|
|
|
222
|
my $val = shift(); |
|
184
|
|
|
|
|
|
|
|
|
185
|
183
|
50
|
33
|
|
|
1360
|
if ($name eq 'strict') { |
|
|
|
50
|
33
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
186
|
0
|
|
|
|
|
0
|
require strict; |
|
187
|
|
|
|
|
|
|
|
|
188
|
0
|
0
|
|
|
|
0
|
if ($val eq 'none') { |
|
189
|
0
|
|
|
|
|
0
|
$hint_bits &= $strict_bits{$_} for qw/refs subs vars/; |
|
190
|
0
|
|
|
|
|
0
|
next(); |
|
191
|
|
|
|
|
|
|
} |
|
192
|
|
|
|
|
|
|
|
|
193
|
0
|
|
|
|
|
0
|
my @names; |
|
194
|
0
|
0
|
|
|
|
0
|
if ($val eq "all") { |
|
|
|
0
|
|
|
|
|
|
|
195
|
0
|
|
|
|
|
0
|
@names = qw/refs subs vars/; |
|
196
|
|
|
|
|
|
|
} |
|
197
|
|
|
|
|
|
|
elsif (ref $val) { |
|
198
|
0
|
|
|
|
|
0
|
@names = @$val; |
|
199
|
|
|
|
|
|
|
} |
|
200
|
|
|
|
|
|
|
else { |
|
201
|
0
|
|
|
|
|
0
|
@names = split' ', $val; |
|
202
|
|
|
|
|
|
|
} |
|
203
|
0
|
|
|
|
|
0
|
$hint_bits |= $strict_bits{$_} for @names; |
|
204
|
|
|
|
|
|
|
} |
|
205
|
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
elsif ($name eq '$[') { |
|
207
|
0
|
|
|
|
|
0
|
if (OPpCONST_ARYBASE) { |
|
208
|
|
|
|
|
|
|
$arybase = $val; |
|
209
|
|
|
|
|
|
|
} else { |
|
210
|
0
|
0
|
|
|
|
0
|
croak "\$[ can't be non-zero on this perl" unless $val == 0; |
|
211
|
|
|
|
|
|
|
} |
|
212
|
|
|
|
|
|
|
} |
|
213
|
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
elsif ($name eq 'integer' |
|
215
|
|
|
|
|
|
|
|| $name eq 'bytes' |
|
216
|
|
|
|
|
|
|
|| $name eq 'utf8') { |
|
217
|
0
|
|
|
|
|
0
|
require "$name.pm"; |
|
218
|
0
|
0
|
|
|
|
0
|
if ($val) { |
|
219
|
0
|
|
|
|
|
0
|
$hint_bits |= ${$::{"${name}::"}{"hint_bits"}}; |
|
|
0
|
|
|
|
|
0
|
|
|
220
|
|
|
|
|
|
|
} |
|
221
|
|
|
|
|
|
|
else { |
|
222
|
0
|
|
|
|
|
0
|
$hint_bits &= ~${$::{"${name}::"}{"hint_bits"}}; |
|
|
0
|
|
|
|
|
0
|
|
|
223
|
|
|
|
|
|
|
} |
|
224
|
|
|
|
|
|
|
} |
|
225
|
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
elsif ($name eq 're') { |
|
227
|
0
|
|
|
|
|
0
|
require re; |
|
228
|
0
|
0
|
|
|
|
0
|
if ($val eq 'none') { |
|
229
|
0
|
|
|
|
|
0
|
$hint_bits &= ~re::bits(qw/taint eval/); |
|
230
|
0
|
|
|
|
|
0
|
next(); |
|
231
|
|
|
|
|
|
|
} |
|
232
|
|
|
|
|
|
|
|
|
233
|
0
|
|
|
|
|
0
|
my @names; |
|
234
|
0
|
0
|
|
|
|
0
|
if ($val eq 'all') { |
|
|
|
0
|
|
|
|
|
|
|
235
|
0
|
|
|
|
|
0
|
@names = qw/taint eval/; |
|
236
|
|
|
|
|
|
|
} |
|
237
|
|
|
|
|
|
|
elsif (ref $val) { |
|
238
|
0
|
|
|
|
|
0
|
@names = @$val; |
|
239
|
|
|
|
|
|
|
} |
|
240
|
|
|
|
|
|
|
else { |
|
241
|
0
|
|
|
|
|
0
|
@names = split' ',$val; |
|
242
|
|
|
|
|
|
|
} |
|
243
|
0
|
|
|
|
|
0
|
$hint_bits |= re::bits(@names); |
|
244
|
|
|
|
|
|
|
} |
|
245
|
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
elsif ($name eq 'warnings') { |
|
247
|
0
|
0
|
|
|
|
0
|
if ($val eq 'none') { |
|
248
|
0
|
|
|
|
|
0
|
$warning_bits = $warnings::NONE; |
|
249
|
0
|
|
|
|
|
0
|
next(); |
|
250
|
|
|
|
|
|
|
} |
|
251
|
|
|
|
|
|
|
|
|
252
|
0
|
|
|
|
|
0
|
my @names; |
|
253
|
0
|
0
|
|
|
|
0
|
if (ref $val) { |
|
254
|
0
|
|
|
|
|
0
|
@names = @$val; |
|
255
|
|
|
|
|
|
|
} |
|
256
|
|
|
|
|
|
|
else { |
|
257
|
0
|
|
|
|
|
0
|
@names = split/\s+/, $val; |
|
258
|
|
|
|
|
|
|
} |
|
259
|
|
|
|
|
|
|
|
|
260
|
0
|
0
|
|
|
|
0
|
$warning_bits = $warnings::NONE if !defined ($warning_bits); |
|
261
|
0
|
|
|
|
|
0
|
$warning_bits |= warnings::bits(@names); |
|
262
|
|
|
|
|
|
|
} |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
elsif ($name eq 'warning_bits') { |
|
265
|
61
|
|
|
|
|
162
|
$warning_bits = $val; |
|
266
|
|
|
|
|
|
|
} |
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
elsif ($name eq 'hint_bits') { |
|
269
|
61
|
|
|
|
|
153
|
$hint_bits = $val; |
|
270
|
|
|
|
|
|
|
} |
|
271
|
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
elsif ($name eq '%^H') { |
|
273
|
61
|
|
|
|
|
178
|
$hinthash = $val; |
|
274
|
|
|
|
|
|
|
} |
|
275
|
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
else { |
|
277
|
0
|
|
|
|
|
0
|
croak "Unknown pragma type: $name"; |
|
278
|
|
|
|
|
|
|
} |
|
279
|
|
|
|
|
|
|
} |
|
280
|
61
|
50
|
|
|
|
161
|
if (@_) { |
|
281
|
0
|
|
|
|
|
0
|
croak "The ambient_pragmas method expects an even number of args"; |
|
282
|
|
|
|
|
|
|
} |
|
283
|
|
|
|
|
|
|
|
|
284
|
61
|
|
|
|
|
180
|
$self->{'ambient_arybase'} = $arybase; |
|
285
|
61
|
|
|
|
|
132
|
$self->{'ambient_warnings'} = $warning_bits; |
|
286
|
61
|
|
|
|
|
119
|
$self->{'ambient_hints'} = $hint_bits; |
|
287
|
61
|
|
|
|
|
1057
|
$self->{'ambient_hinthash'} = $hinthash; |
|
288
|
|
|
|
|
|
|
} |
|
289
|
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
sub anon_hash_or_list($$$) |
|
291
|
|
|
|
|
|
|
{ |
|
292
|
0
|
|
|
0
|
0
|
0
|
my ($self, $op, $cx) = @_; |
|
293
|
0
|
|
|
|
|
0
|
my $name = $op->name; |
|
294
|
0
|
|
|
|
|
0
|
my($pre, $post) = @{{"anonlist" => ["[","]"], |
|
295
|
0
|
|
|
|
|
0
|
"anonhash" => ["{","}"]}->{$name}}; |
|
296
|
0
|
|
|
|
|
0
|
my($expr, @exprs); |
|
297
|
0
|
|
|
|
|
0
|
my $first_op = $op->first; |
|
298
|
0
|
|
|
|
|
0
|
$op = $first_op->sibling; # skip pushmark |
|
299
|
0
|
|
|
|
|
0
|
for (; !B::Deparse::null($op); $op = $op->sibling) { |
|
300
|
0
|
|
|
|
|
0
|
$expr = $self->deparse($op, 6, $op); |
|
301
|
0
|
|
|
|
|
0
|
push @exprs, $expr; |
|
302
|
|
|
|
|
|
|
} |
|
303
|
|
|
|
|
|
|
# if ($pre eq "{" and $cx < 1) { |
|
304
|
|
|
|
|
|
|
# # Disambiguate that it's not a block |
|
305
|
|
|
|
|
|
|
# $pre = "+{"; |
|
306
|
|
|
|
|
|
|
# } |
|
307
|
|
|
|
|
|
|
|
|
308
|
0
|
|
|
|
|
0
|
my $node = $self->info_from_template("$name $pre $post", $op, |
|
309
|
|
|
|
|
|
|
"$pre%C$post", |
|
310
|
|
|
|
|
|
|
[[0, $#exprs, ', ']], \@exprs); |
|
311
|
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
# Set the skipped op as the opener of the list. |
|
313
|
0
|
|
|
|
|
0
|
my $position = [0, 1]; |
|
314
|
|
|
|
|
|
|
my $first_node = $self->info_from_string($first_op->name, $first_op, |
|
315
|
|
|
|
|
|
|
$node->{text}, |
|
316
|
0
|
|
|
|
|
0
|
{position => $position}); |
|
317
|
0
|
|
|
|
|
0
|
$node->update_other_ops($first_node); |
|
318
|
0
|
|
|
|
|
0
|
return $node; |
|
319
|
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
} |
|
321
|
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
sub assoc_class { |
|
323
|
4381
|
|
|
4381
|
0
|
5518
|
my $op = shift; |
|
324
|
4381
|
|
|
|
|
14289
|
my $name = $op->name; |
|
325
|
4381
|
100
|
100
|
|
|
9984
|
if ($name eq "concat" and $op->first->name eq "concat") { |
|
326
|
|
|
|
|
|
|
# avoid spurious '=' -- see comment in pp_concat |
|
327
|
4
|
|
|
|
|
17
|
return "concat"; |
|
328
|
|
|
|
|
|
|
} |
|
329
|
4377
|
100
|
66
|
|
|
25388
|
if ($name eq "null" and B::class($op) eq "UNOP" |
|
|
|
|
100
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
330
|
|
|
|
|
|
|
and $op->first->name =~ /^(and|x?or)$/ |
|
331
|
|
|
|
|
|
|
and B::Deparse::null $op->first->sibling) |
|
332
|
|
|
|
|
|
|
{ |
|
333
|
|
|
|
|
|
|
# Like all conditional constructs, OP_ANDs and OP_ORs are topped |
|
334
|
|
|
|
|
|
|
# with a null that's used as the common end point of the two |
|
335
|
|
|
|
|
|
|
# flows of control. For precedence purposes, ignore it. |
|
336
|
|
|
|
|
|
|
# (COND_EXPRs have these too, but we don't bother with |
|
337
|
|
|
|
|
|
|
# their associativity). |
|
338
|
26
|
|
|
|
|
141
|
return assoc_class($op->first); |
|
339
|
|
|
|
|
|
|
} |
|
340
|
4351
|
100
|
|
|
|
26641
|
return $name . ($op->flags & B::OPf_STACKED ? "=" : ""); |
|
341
|
|
|
|
|
|
|
} |
|
342
|
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
# routines implementing classes of ops |
|
344
|
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
sub baseop |
|
346
|
|
|
|
|
|
|
{ |
|
347
|
48
|
|
|
48
|
0
|
108
|
my($self, $op, $cx, $name) = @_; |
|
348
|
48
|
|
|
|
|
1333
|
return $self->info_from_string("baseop $name", $op, $self->keyword($name)); |
|
349
|
|
|
|
|
|
|
} |
|
350
|
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
# Handle binary operators like +, and assignment |
|
352
|
|
|
|
|
|
|
sub binop |
|
353
|
|
|
|
|
|
|
{ |
|
354
|
|
|
|
|
|
|
|
|
355
|
1378
|
|
|
1378
|
0
|
3593
|
my ($self, $op, $cx, $opname, $prec) = @_; |
|
356
|
1378
|
|
|
|
|
3080
|
my ($flags, $type) = (0, ''); |
|
357
|
1378
|
100
|
|
|
|
3367
|
if (scalar(@_) > 5) { |
|
358
|
1348
|
|
|
|
|
2089
|
$flags = $_[5]; |
|
359
|
1348
|
100
|
|
|
|
3229
|
$type = $_[6] if (scalar(@_) > 6); |
|
360
|
|
|
|
|
|
|
} |
|
361
|
1378
|
|
|
|
|
5401
|
my $left = $op->first; |
|
362
|
1378
|
|
|
|
|
4535
|
my $right = $op->last; |
|
363
|
1378
|
|
|
|
|
2316
|
my $eq = ""; |
|
364
|
1378
|
100
|
100
|
|
|
7825
|
if ($op->flags & B::OPf_STACKED && $flags & B::Deparse::ASSIGN) { |
|
365
|
5
|
|
|
|
|
7
|
$eq = "="; |
|
366
|
5
|
|
|
|
|
7
|
$prec = 7; |
|
367
|
|
|
|
|
|
|
} |
|
368
|
1378
|
100
|
|
|
|
3028
|
if ($flags & SWAP_CHILDREN) { |
|
369
|
1315
|
|
|
|
|
2559
|
($left, $right) = ($right, $left); |
|
370
|
|
|
|
|
|
|
} |
|
371
|
1378
|
|
|
|
|
3701
|
my $lhs = $self->deparse_binop_left($op, $left, $prec); |
|
372
|
1378
|
50
|
66
|
|
|
8799
|
if ($flags & LIST_CONTEXT |
|
373
|
|
|
|
|
|
|
&& $lhs->{text} !~ /^(my|our|local|)[\@\(]/) { |
|
374
|
0
|
|
0
|
|
|
0
|
$lhs->{maybe_parens} ||= {}; |
|
375
|
0
|
|
|
|
|
0
|
$lhs->{maybe_parens}{force} = 'true'; |
|
376
|
0
|
|
|
|
|
0
|
$lhs->{text} = "($lhs->{text})"; |
|
377
|
|
|
|
|
|
|
} |
|
378
|
|
|
|
|
|
|
|
|
379
|
1378
|
|
|
|
|
4547
|
my $rhs = $self->deparse_binop_right($op, $right, $prec); |
|
380
|
1378
|
100
|
|
|
|
3224
|
if ($flags & SWAP_CHILDREN) { |
|
381
|
|
|
|
|
|
|
# Not sure why this is right |
|
382
|
1315
|
|
|
|
|
2892
|
$lhs->{prev_expr} = $rhs; |
|
383
|
|
|
|
|
|
|
} else { |
|
384
|
63
|
|
|
|
|
219
|
$rhs->{prev_expr} = $lhs; |
|
385
|
|
|
|
|
|
|
} |
|
386
|
|
|
|
|
|
|
|
|
387
|
1378
|
|
100
|
|
|
3645
|
$type = $type || 'binary operator'; |
|
388
|
1378
|
|
|
|
|
3021
|
$type .= " $opname$eq"; |
|
389
|
1378
|
|
|
|
|
9143
|
my $node = $self->info_from_template($type, $op, "%c $opname$eq %c", |
|
390
|
|
|
|
|
|
|
undef, [$lhs, $rhs], |
|
391
|
|
|
|
|
|
|
{maybe_parens => [$self, $cx, $prec]}); |
|
392
|
1378
|
|
|
|
|
3781
|
$node->{prev_expr} = $rhs; |
|
393
|
1378
|
|
|
|
|
5327
|
return $node; |
|
394
|
|
|
|
|
|
|
} |
|
395
|
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
# Left associative operators, like '+', for which |
|
397
|
|
|
|
|
|
|
# $a + $b + $c is equivalent to ($a + $b) + $c |
|
398
|
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
BEGIN { |
|
400
|
8
|
|
|
8
|
|
10170
|
%left = ('multiply' => 19, 'i_multiply' => 19, |
|
401
|
|
|
|
|
|
|
'divide' => 19, 'i_divide' => 19, |
|
402
|
|
|
|
|
|
|
'modulo' => 19, 'i_modulo' => 19, |
|
403
|
|
|
|
|
|
|
'repeat' => 19, |
|
404
|
|
|
|
|
|
|
'add' => 18, 'i_add' => 18, |
|
405
|
|
|
|
|
|
|
'subtract' => 18, 'i_subtract' => 18, |
|
406
|
|
|
|
|
|
|
'concat' => 18, |
|
407
|
|
|
|
|
|
|
'left_shift' => 17, 'right_shift' => 17, |
|
408
|
|
|
|
|
|
|
'bit_and' => 13, 'nbit_and' => 13, 'sbit_and' => 13, |
|
409
|
|
|
|
|
|
|
'bit_or' => 12, 'bit_xor' => 12, |
|
410
|
|
|
|
|
|
|
'sbit_or' => 12, 'sbit_xor' => 12, |
|
411
|
|
|
|
|
|
|
'nbit_or' => 12, 'nbit_xor' => 12, |
|
412
|
|
|
|
|
|
|
'and' => 3, |
|
413
|
|
|
|
|
|
|
'or' => 2, 'xor' => 2, |
|
414
|
|
|
|
|
|
|
); |
|
415
|
|
|
|
|
|
|
} |
|
416
|
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
sub code_list { |
|
418
|
0
|
|
|
0
|
0
|
0
|
my ($self, $op, $cv) = @_; |
|
419
|
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
# localise stuff relating to the current sub |
|
421
|
|
|
|
|
|
|
$cv and |
|
422
|
|
|
|
|
|
|
local($self->{'curcv'}) = $cv, |
|
423
|
|
|
|
|
|
|
local($self->{'curcvlex'}), |
|
424
|
|
|
|
|
|
|
local(@$self{qw'curstash warnings hints hinthash curcop'}) |
|
425
|
0
|
0
|
|
|
|
0
|
= @$self{qw'curstash warnings hints hinthash curcop'}; |
|
426
|
|
|
|
|
|
|
|
|
427
|
0
|
|
|
|
|
0
|
my $re; |
|
428
|
0
|
|
|
|
|
0
|
for ($op = $op->first->sibling; !B::Deparse::null($op); $op = $op->sibling) { |
|
429
|
0
|
0
|
0
|
|
|
0
|
if ($op->name eq 'null' and $op->flags & OPf_SPECIAL) { |
|
430
|
0
|
|
|
|
|
0
|
my $scope = $op->first; |
|
431
|
|
|
|
|
|
|
# 0 context (last arg to scopeop) means statement context, so |
|
432
|
|
|
|
|
|
|
# the contents of the block will not be wrapped in do{...}. |
|
433
|
0
|
|
|
|
|
0
|
my $block = scopeop($scope->first->name eq "enter", $self, |
|
434
|
|
|
|
|
|
|
$scope, 0); |
|
435
|
|
|
|
|
|
|
# next op is the source code of the block |
|
436
|
0
|
|
|
|
|
0
|
$op = $op->sibling; |
|
437
|
0
|
|
|
|
|
0
|
$re .= ($self->const_sv($op)->PV =~ m|^(\(\?\??\{)|)[0]; |
|
438
|
0
|
|
|
|
|
0
|
my $multiline = $block =~ /\n/; |
|
439
|
0
|
0
|
|
|
|
0
|
$re .= $multiline ? "\n\t" : ' '; |
|
440
|
0
|
|
|
|
|
0
|
$re .= $block; |
|
441
|
0
|
0
|
|
|
|
0
|
$re .= $multiline ? "\n\b})" : " })"; |
|
442
|
|
|
|
|
|
|
} else { |
|
443
|
0
|
|
|
|
|
0
|
$re = B::Deparse::re_dq_disambiguate($re, $self->re_dq($op)); |
|
444
|
|
|
|
|
|
|
} |
|
445
|
|
|
|
|
|
|
} |
|
446
|
0
|
|
|
|
|
0
|
$re; |
|
447
|
|
|
|
|
|
|
} |
|
448
|
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
# Concatenation or '.' is special because concats-of-concats are |
|
450
|
|
|
|
|
|
|
# optimized to save copying by making all but the first concat |
|
451
|
|
|
|
|
|
|
# stacked. The effect is as if the programmer had written: |
|
452
|
|
|
|
|
|
|
# ($a . $b) .= $c' |
|
453
|
|
|
|
|
|
|
# but the above is illegal. |
|
454
|
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
sub concat { |
|
456
|
6
|
|
|
6
|
0
|
13
|
my $self = shift; |
|
457
|
6
|
|
|
|
|
14
|
my($op, $cx) = @_; |
|
458
|
6
|
|
|
|
|
29
|
my $left = $op->first; |
|
459
|
6
|
|
|
|
|
23
|
my $right = $op->last; |
|
460
|
6
|
|
|
|
|
12
|
my $eq = ""; |
|
461
|
6
|
|
|
|
|
11
|
my $prec = 18; |
|
462
|
6
|
100
|
100
|
|
|
43
|
if ($op->flags & OPf_STACKED and $op->first->name ne "concat") { |
|
463
|
1
|
|
|
|
|
3
|
$eq = "="; |
|
464
|
1
|
|
|
|
|
3
|
$prec = 7; |
|
465
|
|
|
|
|
|
|
} |
|
466
|
6
|
|
|
|
|
21
|
my $lhs = $self->deparse_binop_left($op, $left, $prec); |
|
467
|
6
|
|
|
|
|
28
|
my $rhs = $self->deparse_binop_right($op, $right, $prec); |
|
468
|
6
|
|
|
|
|
53
|
return $self->info_from_template(".$eq", $op, |
|
469
|
|
|
|
|
|
|
"%c .$eq %c", undef, [$lhs, $rhs], |
|
470
|
|
|
|
|
|
|
{maybe_parens => [$self, $cx, $prec]}); |
|
471
|
|
|
|
|
|
|
} |
|
472
|
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
# Handle pp_dbstate, and pp_nextstate and COP ops. |
|
474
|
|
|
|
|
|
|
# |
|
475
|
|
|
|
|
|
|
# Notice how subs and formats are inserted between statements here; |
|
476
|
|
|
|
|
|
|
# also $[ assignments and pragmas. |
|
477
|
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
sub cops |
|
479
|
|
|
|
|
|
|
{ |
|
480
|
2087
|
|
|
2087
|
0
|
4669
|
my ($self, $op, $cx, $name) = @_; |
|
481
|
2087
|
|
|
|
|
3578
|
$self->{'curcop'} = $op; |
|
482
|
2087
|
|
|
|
|
3250
|
my @texts = (); |
|
483
|
2087
|
|
|
|
|
3331
|
my $opts = {}; |
|
484
|
2087
|
|
|
|
|
3099
|
my @args_spec = (); |
|
485
|
2087
|
|
|
|
|
3088
|
my $fmt = '%;'; |
|
486
|
|
|
|
|
|
|
|
|
487
|
2087
|
|
|
|
|
17138
|
push @texts, $self->B::Deparse::cop_subs($op); |
|
488
|
|
|
|
|
|
|
|
|
489
|
2087
|
50
|
|
|
|
4104
|
if (@texts) { |
|
490
|
|
|
|
|
|
|
# Special marker to swallow up the semicolon |
|
491
|
0
|
|
|
|
|
0
|
$opts->{'omit_next_semicolon'} = 1; |
|
492
|
|
|
|
|
|
|
} |
|
493
|
|
|
|
|
|
|
|
|
494
|
2087
|
|
|
|
|
7221
|
my $stash = $op->stashpv; |
|
495
|
2087
|
100
|
|
|
|
5697
|
if ($stash ne $self->{'curstash'}) { |
|
496
|
1264
|
|
|
|
|
581021
|
push @texts, $self->keyword("package") . " $stash;"; |
|
497
|
1264
|
|
|
|
|
4673
|
$self->{'curstash'} = $stash; |
|
498
|
|
|
|
|
|
|
} |
|
499
|
|
|
|
|
|
|
|
|
500
|
2087
|
|
|
|
|
2813
|
if (OPpCONST_ARYBASE && $self->{'arybase'} != $op->arybase) { |
|
501
|
|
|
|
|
|
|
push @texts, '$[ = '. $op->arybase .";"; |
|
502
|
|
|
|
|
|
|
$self->{'arybase'} = $op->arybase; |
|
503
|
|
|
|
|
|
|
} |
|
504
|
|
|
|
|
|
|
|
|
505
|
2087
|
|
|
|
|
7824
|
my $warnings = $op->warnings; |
|
506
|
2087
|
|
|
|
|
3038
|
my $warning_bits; |
|
507
|
2087
|
100
|
66
|
|
|
15210
|
if ($warnings->isa("B::SPECIAL") && $$warnings == 4) { |
|
|
|
50
|
33
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
508
|
200
|
|
|
|
|
613
|
$warning_bits = $warnings::Bits{"all"} & WARN_MASK; |
|
509
|
|
|
|
|
|
|
} |
|
510
|
|
|
|
|
|
|
elsif ($warnings->isa("B::SPECIAL") && $$warnings == 5) { |
|
511
|
1887
|
|
|
|
|
3470
|
$warning_bits = $warnings::NONE; |
|
512
|
|
|
|
|
|
|
} |
|
513
|
|
|
|
|
|
|
elsif ($warnings->isa("B::SPECIAL")) { |
|
514
|
0
|
|
|
|
|
0
|
$warning_bits = undef; |
|
515
|
|
|
|
|
|
|
} |
|
516
|
|
|
|
|
|
|
else { |
|
517
|
0
|
|
|
|
|
0
|
$warning_bits = $warnings->PV & WARN_MASK; |
|
518
|
|
|
|
|
|
|
} |
|
519
|
|
|
|
|
|
|
|
|
520
|
2087
|
100
|
66
|
|
|
8741
|
if (defined ($warning_bits) and |
|
|
|
|
33
|
|
|
|
|
|
521
|
|
|
|
|
|
|
!defined($self->{warnings}) || $self->{'warnings'} ne $warning_bits) { |
|
522
|
1266
|
|
|
|
|
5339
|
my @warnings = $self->declare_warnings($self->{'warnings'}, $warning_bits); |
|
523
|
1266
|
|
|
|
|
2903
|
foreach my $warning (@warnings) { |
|
524
|
1266
|
|
|
|
|
2461
|
push @texts, $warning; |
|
525
|
|
|
|
|
|
|
} |
|
526
|
1266
|
|
|
|
|
2658
|
$self->{'warnings'} = $warning_bits; |
|
527
|
|
|
|
|
|
|
} |
|
528
|
|
|
|
|
|
|
|
|
529
|
2087
|
50
|
|
|
|
8874
|
my $hints = $] < 5.008009 ? $op->private : $op->hints; |
|
530
|
2087
|
|
|
|
|
3598
|
my $old_hints = $self->{'hints'}; |
|
531
|
2087
|
100
|
|
|
|
4256
|
if ($self->{'hints'} != $hints) { |
|
532
|
1321
|
|
|
|
|
5000
|
my @hints = $self->declare_hints($self->{'hints'}, $hints); |
|
533
|
1321
|
|
|
|
|
2407
|
foreach my $hint (@hints) { |
|
534
|
1266
|
|
|
|
|
2312
|
push @texts, $hint; |
|
535
|
|
|
|
|
|
|
} |
|
536
|
1321
|
|
|
|
|
2376
|
$self->{'hints'} = $hints; |
|
537
|
|
|
|
|
|
|
} |
|
538
|
|
|
|
|
|
|
|
|
539
|
2087
|
|
|
|
|
2595
|
my $newhh; |
|
540
|
2087
|
50
|
|
|
|
4259
|
if ($] > 5.009) { |
|
541
|
2087
|
|
|
|
|
10831
|
$newhh = $op->hints_hash->HASH; |
|
542
|
|
|
|
|
|
|
} |
|
543
|
|
|
|
|
|
|
|
|
544
|
2087
|
50
|
|
|
|
5426
|
if ($] >= 5.015006) { |
|
545
|
|
|
|
|
|
|
# feature bundle hints |
|
546
|
2087
|
|
|
|
|
3415
|
my $from = $old_hints & $feature::hint_mask; |
|
547
|
2087
|
|
|
|
|
2765
|
my $to = $ hints & $feature::hint_mask; |
|
548
|
2087
|
100
|
|
|
|
4007
|
if ($from != $to) { |
|
549
|
9
|
100
|
|
|
|
20
|
if ($to == $feature::hint_mask) { |
|
550
|
5
|
50
|
|
|
|
18
|
if ($self->{'hinthash'}) { |
|
551
|
|
|
|
|
|
|
delete $self->{'hinthash'}{$_} |
|
552
|
5
|
|
|
|
|
11
|
for grep /^feature_/, keys %{$self->{'hinthash'}}; |
|
|
5
|
|
|
|
|
88
|
|
|
553
|
|
|
|
|
|
|
} |
|
554
|
0
|
|
|
|
|
0
|
else { $self->{'hinthash'} = {} } |
|
555
|
|
|
|
|
|
|
$self->{'hinthash'} |
|
556
|
|
|
|
|
|
|
= B::Deparse::_features_from_bundle($from, |
|
557
|
5
|
|
|
|
|
65
|
$self->{'hinthash'}); |
|
558
|
|
|
|
|
|
|
} |
|
559
|
|
|
|
|
|
|
else { |
|
560
|
4
|
|
|
|
|
11
|
my $bundle = |
|
561
|
|
|
|
|
|
|
$feature::hint_bundles[$to >> $feature::hint_shift]; |
|
562
|
4
|
|
|
|
|
19
|
$bundle =~ s/(\d[13579])\z/$1+1/e; # 5.11 => 5.12 |
|
|
2
|
|
|
|
|
10
|
|
|
563
|
4
|
|
|
|
|
1934
|
push @texts, |
|
564
|
|
|
|
|
|
|
$self->keyword("no") . " feature ':all'", |
|
565
|
|
|
|
|
|
|
$self->keyword("use") . " feature ':$bundle'"; |
|
566
|
|
|
|
|
|
|
} |
|
567
|
|
|
|
|
|
|
} |
|
568
|
|
|
|
|
|
|
} |
|
569
|
|
|
|
|
|
|
|
|
570
|
2087
|
50
|
|
|
|
4011
|
if ($] > 5.009) { |
|
571
|
|
|
|
|
|
|
# FIXME use format specifiers |
|
572
|
|
|
|
|
|
|
my @hints = $self->declare_hinthash( |
|
573
|
2087
|
|
|
|
|
7368
|
$self->{'hinthash'}, $newhh, 0, $self->{hints}); |
|
574
|
2087
|
|
|
|
|
3855
|
foreach my $hint (@hints) { |
|
575
|
3
|
|
|
|
|
9
|
push @texts, $hint; |
|
576
|
|
|
|
|
|
|
} |
|
577
|
2087
|
|
|
|
|
3713
|
$self->{'hinthash'} = $newhh; |
|
578
|
|
|
|
|
|
|
} |
|
579
|
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
|
|
581
|
|
|
|
|
|
|
# This should go after of any branches that add statements, to |
|
582
|
|
|
|
|
|
|
# increase the chances that it refers to the same line it did in |
|
583
|
|
|
|
|
|
|
# the original program. |
|
584
|
2087
|
50
|
33
|
|
|
5055
|
if ($self->{'linenums'} && $cx != .5) { # $cx == .5 means in a format |
|
585
|
0
|
|
|
|
|
0
|
my $line = sprintf("\n# line %s '%s'", $op->line, $op->file); |
|
586
|
0
|
0
|
|
|
|
0
|
$line .= sprintf(" 0x%x", $$op) if $self->{'opaddr'}; |
|
587
|
0
|
|
|
|
|
0
|
$opts->{'omit_next_semicolon'} = 1; |
|
588
|
0
|
|
|
|
|
0
|
push @texts, $line; |
|
589
|
|
|
|
|
|
|
} |
|
590
|
|
|
|
|
|
|
|
|
591
|
2087
|
50
|
|
|
|
8452
|
if ($op->label) { |
|
592
|
0
|
|
|
|
|
0
|
$fmt .= "%c\n"; |
|
593
|
0
|
|
|
|
|
0
|
push @args_spec, scalar(@args_spec); |
|
594
|
0
|
|
|
|
|
0
|
push @texts, $op->label . ": " ; |
|
595
|
|
|
|
|
|
|
} |
|
596
|
|
|
|
|
|
|
|
|
597
|
2087
|
|
|
|
|
6680
|
my $node = $self->info_from_template($name, $op, $fmt, |
|
598
|
|
|
|
|
|
|
\@args_spec, \@texts, $opts); |
|
599
|
2087
|
|
|
|
|
8133
|
return $node; |
|
600
|
|
|
|
|
|
|
} |
|
601
|
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
sub deparse_binop_left { |
|
603
|
1451
|
|
|
1451
|
0
|
2463
|
my $self = shift; |
|
604
|
1451
|
|
|
|
|
2844
|
my($op, $left, $prec) = @_; |
|
605
|
1451
|
100
|
100
|
|
|
3998
|
if ($left{assoc_class($op)} && $left{assoc_class($left)} |
|
|
|
|
100
|
|
|
|
|
|
606
|
|
|
|
|
|
|
and $left{assoc_class($op)} == $left{assoc_class($left)}) |
|
607
|
|
|
|
|
|
|
{ |
|
608
|
14
|
|
|
|
|
67
|
return $self->deparse($left, $prec - .00001, $op); |
|
609
|
|
|
|
|
|
|
} else { |
|
610
|
1437
|
|
|
|
|
4272
|
return $self->deparse($left, $prec, $op); |
|
611
|
|
|
|
|
|
|
} |
|
612
|
|
|
|
|
|
|
} |
|
613
|
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
# Right associative operators, like '=', for which |
|
615
|
|
|
|
|
|
|
# $a = $b = $c is equivalent to $a = ($b = $c) |
|
616
|
|
|
|
|
|
|
|
|
617
|
|
|
|
|
|
|
BEGIN { |
|
618
|
8
|
|
|
8
|
|
82282
|
%right = ('pow' => 22, |
|
619
|
|
|
|
|
|
|
'sassign=' => 7, 'aassign=' => 7, |
|
620
|
|
|
|
|
|
|
'multiply=' => 7, 'i_multiply=' => 7, |
|
621
|
|
|
|
|
|
|
'divide=' => 7, 'i_divide=' => 7, |
|
622
|
|
|
|
|
|
|
'modulo=' => 7, 'i_modulo=' => 7, |
|
623
|
|
|
|
|
|
|
'repeat=' => 7, |
|
624
|
|
|
|
|
|
|
'add=' => 7, 'i_add=' => 7, |
|
625
|
|
|
|
|
|
|
'subtract=' => 7, 'i_subtract=' => 7, |
|
626
|
|
|
|
|
|
|
'concat=' => 7, |
|
627
|
|
|
|
|
|
|
'left_shift=' => 7, 'right_shift=' => 7, |
|
628
|
|
|
|
|
|
|
'bit_and=' => 7, |
|
629
|
|
|
|
|
|
|
'bit_or=' => 7, 'bit_xor=' => 7, |
|
630
|
|
|
|
|
|
|
'andassign' => 7, |
|
631
|
|
|
|
|
|
|
'orassign' => 7, |
|
632
|
|
|
|
|
|
|
); |
|
633
|
|
|
|
|
|
|
} |
|
634
|
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
sub deparse_format($$$) |
|
636
|
|
|
|
|
|
|
{ |
|
637
|
0
|
|
|
0
|
0
|
0
|
my ($self, $form, $parent) = @_; |
|
638
|
0
|
|
|
|
|
0
|
my @texts; |
|
639
|
0
|
|
|
|
|
0
|
local($self->{'curcv'}) = $form; |
|
640
|
0
|
|
|
|
|
0
|
local($self->{'curcvlex'}); |
|
641
|
0
|
|
|
|
|
0
|
local($self->{'in_format'}) = 1; |
|
642
|
|
|
|
|
|
|
local(@$self{qw'curstash warnings hints hinthash'}) |
|
643
|
0
|
|
|
|
|
0
|
= @$self{qw'curstash warnings hints hinthash'}; |
|
644
|
0
|
|
|
|
|
0
|
my $op = $form->ROOT; |
|
645
|
0
|
|
|
|
|
0
|
local $B::overlay = {}; |
|
646
|
0
|
|
|
|
|
0
|
$self->pessimise($op, $form->START); |
|
647
|
|
|
|
|
|
|
my $info = { |
|
648
|
|
|
|
|
|
|
op => $op, |
|
649
|
|
|
|
|
|
|
parent => $parent, |
|
650
|
0
|
|
|
|
|
0
|
cop => $self->{'curcop'} |
|
651
|
|
|
|
|
|
|
}; |
|
652
|
0
|
|
|
|
|
0
|
$self->{optree}{$$op} = $info; |
|
653
|
|
|
|
|
|
|
|
|
654
|
0
|
0
|
0
|
|
|
0
|
if ($op->first->name eq 'stub' || $op->first->name eq 'nextstate') { |
|
655
|
0
|
|
|
|
|
0
|
my $info->{text} = "\f."; |
|
656
|
0
|
|
|
|
|
0
|
return $info; |
|
657
|
|
|
|
|
|
|
} |
|
658
|
|
|
|
|
|
|
|
|
659
|
0
|
|
|
|
|
0
|
$op->{other_ops} = [$op->first]; |
|
660
|
0
|
|
|
|
|
0
|
$op = $op->first->first; # skip leavewrite, lineseq |
|
661
|
0
|
|
|
|
|
0
|
my $kid; |
|
662
|
0
|
|
|
|
|
0
|
while (not B::Deparse::null $op) { |
|
663
|
0
|
|
|
|
|
0
|
push @{$op->{other_ops}}, $op; |
|
|
0
|
|
|
|
|
0
|
|
|
664
|
0
|
|
|
|
|
0
|
$op = $op->sibling; # skip nextstate |
|
665
|
0
|
|
|
|
|
0
|
my @body; |
|
666
|
0
|
|
|
|
|
0
|
push @{$op->{other_ops}}, $op->first; |
|
|
0
|
|
|
|
|
0
|
|
|
667
|
0
|
|
|
|
|
0
|
$kid = $op->first->sibling; # skip a pushmark |
|
668
|
0
|
|
|
|
|
0
|
push @texts, "\f".$self->const_sv($kid)->PV; |
|
669
|
0
|
|
|
|
|
0
|
push @{$op->{other_ops}}, $kid; |
|
|
0
|
|
|
|
|
0
|
|
|
670
|
0
|
|
|
|
|
0
|
$kid = $kid->sibling; |
|
671
|
0
|
|
|
|
|
0
|
for (; not B::Deparse::null $kid; $kid = $kid->sibling) { |
|
672
|
0
|
|
|
|
|
0
|
push @body, $self->deparse($kid, -1, $op); |
|
673
|
0
|
|
|
|
|
0
|
$body[-1] =~ s/;\z//; |
|
674
|
|
|
|
|
|
|
} |
|
675
|
0
|
0
|
|
|
|
0
|
push @texts, "\f".$self->combine2str("\n", \@body) if @body; |
|
676
|
0
|
|
|
|
|
0
|
$op = $op->sibling; |
|
677
|
|
|
|
|
|
|
} |
|
678
|
|
|
|
|
|
|
|
|
679
|
0
|
|
|
|
|
0
|
$info->{text} = $self->combine2str(\@texts) . "\f."; |
|
680
|
0
|
|
|
|
|
0
|
$info->{texts} = \@texts; |
|
681
|
0
|
|
|
|
|
0
|
return $info; |
|
682
|
|
|
|
|
|
|
} |
|
683
|
|
|
|
|
|
|
|
|
684
|
|
|
|
|
|
|
sub dedup_func_parens($$) |
|
685
|
|
|
|
|
|
|
{ |
|
686
|
573
|
|
|
573
|
0
|
996
|
my $self = shift; |
|
687
|
573
|
|
|
|
|
1308
|
my ($args_ref) = @_; |
|
688
|
573
|
|
|
|
|
1333
|
my @args = @$args_ref; |
|
689
|
|
|
|
|
|
|
return ( |
|
690
|
|
|
|
|
|
|
scalar @args == 1 && |
|
691
|
|
|
|
|
|
|
substr($args[0]->{text}, 0, 1) eq '(' && |
|
692
|
573
|
|
33
|
|
|
3470
|
substr($args[0]->{text}, 0, 1) eq ')'); |
|
693
|
|
|
|
|
|
|
} |
|
694
|
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
sub dedup_parens_func($$$) |
|
696
|
|
|
|
|
|
|
{ |
|
697
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
|
698
|
0
|
|
|
|
|
0
|
my $sub_info = shift; |
|
699
|
0
|
|
|
|
|
0
|
my ($args_ref) = @_; |
|
700
|
0
|
|
|
|
|
0
|
my @args = @$args_ref; |
|
701
|
0
|
0
|
0
|
|
|
0
|
if (scalar @args == 1 && substr($args[0], 0, 1) eq '(' && |
|
|
|
|
0
|
|
|
|
|
|
702
|
|
|
|
|
|
|
substr($args[0], -1, 1) eq ')') { |
|
703
|
0
|
|
|
|
|
0
|
return ($sub_info, $self->combine(', ', \@args), ); |
|
704
|
|
|
|
|
|
|
} else { |
|
705
|
0
|
|
|
|
|
0
|
return ($sub_info, '(', $self->combine(', ', \@args), ')', ); |
|
706
|
|
|
|
|
|
|
} |
|
707
|
|
|
|
|
|
|
} |
|
708
|
|
|
|
|
|
|
|
|
709
|
|
|
|
|
|
|
sub deparse_binop_right { |
|
710
|
1451
|
|
|
1451
|
0
|
2427
|
my $self = shift; |
|
711
|
1451
|
|
|
|
|
3015
|
my($op, $right, $prec) = @_; |
|
712
|
1451
|
50
|
66
|
|
|
3143
|
if ($right{assoc_class($op)} && $right{assoc_class($right)} |
|
|
|
|
33
|
|
|
|
|
|
713
|
|
|
|
|
|
|
and $right{assoc_class($op)} == $right{assoc_class($right)}) |
|
714
|
|
|
|
|
|
|
{ |
|
715
|
0
|
|
|
|
|
0
|
return $self->deparse($right, $prec - .00001, $op); |
|
716
|
|
|
|
|
|
|
} else { |
|
717
|
1451
|
|
|
|
|
4453
|
return $self->deparse($right, $prec, $op); |
|
718
|
|
|
|
|
|
|
} |
|
719
|
|
|
|
|
|
|
} |
|
720
|
|
|
|
|
|
|
|
|
721
|
|
|
|
|
|
|
# Iterate via sibling links a list of OP nodes starting with |
|
722
|
|
|
|
|
|
|
# $first. Each OP is deparsed, with $op and $precedence each to get a |
|
723
|
|
|
|
|
|
|
# node. Then the "prev" field in the node is set, and finally it is |
|
724
|
|
|
|
|
|
|
# pushed onto the end of the $exprs reference ARRAY. |
|
725
|
|
|
|
|
|
|
sub deparse_op_siblings($$$$$) |
|
726
|
|
|
|
|
|
|
{ |
|
727
|
871
|
|
|
871
|
0
|
2214
|
my ($self, $exprs, $kid, $op, $precedence) = @_; |
|
728
|
871
|
|
|
|
|
1526
|
my $prev_expr = undef; |
|
729
|
871
|
100
|
|
|
|
1292
|
$prev_expr = $exprs->[-1] if scalar @{$exprs}; |
|
|
871
|
|
|
|
|
2140
|
|
|
730
|
871
|
|
|
|
|
7481
|
for ( ; !B::Deparse::null($kid); $kid = $kid->sibling) { |
|
731
|
1642
|
|
|
|
|
4715
|
my $expr = $self->deparse($kid, $precedence, $op); |
|
732
|
1642
|
50
|
|
|
|
3444
|
if (defined $expr) { |
|
733
|
1642
|
|
|
|
|
3671
|
$expr->{prev_expr} = $prev_expr; |
|
734
|
1642
|
|
|
|
|
2221
|
$prev_expr = $expr; |
|
735
|
1642
|
|
|
|
|
19177
|
push @$exprs, $expr; |
|
736
|
|
|
|
|
|
|
} |
|
737
|
|
|
|
|
|
|
} |
|
738
|
|
|
|
|
|
|
} |
|
739
|
|
|
|
|
|
|
|
|
740
|
|
|
|
|
|
|
|
|
741
|
|
|
|
|
|
|
# tr/// and s/// (and tr[][], tr[]//, tr###, etc) |
|
742
|
|
|
|
|
|
|
# note that tr(from)/to/ is OK, but not tr/from/(to) |
|
743
|
|
|
|
|
|
|
sub double_delim { |
|
744
|
|
|
|
|
|
|
my($from, $to) = @_; |
|
745
|
|
|
|
|
|
|
my($succeed, $delim); |
|
746
|
|
|
|
|
|
|
if ($from !~ m[/] and $to !~ m[/]) { |
|
747
|
|
|
|
|
|
|
return "/$from/$to/"; |
|
748
|
|
|
|
|
|
|
} elsif (($succeed, $from) = B::Deparse::balanced_delim($from) and $succeed) { |
|
749
|
|
|
|
|
|
|
if (($succeed, $to) = B::Deparse::balanced_delim($to) and $succeed) { |
|
750
|
|
|
|
|
|
|
return "$from$to"; |
|
751
|
|
|
|
|
|
|
} else { |
|
752
|
|
|
|
|
|
|
for $delim ('/', '"', '#') { # note no "'" -- s''' is special |
|
753
|
|
|
|
|
|
|
return "$from$delim$to$delim" if index($to, $delim) == -1; |
|
754
|
|
|
|
|
|
|
} |
|
755
|
|
|
|
|
|
|
$to =~ s[/][\\/]g; |
|
756
|
|
|
|
|
|
|
return "$from/$to/"; |
|
757
|
|
|
|
|
|
|
} |
|
758
|
|
|
|
|
|
|
} else { |
|
759
|
|
|
|
|
|
|
for $delim ('/', '"', '#') { # note no ' |
|
760
|
|
|
|
|
|
|
return "$delim$from$delim$to$delim" |
|
761
|
|
|
|
|
|
|
if index($to . $from, $delim) == -1; |
|
762
|
|
|
|
|
|
|
} |
|
763
|
|
|
|
|
|
|
$from =~ s[/][\\/]g; |
|
764
|
|
|
|
|
|
|
$to =~ s[/][\\/]g; |
|
765
|
|
|
|
|
|
|
return "/$from/$to/"; |
|
766
|
|
|
|
|
|
|
} |
|
767
|
|
|
|
|
|
|
} |
|
768
|
|
|
|
|
|
|
|
|
769
|
|
|
|
|
|
|
sub dq($$$) |
|
770
|
|
|
|
|
|
|
{ |
|
771
|
16
|
|
|
16
|
0
|
32
|
my ($self, $op, $parent) = @_; |
|
772
|
16
|
|
|
|
|
45
|
my $type = $op->name; |
|
773
|
16
|
|
|
|
|
21
|
my $info; |
|
774
|
16
|
100
|
|
|
|
42
|
if ($type eq "const") { |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
775
|
14
|
50
|
|
|
|
39
|
return info_from_text($op, $self, '$[', 'dq constant ary', {}) if $op->private & OPpCONST_ARYBASE; |
|
776
|
14
|
|
|
|
|
143
|
return info_from_text($op, $self, |
|
777
|
|
|
|
|
|
|
B::Deparse::uninterp(B::Deparse::escape_str(B::Deparse::unback($self->const_sv($op)->as_string))), |
|
778
|
|
|
|
|
|
|
'dq constant', {}); |
|
779
|
|
|
|
|
|
|
} elsif ($type eq "concat") { |
|
780
|
0
|
|
|
|
|
0
|
my $first = $self->dq($op->first, $op); |
|
781
|
0
|
|
|
|
|
0
|
my $last = $self->dq($op->last, $op); |
|
782
|
|
|
|
|
|
|
|
|
783
|
|
|
|
|
|
|
# FIXME: convert to newer conventions |
|
784
|
|
|
|
|
|
|
# Disambiguate "${foo}bar", "${foo}{bar}", "${foo}[1]", "$foo\::bar" |
|
785
|
|
|
|
|
|
|
($last->{text} =~ /^[A-Z\\\^\[\]_?]/ && |
|
786
|
|
|
|
|
|
|
$first->{text} =~ s/([\$@])\^$/${1}{^}/) # "${^}W" etc |
|
787
|
|
|
|
|
|
|
|| ($last->{text} =~ /^[:'{\[\w_]/ && #' |
|
788
|
0
|
0
|
0
|
|
|
0
|
$first->{text} =~ s/([\$@])([A-Za-z_]\w*)$/${1}{$2}/); |
|
|
|
|
0
|
|
|
|
|
|
789
|
|
|
|
|
|
|
|
|
790
|
0
|
|
|
|
|
0
|
return info_from_list($op, $self, [$first->{text}, $last->{text}], '', 'dq_concat', |
|
791
|
|
|
|
|
|
|
{body => [$first, $last]}); |
|
792
|
|
|
|
|
|
|
} elsif ($type eq "join") { |
|
793
|
0
|
|
|
|
|
0
|
return $self->deparse($op->last, 26, $op); # was join($", @ary) |
|
794
|
|
|
|
|
|
|
} else { |
|
795
|
2
|
|
|
|
|
9
|
return $self->deparse($op, 26, $parent); |
|
796
|
|
|
|
|
|
|
} |
|
797
|
0
|
|
|
|
|
0
|
my $kid = $self->dq($op->first->sibling, $op); |
|
798
|
0
|
|
|
|
|
0
|
my $kid_text = $kid->{text}; |
|
799
|
0
|
0
|
|
|
|
0
|
if ($type eq "uc") { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
800
|
0
|
|
|
|
|
0
|
$info = info_from_lists(['\U', $kid, '\E'], '', 'dq_uc', {}); |
|
801
|
|
|
|
|
|
|
} elsif ($type eq "lc") { |
|
802
|
0
|
|
|
|
|
0
|
$info = info_from_lists(['\L', $kid, '\E'], '', 'dq_lc', {}); |
|
803
|
|
|
|
|
|
|
} elsif ($type eq "ucfirst") { |
|
804
|
0
|
|
|
|
|
0
|
$info = info_from_lists(['\u', $kid, '\E'], '', 'dq_ucfirst', {}); |
|
805
|
|
|
|
|
|
|
} elsif ($type eq "lcfirst") { |
|
806
|
0
|
|
|
|
|
0
|
$info = info_from_lists(['\l', $kid, '\E'], '', 'dq_lcfirst', {}); |
|
807
|
|
|
|
|
|
|
} elsif ($type eq "quotemeta") { |
|
808
|
0
|
|
|
|
|
0
|
$info = info_from_lists(['\Q', $kid, '\E'], '', 'dq_quotemeta', {}); |
|
809
|
|
|
|
|
|
|
} elsif ($type eq "fc") { |
|
810
|
0
|
|
|
|
|
0
|
$info = info_from_lists(['\F', $kid, '\E'], '', 'dq_fc', {}); |
|
811
|
|
|
|
|
|
|
} |
|
812
|
0
|
|
|
|
|
0
|
$info->{body} = [$kid]; |
|
813
|
0
|
|
|
|
|
0
|
return $info; |
|
814
|
|
|
|
|
|
|
} |
|
815
|
|
|
|
|
|
|
|
|
816
|
|
|
|
|
|
|
# Handle unary operators that can occur as pseudo-listops inside |
|
817
|
|
|
|
|
|
|
# double quotes |
|
818
|
|
|
|
|
|
|
sub dq_unop |
|
819
|
|
|
|
|
|
|
{ |
|
820
|
20
|
|
|
20
|
0
|
79
|
my($self, $op, $cx, $name, $prec, $flags) = (@_, 0, 0); |
|
821
|
20
|
|
|
|
|
33
|
my $kid; |
|
822
|
20
|
50
|
|
|
|
91
|
if ($op->flags & B::OPf_KIDS) { |
|
823
|
20
|
|
|
|
|
34
|
my $pushmark_op = undef; |
|
824
|
20
|
|
|
|
|
80
|
$kid = $op->first; |
|
825
|
20
|
50
|
|
|
|
210
|
if (not B::Deparse::null $kid->sibling) { |
|
826
|
|
|
|
|
|
|
# If there's more than one kid, the first is an ex-pushmark. |
|
827
|
0
|
|
|
|
|
0
|
$pushmark_op = $kid; |
|
828
|
0
|
|
|
|
|
0
|
$kid = $kid->sibling; |
|
829
|
|
|
|
|
|
|
} |
|
830
|
20
|
|
|
|
|
109
|
my $info = $self->maybe_parens_unop($name, $kid, $cx, $op); |
|
831
|
20
|
50
|
|
|
|
62
|
if ($pushmark_op) { |
|
832
|
|
|
|
|
|
|
# For the pushmark opc we'll consider it the "name" portion |
|
833
|
|
|
|
|
|
|
# of info. We examine that to get the text. |
|
834
|
0
|
|
|
|
|
0
|
my $text = $info->{text}; |
|
835
|
0
|
|
|
|
|
0
|
my $word_end = index($text, ' '); |
|
836
|
0
|
0
|
|
|
|
0
|
$word_end = length($text) unless $word_end > 0; |
|
837
|
0
|
|
|
|
|
0
|
my $pushmark_info = |
|
838
|
|
|
|
|
|
|
$self->info_from_string("dq $name", $op, $text, |
|
839
|
|
|
|
|
|
|
{position => [0, $word_end]}); |
|
840
|
0
|
|
|
|
|
0
|
$info->{other_ops} = [$pushmark_info]; |
|
841
|
|
|
|
|
|
|
# $info->{other_ops} = [$pushmark_op]; |
|
842
|
|
|
|
|
|
|
} |
|
843
|
20
|
|
|
|
|
74
|
return $info; |
|
844
|
|
|
|
|
|
|
} else { |
|
845
|
0
|
0
|
|
|
|
0
|
$name .= '()' if $op->flags & B::OPf_SPECIAL; |
|
846
|
0
|
|
|
|
|
0
|
return $self->info_from_string("dq $name", $op, $name) |
|
847
|
|
|
|
|
|
|
} |
|
848
|
0
|
|
|
|
|
0
|
Carp::confess("unhandled condition in dq_unop"); |
|
849
|
|
|
|
|
|
|
} |
|
850
|
|
|
|
|
|
|
|
|
851
|
|
|
|
|
|
|
sub dquote |
|
852
|
|
|
|
|
|
|
{ |
|
853
|
0
|
|
|
0
|
0
|
0
|
my($self, $op, $cx) = @_; |
|
854
|
|
|
|
|
|
|
# FIXME figure out how to use this |
|
855
|
0
|
|
|
|
|
0
|
my $skipped_ops = [$op->first]; |
|
856
|
0
|
|
|
|
|
0
|
my $kid = $op->first->sibling; # skip ex-stringify, pushmark |
|
857
|
0
|
0
|
|
|
|
0
|
return $self->deparse($kid, $cx, $op) if $self->{'unquote'}; |
|
858
|
|
|
|
|
|
|
$self->maybe_targmy($kid, $cx, |
|
859
|
0
|
|
|
0
|
|
0
|
sub {$self->single_delim($kid, "qq", '"', |
|
860
|
|
|
|
|
|
|
$self->info2str($self->dq($_[1], $op)) |
|
861
|
0
|
|
|
|
|
0
|
)}); |
|
862
|
|
|
|
|
|
|
} |
|
863
|
|
|
|
|
|
|
|
|
864
|
|
|
|
|
|
|
sub elem |
|
865
|
|
|
|
|
|
|
{ |
|
866
|
1
|
|
|
1
|
0
|
3
|
my ($self, $op, $cx, $left, $right, $padname) = @_; |
|
867
|
1
|
|
|
|
|
8
|
my($array, $idx) = ($op->first, $op->first->sibling); |
|
868
|
|
|
|
|
|
|
|
|
869
|
1
|
|
|
|
|
8
|
my $idx_info = $self->elem_or_slice_single_index($idx, $op); |
|
870
|
1
|
|
|
|
|
10
|
my $opts = {body => [$idx_info]}; |
|
871
|
|
|
|
|
|
|
|
|
872
|
1
|
50
|
|
|
|
9
|
unless ($array->name eq $padname) { # Maybe this has been fixed |
|
873
|
0
|
|
|
|
|
0
|
$opts->{other_ops} = [$array]; |
|
874
|
0
|
|
|
|
|
0
|
$array = $array->first; # skip rv2av (or ex-rv2av in _53+) |
|
875
|
|
|
|
|
|
|
} |
|
876
|
1
|
|
|
|
|
4
|
my @texts = (); |
|
877
|
1
|
|
|
|
|
2
|
my $info; |
|
878
|
1
|
|
|
|
|
7
|
my $array_name=$self->elem_or_slice_array_name($array, $left, $padname, 1); |
|
879
|
1
|
50
|
|
|
|
3
|
if ($array_name) { |
|
880
|
1
|
50
|
|
|
|
3
|
if ($array_name !~ /->\z/) { |
|
881
|
1
|
50
|
|
|
|
3
|
if ($array_name eq '#') { |
|
882
|
0
|
|
|
|
|
0
|
$array_name = '${#}'; |
|
883
|
|
|
|
|
|
|
} else { |
|
884
|
1
|
|
|
|
|
3
|
$array_name = '$' . $array_name ; |
|
885
|
|
|
|
|
|
|
} |
|
886
|
|
|
|
|
|
|
} |
|
887
|
1
|
|
|
|
|
2
|
push @texts, $array_name; |
|
888
|
1
|
50
|
|
|
|
3
|
push @texts, $left if $left; |
|
889
|
1
|
|
|
|
|
2
|
push @texts, $idx_info->{text}, $right; |
|
890
|
1
|
|
|
|
|
5
|
return info_from_list($op, $self, \@texts, '', 'elem', $opts) |
|
891
|
|
|
|
|
|
|
} else { |
|
892
|
|
|
|
|
|
|
# $x[20][3]{hi} or expr->[20] |
|
893
|
0
|
|
|
|
|
0
|
my $type; |
|
894
|
0
|
|
|
|
|
0
|
my $array_info = $self->deparse($array, 24, $op); |
|
895
|
0
|
|
|
|
|
0
|
push @{$info->{body}}, $array_info; |
|
|
0
|
|
|
|
|
0
|
|
|
896
|
0
|
|
|
|
|
0
|
@texts = ($array_info->{text}); |
|
897
|
0
|
0
|
|
|
|
0
|
if (is_subscriptable($array)) { |
|
898
|
0
|
|
|
|
|
0
|
push @texts, $left, $idx_info->{text}, $right; |
|
899
|
0
|
|
|
|
|
0
|
$type = 'elem_no_arrow'; |
|
900
|
|
|
|
|
|
|
} else { |
|
901
|
0
|
|
|
|
|
0
|
push @texts, '->', $left, $idx_info->{text}, $right; |
|
902
|
0
|
|
|
|
|
0
|
$type = 'elem_arrow'; |
|
903
|
|
|
|
|
|
|
} |
|
904
|
0
|
|
|
|
|
0
|
return info_from_list($op, $self, \@texts, '', $type, $opts); |
|
905
|
|
|
|
|
|
|
} |
|
906
|
0
|
|
|
|
|
0
|
Carp::confess("unhandled condition in elem"); |
|
907
|
|
|
|
|
|
|
} |
|
908
|
|
|
|
|
|
|
|
|
909
|
|
|
|
|
|
|
sub e_anoncode($$) |
|
910
|
|
|
|
|
|
|
{ |
|
911
|
2
|
|
|
2
|
0
|
6
|
my ($self, $info) = @_; |
|
912
|
2
|
|
|
|
|
11
|
my $sub_info = $self->deparse_sub($info->{code}); |
|
913
|
|
|
|
|
|
|
return $self->info_from_template('sub anonymous', $sub_info->{op}, |
|
914
|
2
|
|
|
|
|
12
|
'sub %c', [0], [$sub_info]); |
|
915
|
|
|
|
|
|
|
} |
|
916
|
|
|
|
|
|
|
|
|
917
|
|
|
|
|
|
|
# Handle filetest operators -r, stat, etc. |
|
918
|
|
|
|
|
|
|
sub filetest |
|
919
|
|
|
|
|
|
|
{ |
|
920
|
14
|
|
|
14
|
0
|
43
|
my($self, $op, $cx, $name) = @_; |
|
921
|
14
|
50
|
|
|
|
97
|
if (B::class($op) eq "UNOP") { |
|
|
|
0
|
|
|
|
|
|
|
922
|
|
|
|
|
|
|
# Genuine '-X' filetests are exempt from the LLAFR, but not |
|
923
|
|
|
|
|
|
|
# l?stat() |
|
924
|
14
|
100
|
|
|
|
55
|
if ($name =~ /^-/) { |
|
925
|
6
|
|
|
|
|
43
|
my $kid = $self->deparse($op->first, 16, $op); |
|
926
|
6
|
|
|
|
|
47
|
return $self->info_from_template("filetest $name", $op, |
|
927
|
|
|
|
|
|
|
"$name %c", undef, [$kid], |
|
928
|
|
|
|
|
|
|
{maybe_parens => [$self, $cx, 16]}); |
|
929
|
|
|
|
|
|
|
} |
|
930
|
8
|
|
|
|
|
65
|
return $self->maybe_parens_unop($name, $op->first, $cx, $op); |
|
931
|
|
|
|
|
|
|
} elsif (B::class($op) =~ /^(SV|PAD)OP$/) { |
|
932
|
0
|
|
|
|
|
0
|
my ($fmt, $type); |
|
933
|
0
|
|
|
|
|
0
|
my $gv_node = $self->pp_gv($op, 1); |
|
934
|
0
|
0
|
|
|
|
0
|
if ($self->func_needs_parens($gv_node->{text}, $cx, 16)) { |
|
935
|
0
|
|
|
|
|
0
|
$fmt = "$name(%c)"; |
|
936
|
0
|
|
|
|
|
0
|
$type = "filetest $name()"; |
|
937
|
|
|
|
|
|
|
} else { |
|
938
|
0
|
|
|
|
|
0
|
$fmt = "$name %c"; |
|
939
|
0
|
|
|
|
|
0
|
$type = "filetest $name"; |
|
940
|
|
|
|
|
|
|
} |
|
941
|
0
|
|
|
|
|
0
|
return $self->info_from_template($type, $op, $fmt, undef, [$gv_node]); |
|
942
|
|
|
|
|
|
|
} else { |
|
943
|
|
|
|
|
|
|
# I don't think baseop filetests ever survive ck_filetest, but... |
|
944
|
0
|
|
|
|
|
0
|
return $self->info_from_string("filetest $name", $op, $name); |
|
945
|
|
|
|
|
|
|
} |
|
946
|
|
|
|
|
|
|
} |
|
947
|
|
|
|
|
|
|
|
|
948
|
|
|
|
|
|
|
sub for_loop($$$$) { |
|
949
|
0
|
|
|
0
|
0
|
0
|
my ($self, $op, $cx, $parent) = @_; |
|
950
|
0
|
|
|
|
|
0
|
my $init = $self->deparse($op, 1, $parent); |
|
951
|
0
|
|
|
|
|
0
|
my $s = $op->sibling; |
|
952
|
0
|
0
|
|
|
|
0
|
my $ll = $s->name eq "unstack" ? $s->sibling : $s->first->sibling; |
|
953
|
0
|
|
|
|
|
0
|
return $self->loop_common($ll, $cx, $init); |
|
954
|
|
|
|
|
|
|
} |
|
955
|
|
|
|
|
|
|
|
|
956
|
|
|
|
|
|
|
# Returns in function (whose name is not passed as a parameter) will |
|
957
|
|
|
|
|
|
|
# need to surround its argements (the first argument is $first_param) |
|
958
|
|
|
|
|
|
|
# in parenthesis. To determine this, we also pass in the operator |
|
959
|
|
|
|
|
|
|
# precedence, $prec, and the current expression context value, $cx |
|
960
|
|
|
|
|
|
|
sub func_needs_parens($$$$) |
|
961
|
|
|
|
|
|
|
{ |
|
962
|
77
|
|
|
77
|
0
|
188
|
my($self, $first_param, $cx, $prec) = @_; |
|
963
|
77
|
|
66
|
|
|
387
|
return ($prec <= $cx) || (substr($first_param, 0, 1) eq "(") || $self->{'parens'}; |
|
964
|
|
|
|
|
|
|
} |
|
965
|
|
|
|
|
|
|
|
|
966
|
|
|
|
|
|
|
sub givwhen |
|
967
|
|
|
|
|
|
|
{ |
|
968
|
0
|
|
|
0
|
0
|
0
|
my($self, $op, $cx, $give_when) = @_; |
|
969
|
|
|
|
|
|
|
|
|
970
|
0
|
|
|
|
|
0
|
my @arg_spec = (); |
|
971
|
0
|
|
|
|
|
0
|
my @nodes = (); |
|
972
|
0
|
|
|
|
|
0
|
my $enterop = $op->first; |
|
973
|
0
|
|
|
|
|
0
|
my $fmt; |
|
974
|
0
|
|
|
|
|
0
|
my ($head, $block); |
|
975
|
0
|
0
|
|
|
|
0
|
if ($enterop->flags & B::OPf_SPECIAL) { |
|
976
|
0
|
|
|
|
|
0
|
$head = $self->keyword("default"); |
|
977
|
0
|
|
|
|
|
0
|
$fmt = "$give_when ($head)\n\%+%c\n%-}\n"; |
|
978
|
0
|
|
|
|
|
0
|
$block = $self->deparse($enterop->first, 0, $enterop, $op); |
|
979
|
|
|
|
|
|
|
} |
|
980
|
|
|
|
|
|
|
else { |
|
981
|
0
|
|
|
|
|
0
|
my $cond = $enterop->first; |
|
982
|
0
|
|
|
|
|
0
|
my $cond_node = $self->deparse($cond, 1, $enterop, $op); |
|
983
|
0
|
|
|
|
|
0
|
push @nodes, $cond_node; |
|
984
|
0
|
|
|
|
|
0
|
$fmt = "$give_when (%c)\n\%+%c\n%-}\n"; |
|
985
|
0
|
|
|
|
|
0
|
$block = $self->deparse($cond->sibling, 0, $enterop, $op); |
|
986
|
|
|
|
|
|
|
} |
|
987
|
0
|
|
|
|
|
0
|
push @nodes, $block; |
|
988
|
|
|
|
|
|
|
|
|
989
|
0
|
|
|
|
|
0
|
return $self->info_from_template("{} $give_when", |
|
990
|
|
|
|
|
|
|
"%c\n\%+%c\n%-}\n", [0, 1], |
|
991
|
|
|
|
|
|
|
\@nodes); |
|
992
|
|
|
|
|
|
|
} |
|
993
|
|
|
|
|
|
|
|
|
994
|
|
|
|
|
|
|
# Handles the indirect operators, print, say(), sort() |
|
995
|
|
|
|
|
|
|
sub indirop |
|
996
|
|
|
|
|
|
|
{ |
|
997
|
49
|
|
|
49
|
0
|
98
|
my($self, $op, $cx, $name) = @_; |
|
998
|
49
|
|
|
|
|
63
|
my($expr, @exprs); |
|
999
|
49
|
|
|
|
|
207
|
my $firstkid = my $kid = $op->first->sibling; |
|
1000
|
49
|
|
|
|
|
85
|
my $indir_info = undef; |
|
1001
|
49
|
|
|
|
|
59
|
my $type = $name; |
|
1002
|
49
|
|
|
|
|
118
|
my $first_op = $op->first; |
|
1003
|
49
|
|
|
|
|
122
|
my @skipped_ops = ($first_op); |
|
1004
|
49
|
|
|
|
|
63
|
my @indir = (); |
|
1005
|
49
|
|
|
|
|
59
|
my @args_spec; |
|
1006
|
|
|
|
|
|
|
|
|
1007
|
49
|
|
|
|
|
60
|
my $fmt = ''; |
|
1008
|
|
|
|
|
|
|
|
|
1009
|
49
|
100
|
|
|
|
149
|
if ($op->flags & OPf_STACKED) { |
|
1010
|
3
|
|
|
|
|
7
|
push @skipped_ops, $kid; |
|
1011
|
3
|
|
|
|
|
8
|
my $indir_op = $kid->first; # skip rv2gv |
|
1012
|
3
|
50
|
0
|
|
|
12
|
if (B::Deparse::is_scope($indir_op)) { |
|
|
|
0
|
|
|
|
|
|
|
1013
|
3
|
|
|
|
|
9
|
$indir_info = $self->deparse($indir_op, 0, $op); |
|
1014
|
3
|
50
|
|
|
|
8
|
if ($indir_info->{text} eq '') { |
|
1015
|
0
|
|
|
|
|
0
|
$fmt = '{;}'; |
|
1016
|
|
|
|
|
|
|
} else { |
|
1017
|
3
|
|
|
|
|
5
|
$fmt = '{%c}'; |
|
1018
|
|
|
|
|
|
|
} |
|
1019
|
|
|
|
|
|
|
} elsif ($indir_op->name eq "const" && $indir_op->private & OPpCONST_BARE) { |
|
1020
|
0
|
|
|
|
|
0
|
$fmt = $self->const_sv($indir_op)->PV; |
|
1021
|
|
|
|
|
|
|
} else { |
|
1022
|
0
|
|
|
|
|
0
|
$indir_info = $self->deparse($indir_op, 24, $op); |
|
1023
|
0
|
|
|
|
|
0
|
$fmt = '%c'; |
|
1024
|
|
|
|
|
|
|
} |
|
1025
|
3
|
|
|
|
|
5
|
$fmt .= ' '; |
|
1026
|
3
|
|
|
|
|
13
|
$kid = $kid->sibling; |
|
1027
|
|
|
|
|
|
|
} |
|
1028
|
|
|
|
|
|
|
|
|
1029
|
49
|
50
|
66
|
|
|
270
|
if ($name eq "sort" && $op->private & (OPpSORT_NUMERIC | OPpSORT_INTEGER)) { |
|
|
|
50
|
66
|
|
|
|
|
|
1030
|
0
|
|
|
|
|
0
|
$type = 'indirop sort numeric or integer'; |
|
1031
|
0
|
0
|
|
|
|
0
|
$fmt = ($op->private & OPpSORT_DESCEND) |
|
1032
|
|
|
|
|
|
|
? '{$b <=> $a} ': '{$a <=> $b} '; |
|
1033
|
|
|
|
|
|
|
} elsif ($name eq "sort" && $op->private & OPpSORT_DESCEND) { |
|
1034
|
0
|
|
|
|
|
0
|
$type = 'indirop sort descend'; |
|
1035
|
0
|
|
|
|
|
0
|
$fmt = '{$b cmp $a} '; |
|
1036
|
|
|
|
|
|
|
} |
|
1037
|
|
|
|
|
|
|
|
|
1038
|
|
|
|
|
|
|
# FIXME: turn into a function; |
|
1039
|
49
|
|
|
|
|
71
|
my $prev_expr = $exprs[-1]; |
|
1040
|
49
|
|
|
|
|
289
|
for (; !B::Deparse::null($kid); $kid = $kid->sibling) { |
|
1041
|
|
|
|
|
|
|
# This prevents us from using deparse_op_siblings |
|
1042
|
57
|
|
|
|
|
74
|
my $operator_context; |
|
1043
|
57
|
100
|
100
|
|
|
287
|
if (!$fmt && $kid == $firstkid |
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
1044
|
|
|
|
|
|
|
&& $name eq "sort" |
|
1045
|
|
|
|
|
|
|
&& $firstkid->name =~ /^enter(xs)?sub/) { |
|
1046
|
1
|
|
|
|
|
5
|
$operator_context = 16; |
|
1047
|
|
|
|
|
|
|
} else { |
|
1048
|
56
|
|
|
|
|
73
|
$operator_context = 6; |
|
1049
|
|
|
|
|
|
|
} |
|
1050
|
57
|
|
|
|
|
171
|
$expr = $self->deparse($kid, $operator_context, $op); |
|
1051
|
57
|
50
|
|
|
|
117
|
if (defined $expr) { |
|
1052
|
57
|
|
|
|
|
120
|
$expr->{prev_expr} = $prev_expr; |
|
1053
|
57
|
|
|
|
|
68
|
$prev_expr = $expr; |
|
1054
|
57
|
|
|
|
|
639
|
push @exprs, $expr; |
|
1055
|
|
|
|
|
|
|
} |
|
1056
|
|
|
|
|
|
|
} |
|
1057
|
|
|
|
|
|
|
|
|
1058
|
|
|
|
|
|
|
# Extend $name possibly by adding "reverse". |
|
1059
|
49
|
|
|
|
|
91
|
my $name2; |
|
1060
|
49
|
50
|
66
|
|
|
163
|
if ($name eq "sort" && $op->private & OPpSORT_REVERSE) { |
|
1061
|
0
|
|
|
|
|
0
|
$name2 = $self->keyword('reverse') . ' ' . $self->keyword('sort'); |
|
1062
|
|
|
|
|
|
|
} else { |
|
1063
|
49
|
|
|
|
|
1150
|
$name2 = $self->keyword($name) |
|
1064
|
|
|
|
|
|
|
} |
|
1065
|
|
|
|
|
|
|
|
|
1066
|
49
|
100
|
100
|
|
|
194
|
if ($name eq "sort" && ($op->private & OPpSORT_INPLACE)) { |
|
1067
|
2
|
|
|
|
|
4
|
$fmt = "%c = $name2 $fmt %c"; |
|
1068
|
|
|
|
|
|
|
# FIXME: do better with skipped ops |
|
1069
|
2
|
|
|
|
|
8
|
return $self->info_from_template("indirop sort inplace", $op, $fmt, |
|
1070
|
|
|
|
|
|
|
[0, 0], \@exprs, |
|
1071
|
|
|
|
|
|
|
{prev_expr => $prev_expr}); |
|
1072
|
|
|
|
|
|
|
} |
|
1073
|
|
|
|
|
|
|
|
|
1074
|
|
|
|
|
|
|
|
|
1075
|
47
|
|
|
|
|
64
|
my $node; |
|
1076
|
47
|
|
|
|
|
71
|
$prev_expr = $exprs[-1]; |
|
1077
|
47
|
50
|
66
|
|
|
435
|
if ($fmt ne "" && $name eq "sort") { |
|
|
|
100
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
1078
|
|
|
|
|
|
|
# We don't want to say "sort(f 1, 2, 3)", since perl -w will |
|
1079
|
|
|
|
|
|
|
# give bareword warnings in that case. Therefore if context |
|
1080
|
|
|
|
|
|
|
# requires, we'll put parens around the outside "(sort f 1, 2, |
|
1081
|
|
|
|
|
|
|
# 3)". Unfortunately, we'll currently think the parens are |
|
1082
|
|
|
|
|
|
|
# necessary more often that they really are, because we don't |
|
1083
|
|
|
|
|
|
|
# distinguish which side of an assignment we're on. |
|
1084
|
0
|
|
|
|
|
0
|
$node = $self->info_from_template($name2, $op, |
|
1085
|
|
|
|
|
|
|
"$name2 %C", |
|
1086
|
|
|
|
|
|
|
[[0, $#exprs, ', ']], |
|
1087
|
|
|
|
|
|
|
\@exprs, |
|
1088
|
|
|
|
|
|
|
{ |
|
1089
|
|
|
|
|
|
|
other_ops => \@skipped_ops, |
|
1090
|
|
|
|
|
|
|
maybe_parens => { |
|
1091
|
|
|
|
|
|
|
context => $cx, |
|
1092
|
|
|
|
|
|
|
precedence => 5}, |
|
1093
|
|
|
|
|
|
|
prev_expr => $prev_expr |
|
1094
|
|
|
|
|
|
|
}); |
|
1095
|
|
|
|
|
|
|
|
|
1096
|
|
|
|
|
|
|
} elsif (!$fmt && $name eq "sort" |
|
1097
|
|
|
|
|
|
|
&& !B::Deparse::null($op->first->sibling) |
|
1098
|
|
|
|
|
|
|
&& $op->first->sibling->name eq 'entersub' ) { |
|
1099
|
|
|
|
|
|
|
# We cannot say sort foo(bar), as foo will be interpreted as a |
|
1100
|
|
|
|
|
|
|
# comparison routine. We have to say sort(...) in that case. |
|
1101
|
1
|
|
|
|
|
14
|
$node = $self->info_from_template("indirop $name2()", $op, |
|
1102
|
|
|
|
|
|
|
"$name2(%C)", |
|
1103
|
|
|
|
|
|
|
[[0, $#exprs, ', ']], |
|
1104
|
|
|
|
|
|
|
\@exprs, |
|
1105
|
|
|
|
|
|
|
{other_ops => \@skipped_ops, |
|
1106
|
|
|
|
|
|
|
prev_expr => $prev_expr}); |
|
1107
|
|
|
|
|
|
|
|
|
1108
|
|
|
|
|
|
|
} else { |
|
1109
|
46
|
100
|
|
|
|
93
|
if (@exprs) { |
|
1110
|
42
|
|
|
|
|
73
|
my $type = "indirop"; |
|
1111
|
42
|
|
|
|
|
78
|
my $args_fmt; |
|
1112
|
42
|
100
|
|
|
|
127
|
if ($self->func_needs_parens($exprs[0]->{text}, $cx, 5)) { |
|
1113
|
32
|
|
|
|
|
57
|
$type = "indirop $name2()"; |
|
1114
|
32
|
|
|
|
|
47
|
$args_fmt = "(%C)"; |
|
1115
|
|
|
|
|
|
|
} else { |
|
1116
|
10
|
|
|
|
|
22
|
$type = "indirop $name2"; |
|
1117
|
10
|
|
|
|
|
15
|
$args_fmt = "%C"; |
|
1118
|
|
|
|
|
|
|
} |
|
1119
|
42
|
|
|
|
|
135
|
@args_spec = ([0, $#exprs, ', ']); |
|
1120
|
42
|
100
|
|
|
|
86
|
if ($fmt) { |
|
1121
|
3
|
|
|
|
|
8
|
$fmt = "${name2} ${fmt}${args_fmt}"; |
|
1122
|
3
|
50
|
|
|
|
7
|
if ($indir_info) { |
|
1123
|
3
|
|
|
|
|
15
|
unshift @exprs, $indir_info; |
|
1124
|
3
|
|
|
|
|
9
|
@args_spec = (0, [1, $#exprs, ', ']); |
|
1125
|
|
|
|
|
|
|
} |
|
1126
|
|
|
|
|
|
|
} else { |
|
1127
|
39
|
100
|
|
|
|
92
|
if (substr($args_fmt, 0, 1) eq '(') { |
|
1128
|
32
|
|
|
|
|
43
|
$fmt = "${name2}$args_fmt"; |
|
1129
|
|
|
|
|
|
|
} else { |
|
1130
|
7
|
|
|
|
|
17
|
$fmt = "${name2} $args_fmt"; |
|
1131
|
|
|
|
|
|
|
} |
|
1132
|
39
|
|
|
|
|
99
|
@args_spec = [0, $#exprs, ', ']; |
|
1133
|
|
|
|
|
|
|
} |
|
1134
|
|
|
|
|
|
|
|
|
1135
|
42
|
|
|
|
|
185
|
$node = $self->info_from_template($type, $op, $fmt, |
|
1136
|
|
|
|
|
|
|
\@args_spec, \@exprs, |
|
1137
|
|
|
|
|
|
|
{prev_expr => $prev_expr}); |
|
1138
|
|
|
|
|
|
|
} else { |
|
1139
|
4
|
|
|
|
|
8
|
$type="indirop $name2"; |
|
1140
|
|
|
|
|
|
|
# Should this be maybe_parens()? |
|
1141
|
4
|
50
|
|
|
|
7
|
$type .= '()' if (7 < $cx); # FIXME - do with format specifier |
|
1142
|
4
|
|
|
|
|
12
|
$node = $self->info_from_string($type, $op, $name2); |
|
1143
|
|
|
|
|
|
|
} |
|
1144
|
|
|
|
|
|
|
} |
|
1145
|
|
|
|
|
|
|
|
|
1146
|
|
|
|
|
|
|
# Handle skipped ops |
|
1147
|
47
|
|
|
|
|
106
|
my @new_ops; |
|
1148
|
47
|
|
|
|
|
89
|
my $position = [0, length($name2)]; |
|
1149
|
47
|
|
|
|
|
73
|
my $str = $node->{text}; |
|
1150
|
47
|
|
|
|
|
71
|
foreach my $skipped_op (@skipped_ops) { |
|
1151
|
50
|
|
|
|
|
286
|
my $new_op = $self->info_from_string($op->name, $skipped_op, $str, |
|
1152
|
|
|
|
|
|
|
{position => $position}); |
|
1153
|
50
|
|
|
|
|
135
|
push @new_ops, $new_op; |
|
1154
|
|
|
|
|
|
|
} |
|
1155
|
47
|
|
|
|
|
84
|
$node->{other_ops} = \@new_ops; |
|
1156
|
47
|
|
|
|
|
147
|
return $node; |
|
1157
|
|
|
|
|
|
|
} |
|
1158
|
|
|
|
|
|
|
|
|
1159
|
|
|
|
|
|
|
# 5.16 doesn't have this so we include it, even though it's not |
|
1160
|
|
|
|
|
|
|
# going to get used? |
|
1161
|
|
|
|
|
|
|
sub is_lexical_subs { |
|
1162
|
0
|
|
|
0
|
0
|
0
|
my (@ops) = shift; |
|
1163
|
0
|
|
|
|
|
0
|
for my $op (@ops) { |
|
1164
|
0
|
0
|
|
|
|
0
|
return 0 if $op->name !~ /\A(?:introcv|clonecv)\z/; |
|
1165
|
|
|
|
|
|
|
} |
|
1166
|
0
|
|
|
|
|
0
|
return 1; |
|
1167
|
|
|
|
|
|
|
} |
|
1168
|
|
|
|
|
|
|
|
|
1169
|
|
|
|
|
|
|
# The version of null_op_list after 5.22 |
|
1170
|
|
|
|
|
|
|
# Note: this uses "op" not "kid" |
|
1171
|
|
|
|
|
|
|
sub is_list_newer($$) { |
|
1172
|
5254
|
|
|
5254
|
0
|
8455
|
my ($self, $op) = @_; |
|
1173
|
5254
|
|
|
|
|
13656
|
my $kid = $op->first; |
|
1174
|
5254
|
100
|
|
|
|
19746
|
return 1 if $kid->name eq 'pushmark'; |
|
1175
|
2647
|
|
66
|
|
|
86557
|
return ($kid->name eq 'null' |
|
1176
|
|
|
|
|
|
|
&& $kid->targ == OP_PUSHMARK |
|
1177
|
|
|
|
|
|
|
&& B::Deparse::_op_is_or_was($op, B::Deparse::OP_LIST)); |
|
1178
|
|
|
|
|
|
|
} |
|
1179
|
|
|
|
|
|
|
|
|
1180
|
|
|
|
|
|
|
|
|
1181
|
|
|
|
|
|
|
# The version of null_op_list before 5.22 |
|
1182
|
|
|
|
|
|
|
# Note: this uses "kid", not "op" |
|
1183
|
|
|
|
|
|
|
sub is_list_older($) { |
|
1184
|
0
|
|
|
0
|
0
|
0
|
my ($self, $kid) = @_; |
|
1185
|
|
|
|
|
|
|
# Something may be funky where without the convesion we are getting "" |
|
1186
|
|
|
|
|
|
|
# as a return |
|
1187
|
0
|
0
|
|
|
|
0
|
return ($kid->name eq 'pushmark') ? 1 : 0; |
|
1188
|
|
|
|
|
|
|
} |
|
1189
|
|
|
|
|
|
|
|
|
1190
|
|
|
|
|
|
|
# This handle logical ops: "if"/"until", "&&", "and", ... |
|
1191
|
|
|
|
|
|
|
# The one-line "while"/"until" is handled in pp_leave. |
|
1192
|
|
|
|
|
|
|
sub logop |
|
1193
|
|
|
|
|
|
|
{ |
|
1194
|
97
|
|
|
97
|
0
|
288
|
my ($self, $op, $cx, $lowop, $lowprec, $highop, |
|
1195
|
|
|
|
|
|
|
$highprec, $blockname) = @_; |
|
1196
|
97
|
|
|
|
|
503
|
my $left = $op->first; |
|
1197
|
97
|
|
|
|
|
492
|
my $right = $op->first->sibling; |
|
1198
|
97
|
|
|
|
|
212
|
my ($lhs, $rhs, $type, $opname); |
|
1199
|
97
|
|
|
|
|
158
|
my $opts = {}; |
|
1200
|
97
|
50
|
66
|
|
|
1264
|
if ($cx < 1 and B::Deparse::is_scope($right) and $blockname |
|
|
|
100
|
33
|
|
|
|
|
|
|
|
100
|
33
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
1201
|
|
|
|
|
|
|
and $self->{'expand'} < 7) { |
|
1202
|
|
|
|
|
|
|
# Is this branch used in 5.26 and above? |
|
1203
|
|
|
|
|
|
|
# ($a) {$b} |
|
1204
|
0
|
|
|
|
|
0
|
my $if_cond_info = $self->deparse($left, 1, $op); |
|
1205
|
0
|
|
|
|
|
0
|
my $if_body_info = $self->deparse($right, 0, $op); |
|
1206
|
0
|
|
|
|
|
0
|
return $self->info_from_template("$blockname () {}", $op, |
|
1207
|
|
|
|
|
|
|
"$blockname (%c) {\n%+%c\n%-}", |
|
1208
|
|
|
|
|
|
|
[0, 1], |
|
1209
|
|
|
|
|
|
|
[$if_cond_info, $if_body_info], $opts); |
|
1210
|
|
|
|
|
|
|
} elsif ($cx < 1 and $blockname and not $self->{'parens'} |
|
1211
|
|
|
|
|
|
|
and $self->{'expand'} < 7) { # $b if $a |
|
1212
|
|
|
|
|
|
|
# Note: order of lhs and rhs is reversed |
|
1213
|
35
|
|
|
|
|
167
|
$lhs = $self->deparse($right, 1, $op); |
|
1214
|
35
|
|
|
|
|
114
|
$rhs = $self->deparse($left, 1, $op); |
|
1215
|
35
|
|
|
|
|
79
|
$opname = $blockname; |
|
1216
|
35
|
|
|
|
|
79
|
$type = "suffix $opname" |
|
1217
|
|
|
|
|
|
|
} elsif ($cx > $lowprec and $highop) { |
|
1218
|
|
|
|
|
|
|
# low-precedence operator like $a && $b |
|
1219
|
16
|
|
|
|
|
51
|
$lhs = $self->deparse_binop_left($op, $left, $highprec); |
|
1220
|
16
|
|
|
|
|
61
|
$rhs = $self->deparse_binop_right($op, $right, $highprec); |
|
1221
|
16
|
|
|
|
|
34
|
$opname = $highop; |
|
1222
|
16
|
|
|
|
|
73
|
$opts = {maybe_parens => [$self, $cx, $highprec]}; |
|
1223
|
|
|
|
|
|
|
} else { |
|
1224
|
|
|
|
|
|
|
# high-precedence operator like $a and $b |
|
1225
|
46
|
|
|
|
|
138
|
$lhs = $self->deparse_binop_left($op, $left, $lowprec); |
|
1226
|
46
|
|
|
|
|
230
|
$rhs = $self->deparse_binop_right($op, $right, $lowprec); |
|
1227
|
46
|
|
|
|
|
99
|
$opname = $lowop; |
|
1228
|
46
|
|
|
|
|
189
|
$opts = {maybe_parens => [$self, $cx, $lowprec]}; |
|
1229
|
|
|
|
|
|
|
} |
|
1230
|
97
|
|
66
|
|
|
382
|
$type ||= $opname; |
|
1231
|
97
|
|
|
|
|
450
|
return $self->info_from_template($type, $op, "%c $opname %c", |
|
1232
|
|
|
|
|
|
|
[0, 1], [$lhs, $rhs], $opts); |
|
1233
|
|
|
|
|
|
|
} |
|
1234
|
|
|
|
|
|
|
|
|
1235
|
|
|
|
|
|
|
# This handle list ops: "open", "pack", "return" ... |
|
1236
|
|
|
|
|
|
|
sub listop |
|
1237
|
|
|
|
|
|
|
{ |
|
1238
|
298
|
|
|
298
|
0
|
947
|
my($self, $op, $cx, $name, $kid, $nollafr) = @_; |
|
1239
|
298
|
|
|
|
|
496
|
my(@exprs, @new_nodes, @skipped_ops); |
|
1240
|
298
|
|
66
|
|
|
1229
|
my $parens = ($cx >= 5) || $self->{'parens'}; |
|
1241
|
|
|
|
|
|
|
|
|
1242
|
298
|
100
|
|
|
|
759
|
unless ($kid) { |
|
1243
|
271
|
|
|
|
|
1202
|
push @skipped_ops, $op->first; |
|
1244
|
271
|
|
|
|
|
1444
|
$kid = $op->first->sibling; |
|
1245
|
|
|
|
|
|
|
} |
|
1246
|
|
|
|
|
|
|
|
|
1247
|
|
|
|
|
|
|
# If there are no arguments, add final parentheses (or parenthesize the |
|
1248
|
|
|
|
|
|
|
# whole thing if the llafr does not apply) to account for cases like |
|
1249
|
|
|
|
|
|
|
# (return)+1 or setpgrp()+1. When the llafr does not apply, we use a |
|
1250
|
|
|
|
|
|
|
# precedence of 6 (< comma), as "return, 1" does not need parentheses. |
|
1251
|
298
|
100
|
|
|
|
2253
|
if (B::Deparse::null $kid) { |
|
1252
|
24
|
|
|
|
|
666
|
my $fullname = $self->keyword($name); |
|
1253
|
24
|
100
|
|
|
|
129
|
my $text = $nollafr |
|
1254
|
|
|
|
|
|
|
? $self->maybe_parens($fullname, $cx, 7) |
|
1255
|
|
|
|
|
|
|
: $fullname . '()' x (7 < $cx); |
|
1256
|
24
|
|
|
|
|
111
|
return $self->info_from_string("listop $name", $op, $text); |
|
1257
|
|
|
|
|
|
|
} |
|
1258
|
274
|
|
|
|
|
499
|
my $first; |
|
1259
|
274
|
|
|
|
|
9758
|
my $fullname = $self->keyword($name); |
|
1260
|
274
|
|
|
|
|
2079
|
my $proto = prototype("CORE::$name"); |
|
1261
|
274
|
100
|
100
|
|
|
2918
|
if ( |
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
1262
|
|
|
|
|
|
|
( (defined $proto && $proto =~ /^;?\*/) |
|
1263
|
|
|
|
|
|
|
|| $name eq 'select' # select(F) doesn't have a proto |
|
1264
|
|
|
|
|
|
|
) |
|
1265
|
|
|
|
|
|
|
&& $kid->name eq "rv2gv" |
|
1266
|
|
|
|
|
|
|
&& !($kid->private & B::OPpLVAL_INTRO) |
|
1267
|
|
|
|
|
|
|
) { |
|
1268
|
74
|
|
|
|
|
813
|
$first = $self->rv2gv_or_string($kid->first, $op); |
|
1269
|
|
|
|
|
|
|
} |
|
1270
|
|
|
|
|
|
|
else { |
|
1271
|
200
|
|
|
|
|
782
|
$first = $self->deparse($kid, 6, $op); |
|
1272
|
|
|
|
|
|
|
} |
|
1273
|
274
|
50
|
66
|
|
|
1164
|
if ($name eq "chmod" && $first->{text} =~ /^\d+$/) { |
|
1274
|
0
|
|
|
0
|
|
0
|
my $transform_fn = sub {sprintf("%#o", $self->info2str(shift))}; |
|
|
0
|
|
|
|
|
0
|
|
|
1275
|
0
|
|
|
|
|
0
|
$first = $self->info_from_template("chmod octal", undef, |
|
1276
|
|
|
|
|
|
|
"%F", [[0, $transform_fn]], |
|
1277
|
|
|
|
|
|
|
[$first], {'relink_children' => [0]}); |
|
1278
|
0
|
|
|
|
|
0
|
push @new_nodes, $first; |
|
1279
|
|
|
|
|
|
|
} |
|
1280
|
|
|
|
|
|
|
|
|
1281
|
|
|
|
|
|
|
# FIXME: fold this into a template |
|
1282
|
|
|
|
|
|
|
$first->{text} = "+" + $first->{text} |
|
1283
|
274
|
50
|
66
|
|
|
1125
|
if not $parens and not $nollafr and substr($first->{text}, 0, 1) eq "("; |
|
|
|
|
66
|
|
|
|
|
|
1284
|
|
|
|
|
|
|
|
|
1285
|
274
|
|
|
|
|
649
|
push @exprs, $first; |
|
1286
|
274
|
|
|
|
|
1461
|
$kid = $kid->sibling; |
|
1287
|
274
|
100
|
100
|
|
|
1715
|
if (defined $proto && $proto =~ /^\*\*/ && $kid->name eq "rv2gv" |
|
|
|
|
66
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
1288
|
|
|
|
|
|
|
&& !($kid->private & B::OPpLVAL_INTRO)) { |
|
1289
|
6
|
|
|
|
|
45
|
$first = $self->rv2gv_or_string($kid->first, $op); |
|
1290
|
6
|
|
|
|
|
15
|
push @exprs, $first; |
|
1291
|
6
|
|
|
|
|
29
|
$kid = $kid->sibling; |
|
1292
|
|
|
|
|
|
|
} |
|
1293
|
|
|
|
|
|
|
|
|
1294
|
274
|
|
|
|
|
1173
|
$self->deparse_op_siblings(\@exprs, $kid, $op, 6); |
|
1295
|
|
|
|
|
|
|
|
|
1296
|
274
|
50
|
66
|
|
|
944
|
if ($name eq "reverse" && ($op->private & B::OPpREVERSE_INPLACE)) { |
|
1297
|
0
|
|
|
|
|
0
|
my $fmt; |
|
1298
|
|
|
|
|
|
|
my $type; |
|
1299
|
0
|
0
|
|
|
|
0
|
if ($parens) { |
|
1300
|
0
|
|
|
|
|
0
|
$fmt = "%c = $fullname(%c)"; |
|
1301
|
0
|
|
|
|
|
0
|
$type = "listop reverse ()" |
|
1302
|
|
|
|
|
|
|
} else { |
|
1303
|
0
|
|
|
|
|
0
|
$fmt = "%c = $fullname(%c)"; |
|
1304
|
0
|
|
|
|
|
0
|
$type = "listop reverse" |
|
1305
|
|
|
|
|
|
|
} |
|
1306
|
0
|
|
|
|
|
0
|
my @nodes = ($exprs[0], $exprs[0]); |
|
1307
|
0
|
|
|
|
|
0
|
return $self->info_from_template($type, $op, $fmt, undef, |
|
1308
|
|
|
|
|
|
|
[$exprs[0], $exprs[0]]); |
|
1309
|
|
|
|
|
|
|
} |
|
1310
|
|
|
|
|
|
|
|
|
1311
|
274
|
|
|
|
|
567
|
my $opts = {}; |
|
1312
|
274
|
|
|
|
|
662
|
my $type; |
|
1313
|
|
|
|
|
|
|
my $fmt; |
|
1314
|
|
|
|
|
|
|
|
|
1315
|
274
|
50
|
66
|
|
|
1225
|
if ($name =~ /^(system|exec)$/ |
|
|
|
|
33
|
|
|
|
|
|
1316
|
|
|
|
|
|
|
&& ($op->flags & B::OPf_STACKED) |
|
1317
|
|
|
|
|
|
|
&& @exprs > 1) |
|
1318
|
|
|
|
|
|
|
{ |
|
1319
|
|
|
|
|
|
|
# handle the "system(prog a1, a2, ...)" form |
|
1320
|
|
|
|
|
|
|
# where there is no ', ' between the first two arguments. |
|
1321
|
0
|
0
|
0
|
|
|
0
|
if ($parens && $nollafr) { |
|
|
|
0
|
|
|
|
|
|
|
1322
|
0
|
|
|
|
|
0
|
$fmt = "($fullname %c %C)"; |
|
1323
|
0
|
|
|
|
|
0
|
$type = "listop ($fullname)"; |
|
1324
|
|
|
|
|
|
|
} elsif ($parens) { |
|
1325
|
0
|
|
|
|
|
0
|
$fmt = "$fullname(%c %C)"; |
|
1326
|
0
|
|
|
|
|
0
|
$type = "listop $fullname()"; |
|
1327
|
|
|
|
|
|
|
} else { |
|
1328
|
0
|
|
|
|
|
0
|
$fmt = "$fullname %c %C"; |
|
1329
|
0
|
|
|
|
|
0
|
$type = "listop $fullname"; |
|
1330
|
|
|
|
|
|
|
} |
|
1331
|
0
|
|
|
|
|
0
|
return $self->info_from_template($type, $op, $fmt, |
|
1332
|
|
|
|
|
|
|
[0, [1, $#exprs, ', ']], \@exprs); |
|
1333
|
|
|
|
|
|
|
|
|
1334
|
|
|
|
|
|
|
} |
|
1335
|
|
|
|
|
|
|
|
|
1336
|
274
|
|
|
|
|
557
|
$fmt = "%c %C"; |
|
1337
|
274
|
100
|
100
|
|
|
1205
|
if ($parens && $nollafr) { |
|
|
|
100
|
|
|
|
|
|
|
1338
|
|
|
|
|
|
|
# FIXME: do with parens mechanism |
|
1339
|
3
|
|
|
|
|
9
|
$fmt = "($fullname %C)"; |
|
1340
|
3
|
|
|
|
|
6
|
$type = "listop ($fullname)"; |
|
1341
|
|
|
|
|
|
|
} elsif ($parens) { |
|
1342
|
242
|
|
|
|
|
505
|
$fmt = "$fullname(%C)"; |
|
1343
|
242
|
|
|
|
|
587
|
$type = "listop $fullname()"; |
|
1344
|
|
|
|
|
|
|
} else { |
|
1345
|
29
|
|
|
|
|
73
|
$fmt = "$fullname %C"; |
|
1346
|
29
|
|
|
|
|
66
|
$type = "listop $fullname"; |
|
1347
|
|
|
|
|
|
|
} |
|
1348
|
274
|
50
|
|
|
|
673
|
$opts->{synthesized_nodes} = \@new_nodes if @new_nodes; |
|
1349
|
274
|
|
|
|
|
1507
|
my $node = $self->info_from_template($type, $op, $fmt, |
|
1350
|
|
|
|
|
|
|
[[0, $#exprs, ', ']], \@exprs, |
|
1351
|
|
|
|
|
|
|
$opts); |
|
1352
|
274
|
|
|
|
|
720
|
$node->{prev_expr} = $exprs[-1]; |
|
1353
|
274
|
100
|
|
|
|
869
|
if (@skipped_ops) { |
|
1354
|
|
|
|
|
|
|
# if we have skipped ops like pushmark, we will use $full name |
|
1355
|
|
|
|
|
|
|
# as the part it represents. |
|
1356
|
|
|
|
|
|
|
## FIXME |
|
1357
|
247
|
|
|
|
|
381
|
my @new_ops; |
|
1358
|
247
|
|
|
|
|
579
|
my $position = [0, length($fullname)]; |
|
1359
|
247
|
|
|
|
|
465
|
my $str = $node->{text}; |
|
1360
|
247
|
|
|
|
|
319
|
my @skipped_nodes; |
|
1361
|
247
|
|
|
|
|
500
|
for my $skipped_op (@skipped_ops) { |
|
1362
|
247
|
|
|
|
|
1736
|
my $new_op = $self->info_from_string($op->name, $skipped_op, $str, |
|
1363
|
|
|
|
|
|
|
{position => $position}); |
|
1364
|
247
|
|
|
|
|
907
|
push @new_ops, $new_op; |
|
1365
|
|
|
|
|
|
|
} |
|
1366
|
247
|
|
|
|
|
667
|
$node->{other_ops} = \@new_ops; |
|
1367
|
|
|
|
|
|
|
} |
|
1368
|
274
|
|
|
|
|
1116
|
return $node; |
|
1369
|
|
|
|
|
|
|
} |
|
1370
|
|
|
|
|
|
|
|
|
1371
|
|
|
|
|
|
|
sub loop_common |
|
1372
|
|
|
|
|
|
|
{ |
|
1373
|
5
|
|
|
5
|
0
|
9
|
my $self = shift; |
|
1374
|
5
|
|
|
|
|
16
|
my($op, $cx, $init) = @_; |
|
1375
|
5
|
|
|
|
|
19
|
my $enter = $op->first; |
|
1376
|
5
|
|
|
|
|
15
|
my $kid = $enter->sibling; |
|
1377
|
|
|
|
|
|
|
|
|
1378
|
5
|
|
|
|
|
10
|
my @skipped_ops = ($enter); |
|
1379
|
|
|
|
|
|
|
local(@$self{qw'curstash warnings hints hinthash'}) |
|
1380
|
5
|
|
|
|
|
24
|
= @$self{qw'curstash warnings hints hinthash'}; |
|
1381
|
|
|
|
|
|
|
|
|
1382
|
5
|
|
|
|
|
9
|
my ($body, @body); |
|
1383
|
5
|
|
|
|
|
9
|
my @nodes = (); |
|
1384
|
5
|
|
|
|
|
9
|
my ($bare, $cond_info) = (0, undef); |
|
1385
|
5
|
|
|
|
|
7
|
my $fmt = ''; |
|
1386
|
5
|
|
|
|
|
4
|
my $var_fmt; |
|
1387
|
5
|
|
|
|
|
8
|
my @args_spec = (); |
|
1388
|
5
|
|
|
|
|
10
|
my $opts = {}; |
|
1389
|
5
|
|
|
|
|
9
|
my $type = 'loop'; |
|
1390
|
|
|
|
|
|
|
|
|
1391
|
5
|
50
|
|
|
|
20
|
if ($kid->name eq "lineseq") { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
1392
|
|
|
|
|
|
|
# bare or infinite loop |
|
1393
|
5
|
|
|
|
|
10
|
$type .= ' while (1)'; |
|
1394
|
|
|
|
|
|
|
|
|
1395
|
5
|
100
|
|
|
|
27
|
if ($kid->last->name eq "unstack") { # infinite |
|
1396
|
1
|
|
|
|
|
3
|
$fmt .= 'while (1)'; |
|
1397
|
|
|
|
|
|
|
} else { |
|
1398
|
4
|
|
|
|
|
8
|
$bare = 1; |
|
1399
|
|
|
|
|
|
|
} |
|
1400
|
5
|
|
|
|
|
8
|
$body = $kid; |
|
1401
|
|
|
|
|
|
|
} elsif ($enter->name eq "enteriter") { |
|
1402
|
|
|
|
|
|
|
# foreach |
|
1403
|
0
|
|
|
|
|
0
|
$type .= ' foreach'; |
|
1404
|
|
|
|
|
|
|
|
|
1405
|
0
|
|
|
|
|
0
|
my $ary = $enter->first->sibling; # first was pushmark |
|
1406
|
0
|
|
|
|
|
0
|
push @skipped_ops, $enter->first, $ary->first->sibling; |
|
1407
|
0
|
|
|
|
|
0
|
my ($ary_fmt, $var_info); |
|
1408
|
0
|
|
|
|
|
0
|
my $var = $ary->sibling; |
|
1409
|
0
|
0
|
|
|
|
0
|
if (B::Deparse::null $var) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
1410
|
0
|
0
|
0
|
|
|
0
|
if (($enter->flags & B::OPf_SPECIAL) && ($] < 5.009)) { |
|
1411
|
|
|
|
|
|
|
# thread special var, under 5005threads |
|
1412
|
0
|
|
|
|
|
0
|
$var_fmt = $self->pp_threadsv($enter, 1); |
|
1413
|
|
|
|
|
|
|
} else { # regular my() variable |
|
1414
|
0
|
|
|
|
|
0
|
$var_info = $self->pp_padsv($enter, 1, 1); |
|
1415
|
0
|
|
|
|
|
0
|
push @nodes, $var_info; |
|
1416
|
0
|
|
|
|
|
0
|
$var_fmt = '%c'; |
|
1417
|
0
|
|
|
|
|
0
|
push @args_spec, $#nodes; |
|
1418
|
|
|
|
|
|
|
} |
|
1419
|
|
|
|
|
|
|
} elsif ($var->name eq "rv2gv") { |
|
1420
|
0
|
|
|
|
|
0
|
$var_info = $self->pp_rv2sv($var, 1); |
|
1421
|
0
|
|
|
|
|
0
|
push @nodes, $var_info; |
|
1422
|
0
|
0
|
|
|
|
0
|
if ($enter->private & B::OPpOUR_INTRO) { |
|
1423
|
|
|
|
|
|
|
# "our" declarations don't have package names |
|
1424
|
0
|
|
|
0
|
|
0
|
my $transform_fn = sub {$_[0] =~ s/^(.).*::/$1/}; |
|
|
0
|
|
|
|
|
0
|
|
|
1425
|
0
|
|
|
|
|
0
|
$var_fmt = "our %F"; |
|
1426
|
0
|
|
|
|
|
0
|
push @args_spec, [$#nodes, $transform_fn]; |
|
1427
|
|
|
|
|
|
|
} else { |
|
1428
|
0
|
|
|
|
|
0
|
$var_fmt = '%c'; |
|
1429
|
0
|
|
|
|
|
0
|
push @args_spec, $#nodes; |
|
1430
|
|
|
|
|
|
|
} |
|
1431
|
|
|
|
|
|
|
} elsif ($var->name eq "gv") { |
|
1432
|
0
|
|
|
|
|
0
|
$var_info = $self->deparse($var, 1, $op); |
|
1433
|
0
|
|
|
|
|
0
|
push @nodes, $var_info; |
|
1434
|
0
|
|
|
|
|
0
|
$var_fmt = '$%c'; |
|
1435
|
0
|
|
|
|
|
0
|
push @args_spec, $#nodes; |
|
1436
|
|
|
|
|
|
|
} |
|
1437
|
|
|
|
|
|
|
|
|
1438
|
0
|
0
|
0
|
|
|
0
|
if ($ary->name eq 'null' and $enter->private & B::OPpITER_REVERSED) { |
|
|
|
0
|
0
|
|
|
|
|
|
1439
|
|
|
|
|
|
|
# "reverse" was optimised away |
|
1440
|
0
|
|
|
|
|
0
|
push @nodes, listop($self, $ary->first->sibling, 1, 'reverse'); |
|
1441
|
0
|
|
|
|
|
0
|
$ary_fmt = "%c"; |
|
1442
|
0
|
|
|
|
|
0
|
push @args_spec, $#nodes; |
|
1443
|
|
|
|
|
|
|
} elsif ($enter->flags & B::OPf_STACKED |
|
1444
|
|
|
|
|
|
|
and not B::Deparse::null $ary->first->sibling->sibling) { |
|
1445
|
0
|
|
|
|
|
0
|
push @args_spec, scalar(@nodes), scalar(@nodes+1); |
|
1446
|
0
|
|
|
|
|
0
|
push @nodes, ($self->deparse($ary->first->sibling, 9, $op), |
|
1447
|
|
|
|
|
|
|
$self->deparse($ary->first->sibling->sibling, 9, $op)); |
|
1448
|
0
|
|
|
|
|
0
|
$ary_fmt = '(%c .. %c)'; |
|
1449
|
|
|
|
|
|
|
|
|
1450
|
|
|
|
|
|
|
} else { |
|
1451
|
0
|
|
|
|
|
0
|
push @nodes, $self->deparse($ary, 1, $op); |
|
1452
|
0
|
|
|
|
|
0
|
$ary_fmt = "%c"; |
|
1453
|
0
|
|
|
|
|
0
|
push @args_spec, $#nodes; |
|
1454
|
|
|
|
|
|
|
} |
|
1455
|
|
|
|
|
|
|
|
|
1456
|
|
|
|
|
|
|
# skip OP_AND and OP_ITER |
|
1457
|
0
|
|
|
|
|
0
|
push @skipped_ops, $kid->first, $kid->first->first; |
|
1458
|
0
|
|
|
|
|
0
|
$body = $kid->first->first->sibling; |
|
1459
|
|
|
|
|
|
|
|
|
1460
|
0
|
0
|
0
|
|
|
0
|
if (!B::Deparse::is_state $body->first |
|
1461
|
|
|
|
|
|
|
and $body->first->name !~ /^(?:stub|leave|scope)$/) { |
|
1462
|
|
|
|
|
|
|
# FIXME: |
|
1463
|
|
|
|
|
|
|
# Carp::confess("var ne \$_") unless join('', @var_text) eq '$_'; |
|
1464
|
0
|
|
|
|
|
0
|
push @skipped_ops, $body->first; |
|
1465
|
0
|
|
|
|
|
0
|
$body = $body->first; |
|
1466
|
0
|
|
|
|
|
0
|
my $body_info = $self->deparse($body, 2, $op); |
|
1467
|
0
|
|
|
|
|
0
|
push @nodes, $body_info; |
|
1468
|
0
|
|
|
|
|
0
|
return $self->info_from_template("foreach", $op, |
|
1469
|
|
|
|
|
|
|
"$var_fmt foreach ($ary_fmt)", |
|
1470
|
|
|
|
|
|
|
\@args_spec, \@nodes, |
|
1471
|
|
|
|
|
|
|
{other_ops => \@skipped_ops}); |
|
1472
|
|
|
|
|
|
|
} |
|
1473
|
0
|
|
|
|
|
0
|
$fmt = "foreach $var_fmt $ary_fmt"; |
|
1474
|
|
|
|
|
|
|
} elsif ($kid->name eq "null") { |
|
1475
|
|
|
|
|
|
|
# while/until |
|
1476
|
|
|
|
|
|
|
|
|
1477
|
0
|
|
|
|
|
0
|
$kid = $kid->first; |
|
1478
|
0
|
|
|
|
|
0
|
my $name = {"and" => "while", "or" => "until"}->{$kid->name}; |
|
1479
|
0
|
|
|
|
|
0
|
$type .= " $name"; |
|
1480
|
0
|
|
|
|
|
0
|
$cond_info = $self->deparse($kid->first, 1, $op); |
|
1481
|
0
|
|
|
|
|
0
|
$fmt = "$name (%c) "; |
|
1482
|
0
|
|
|
|
|
0
|
push @nodes, $cond_info; |
|
1483
|
0
|
|
|
|
|
0
|
$body = $kid->first->sibling; |
|
1484
|
0
|
|
|
|
|
0
|
@args_spec = (0); |
|
1485
|
|
|
|
|
|
|
} elsif ($kid->name eq "stub") { |
|
1486
|
|
|
|
|
|
|
# bare and empty |
|
1487
|
0
|
|
|
|
|
0
|
return info_from_text($op, $self, '{;}', 'empty loop', {}); |
|
1488
|
|
|
|
|
|
|
} |
|
1489
|
|
|
|
|
|
|
|
|
1490
|
|
|
|
|
|
|
# If there isn't a continue block, then the next pointer for the loop |
|
1491
|
|
|
|
|
|
|
# will point to the unstack, which is kid's last child, except |
|
1492
|
|
|
|
|
|
|
# in a bare loop, when it will point to the leaveloop. When neither of |
|
1493
|
|
|
|
|
|
|
# these conditions hold, then the second-to-last child is the continue |
|
1494
|
|
|
|
|
|
|
# block (or the last in a bare loop). |
|
1495
|
5
|
|
|
|
|
16
|
my $cont_start = $enter->nextop; |
|
1496
|
5
|
|
|
|
|
7
|
my ($cont, @cont_text, $body_info); |
|
1497
|
5
|
|
|
|
|
11
|
my @cont = (); |
|
1498
|
5
|
50
|
66
|
|
|
28
|
if ($$cont_start != $$op && ${$cont_start} != ${$body->last}) { |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
4
|
|
|
1499
|
0
|
|
|
|
|
0
|
$type .= ' continue'; |
|
1500
|
|
|
|
|
|
|
|
|
1501
|
0
|
0
|
|
|
|
0
|
if ($bare) { |
|
1502
|
0
|
|
|
|
|
0
|
$cont = $body->last; |
|
1503
|
|
|
|
|
|
|
} else { |
|
1504
|
0
|
|
|
|
|
0
|
$cont = $body->first; |
|
1505
|
0
|
|
|
|
|
0
|
while (!B::Deparse::null($cont->sibling->sibling)) { |
|
1506
|
0
|
|
|
|
|
0
|
$cont = $cont->sibling; |
|
1507
|
|
|
|
|
|
|
} |
|
1508
|
|
|
|
|
|
|
} |
|
1509
|
0
|
|
|
|
|
0
|
my $state = $body->first; |
|
1510
|
0
|
|
|
|
|
0
|
my $cuddle = " "; |
|
1511
|
0
|
|
|
|
|
0
|
my @states; |
|
1512
|
0
|
|
|
|
|
0
|
for (; $$state != $$cont; $state = $state->sibling) { |
|
1513
|
0
|
|
|
|
|
0
|
push @states, $state; |
|
1514
|
|
|
|
|
|
|
} |
|
1515
|
0
|
|
|
|
|
0
|
$body_info = $self->lineseq(undef, 0, @states); |
|
1516
|
0
|
0
|
0
|
|
|
0
|
if (defined $cond_info |
|
|
|
|
0
|
|
|
|
|
|
1517
|
|
|
|
|
|
|
and not B::Deparse::is_scope($cont) |
|
1518
|
|
|
|
|
|
|
and $self->{'expand'} < 3) { |
|
1519
|
0
|
|
|
|
|
0
|
my $cont_info = $self->deparse($cont, 1, $op); |
|
1520
|
0
|
0
|
|
|
|
0
|
my $init = defined($init) ? $init : ' '; |
|
1521
|
0
|
|
|
|
|
0
|
@nodes = ($init, $cond_info, $cont_info); |
|
1522
|
|
|
|
|
|
|
# @nodes_text = ('for', '(', "$init_text;", $cont_info->{text}, ')'); |
|
1523
|
0
|
|
|
|
|
0
|
$fmt = 'for (%c; %c; %c) '; |
|
1524
|
0
|
|
|
|
|
0
|
@args_spec = (0, 1, 2); |
|
1525
|
0
|
|
|
|
|
0
|
$opts->{'omit_next_semicolon'} = 1; |
|
1526
|
|
|
|
|
|
|
} else { |
|
1527
|
0
|
|
|
|
|
0
|
my $cont_info = $self->deparse($cont, 0, $op); |
|
1528
|
0
|
|
|
|
|
0
|
@nodes = ($init, $cont_info); |
|
1529
|
0
|
|
|
|
|
0
|
@args_spec = (0, 1); |
|
1530
|
0
|
|
|
|
|
0
|
$opts->{'omit_next_semicolon'} = 1; |
|
1531
|
|
|
|
|
|
|
@cont_text = ($cuddle, 'continue', "{\n\t", |
|
1532
|
0
|
|
|
|
|
0
|
$cont_info->{text} , "\n\b}"); |
|
1533
|
|
|
|
|
|
|
} |
|
1534
|
|
|
|
|
|
|
} else { |
|
1535
|
5
|
50
|
|
|
|
14
|
return info_from_text($op, $self, '', 'loop_no_body', {}) |
|
1536
|
|
|
|
|
|
|
if !defined $body; |
|
1537
|
5
|
50
|
|
|
|
16
|
if (defined $init) { |
|
1538
|
0
|
|
|
|
|
0
|
@nodes = ($init, $cond_info); |
|
1539
|
0
|
|
|
|
|
0
|
$fmt = 'for (%c; %c;) '; |
|
1540
|
0
|
|
|
|
|
0
|
@args_spec = (0, 1); |
|
1541
|
|
|
|
|
|
|
} |
|
1542
|
5
|
|
|
|
|
12
|
$opts->{'omit_next_semicolon'} = 1; |
|
1543
|
5
|
|
|
|
|
18
|
$body_info = $self->deparse($body, 0, $op); |
|
1544
|
|
|
|
|
|
|
} |
|
1545
|
|
|
|
|
|
|
|
|
1546
|
|
|
|
|
|
|
# (my $body_text = $body_info->{text}) =~ s/;?$/;\n/; |
|
1547
|
|
|
|
|
|
|
# my @texts = (@nodes_text, "{\n\t", $body_text, "\b}", @cont_text); |
|
1548
|
|
|
|
|
|
|
|
|
1549
|
5
|
|
|
|
|
12
|
push @nodes, $body_info; |
|
1550
|
5
|
|
|
|
|
11
|
push @args_spec, $#nodes; |
|
1551
|
5
|
|
|
|
|
11
|
$fmt .= " {\n%+%c%-\n}"; |
|
1552
|
5
|
50
|
|
|
|
14
|
if (@cont_text) { |
|
1553
|
0
|
|
|
|
|
0
|
push @nodes, @cont_text; |
|
1554
|
0
|
|
|
|
|
0
|
push @args_spec, $#nodes; |
|
1555
|
0
|
|
|
|
|
0
|
$type .= ' cont'; |
|
1556
|
0
|
|
|
|
|
0
|
$fmt .= '%c'; |
|
1557
|
|
|
|
|
|
|
} |
|
1558
|
5
|
|
|
|
|
16
|
return $self->info_from_template($type, $op, $fmt, \@args_spec, \@nodes, $opts) |
|
1559
|
|
|
|
|
|
|
} |
|
1560
|
|
|
|
|
|
|
|
|
1561
|
|
|
|
|
|
|
# loop expressions |
|
1562
|
|
|
|
|
|
|
sub loopex |
|
1563
|
|
|
|
|
|
|
{ |
|
1564
|
0
|
|
|
0
|
0
|
0
|
my ($self, $op, $cx, $name) = @_; |
|
1565
|
0
|
|
|
|
|
0
|
my $opts = {maybe_parens => [$self, $cx, 7]}; |
|
1566
|
0
|
0
|
|
|
|
0
|
if (B::class($op) eq "PVOP") { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
1567
|
0
|
|
|
|
|
0
|
return info_from_list($op, $self, [$name, $op->pv], ' ', |
|
1568
|
|
|
|
|
|
|
"loop $name $op->pv", $opts); |
|
1569
|
|
|
|
|
|
|
} elsif (B::class($op) eq "OP") { |
|
1570
|
|
|
|
|
|
|
# no-op |
|
1571
|
0
|
|
|
|
|
0
|
return $self->info_from_string("loopex op $name", |
|
1572
|
|
|
|
|
|
|
$op, $name, $opts); |
|
1573
|
|
|
|
|
|
|
} elsif (B::class($op) eq "UNOP") { |
|
1574
|
0
|
|
|
|
|
0
|
(my $kid_info = $self->deparse($op->first, 7)) =~ s/^\cS//; |
|
1575
|
|
|
|
|
|
|
# last foo() is a syntax error. So we might surround it with parens. |
|
1576
|
|
|
|
|
|
|
my $transform_fn = sub { |
|
1577
|
0
|
|
|
0
|
|
0
|
my $text = shift->{text}; |
|
1578
|
0
|
0
|
|
|
|
0
|
$text = "($text)" if $text =~ /^(?!\d)\w/; |
|
1579
|
0
|
|
|
|
|
0
|
return $text; |
|
1580
|
0
|
|
|
|
|
0
|
}; |
|
1581
|
0
|
|
|
|
|
0
|
return $self->info_from_template("loopex unop $name", |
|
1582
|
|
|
|
|
|
|
$op, "$name %F", |
|
1583
|
|
|
|
|
|
|
undef, [$kid_info], $opts); |
|
1584
|
|
|
|
|
|
|
} else { |
|
1585
|
0
|
|
|
|
|
0
|
return $self->info_from_string("loop $name", |
|
1586
|
|
|
|
|
|
|
$op, $name, "loop $name", $opts); |
|
1587
|
|
|
|
|
|
|
} |
|
1588
|
0
|
|
|
|
|
0
|
Carp::confess("unhandled condition in lopex"); |
|
1589
|
|
|
|
|
|
|
} |
|
1590
|
|
|
|
|
|
|
|
|
1591
|
|
|
|
|
|
|
# Logical assignment operations, e.g. ||= &&=, //= |
|
1592
|
|
|
|
|
|
|
sub logassignop |
|
1593
|
|
|
|
|
|
|
{ |
|
1594
|
0
|
|
|
0
|
0
|
0
|
my ($self, $op, $cx, $opname) = @_; |
|
1595
|
0
|
|
|
|
|
0
|
my $left_op = $op->first; |
|
1596
|
|
|
|
|
|
|
|
|
1597
|
0
|
|
|
|
|
0
|
my $sassign_op = $left_op->sibling; |
|
1598
|
0
|
|
|
|
|
0
|
my $right_op = $sassign_op->first; # skip sassign |
|
1599
|
0
|
|
|
|
|
0
|
my $left_node = $self->deparse($left_op, 7, $op); |
|
1600
|
0
|
|
|
|
|
0
|
my $right_node = $self->deparse($right_op, 7, $op); |
|
1601
|
0
|
|
|
|
|
0
|
my $node = $self->info_from_template( |
|
1602
|
|
|
|
|
|
|
"logical assign $opname", $op, |
|
1603
|
|
|
|
|
|
|
"%c $opname %c", undef, [$left_node, $right_node], |
|
1604
|
|
|
|
|
|
|
{other_ops => [$op->first->sibling], |
|
1605
|
|
|
|
|
|
|
maybe_parens => [$self, $cx, 7]}); |
|
1606
|
|
|
|
|
|
|
|
|
1607
|
|
|
|
|
|
|
# Handle skipped sassign |
|
1608
|
0
|
|
|
|
|
0
|
my $str = $node->{text}; |
|
1609
|
0
|
|
|
|
|
0
|
my $position = [length($left_node->{text})+1, length($opname)]; |
|
1610
|
0
|
|
|
|
|
0
|
my $new_op = $self->info_from_string($sassign_op->name, $sassign_op, $str, |
|
1611
|
|
|
|
|
|
|
{position => $position}); |
|
1612
|
0
|
|
|
|
|
0
|
$node->{other_ops} = [$new_op]; |
|
1613
|
0
|
|
|
|
|
0
|
return $node; |
|
1614
|
|
|
|
|
|
|
|
|
1615
|
|
|
|
|
|
|
} |
|
1616
|
|
|
|
|
|
|
|
|
1617
|
|
|
|
|
|
|
sub mapop |
|
1618
|
|
|
|
|
|
|
{ |
|
1619
|
24
|
|
|
24
|
0
|
46
|
my($self, $op, $cx, $name) = @_; |
|
1620
|
24
|
|
|
|
|
59
|
my $kid = $op->first; # this is the (map|grep)start |
|
1621
|
|
|
|
|
|
|
|
|
1622
|
24
|
|
|
|
|
93
|
my @skipped_ops = ($kid, $kid->first); |
|
1623
|
24
|
|
|
|
|
89
|
$kid = $kid->first->sibling; # skip a pushmark |
|
1624
|
|
|
|
|
|
|
|
|
1625
|
24
|
|
|
|
|
69
|
my $code_block = $kid->first; # skip a null |
|
1626
|
|
|
|
|
|
|
|
|
1627
|
24
|
|
|
|
|
52
|
my ($code_block_node, @nodes); |
|
1628
|
24
|
|
|
|
|
0
|
my ($fmt, $first_arg_fmt, $is_block); |
|
1629
|
24
|
|
|
|
|
33
|
my $type = "map $name"; |
|
1630
|
24
|
|
|
|
|
30
|
my @args_spec = (); |
|
1631
|
|
|
|
|
|
|
|
|
1632
|
24
|
50
|
|
|
|
363
|
if (B::Deparse::is_scope $code_block) { |
|
1633
|
0
|
|
|
|
|
0
|
$code_block_node = $self->deparse($code_block, 0, $op); |
|
1634
|
|
|
|
|
|
|
my $transform_fn = sub { |
|
1635
|
|
|
|
|
|
|
# remove first \n in block. |
|
1636
|
0
|
|
|
0
|
|
0
|
($_[0]->{text})=~ s/^\n\s*//; |
|
1637
|
0
|
|
|
|
|
0
|
return $_[0]->{text}; |
|
1638
|
0
|
|
|
|
|
0
|
}; |
|
1639
|
0
|
|
|
|
|
0
|
push @args_spec, [0, $transform_fn]; |
|
1640
|
0
|
|
|
|
|
0
|
$first_arg_fmt = '{ %F }'; |
|
1641
|
|
|
|
|
|
|
|
|
1642
|
|
|
|
|
|
|
## Alternate simpler form: |
|
1643
|
|
|
|
|
|
|
# push @args_spec, 0; |
|
1644
|
|
|
|
|
|
|
# $first_arg_fmt = '{ %c }'; |
|
1645
|
0
|
|
|
|
|
0
|
$type .= " block"; |
|
1646
|
0
|
|
|
|
|
0
|
$is_block = 1; |
|
1647
|
|
|
|
|
|
|
|
|
1648
|
|
|
|
|
|
|
} else { |
|
1649
|
24
|
|
|
|
|
79
|
$code_block_node = $self->deparse($code_block, 24, $op); |
|
1650
|
24
|
|
|
|
|
43
|
push @args_spec, 0; |
|
1651
|
24
|
|
|
|
|
31
|
$first_arg_fmt = '%c'; |
|
1652
|
24
|
|
|
|
|
34
|
$type .= " expr"; |
|
1653
|
24
|
|
|
|
|
24
|
$is_block = 0; |
|
1654
|
|
|
|
|
|
|
} |
|
1655
|
24
|
|
|
|
|
41
|
push @nodes, $code_block_node; |
|
1656
|
24
|
|
|
|
|
64
|
$self->{optree}{$code_block_node->{addr}} = $code_block_node; |
|
1657
|
|
|
|
|
|
|
|
|
1658
|
24
|
|
|
|
|
30
|
push @skipped_ops, $kid; |
|
1659
|
24
|
|
|
|
|
93
|
$kid = $kid->sibling; |
|
1660
|
24
|
|
|
|
|
106
|
$self->deparse_op_siblings(\@nodes, $kid, $op, 6); |
|
1661
|
24
|
|
|
|
|
61
|
push @args_spec, [1, $#nodes, ', ']; |
|
1662
|
|
|
|
|
|
|
|
|
1663
|
24
|
|
|
|
|
32
|
my $suffix = ''; |
|
1664
|
24
|
50
|
|
|
|
71
|
if ($self->func_needs_parens($nodes[0]->{text}, $cx, 5)) { |
|
1665
|
24
|
|
|
|
|
43
|
$fmt = "$name($first_arg_fmt"; |
|
1666
|
24
|
|
|
|
|
31
|
$suffix = ')'; |
|
1667
|
|
|
|
|
|
|
} else { |
|
1668
|
0
|
|
|
|
|
0
|
$fmt = "$name $first_arg_fmt"; |
|
1669
|
|
|
|
|
|
|
} |
|
1670
|
24
|
100
|
|
|
|
52
|
if (@nodes > 1) { |
|
1671
|
16
|
50
|
|
|
|
23
|
if ($is_block) { |
|
1672
|
0
|
|
|
|
|
0
|
$fmt .= " "; |
|
1673
|
|
|
|
|
|
|
} else { |
|
1674
|
16
|
|
|
|
|
20
|
$fmt .= ", "; |
|
1675
|
|
|
|
|
|
|
} |
|
1676
|
16
|
|
|
|
|
22
|
$fmt .= "%C"; |
|
1677
|
|
|
|
|
|
|
} |
|
1678
|
24
|
|
|
|
|
41
|
$fmt .= $suffix; |
|
1679
|
24
|
|
|
|
|
102
|
my $node = $self->info_from_template($type, $op, $fmt, |
|
1680
|
|
|
|
|
|
|
\@args_spec, \@nodes, |
|
1681
|
|
|
|
|
|
|
{other_ops => \@skipped_ops}); |
|
1682
|
24
|
|
|
|
|
50
|
$code_block_node->{parent} = $node->{addr}; |
|
1683
|
|
|
|
|
|
|
|
|
1684
|
|
|
|
|
|
|
# Handle skipped ops |
|
1685
|
24
|
|
|
|
|
28
|
my @new_ops; |
|
1686
|
24
|
|
|
|
|
33
|
my $str = $node->{text}; |
|
1687
|
24
|
|
|
|
|
29
|
my $position; |
|
1688
|
24
|
50
|
|
|
|
35
|
if ($is_block) { |
|
1689
|
|
|
|
|
|
|
# Make the position be the position of the "{". |
|
1690
|
0
|
|
|
|
|
0
|
$position = [length($name)+1, 1]; |
|
1691
|
|
|
|
|
|
|
} else { |
|
1692
|
|
|
|
|
|
|
# Make the position be the name portion |
|
1693
|
24
|
|
|
|
|
50
|
$position = [0, length($name)]; |
|
1694
|
|
|
|
|
|
|
} |
|
1695
|
24
|
|
|
|
|
27
|
my @skipped_nodes; |
|
1696
|
24
|
|
|
|
|
38
|
for my $skipped_op (@skipped_ops) { |
|
1697
|
72
|
|
|
|
|
305
|
my $new_op = $self->info_from_string($op->name, $skipped_op, $str, |
|
1698
|
|
|
|
|
|
|
{position => $position}); |
|
1699
|
72
|
|
|
|
|
143
|
push @new_ops, $new_op; |
|
1700
|
|
|
|
|
|
|
} |
|
1701
|
24
|
|
|
|
|
40
|
$node->{other_ops} = \@new_ops; |
|
1702
|
24
|
|
|
|
|
76
|
return $node; |
|
1703
|
|
|
|
|
|
|
} |
|
1704
|
|
|
|
|
|
|
|
|
1705
|
|
|
|
|
|
|
|
|
1706
|
|
|
|
|
|
|
# osmic acid -- see osmium tetroxide |
|
1707
|
|
|
|
|
|
|
|
|
1708
|
|
|
|
|
|
|
my %matchwords; |
|
1709
|
|
|
|
|
|
|
map($matchwords{join "", sort split //, $_} = $_, 'cig', 'cog', 'cos', 'cogs', |
|
1710
|
|
|
|
|
|
|
'cox', 'go', 'is', 'ism', 'iso', 'mig', 'mix', 'osmic', 'ox', 'sic', |
|
1711
|
|
|
|
|
|
|
'sig', 'six', 'smog', 'so', 'soc', 'sog', 'xi'); |
|
1712
|
|
|
|
|
|
|
|
|
1713
|
|
|
|
|
|
|
sub matchop |
|
1714
|
|
|
|
|
|
|
{ |
|
1715
|
6
|
50
|
|
6
|
0
|
39
|
$] < 5.022 ? matchop_older(@_) : matchop_newer(@_); |
|
1716
|
|
|
|
|
|
|
} |
|
1717
|
|
|
|
|
|
|
|
|
1718
|
|
|
|
|
|
|
# matchop for Perl 5.22 and later |
|
1719
|
|
|
|
|
|
|
sub matchop_newer |
|
1720
|
|
|
|
|
|
|
{ |
|
1721
|
6
|
|
|
6
|
0
|
16
|
my($self, $op, $cx, $name, $delim) = @_; |
|
1722
|
6
|
|
|
|
|
29
|
my $kid = $op->first; |
|
1723
|
6
|
|
|
|
|
13
|
my $info = {}; |
|
1724
|
6
|
|
|
|
|
11
|
my @body = (); |
|
1725
|
6
|
|
|
|
|
47
|
my ($binop, $var_str, $re_str) = ("", "", ""); |
|
1726
|
6
|
|
|
|
|
13
|
my $var_node; |
|
1727
|
|
|
|
|
|
|
my $re; |
|
1728
|
6
|
100
|
33
|
|
|
44
|
if ($op->flags & B::OPf_STACKED) { |
|
|
|
50
|
|
|
|
|
|
|
1729
|
4
|
|
|
|
|
5
|
$binop = 1; |
|
1730
|
4
|
|
|
|
|
10
|
$var_node = $self->deparse($kid, 20, $op); |
|
1731
|
4
|
|
|
|
|
8
|
$var_str = $var_node->{text}; |
|
1732
|
4
|
|
|
|
|
35
|
push @body, $var_node; |
|
1733
|
4
|
|
|
|
|
23
|
$kid = $kid->sibling; |
|
1734
|
|
|
|
|
|
|
} |
|
1735
|
|
|
|
|
|
|
# not $name; $name will be 'm' for both match and split |
|
1736
|
|
|
|
|
|
|
elsif ($op->name eq 'match' and my $targ = $op->targ) { |
|
1737
|
0
|
|
|
|
|
0
|
$binop = 1; |
|
1738
|
0
|
|
|
|
|
0
|
$var_str = $self->padname($targ); |
|
1739
|
|
|
|
|
|
|
} |
|
1740
|
6
|
|
|
|
|
14
|
my $quote = 1; |
|
1741
|
6
|
|
|
|
|
18
|
my $pmflags = $op->pmflags; |
|
1742
|
6
|
|
|
|
|
8
|
my $rhs_bound_to_defsv; |
|
1743
|
6
|
|
|
|
|
11
|
my ($cv, $bregexp); |
|
1744
|
6
|
|
|
|
|
49
|
my $have_kid = !B::Deparse::null $kid; |
|
1745
|
|
|
|
|
|
|
# Check for code blocks first |
|
1746
|
6
|
50
|
66
|
|
|
48
|
if (not B::Deparse::null my $code_list = $op->code_list) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
1747
|
0
|
0
|
|
|
|
0
|
$re = $self->code_list($code_list, |
|
1748
|
|
|
|
|
|
|
$op->name eq 'qr' |
|
1749
|
|
|
|
|
|
|
? $self->padval( |
|
1750
|
|
|
|
|
|
|
$kid->first # ex-list |
|
1751
|
|
|
|
|
|
|
->first # pushmark |
|
1752
|
|
|
|
|
|
|
->sibling # entersub |
|
1753
|
|
|
|
|
|
|
->first # ex-list |
|
1754
|
|
|
|
|
|
|
->first # pushmark |
|
1755
|
|
|
|
|
|
|
->sibling # srefgen |
|
1756
|
|
|
|
|
|
|
->first # ex-list |
|
1757
|
|
|
|
|
|
|
->first # anoncode |
|
1758
|
|
|
|
|
|
|
->targ |
|
1759
|
|
|
|
|
|
|
) |
|
1760
|
|
|
|
|
|
|
: undef); |
|
1761
|
6
|
|
|
|
|
96
|
} elsif (${$bregexp = $op->pmregexp} && ${$cv = $bregexp->qr_anoncv}) { |
|
|
1
|
|
|
|
|
5
|
|
|
1762
|
0
|
|
|
|
|
0
|
my $patop = $cv->ROOT # leavesub |
|
1763
|
|
|
|
|
|
|
->first # qr |
|
1764
|
|
|
|
|
|
|
->code_list;# list |
|
1765
|
0
|
|
|
|
|
0
|
$re = $self->code_list($patop, $cv); |
|
1766
|
|
|
|
|
|
|
} elsif (!$have_kid) { |
|
1767
|
1
|
|
|
|
|
95
|
$re_str = B::Deparse::re_uninterp(B::Deparse::escape_str(B::Deparse::re_unback($op->precomp))); |
|
1768
|
|
|
|
|
|
|
} elsif ($kid->name ne 'regcomp') { |
|
1769
|
0
|
0
|
|
|
|
0
|
if ($op->name eq 'split') { |
|
1770
|
|
|
|
|
|
|
# split has other kids, not just regcomp |
|
1771
|
0
|
|
|
|
|
0
|
$re = re_uninterp(B::Deparse::escape_re(re_unback($op->precomp))); |
|
1772
|
|
|
|
|
|
|
} else { |
|
1773
|
0
|
|
|
|
|
0
|
carp("found ".$kid->name." where regcomp expected"); |
|
1774
|
|
|
|
|
|
|
} |
|
1775
|
|
|
|
|
|
|
} else { |
|
1776
|
5
|
|
|
|
|
28
|
($re, $quote) = $self->regcomp($kid, 21); |
|
1777
|
5
|
|
|
|
|
11
|
push @body, $re; |
|
1778
|
5
|
|
|
|
|
10
|
$re_str = $re->{text}; |
|
1779
|
5
|
|
|
|
|
28
|
my $matchop = $kid->first; |
|
1780
|
5
|
50
|
|
|
|
20
|
if ($matchop->name eq 'regcrest') { |
|
1781
|
0
|
|
|
|
|
0
|
$matchop = $matchop->first; |
|
1782
|
|
|
|
|
|
|
} |
|
1783
|
5
|
100
|
66
|
|
|
57
|
if ($matchop->name =~ /^(?:match|transr?|subst)\z/ |
|
1784
|
|
|
|
|
|
|
&& $matchop->flags & B::OPf_SPECIAL) { |
|
1785
|
4
|
|
|
|
|
7
|
$rhs_bound_to_defsv = 1; |
|
1786
|
|
|
|
|
|
|
} |
|
1787
|
|
|
|
|
|
|
} |
|
1788
|
6
|
|
|
|
|
15
|
my $flags = ''; |
|
1789
|
6
|
50
|
|
|
|
14
|
$flags .= "c" if $pmflags & B::PMf_CONTINUE; |
|
1790
|
6
|
|
|
|
|
114
|
$flags .= $self->re_flags($op); |
|
1791
|
6
|
|
|
|
|
22
|
$flags = join '', sort split //, $flags; |
|
1792
|
6
|
50
|
|
|
|
15
|
$flags = $matchwords{$flags} if $matchwords{$flags}; |
|
1793
|
|
|
|
|
|
|
|
|
1794
|
6
|
50
|
|
|
|
17
|
if ($pmflags & B::PMf_ONCE) { |
|
|
|
100
|
|
|
|
|
|
|
1795
|
|
|
|
|
|
|
# only one kind of delimiter works here |
|
1796
|
0
|
|
|
|
|
0
|
$re_str =~ s/\?/\\?/g; |
|
1797
|
|
|
|
|
|
|
# explicit 'm' is required |
|
1798
|
0
|
|
|
|
|
0
|
$re_str = $self->keyword("m") . "?$re_str?"; |
|
1799
|
|
|
|
|
|
|
} elsif ($quote) { |
|
1800
|
2
|
|
|
|
|
11
|
my $re = $self->single_delim($kid, $name, $delim, $re_str); |
|
1801
|
2
|
|
|
|
|
5
|
push @body, $re; |
|
1802
|
2
|
|
|
|
|
6
|
$re_str = $re->{text}; |
|
1803
|
|
|
|
|
|
|
} |
|
1804
|
6
|
|
|
|
|
10
|
my $opts = {}; |
|
1805
|
6
|
|
|
|
|
35
|
my @texts; |
|
1806
|
6
|
100
|
|
|
|
15
|
$re_str .= $flags if $quote; |
|
1807
|
6
|
|
|
|
|
9
|
my $type; |
|
1808
|
6
|
100
|
|
|
|
13
|
if ($binop) { |
|
1809
|
|
|
|
|
|
|
# FIXME: use template string |
|
1810
|
4
|
50
|
|
|
|
6
|
if ($rhs_bound_to_defsv) { |
|
1811
|
4
|
|
|
|
|
11
|
@texts = ($var_str, ' =~ ($_ =~ ', $re_str, ')'); |
|
1812
|
|
|
|
|
|
|
} else { |
|
1813
|
0
|
|
|
|
|
0
|
@texts = ($var_str, ' =~ ', $re_str); |
|
1814
|
|
|
|
|
|
|
} |
|
1815
|
4
|
|
|
|
|
10
|
$opts->{maybe_parens} = [$self, $cx, 20]; |
|
1816
|
4
|
|
|
|
|
6
|
$type = 'binary match ~='; |
|
1817
|
|
|
|
|
|
|
} else { |
|
1818
|
2
|
|
|
|
|
6
|
@texts = ($re_str); |
|
1819
|
2
|
|
|
|
|
4
|
$type = 'unary ($_) match'; |
|
1820
|
|
|
|
|
|
|
} |
|
1821
|
6
|
|
|
|
|
18
|
return info_from_list($op, $self, \@texts, '', $type, $opts); |
|
1822
|
|
|
|
|
|
|
} |
|
1823
|
|
|
|
|
|
|
|
|
1824
|
|
|
|
|
|
|
# matchop for Perl before 5.22 |
|
1825
|
|
|
|
|
|
|
sub matchop_older |
|
1826
|
|
|
|
|
|
|
{ |
|
1827
|
0
|
|
|
0
|
0
|
0
|
my($self, $op, $cx, $name, $delim) = @_; |
|
1828
|
0
|
|
|
|
|
0
|
my $kid = $op->first; |
|
1829
|
0
|
|
|
|
|
0
|
my $info = {}; |
|
1830
|
0
|
|
|
|
|
0
|
my @body = (); |
|
1831
|
0
|
|
|
|
|
0
|
my ($binop, $var, $re_str) = ("", "", ""); |
|
1832
|
0
|
|
|
|
|
0
|
my $re; |
|
1833
|
0
|
0
|
|
|
|
0
|
if ($op->flags & B::OPf_STACKED) { |
|
1834
|
0
|
|
|
|
|
0
|
$binop = 1; |
|
1835
|
0
|
|
|
|
|
0
|
$var = $self->deparse($kid, 20, $op); |
|
1836
|
0
|
|
|
|
|
0
|
push @body, $var; |
|
1837
|
0
|
|
|
|
|
0
|
$kid = $kid->sibling; |
|
1838
|
|
|
|
|
|
|
} |
|
1839
|
0
|
|
|
|
|
0
|
my $quote = 1; |
|
1840
|
0
|
|
|
|
|
0
|
my $pmflags = $op->pmflags; |
|
1841
|
0
|
|
|
|
|
0
|
my $extended = ($pmflags & B::PMf_EXTENDED); |
|
1842
|
0
|
|
|
|
|
0
|
my $rhs_bound_to_defsv; |
|
1843
|
0
|
0
|
|
|
|
0
|
if (B::Deparse::null $kid) { |
|
|
|
0
|
|
|
|
|
|
|
1844
|
0
|
|
|
|
|
0
|
my $unbacked = B::Deparse::re_unback($op->precomp); |
|
1845
|
0
|
0
|
|
|
|
0
|
if ($extended) { |
|
1846
|
0
|
|
|
|
|
0
|
$re_str = B::Deparse::re_uninterp_extended(B::Deparse::escape_extended_re($unbacked)); |
|
1847
|
|
|
|
|
|
|
} else { |
|
1848
|
0
|
|
|
|
|
0
|
$re_str = B::Deparse::re_uninterp(B::Deparse::escape_str(B::Deparse::re_unback($op->precomp))); |
|
1849
|
|
|
|
|
|
|
} |
|
1850
|
|
|
|
|
|
|
} elsif ($kid->name ne 'regcomp') { |
|
1851
|
0
|
|
|
|
|
0
|
carp("found ".$kid->name." where regcomp expected"); |
|
1852
|
|
|
|
|
|
|
} else { |
|
1853
|
0
|
|
|
|
|
0
|
($re, $quote) = $self->regcomp($kid, 21, $extended); |
|
1854
|
0
|
|
|
|
|
0
|
push @body, $re; |
|
1855
|
0
|
|
|
|
|
0
|
$re_str = $re->{text}; |
|
1856
|
0
|
|
|
|
|
0
|
my $matchop = $kid->first; |
|
1857
|
0
|
0
|
|
|
|
0
|
if ($matchop->name eq 'regcrest') { |
|
1858
|
0
|
|
|
|
|
0
|
$matchop = $matchop->first; |
|
1859
|
|
|
|
|
|
|
} |
|
1860
|
0
|
0
|
0
|
|
|
0
|
if ($matchop->name =~ /^(?:match|transr?|subst)\z/ |
|
1861
|
|
|
|
|
|
|
&& $matchop->flags & B::OPf_SPECIAL) { |
|
1862
|
0
|
|
|
|
|
0
|
$rhs_bound_to_defsv = 1; |
|
1863
|
|
|
|
|
|
|
} |
|
1864
|
|
|
|
|
|
|
} |
|
1865
|
0
|
|
|
|
|
0
|
my $flags = ''; |
|
1866
|
0
|
0
|
|
|
|
0
|
$flags .= "c" if $pmflags & B::PMf_CONTINUE; |
|
1867
|
0
|
|
|
|
|
0
|
$flags .= $self->re_flags($op); |
|
1868
|
0
|
|
|
|
|
0
|
$flags = join '', sort split //, $flags; |
|
1869
|
0
|
0
|
|
|
|
0
|
$flags = $matchwords{$flags} if $matchwords{$flags}; |
|
1870
|
|
|
|
|
|
|
|
|
1871
|
0
|
0
|
|
|
|
0
|
if ($pmflags & B::PMf_ONCE) { # only one kind of delimiter works here |
|
|
|
0
|
|
|
|
|
|
|
1872
|
0
|
|
|
|
|
0
|
$re_str =~ s/\?/\\?/g; |
|
1873
|
0
|
|
|
|
|
0
|
$re_str = "?$re_str?"; |
|
1874
|
|
|
|
|
|
|
} elsif ($quote) { |
|
1875
|
0
|
|
|
|
|
0
|
my $re = $self->single_delim($kid, $name, $delim, $re_str); |
|
1876
|
0
|
|
|
|
|
0
|
push @body, $re; |
|
1877
|
0
|
|
|
|
|
0
|
$re_str = $re->{text}; |
|
1878
|
|
|
|
|
|
|
} |
|
1879
|
0
|
|
|
|
|
0
|
my $opts = {body => \@body}; |
|
1880
|
0
|
|
|
|
|
0
|
my @texts; |
|
1881
|
0
|
0
|
|
|
|
0
|
$re_str .= $flags if $quote; |
|
1882
|
0
|
|
|
|
|
0
|
my $type; |
|
1883
|
0
|
0
|
|
|
|
0
|
if ($binop) { |
|
1884
|
0
|
0
|
|
|
|
0
|
if ($rhs_bound_to_defsv) { |
|
1885
|
0
|
|
|
|
|
0
|
@texts = ($var->{text}, ' =~ ', "(", '$_', ' =~ ', $re_str, ')'); |
|
1886
|
|
|
|
|
|
|
} else { |
|
1887
|
0
|
|
|
|
|
0
|
@texts = ($var->{text}, ' =~ ', $re_str); |
|
1888
|
|
|
|
|
|
|
} |
|
1889
|
0
|
|
|
|
|
0
|
$opts->{maybe_parens} = [$self, $cx, 20]; |
|
1890
|
0
|
|
|
|
|
0
|
$type = 'matchop_binop'; |
|
1891
|
|
|
|
|
|
|
} else { |
|
1892
|
0
|
|
|
|
|
0
|
@texts = ($re_str); |
|
1893
|
0
|
|
|
|
|
0
|
$type = 'matchop_unnop'; |
|
1894
|
|
|
|
|
|
|
} |
|
1895
|
0
|
|
|
|
|
0
|
return info_from_list($op, $self, \@texts, '', $type, $opts); |
|
1896
|
|
|
|
|
|
|
} |
|
1897
|
|
|
|
|
|
|
|
|
1898
|
|
|
|
|
|
|
# FIXME: remove this |
|
1899
|
|
|
|
|
|
|
sub map_texts($$) |
|
1900
|
|
|
|
|
|
|
{ |
|
1901
|
0
|
|
|
0
|
0
|
0
|
my ($self, $args) = @_; |
|
1902
|
0
|
|
|
|
|
0
|
my @result ; |
|
1903
|
0
|
|
|
|
|
0
|
foreach my $expr (@$args) { |
|
1904
|
0
|
0
|
0
|
|
|
0
|
if (ref $expr eq 'ARRAY' and scalar(@$expr) == 2) { |
|
1905
|
|
|
|
|
|
|
# First item is hash and second item is op address. |
|
1906
|
0
|
|
|
|
|
0
|
push @result, [$expr->[0]{text}, $expr->[1]]; |
|
1907
|
|
|
|
|
|
|
} else { |
|
1908
|
0
|
|
|
|
|
0
|
push @result, [$expr->{text}, $expr->{addr}]; |
|
1909
|
|
|
|
|
|
|
} |
|
1910
|
|
|
|
|
|
|
} |
|
1911
|
0
|
|
|
|
|
0
|
return @result; |
|
1912
|
|
|
|
|
|
|
} |
|
1913
|
|
|
|
|
|
|
|
|
1914
|
|
|
|
|
|
|
# FIXME: This is weird. Regularize var_info |
|
1915
|
|
|
|
|
|
|
sub maybe_local { |
|
1916
|
19
|
|
|
19
|
0
|
45
|
my($self, $op, $cx, $var_info) = @_; |
|
1917
|
19
|
|
|
|
|
39
|
$var_info->{parent} = $$op; |
|
1918
|
19
|
|
|
|
|
41
|
return maybe_local_str($self, $op, $cx, $var_info); |
|
1919
|
|
|
|
|
|
|
} |
|
1920
|
|
|
|
|
|
|
|
|
1921
|
|
|
|
|
|
|
# Handles "our", "local", "my" variables (and possibly no |
|
1922
|
|
|
|
|
|
|
# declaration of these) in scalar and array contexts. |
|
1923
|
|
|
|
|
|
|
# The complications include stripping a package name on |
|
1924
|
|
|
|
|
|
|
# "our" variables, and not including parenthesis when |
|
1925
|
|
|
|
|
|
|
# not needed, unless there's a setting to always include |
|
1926
|
|
|
|
|
|
|
# parenthesis. |
|
1927
|
|
|
|
|
|
|
|
|
1928
|
|
|
|
|
|
|
sub maybe_local_str |
|
1929
|
|
|
|
|
|
|
{ |
|
1930
|
1447
|
|
|
1447
|
0
|
3244
|
my($self, $op, $cx, $info) = @_; |
|
1931
|
1447
|
|
|
|
|
2140
|
my ($text, $is_node); |
|
1932
|
1447
|
100
|
66
|
|
|
3948
|
if (ref $info && $info->isa("B::DeparseTree::TreeNode")) { |
|
1933
|
94
|
|
|
|
|
266
|
$text = $self->info2str($info); |
|
1934
|
94
|
|
|
|
|
179
|
$is_node = 1; |
|
1935
|
|
|
|
|
|
|
} else { |
|
1936
|
1353
|
|
|
|
|
1814
|
$text = $info; |
|
1937
|
1353
|
|
|
|
|
1875
|
$is_node = 0; |
|
1938
|
|
|
|
|
|
|
} |
|
1939
|
|
|
|
|
|
|
|
|
1940
|
1447
|
100
|
|
|
|
8938
|
my $our_intro = ($op->name =~ /^(gv|rv2)[ash]v$/) ? OPpOUR_INTRO : 0; |
|
1941
|
1447
|
|
|
|
|
2546
|
my ($fmt, $type); |
|
1942
|
1447
|
100
|
100
|
|
|
6077
|
if ($op->private & (OPpLVAL_INTRO|$our_intro) |
|
1943
|
|
|
|
|
|
|
and not $self->{'avoid_local'}{$$op}) { |
|
1944
|
7
|
100
|
|
|
|
42
|
my $our_local = ($op->private & OPpLVAL_INTRO) ? "local" : "our"; |
|
1945
|
7
|
100
|
|
|
|
33
|
if( $our_local eq 'our' ) { |
|
1946
|
|
|
|
|
|
|
# "our" variables needs to strip off package the prefix |
|
1947
|
|
|
|
|
|
|
|
|
1948
|
4
|
0
|
0
|
|
|
46
|
if ( $text !~ /^\W(\w+::)*\w+\z/ |
|
|
|
|
33
|
|
|
|
|
|
1949
|
|
|
|
|
|
|
and !utf8::decode($text) || $text !~ /^\W(\w+::)*\w+\z/ |
|
1950
|
|
|
|
|
|
|
) { |
|
1951
|
0
|
|
|
|
|
0
|
Carp::confess("Unexpected our text $text"); |
|
1952
|
|
|
|
|
|
|
} |
|
1953
|
|
|
|
|
|
|
|
|
1954
|
4
|
50
|
|
|
|
19
|
if ($] >= 5.024) { |
|
1955
|
4
|
50
|
|
|
|
68
|
if ($type = $self->B::Deparse::find_our_type($text)) { |
|
1956
|
0
|
|
|
|
|
0
|
$our_local .= ' ' . $type; |
|
1957
|
|
|
|
|
|
|
} |
|
1958
|
|
|
|
|
|
|
} |
|
1959
|
|
|
|
|
|
|
|
|
1960
|
4
|
50
|
66
|
|
|
55
|
if (!B::Deparse::want_scalar($op) |
|
1961
|
|
|
|
|
|
|
&& $self->func_needs_parens($text, $cx, 16)) { |
|
1962
|
0
|
|
|
|
|
0
|
$type = "$our_local ()"; |
|
1963
|
0
|
|
|
|
|
0
|
$fmt = "$our_local(%F)"; |
|
1964
|
|
|
|
|
|
|
} else { |
|
1965
|
4
|
|
|
|
|
9
|
$type = "$our_local"; |
|
1966
|
4
|
|
|
|
|
14
|
$fmt = "$our_local %F"; |
|
1967
|
|
|
|
|
|
|
} |
|
1968
|
|
|
|
|
|
|
my $transform_fn = sub { |
|
1969
|
30
|
100
|
|
30
|
|
55
|
my $text = $is_node ? $_[0]->{text} : $_[0]; |
|
1970
|
|
|
|
|
|
|
# Strip possible package prefix |
|
1971
|
30
|
|
|
|
|
157
|
$text =~ s/(\w+::)+//; |
|
1972
|
30
|
|
|
|
|
94
|
return $text; |
|
1973
|
4
|
|
|
|
|
30
|
}; |
|
1974
|
|
|
|
|
|
|
# $info could be either a string or a node, %c covers both. |
|
1975
|
4
|
|
|
|
|
31
|
return $self->info_from_template($type, $op, $fmt, |
|
1976
|
|
|
|
|
|
|
[[0, $transform_fn]], [$info]); |
|
1977
|
|
|
|
|
|
|
} |
|
1978
|
|
|
|
|
|
|
|
|
1979
|
|
|
|
|
|
|
# Not an "our" declaration. |
|
1980
|
3
|
50
|
|
|
|
16
|
if (B::Deparse::want_scalar($op)) { |
|
1981
|
|
|
|
|
|
|
# $info could be either a string or a node, %c covers both |
|
1982
|
3
|
|
|
|
|
12
|
return $self->info_from_template("scalar $our_local", $op, "$our_local %c", undef, [$info]); |
|
1983
|
|
|
|
|
|
|
} else { |
|
1984
|
0
|
0
|
0
|
|
|
0
|
if (!B::Deparse::want_scalar($op) |
|
1985
|
|
|
|
|
|
|
&& $self->func_needs_parens($text, $cx, 16)) { |
|
1986
|
0
|
|
|
|
|
0
|
$fmt = "$our_local(%F)"; |
|
1987
|
0
|
|
|
|
|
0
|
$type = "$our_local()"; |
|
1988
|
|
|
|
|
|
|
} else { |
|
1989
|
0
|
|
|
|
|
0
|
$fmt = "$our_local %F"; |
|
1990
|
0
|
|
|
|
|
0
|
$type = "$our_local"; |
|
1991
|
|
|
|
|
|
|
} |
|
1992
|
0
|
|
|
|
|
0
|
return $self->info_from_template($type, $op, $fmt, undef, [$info]); |
|
1993
|
|
|
|
|
|
|
} |
|
1994
|
|
|
|
|
|
|
} else { |
|
1995
|
1440
|
100
|
66
|
|
|
3834
|
if (ref $info && $info->isa("B::DeparseTree::TreeNode")) { |
|
1996
|
88
|
|
|
|
|
381
|
return $info; |
|
1997
|
|
|
|
|
|
|
} else { |
|
1998
|
1352
|
|
|
|
|
3801
|
return $self->info_from_string('not local', $op, $text); |
|
1999
|
|
|
|
|
|
|
} |
|
2000
|
|
|
|
|
|
|
} |
|
2001
|
|
|
|
|
|
|
} |
|
2002
|
|
|
|
|
|
|
|
|
2003
|
|
|
|
|
|
|
sub maybe_my |
|
2004
|
|
|
|
|
|
|
{ |
|
2005
|
4400
|
50
|
|
4400
|
0
|
13311
|
$] >= 5.026 ? goto &maybe_my_newer : goto &maybe_my_older; |
|
2006
|
|
|
|
|
|
|
} |
|
2007
|
|
|
|
|
|
|
|
|
2008
|
|
|
|
|
|
|
sub maybe_my_newer |
|
2009
|
|
|
|
|
|
|
{ |
|
2010
|
4400
|
|
|
4400
|
0
|
6258
|
my $self = shift; |
|
2011
|
4400
|
|
|
|
|
7958
|
my($op, $cx, $text, $padname, $forbid_parens) = @_; |
|
2012
|
|
|
|
|
|
|
# The @a in \(@a) isn't in ref context, but only when the |
|
2013
|
|
|
|
|
|
|
# parens are there. |
|
2014
|
4400
|
|
33
|
|
|
16185
|
my $need_parens = !$forbid_parens && $self->{'in_refgen'} |
|
2015
|
|
|
|
|
|
|
&& $op->name =~ /[ah]v\z/ |
|
2016
|
|
|
|
|
|
|
&& ($op->flags & (B::OPf_PARENS|B::OPf_REF)) == B::OPf_PARENS; |
|
2017
|
|
|
|
|
|
|
# The @a in \my @a must not have parens. |
|
2018
|
4400
|
50
|
33
|
|
|
11615
|
if (!$need_parens && $self->{'in_refgen'}) { |
|
2019
|
0
|
|
|
|
|
0
|
$forbid_parens = 1; |
|
2020
|
|
|
|
|
|
|
} |
|
2021
|
4400
|
100
|
100
|
|
|
19925
|
if ($op->private & B::OPpLVAL_INTRO and not $self->{'avoid_local'}{$$op}) { |
|
2022
|
|
|
|
|
|
|
# Check $padname->FLAGS for statehood, rather than $op->private, |
|
2023
|
|
|
|
|
|
|
# because enteriter ops do not carry the flag. |
|
2024
|
29
|
50
|
|
|
|
73
|
unless (defined($padname)) { |
|
2025
|
0
|
|
|
|
|
0
|
Carp::confess("undefine padname $padname"); |
|
2026
|
|
|
|
|
|
|
} |
|
2027
|
|
|
|
|
|
|
|
|
2028
|
29
|
100
|
|
|
|
11684
|
my $my = |
|
2029
|
|
|
|
|
|
|
$self->keyword($padname->FLAGS & SVpad_STATE ? "state" : "my"); |
|
2030
|
29
|
50
|
|
|
|
146
|
if ($padname->FLAGS & SVpad_TYPED) { |
|
2031
|
0
|
|
|
|
|
0
|
$my .= ' ' . $padname->SvSTASH->NAME; |
|
2032
|
|
|
|
|
|
|
} |
|
2033
|
29
|
50
|
100
|
|
|
292
|
if ($need_parens) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
2034
|
0
|
|
|
|
|
0
|
return $self->info_from_string("$my()", $op, "$my($text)"); |
|
2035
|
|
|
|
|
|
|
} elsif ($forbid_parens || B::Deparse::want_scalar($op)) { |
|
2036
|
21
|
|
|
|
|
117
|
return $self->info_from_string("$my", $op, "$my $text"); |
|
2037
|
|
|
|
|
|
|
} elsif ($self->func_needs_parens($text, $cx, 16)) { |
|
2038
|
0
|
|
|
|
|
0
|
return $self->info_from_string("$my()", $op, "$my($text)"); |
|
2039
|
|
|
|
|
|
|
} else { |
|
2040
|
8
|
|
|
|
|
62
|
return $self->info_from_string("$my", $op, "$my $text"); |
|
2041
|
|
|
|
|
|
|
} |
|
2042
|
|
|
|
|
|
|
} else { |
|
2043
|
4371
|
50
|
|
|
|
12821
|
return $self->info_from_string("not my", $op, $need_parens ? "($text)" : $text); |
|
2044
|
|
|
|
|
|
|
} |
|
2045
|
|
|
|
|
|
|
} |
|
2046
|
|
|
|
|
|
|
|
|
2047
|
|
|
|
|
|
|
sub maybe_my_older |
|
2048
|
|
|
|
|
|
|
{ |
|
2049
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
|
2050
|
0
|
|
|
|
|
0
|
my($op, $cx, $text, $forbid_parens) = @_; |
|
2051
|
0
|
0
|
0
|
|
|
0
|
if ($op->private & OPpLVAL_INTRO and not $self->{'avoid_local'}{$$op}) { |
|
2052
|
0
|
0
|
|
|
|
0
|
my $my_str = $op->private & OPpPAD_STATE |
|
2053
|
|
|
|
|
|
|
? $self->keyword("state") |
|
2054
|
|
|
|
|
|
|
: "my"; |
|
2055
|
0
|
0
|
0
|
|
|
0
|
if ($forbid_parens || B::Deparse::want_scalar($op)) { |
|
2056
|
0
|
|
|
|
|
0
|
return $self->info_from_string('my', $op, "$my_str $text"); |
|
2057
|
|
|
|
|
|
|
} else { |
|
2058
|
0
|
|
|
|
|
0
|
return $self->info_from_string('my (maybe with parens)', $op, |
|
2059
|
|
|
|
|
|
|
"$my_str $text", |
|
2060
|
|
|
|
|
|
|
{maybe_parens => [$self, $cx, 16]}); |
|
2061
|
|
|
|
|
|
|
} |
|
2062
|
|
|
|
|
|
|
} else { |
|
2063
|
0
|
|
|
|
|
0
|
return $self->info_from_string('not my', $op, $text); |
|
2064
|
|
|
|
|
|
|
} |
|
2065
|
|
|
|
|
|
|
} |
|
2066
|
|
|
|
|
|
|
|
|
2067
|
|
|
|
|
|
|
# Possibly add () around $text depending on precedence $prec and |
|
2068
|
|
|
|
|
|
|
# context $cx. We return a string. |
|
2069
|
|
|
|
|
|
|
sub maybe_parens($$$$) |
|
2070
|
|
|
|
|
|
|
{ |
|
2071
|
2
|
|
|
2
|
0
|
8
|
my($self, $text, $cx, $prec) = @_; |
|
2072
|
2
|
100
|
|
|
|
10
|
if (B::DeparseTree::TreeNode::parens_test($self, $cx, $prec)) { |
|
2073
|
1
|
|
|
|
|
8
|
$text = "($text)"; |
|
2074
|
|
|
|
|
|
|
# In a unop, let parent reuse our parens; see maybe_parens_unop |
|
2075
|
|
|
|
|
|
|
# FIXME: |
|
2076
|
1
|
50
|
|
|
|
6
|
$text = "\cS" . $text if $cx == 16; |
|
2077
|
1
|
|
|
|
|
5
|
return $text; |
|
2078
|
|
|
|
|
|
|
} else { |
|
2079
|
1
|
|
|
|
|
4
|
return $text; |
|
2080
|
|
|
|
|
|
|
} |
|
2081
|
|
|
|
|
|
|
} |
|
2082
|
|
|
|
|
|
|
|
|
2083
|
|
|
|
|
|
|
# FIXME: go back to default B::Deparse routine and return a string. |
|
2084
|
|
|
|
|
|
|
sub maybe_parens_func($$$$$) |
|
2085
|
|
|
|
|
|
|
{ |
|
2086
|
1
|
|
|
1
|
0
|
3
|
my($self, $func, $params, $cx, $prec) = @_; |
|
2087
|
1
|
50
|
33
|
|
|
11
|
if ($prec <= $cx or substr($params, 0, 1) eq "(" or $self->{'parens'}) { |
|
|
|
|
33
|
|
|
|
|
|
2088
|
0
|
|
|
|
|
0
|
return ($func, '(', $params, ')'); |
|
2089
|
|
|
|
|
|
|
} else { |
|
2090
|
1
|
|
|
|
|
3
|
return ($func, ' ', $params); |
|
2091
|
|
|
|
|
|
|
} |
|
2092
|
|
|
|
|
|
|
} |
|
2093
|
|
|
|
|
|
|
|
|
2094
|
|
|
|
|
|
|
# Sort of like maybe_parens in that we may possibly add (). However we take |
|
2095
|
|
|
|
|
|
|
# an op rather than text, and return a tree node. Also, we get around |
|
2096
|
|
|
|
|
|
|
# the 'if it looks like a function' rule. |
|
2097
|
|
|
|
|
|
|
sub maybe_parens_unop($$$$$) |
|
2098
|
|
|
|
|
|
|
{ |
|
2099
|
254
|
|
|
254
|
0
|
793
|
my ($self, $name, $op, $cx, $parent, $opts) = @_; |
|
2100
|
254
|
100
|
|
|
|
645
|
$opts = {} unless $opts; |
|
2101
|
254
|
|
|
|
|
764
|
my $info = $self->deparse($op, 1, $parent); |
|
2102
|
254
|
|
|
|
|
446
|
my $fmt; |
|
2103
|
254
|
|
|
|
|
597
|
my @exprs = ($info); |
|
2104
|
254
|
50
|
66
|
|
|
703
|
if ($name eq "umask" && $info->{text} =~ /^\d+$/) { |
|
2105
|
|
|
|
|
|
|
# Display umask numbers in octal. |
|
2106
|
|
|
|
|
|
|
# FIXME: add as a info_node option to run a transformation function |
|
2107
|
|
|
|
|
|
|
# such as the below |
|
2108
|
0
|
|
|
|
|
0
|
$info->{text} = sprintf("%#o", $info->{text}); |
|
2109
|
0
|
|
|
|
|
0
|
$exprs[0] = $info; |
|
2110
|
|
|
|
|
|
|
} |
|
2111
|
254
|
|
|
|
|
6024
|
$name = $self->keyword($name); |
|
2112
|
254
|
100
|
66
|
|
|
1352
|
if ($cx > 16 or $self->{'parens'}) { |
|
2113
|
3
|
|
|
|
|
17
|
my $node = $self->info_from_template( |
|
2114
|
|
|
|
|
|
|
"$name()", $parent, "$name(%c)",[0], \@exprs, $opts); |
|
2115
|
3
|
|
|
|
|
9
|
$node->{prev_expr} = $exprs[0]; |
|
2116
|
3
|
|
|
|
|
13
|
return $node; |
|
2117
|
|
|
|
|
|
|
} else { |
|
2118
|
|
|
|
|
|
|
# FIXME: we don't do \cS |
|
2119
|
|
|
|
|
|
|
# if (substr($text, 0, 1) eq "\cS") { |
|
2120
|
|
|
|
|
|
|
# # use op's parens |
|
2121
|
|
|
|
|
|
|
# return info_from_list($op, $self,[$name, substr($text, 1)], |
|
2122
|
|
|
|
|
|
|
# '', 'maybe_parens_unop_cS', {body => [$info]}); |
|
2123
|
|
|
|
|
|
|
# } else |
|
2124
|
251
|
|
|
|
|
388
|
my $node; |
|
2125
|
251
|
50
|
|
|
|
773
|
if (substr($info->{text}, 0, 1) eq "(") { |
|
2126
|
|
|
|
|
|
|
# avoid looks-like-a-function trap with extra parens |
|
2127
|
|
|
|
|
|
|
# ('+' can lead to ambiguities) |
|
2128
|
0
|
|
|
|
|
0
|
$node = $self->info_from_template( |
|
2129
|
|
|
|
|
|
|
"$name(()) dup remove", $parent, "$name(%c)", [0], \@exprs, $opts); |
|
2130
|
|
|
|
|
|
|
} else { |
|
2131
|
251
|
|
|
|
|
1646
|
$node = $self->info_from_template( |
|
2132
|
|
|
|
|
|
|
"$name ", $parent, "$name %c", [0], \@exprs, $opts); |
|
2133
|
|
|
|
|
|
|
} |
|
2134
|
251
|
|
|
|
|
621
|
$node->{prev_expr} = $exprs[0]; |
|
2135
|
251
|
|
|
|
|
1099
|
return $node; |
|
2136
|
|
|
|
|
|
|
} |
|
2137
|
0
|
|
|
|
|
0
|
Carp::confess("unhandled condition in maybe_parens_unop"); |
|
2138
|
|
|
|
|
|
|
} |
|
2139
|
|
|
|
|
|
|
|
|
2140
|
|
|
|
|
|
|
sub maybe_qualify { |
|
2141
|
1797
|
|
|
1797
|
0
|
4580
|
my ($self,$prefix,$name) = @_; |
|
2142
|
1797
|
100
|
|
|
|
4530
|
my $v = ($prefix eq '$#' ? '@' : $prefix) . $name; |
|
2143
|
1797
|
100
|
66
|
|
|
6799
|
return $name if !$prefix || $name =~ /::/; |
|
2144
|
|
|
|
|
|
|
return $self->{'curstash'}.'::'. $name |
|
2145
|
|
|
|
|
|
|
if |
|
2146
|
|
|
|
|
|
|
$name =~ /^(?!\d)\w/ # alphabetic |
|
2147
|
|
|
|
|
|
|
&& $v !~ /^\$[ab]\z/ # not $a or $b |
|
2148
|
|
|
|
|
|
|
&& !$globalnames{$name} # not a global name |
|
2149
|
|
|
|
|
|
|
&& $self->{hints} & $strict_bits{vars} # strict vars |
|
2150
|
1796
|
100
|
100
|
|
|
31485
|
&& !$self->B::Deparse::lex_in_scope($v,1) # no "our" |
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
2151
|
|
|
|
|
|
|
or $self->B::Deparse::lex_in_scope($v); # conflicts with "my" variable |
|
2152
|
1783
|
|
|
|
|
8101
|
return $name; |
|
2153
|
|
|
|
|
|
|
} |
|
2154
|
|
|
|
|
|
|
|
|
2155
|
|
|
|
|
|
|
# FIXME: need a way to pass in skipped_ops |
|
2156
|
|
|
|
|
|
|
sub maybe_targmy |
|
2157
|
|
|
|
|
|
|
{ |
|
2158
|
10
|
|
|
10
|
0
|
42
|
my($self, $op, $cx, $func, @args) = @_; |
|
2159
|
10
|
50
|
|
|
|
57
|
if ($op->private & OPpTARGET_MY) { |
|
2160
|
0
|
|
|
|
|
0
|
my $var = $self->padname($op->targ); |
|
2161
|
0
|
|
|
|
|
0
|
my $val = $func->($self, $op, 7, @args); |
|
2162
|
0
|
|
|
|
|
0
|
my @texts = ($var, '=', $val); |
|
2163
|
0
|
|
|
|
|
0
|
return $self->info_from_template("my", $op, |
|
2164
|
|
|
|
|
|
|
"%c = %c", [0, 1], |
|
2165
|
|
|
|
|
|
|
[$var, $val], |
|
2166
|
|
|
|
|
|
|
{maybe_parens => [$self, $cx, 7]}); |
|
2167
|
|
|
|
|
|
|
} else { |
|
2168
|
10
|
|
|
|
|
46
|
return $self->$func($op, $cx, @args); |
|
2169
|
|
|
|
|
|
|
} |
|
2170
|
|
|
|
|
|
|
} |
|
2171
|
|
|
|
|
|
|
|
|
2172
|
|
|
|
|
|
|
sub _method |
|
2173
|
|
|
|
|
|
|
{ |
|
2174
|
2
|
|
|
2
|
|
6
|
my($self, $op, $cx) = @_; |
|
2175
|
2
|
|
|
|
|
9
|
my @other_ops = ($op->first); |
|
2176
|
2
|
|
|
|
|
9
|
my $kid = $op->first->sibling; # skip pushmark |
|
2177
|
2
|
|
|
|
|
5
|
my($meth, $obj, @exprs); |
|
2178
|
2
|
50
|
33
|
|
|
11
|
if ($kid->name eq "list" and B::Deparse::want_list $kid) { |
|
2179
|
|
|
|
|
|
|
# When an indirect object isn't a bareword but the args are in |
|
2180
|
|
|
|
|
|
|
# parens, the parens aren't part of the method syntax (the LLAFR |
|
2181
|
|
|
|
|
|
|
# doesn't apply), but they make a list with OPf_PARENS set that |
|
2182
|
|
|
|
|
|
|
# doesn't get flattened by the append_elem that adds the method, |
|
2183
|
|
|
|
|
|
|
# making a (object, arg1, arg2, ...) list where the object |
|
2184
|
|
|
|
|
|
|
# usually is. This can be distinguished from |
|
2185
|
|
|
|
|
|
|
# '($obj, $arg1, $arg2)->meth()' (which is legal if $arg2 is an |
|
2186
|
|
|
|
|
|
|
# object) because in the later the list is in scalar context |
|
2187
|
|
|
|
|
|
|
# as the left side of -> always is, while in the former |
|
2188
|
|
|
|
|
|
|
# the list is in list context as method arguments always are. |
|
2189
|
|
|
|
|
|
|
# (Good thing there aren't method prototypes!) |
|
2190
|
0
|
|
|
|
|
0
|
$meth = $kid->sibling; |
|
2191
|
0
|
|
|
|
|
0
|
push @other_ops, $kid->first; |
|
2192
|
0
|
|
|
|
|
0
|
$kid = $kid->first->sibling; # skip pushmark |
|
2193
|
0
|
|
|
|
|
0
|
$obj = $kid; |
|
2194
|
0
|
|
|
|
|
0
|
$kid = $kid->sibling; |
|
2195
|
0
|
|
|
|
|
0
|
for (; not B::Deparse::null $kid; $kid = $kid->sibling) { |
|
2196
|
0
|
|
|
|
|
0
|
push @exprs, $kid; |
|
2197
|
|
|
|
|
|
|
} |
|
2198
|
|
|
|
|
|
|
} else { |
|
2199
|
2
|
|
|
|
|
5
|
$obj = $kid; |
|
2200
|
2
|
|
|
|
|
5
|
$kid = $kid->sibling; |
|
2201
|
2
|
|
66
|
|
|
51
|
for (; !B::Deparse::null ($kid->sibling) && $kid->name!~/^method(?:_named)?\z/; |
|
2202
|
|
|
|
|
|
|
$kid = $kid->sibling) { |
|
2203
|
1
|
|
|
|
|
17
|
push @exprs, $kid |
|
2204
|
|
|
|
|
|
|
} |
|
2205
|
2
|
|
|
|
|
4
|
$meth = $kid; |
|
2206
|
|
|
|
|
|
|
} |
|
2207
|
|
|
|
|
|
|
|
|
2208
|
2
|
|
|
|
|
3
|
my $method_name = undef; |
|
2209
|
2
|
|
|
|
|
3
|
my $type = 'method'; |
|
2210
|
2
|
50
|
|
|
|
8
|
if ($meth->name eq "method_named") { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
2211
|
2
|
50
|
|
|
|
6
|
if ($] < 5.018) { |
|
2212
|
0
|
|
|
|
|
0
|
$method_name = $self->const_sv($meth)->PV; |
|
2213
|
|
|
|
|
|
|
} else { |
|
2214
|
2
|
|
|
|
|
15
|
$method_name = $self->meth_sv($meth)->PV; |
|
2215
|
|
|
|
|
|
|
} |
|
2216
|
2
|
|
|
|
|
5
|
$type = 'named method'; |
|
2217
|
|
|
|
|
|
|
} elsif ($meth->name eq "method_super") { |
|
2218
|
0
|
|
|
|
|
0
|
$method_name = "SUPER::".$self->meth_sv($meth)->PV; |
|
2219
|
0
|
|
|
|
|
0
|
$type = 'SUPER:: method'; |
|
2220
|
|
|
|
|
|
|
} elsif ($meth->name eq "method_redir") { |
|
2221
|
0
|
|
|
|
|
0
|
$method_name = $self->meth_rclass_sv($meth)->PV.'::'.$self->meth_sv($meth)->PV; |
|
2222
|
0
|
|
|
|
|
0
|
$type = 'method redirected ::'; |
|
2223
|
|
|
|
|
|
|
} elsif ($meth->name eq "method_redir_super") { |
|
2224
|
0
|
|
|
|
|
0
|
$type = '::SUPER:: redirected method'; |
|
2225
|
0
|
|
|
|
|
0
|
$method_name = $self->meth_rclass_sv($meth)->PV.'::SUPER::'. |
|
2226
|
|
|
|
|
|
|
$self->meth_sv($meth)->PV; |
|
2227
|
|
|
|
|
|
|
} else { |
|
2228
|
0
|
|
|
|
|
0
|
$meth = $meth->first; |
|
2229
|
0
|
0
|
|
|
|
0
|
if ($meth->name eq "const") { |
|
2230
|
|
|
|
|
|
|
# As of 5.005_58, this case is probably obsoleted by the |
|
2231
|
|
|
|
|
|
|
# method_named case above |
|
2232
|
0
|
|
|
|
|
0
|
$method_name = $self->const_sv($meth)->PV; # needs to be bare |
|
2233
|
0
|
|
|
|
|
0
|
$type = 'contant method'; |
|
2234
|
|
|
|
|
|
|
} |
|
2235
|
|
|
|
|
|
|
} |
|
2236
|
|
|
|
|
|
|
|
|
2237
|
2
|
|
|
|
|
4
|
my $meth_node = undef; |
|
2238
|
2
|
50
|
|
|
|
3
|
if ($method_name) { |
|
2239
|
2
|
|
|
|
|
8
|
$meth_node = $self->info_from_string($type, |
|
2240
|
|
|
|
|
|
|
$meth, $method_name, |
|
2241
|
|
|
|
|
|
|
{other_ops => \@other_ops}); |
|
2242
|
2
|
|
|
|
|
7
|
$self->{optree}{$$meth} = $meth_node; |
|
2243
|
2
|
50
|
|
|
|
5
|
$meth_node->{parent} = $$op if $op; |
|
2244
|
|
|
|
|
|
|
|
|
2245
|
|
|
|
|
|
|
} |
|
2246
|
|
|
|
|
|
|
return { |
|
2247
|
2
|
|
|
|
|
12
|
method_node => $meth_node, |
|
2248
|
|
|
|
|
|
|
method => $meth, |
|
2249
|
|
|
|
|
|
|
object => $obj, |
|
2250
|
|
|
|
|
|
|
args => \@exprs, |
|
2251
|
|
|
|
|
|
|
}, $cx; |
|
2252
|
|
|
|
|
|
|
} |
|
2253
|
|
|
|
|
|
|
|
|
2254
|
|
|
|
|
|
|
sub e_method { |
|
2255
|
2
|
|
|
2
|
0
|
5
|
my ($self, $op, $minfo, $cx) = @_; |
|
2256
|
2
|
|
|
|
|
7
|
my $obj = $self->deparse($minfo->{object}, 24, $op); |
|
2257
|
2
|
|
|
|
|
5
|
my @body = ($obj); |
|
2258
|
2
|
|
|
|
|
2
|
my $other_ops = $minfo->{other_ops}; |
|
2259
|
|
|
|
|
|
|
|
|
2260
|
2
|
|
|
|
|
3
|
my $meth_info = $minfo->{method_node}; |
|
2261
|
2
|
50
|
|
|
|
4
|
unless ($minfo->{method_node}) { |
|
2262
|
0
|
|
|
|
|
0
|
$meth_info = $self->deparse($minfo->{meth}, 1, $op); |
|
2263
|
|
|
|
|
|
|
} |
|
2264
|
2
|
|
|
|
|
4
|
my @args = map { $self->deparse($_, 6, $op) } @{$minfo->{args}}; |
|
|
1
|
|
|
|
|
2
|
|
|
|
2
|
|
|
|
|
5
|
|
|
2265
|
2
|
|
|
|
|
7
|
my @args_texts = map $_->{text}, @args; |
|
2266
|
2
|
|
|
|
|
7
|
my $args = join(", ", @args_texts); |
|
2267
|
|
|
|
|
|
|
|
|
2268
|
2
|
|
|
|
|
7
|
my $opts = {other_ops => $other_ops, |
|
2269
|
|
|
|
|
|
|
prev_expr => $meth_info}; |
|
2270
|
2
|
|
|
|
|
5
|
my $type; |
|
2271
|
|
|
|
|
|
|
|
|
2272
|
2
|
50
|
33
|
|
|
17
|
if ($minfo->{object}->name eq 'scope' && B::Deparse::want_list $minfo->{object}) { |
|
2273
|
|
|
|
|
|
|
# method { $object } |
|
2274
|
|
|
|
|
|
|
# This must be deparsed this way to preserve list context |
|
2275
|
|
|
|
|
|
|
# of $object. |
|
2276
|
|
|
|
|
|
|
# FIXME |
|
2277
|
0
|
|
|
|
|
0
|
my @texts = (); |
|
2278
|
0
|
|
|
|
|
0
|
my $need_paren = $cx >= 6; |
|
2279
|
0
|
0
|
|
|
|
0
|
if ($need_paren) { |
|
2280
|
0
|
|
|
|
|
0
|
@texts = ('(', $meth_info->{text}, substr($obj,2), |
|
2281
|
|
|
|
|
|
|
$args, ')'); |
|
2282
|
0
|
|
|
|
|
0
|
$type = 'e_method list ()'; |
|
2283
|
|
|
|
|
|
|
} else { |
|
2284
|
0
|
|
|
|
|
0
|
@texts = ($meth_info->{text}, substr($obj,2), $args); |
|
2285
|
0
|
|
|
|
|
0
|
$type = 'e_method list, no ()'; |
|
2286
|
|
|
|
|
|
|
} |
|
2287
|
0
|
|
|
|
|
0
|
return info_from_list($op, $self, \@texts, '', $type, $opts); |
|
2288
|
|
|
|
|
|
|
} |
|
2289
|
|
|
|
|
|
|
|
|
2290
|
2
|
|
|
|
|
6
|
my @nodes = ($obj, $meth_info); |
|
2291
|
2
|
|
|
|
|
10
|
my $fmt; |
|
2292
|
2
|
|
|
|
|
6
|
my @args_spec = (0, 1); |
|
2293
|
2
|
100
|
|
|
|
4
|
if (@{$minfo->{args}}) { |
|
|
2
|
|
|
|
|
7
|
|
|
2294
|
1
|
|
|
|
|
3
|
my $prev_expr = undef; |
|
2295
|
1
|
|
|
|
|
2
|
foreach my $arg (@{$minfo->{args}}) { |
|
|
1
|
|
|
|
|
5
|
|
|
2296
|
1
|
|
|
|
|
5
|
my $expr = $self->deparse($arg, 6, $op); |
|
2297
|
1
|
|
|
|
|
4
|
$expr->{prev_expr} = $prev_expr; |
|
2298
|
1
|
|
|
|
|
4
|
push @nodes, $expr; |
|
2299
|
|
|
|
|
|
|
} |
|
2300
|
1
|
|
|
|
|
4
|
$fmt = "%c->%c(%C)"; |
|
2301
|
1
|
|
|
|
|
4
|
push @args_spec, [2, $#nodes, ', ']; |
|
2302
|
1
|
|
|
|
|
6
|
$type = '$obj->method()'; |
|
2303
|
|
|
|
|
|
|
} else { |
|
2304
|
1
|
|
|
|
|
2
|
$type = '$obj->method'; |
|
2305
|
1
|
|
|
|
|
2
|
$fmt = "%c->%c"; |
|
2306
|
|
|
|
|
|
|
} |
|
2307
|
2
|
|
|
|
|
7
|
return $self->info_from_template($type, $op, $fmt, \@args_spec, \@nodes, $opts); |
|
2308
|
|
|
|
|
|
|
} |
|
2309
|
|
|
|
|
|
|
|
|
2310
|
|
|
|
|
|
|
# Perl 5.14 doesn't have this |
|
2311
|
8
|
|
|
8
|
|
123
|
use constant OP_GLOB => 25; |
|
|
8
|
|
|
|
|
19
|
|
|
|
8
|
|
|
|
|
42033
|
|
|
2312
|
|
|
|
|
|
|
|
|
2313
|
|
|
|
|
|
|
sub null_older |
|
2314
|
|
|
|
|
|
|
{ |
|
2315
|
0
|
|
|
0
|
0
|
0
|
my($self, $op, $cx) = @_; |
|
2316
|
0
|
|
|
|
|
0
|
my $info; |
|
2317
|
0
|
0
|
|
|
|
0
|
if (B::class($op) eq "OP") { |
|
|
|
0
|
|
|
|
|
|
|
2318
|
0
|
0
|
|
|
|
0
|
if ($op->targ == B::Deparse::OP_CONST) { |
|
2319
|
|
|
|
|
|
|
# The Perl source constant value can't be recovered. |
|
2320
|
|
|
|
|
|
|
# We'll use the 'ex_const' value as a substitute |
|
2321
|
0
|
|
|
|
|
0
|
return $self->info_from_string('constant unrecoverable', $op, $self->{'ex_const'}); |
|
2322
|
|
|
|
|
|
|
} else { |
|
2323
|
|
|
|
|
|
|
# FIXME: look over. Is this right? |
|
2324
|
0
|
|
|
|
|
0
|
return $self->info_from_string('constant ""', $op, ''); |
|
2325
|
|
|
|
|
|
|
} |
|
2326
|
|
|
|
|
|
|
} elsif (B::class ($op) eq "COP") { |
|
2327
|
0
|
|
|
|
|
0
|
return $self->cops($op, $cx, $op->name); |
|
2328
|
|
|
|
|
|
|
} |
|
2329
|
0
|
|
|
|
|
0
|
my $kid = $op->first; |
|
2330
|
0
|
0
|
0
|
|
|
0
|
if ($self->is_list_older($kid)) { |
|
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
2331
|
0
|
|
|
|
|
0
|
my $node = $self->pp_list($op, $cx); |
|
2332
|
0
|
|
|
|
|
0
|
$node->update_other_ops($kid); |
|
2333
|
0
|
|
|
|
|
0
|
return $node; |
|
2334
|
|
|
|
|
|
|
} elsif ($kid->name eq "enter") { |
|
2335
|
0
|
|
|
|
|
0
|
return $self->pp_leave($op, $cx); |
|
2336
|
|
|
|
|
|
|
} elsif ($kid->name eq "leave") { |
|
2337
|
0
|
|
|
|
|
0
|
return $self->pp_leave($kid, $cx); |
|
2338
|
|
|
|
|
|
|
} elsif ($kid->name eq "scope") { |
|
2339
|
0
|
|
|
|
|
0
|
return $self->pp_scope($kid, $cx); |
|
2340
|
|
|
|
|
|
|
} elsif ($op->targ == B::Deparse::OP_STRINGIFY) { |
|
2341
|
0
|
|
|
|
|
0
|
return $self->dquote($op, $cx); |
|
2342
|
|
|
|
|
|
|
} elsif ($op->targ == OP_GLOB) { |
|
2343
|
0
|
|
|
|
|
0
|
my @other_ops = ($kid, $kid->first, $kid->first->first); |
|
2344
|
0
|
|
|
|
|
0
|
my $info = $self->pp_glob( |
|
2345
|
|
|
|
|
|
|
$kid # entersub |
|
2346
|
|
|
|
|
|
|
->first # ex-list |
|
2347
|
|
|
|
|
|
|
->first # pushmark |
|
2348
|
|
|
|
|
|
|
->sibling, # glob |
|
2349
|
|
|
|
|
|
|
$cx |
|
2350
|
|
|
|
|
|
|
); |
|
2351
|
0
|
|
|
|
|
0
|
push @{$info->{other_ops}}, @other_ops; |
|
|
0
|
|
|
|
|
0
|
|
|
2352
|
0
|
|
|
|
|
0
|
return $info; |
|
2353
|
|
|
|
|
|
|
} elsif (!B::Deparse::null($kid->sibling) and |
|
2354
|
|
|
|
|
|
|
$kid->sibling->name eq "readline" and |
|
2355
|
|
|
|
|
|
|
$kid->sibling->flags & OPf_STACKED) { |
|
2356
|
0
|
|
|
|
|
0
|
my $lhs = $self->deparse($kid, 7, $op); |
|
2357
|
0
|
|
|
|
|
0
|
my $rhs = $self->deparse($kid->sibling, 7, $kid); |
|
2358
|
0
|
|
|
|
|
0
|
return $self->info_from_template("readline = ", $op, |
|
2359
|
|
|
|
|
|
|
"%c = %c", undef, [$lhs, $rhs], |
|
2360
|
|
|
|
|
|
|
{maybe_parens => [$self, $cx, 7], |
|
2361
|
|
|
|
|
|
|
prev_expr => $rhs}); |
|
2362
|
|
|
|
|
|
|
} elsif (!B::Deparse::null($kid->sibling) and |
|
2363
|
|
|
|
|
|
|
$kid->sibling->name eq "trans" and |
|
2364
|
|
|
|
|
|
|
$kid->sibling->flags & OPf_STACKED) { |
|
2365
|
0
|
|
|
|
|
0
|
my $lhs = $self->deparse($kid, 20, $op); |
|
2366
|
0
|
|
|
|
|
0
|
my $rhs = $self->deparse($kid->sibling, 20, $op); |
|
2367
|
0
|
|
|
|
|
0
|
return $self->info_from_template("trans =~",$op, |
|
2368
|
|
|
|
|
|
|
"%c =~ %c", undef, [$lhs, $rhs], |
|
2369
|
|
|
|
|
|
|
{ maybe_parens => [$self, $cx, 7], |
|
2370
|
|
|
|
|
|
|
prev_expr => $rhs }); |
|
2371
|
|
|
|
|
|
|
} elsif ($op->flags & OPf_SPECIAL && $cx < 1 && !$op->targ) { |
|
2372
|
0
|
|
|
|
|
0
|
my $kid_info = $self->deparse($kid, $cx, $op); |
|
2373
|
0
|
|
|
|
|
0
|
return $self->info_from_template("do { }", $op, |
|
2374
|
|
|
|
|
|
|
"do {\n%+%c\n%-}", undef, [$kid_info]); |
|
2375
|
|
|
|
|
|
|
} elsif (!B::Deparse::null($kid->sibling) and |
|
2376
|
|
|
|
|
|
|
$kid->sibling->name eq "null" and |
|
2377
|
|
|
|
|
|
|
B::class($kid->sibling) eq "UNOP" and |
|
2378
|
|
|
|
|
|
|
$kid->sibling->first->flags & OPf_STACKED and |
|
2379
|
|
|
|
|
|
|
$kid->sibling->first->name eq "rcatline") { |
|
2380
|
0
|
|
|
|
|
0
|
my $lhs = $self->deparse($kid, 18, $op); |
|
2381
|
0
|
|
|
|
|
0
|
my $rhs = $self->deparse($kid->sibling, 18, $op); |
|
2382
|
0
|
|
|
|
|
0
|
return $self->info_from_template("rcatline =",$op, |
|
2383
|
|
|
|
|
|
|
"%c = %c", undef, [$lhs, $rhs], |
|
2384
|
|
|
|
|
|
|
{ maybe_parens => [$self, $cx, 20], |
|
2385
|
|
|
|
|
|
|
prev_expr => $rhs }); |
|
2386
|
|
|
|
|
|
|
} else { |
|
2387
|
0
|
|
|
|
|
0
|
return $self->deparse($kid, $cx, $op); |
|
2388
|
|
|
|
|
|
|
} |
|
2389
|
0
|
|
|
|
|
0
|
Carp::confess("unhandled condition in null"); |
|
2390
|
|
|
|
|
|
|
} |
|
2391
|
|
|
|
|
|
|
|
|
2392
|
|
|
|
|
|
|
sub pushmark_position($) { |
|
2393
|
2611
|
|
|
2611
|
0
|
4518
|
my ($node) = @_; |
|
2394
|
2611
|
|
|
|
|
3684
|
my $l = undef; |
|
2395
|
2611
|
50
|
|
|
|
6304
|
if ($node->{parens}) { |
|
|
|
100
|
|
|
|
|
|
|
2396
|
0
|
|
|
|
|
0
|
return [0, 1]; |
|
2397
|
|
|
|
|
|
|
} elsif (exists $node->{fmt}) { |
|
2398
|
|
|
|
|
|
|
# Match up to %c, %C, or %F after ( or { |
|
2399
|
1247
|
100
|
|
|
|
6913
|
if ($node->{fmt} =~ /^(.*)%[cCF]/) { |
|
2400
|
1200
|
|
|
|
|
3455
|
$l = length($1); |
|
2401
|
|
|
|
|
|
|
} |
|
2402
|
|
|
|
|
|
|
} else { |
|
2403
|
|
|
|
|
|
|
# Match up to first ( or { |
|
2404
|
1364
|
100
|
|
|
|
6137
|
if ($node->{text} =~ /^(.*)\W/) { |
|
2405
|
1356
|
|
|
|
|
3524
|
$l = length($1); |
|
2406
|
|
|
|
|
|
|
} |
|
2407
|
|
|
|
|
|
|
} |
|
2408
|
2611
|
100
|
|
|
|
4679
|
if (defined($l)) { |
|
2409
|
2556
|
100
|
|
|
|
10576
|
$l = $l > 0 ? $l-1 : 0; |
|
2410
|
2556
|
|
|
|
|
5996
|
return [$l, 1] |
|
2411
|
|
|
|
|
|
|
} |
|
2412
|
55
|
|
|
|
|
113
|
return undef; |
|
2413
|
|
|
|
|
|
|
} |
|
2414
|
|
|
|
|
|
|
|
|
2415
|
|
|
|
|
|
|
|
|
2416
|
|
|
|
|
|
|
# Note 5.26 and up |
|
2417
|
|
|
|
|
|
|
sub null_newer |
|
2418
|
|
|
|
|
|
|
{ |
|
2419
|
5255
|
|
|
5255
|
0
|
8889
|
my($self, $op, $cx) = @_; |
|
2420
|
5255
|
|
|
|
|
6241
|
my $node; |
|
2421
|
|
|
|
|
|
|
|
|
2422
|
|
|
|
|
|
|
# might be 'my $s :Foo(bar);' |
|
2423
|
5255
|
50
|
33
|
|
|
10574
|
if ($] >= 5.028 && $op->targ == B::Deparse::OP_LIST) { |
|
2424
|
0
|
|
|
|
|
0
|
Carp::confess("Can't handle var attr yet"); |
|
2425
|
|
|
|
|
|
|
# my $my_attr = maybe_var_attr($self, $op, $cx); |
|
2426
|
|
|
|
|
|
|
# return $my_attr if defined $my_attr; |
|
2427
|
|
|
|
|
|
|
} |
|
2428
|
|
|
|
|
|
|
|
|
2429
|
5255
|
100
|
|
|
|
41303
|
if (B::class($op) eq "OP") { |
|
|
|
50
|
|
|
|
|
|
|
2430
|
|
|
|
|
|
|
# If the Perl source constant value can't be recovered. |
|
2431
|
|
|
|
|
|
|
# We'll use the 'ex_const' value as a substitute |
|
2432
|
1
|
50
|
|
|
|
9
|
return $self->info_from_string("null - constant_unrecoverable",$op, $self->{'ex_const'}) |
|
2433
|
|
|
|
|
|
|
if $op->targ == B::Deparse::OP_CONST; |
|
2434
|
0
|
0
|
|
|
|
0
|
return $self->dquote($op, $cx) if $op->targ == B::Deparse::OP_STRINGIFY; |
|
2435
|
|
|
|
|
|
|
} elsif (B::class($op) eq "COP") { |
|
2436
|
0
|
|
|
|
|
0
|
return $self->cops($op, $cx, $op->name); |
|
2437
|
|
|
|
|
|
|
} else { |
|
2438
|
|
|
|
|
|
|
# All of these use $kid |
|
2439
|
5254
|
|
|
|
|
19512
|
my $kid = $op->first; |
|
2440
|
5254
|
|
|
|
|
7381
|
my $update_node = $kid; |
|
2441
|
5254
|
100
|
66
|
|
|
11694
|
if ($self->is_list_newer($op)) { |
|
|
|
50
|
33
|
|
|
|
|
|
|
|
50
|
66
|
|
|
|
|
|
|
|
50
|
33
|
|
|
|
|
|
|
|
50
|
100
|
|
|
|
|
|
|
|
50
|
66
|
|
|
|
|
|
|
|
50
|
66
|
|
|
|
|
|
|
|
50
|
100
|
|
|
|
|
|
|
|
50
|
66
|
|
|
|
|
|
|
|
50
|
33
|
|
|
|
|
|
2442
|
2611
|
|
|
|
|
7210
|
$node = $self->pp_list($op, $cx); |
|
2443
|
|
|
|
|
|
|
} elsif ($kid->name eq "enter") { |
|
2444
|
0
|
|
|
|
|
0
|
$node = $self->pp_leave($op, $cx); |
|
2445
|
|
|
|
|
|
|
} elsif ($kid->name eq "leave") { |
|
2446
|
0
|
|
|
|
|
0
|
$node = $self->pp_leave($kid, $cx); |
|
2447
|
|
|
|
|
|
|
} elsif ($kid->name eq "scope") { |
|
2448
|
0
|
|
|
|
|
0
|
$node = $self->pp_scope($kid, $cx); |
|
2449
|
|
|
|
|
|
|
} elsif ($op->targ == B::Deparse::OP_STRINGIFY) { |
|
2450
|
|
|
|
|
|
|
# This case is duplicated the below "else". Can it ever happen? |
|
2451
|
0
|
|
|
|
|
0
|
$node = $self->dquote($op, $cx); |
|
2452
|
|
|
|
|
|
|
} elsif ($op->targ == OP_GLOB) { |
|
2453
|
0
|
|
|
|
|
0
|
my @other_ops = ($kid, $kid->first, $kid->first->first); |
|
2454
|
0
|
|
|
|
|
0
|
my $info = $self->pp_glob( |
|
2455
|
|
|
|
|
|
|
$kid # entersub |
|
2456
|
|
|
|
|
|
|
->first # ex-list |
|
2457
|
|
|
|
|
|
|
->first # pushmark |
|
2458
|
|
|
|
|
|
|
->sibling, # glob |
|
2459
|
|
|
|
|
|
|
$cx |
|
2460
|
|
|
|
|
|
|
); |
|
2461
|
|
|
|
|
|
|
# FIXME: mark text. |
|
2462
|
0
|
|
|
|
|
0
|
push @{$info->{other_ops}}, @other_ops; |
|
|
0
|
|
|
|
|
0
|
|
|
2463
|
0
|
|
|
|
|
0
|
return $info; |
|
2464
|
|
|
|
|
|
|
} elsif (!B::Deparse::null($kid->sibling) and |
|
2465
|
|
|
|
|
|
|
$kid->sibling->name eq "readline" and |
|
2466
|
|
|
|
|
|
|
$kid->sibling->flags & OPf_STACKED) { |
|
2467
|
0
|
|
|
|
|
0
|
my $lhs = $self->deparse($kid, 7, $op); |
|
2468
|
0
|
|
|
|
|
0
|
my $rhs = $self->deparse($kid->sibling, 7, $kid); |
|
2469
|
0
|
|
|
|
|
0
|
$node = $self->info_from_template("null: readline = ", $op, |
|
2470
|
|
|
|
|
|
|
"%c = %c", undef, [$lhs, $rhs], |
|
2471
|
|
|
|
|
|
|
{maybe_parens => [$self, $cx, 7], |
|
2472
|
|
|
|
|
|
|
prev_expr => $rhs}); |
|
2473
|
|
|
|
|
|
|
} elsif (!B::Deparse::null($kid->sibling) and |
|
2474
|
|
|
|
|
|
|
$kid->sibling->name =~ /^transr?\z/ and |
|
2475
|
|
|
|
|
|
|
$kid->sibling->flags & OPf_STACKED) { |
|
2476
|
0
|
|
|
|
|
0
|
my $lhs = $self->deparse($kid, 20, $op); |
|
2477
|
0
|
|
|
|
|
0
|
my $rhs = $self->deparse($kid->sibling, 20, $op); |
|
2478
|
0
|
|
|
|
|
0
|
$node = $self->info_from_template("null: trans =~",$op, |
|
2479
|
|
|
|
|
|
|
"%c =~ %c", undef, [$lhs, $rhs], |
|
2480
|
|
|
|
|
|
|
{ maybe_parens => [$self, $cx, 7], |
|
2481
|
|
|
|
|
|
|
prev_expr => $rhs }); |
|
2482
|
|
|
|
|
|
|
} elsif ($op->flags & OPf_SPECIAL && $cx < 1 && !$op->targ) { |
|
2483
|
0
|
|
|
|
|
0
|
my $kid_info = $self->deparse($kid, $cx, $op); |
|
2484
|
0
|
|
|
|
|
0
|
$node = $self->info_from_template("null: do { }", $op, |
|
2485
|
|
|
|
|
|
|
"do {\n%+%c\n%-}", undef, [$kid_info]); |
|
2486
|
|
|
|
|
|
|
} elsif (!B::Deparse::null($kid->sibling) and |
|
2487
|
|
|
|
|
|
|
$kid->sibling->name eq "null" and |
|
2488
|
|
|
|
|
|
|
B::class($kid->sibling) eq "UNOP" and |
|
2489
|
|
|
|
|
|
|
$kid->sibling->first->flags & OPf_STACKED and |
|
2490
|
|
|
|
|
|
|
$kid->sibling->first->name eq "rcatline") { |
|
2491
|
0
|
|
|
|
|
0
|
my $lhs = $self->deparse($kid, 18, $op); |
|
2492
|
0
|
|
|
|
|
0
|
my $rhs = $self->deparse($kid->sibling, 18, $op); |
|
2493
|
0
|
|
|
|
|
0
|
$node = $self->info_from_template("null: rcatline =",$op, |
|
2494
|
|
|
|
|
|
|
"%c = %c", undef, [$lhs, $rhs], |
|
2495
|
|
|
|
|
|
|
{ maybe_parens => [$self, $cx, 20], |
|
2496
|
|
|
|
|
|
|
prev_expr => $rhs }); |
|
2497
|
|
|
|
|
|
|
} else { |
|
2498
|
2643
|
|
|
|
|
8259
|
my $node = $self->deparse($kid, $cx, $op); |
|
2499
|
2643
|
|
|
|
|
11449
|
my $type = "null: " . $op->name; |
|
2500
|
2643
|
|
|
|
|
8937
|
return $self->info_from_template($type, $op, |
|
2501
|
|
|
|
|
|
|
"%c", undef, [$node]); |
|
2502
|
|
|
|
|
|
|
} |
|
2503
|
2611
|
|
|
|
|
6801
|
my $position = pushmark_position($node); |
|
2504
|
2611
|
100
|
|
|
|
5121
|
if ($position) { |
|
2505
|
|
|
|
|
|
|
$update_node = |
|
2506
|
|
|
|
|
|
|
$self->info_from_string($kid->name, $kid, |
|
2507
|
|
|
|
|
|
|
$node->{text}, |
|
2508
|
2556
|
|
|
|
|
16804
|
{position => $position}); |
|
2509
|
|
|
|
|
|
|
} |
|
2510
|
2611
|
|
|
|
|
8724
|
$node->update_other_ops($update_node); |
|
2511
|
2611
|
|
|
|
|
7387
|
return $node; |
|
2512
|
|
|
|
|
|
|
} |
|
2513
|
0
|
|
|
|
|
0
|
Carp::confess("unhandled condition in null"); |
|
2514
|
|
|
|
|
|
|
} |
|
2515
|
|
|
|
|
|
|
|
|
2516
|
|
|
|
|
|
|
sub pp_padsv { |
|
2517
|
4400
|
50
|
|
4400
|
0
|
15016
|
$] >= 5.026 ? goto &pp_padsv_newer : goto &pp_padsv_older; |
|
2518
|
|
|
|
|
|
|
} |
|
2519
|
|
|
|
|
|
|
|
|
2520
|
|
|
|
|
|
|
sub pp_padsv_newer { |
|
2521
|
4400
|
|
|
4400
|
0
|
6663
|
my $self = shift; |
|
2522
|
4400
|
|
|
|
|
7068
|
my($op, $cx, $forbid_parens) = @_; |
|
2523
|
4400
|
|
|
|
|
12490
|
my $targ = $op->targ; |
|
2524
|
4400
|
|
|
|
|
47687
|
return $self->maybe_my($op, $cx, $self->padname($targ), |
|
2525
|
|
|
|
|
|
|
$self->padname_sv($targ), |
|
2526
|
|
|
|
|
|
|
$forbid_parens); |
|
2527
|
|
|
|
|
|
|
} |
|
2528
|
|
|
|
|
|
|
|
|
2529
|
|
|
|
|
|
|
sub pp_padsv_older |
|
2530
|
|
|
|
|
|
|
{ |
|
2531
|
0
|
|
|
0
|
0
|
0
|
my ($self, $op, $cx, $forbid_parens) = @_; |
|
2532
|
0
|
|
|
|
|
0
|
return $self->maybe_my($op, $cx, $self->padname($op->targ), |
|
2533
|
|
|
|
|
|
|
$forbid_parens); |
|
2534
|
|
|
|
|
|
|
} |
|
2535
|
|
|
|
|
|
|
|
|
2536
|
|
|
|
|
|
|
# This is the 5.26 version. It is different from earlier versions. |
|
2537
|
|
|
|
|
|
|
# Is it compatable/ |
|
2538
|
|
|
|
|
|
|
# |
|
2539
|
|
|
|
|
|
|
# 'x' is weird when the left arg is a list |
|
2540
|
|
|
|
|
|
|
sub repeat { |
|
2541
|
5
|
|
|
5
|
0
|
10
|
my $self = shift; |
|
2542
|
5
|
|
|
|
|
13
|
my($op, $cx) = @_; |
|
2543
|
5
|
|
|
|
|
20
|
my $left = $op->first; |
|
2544
|
5
|
|
|
|
|
25
|
my $right = $op->last; |
|
2545
|
5
|
|
|
|
|
11
|
my $eq = ""; |
|
2546
|
5
|
|
|
|
|
19
|
my $prec = 19; |
|
2547
|
5
|
|
|
|
|
10
|
my @skipped_ops = (); |
|
2548
|
5
|
|
|
|
|
6
|
my $left_fmt; |
|
2549
|
5
|
|
|
|
|
10
|
my $type = "repeat"; |
|
2550
|
5
|
|
|
|
|
9
|
my @args_spec = (); |
|
2551
|
5
|
|
|
|
|
10
|
my @exprs = (); |
|
2552
|
5
|
50
|
|
|
|
26
|
if ($op->flags & OPf_STACKED) { |
|
2553
|
0
|
|
|
|
|
0
|
$eq = "="; |
|
2554
|
0
|
|
|
|
|
0
|
$prec = 7; |
|
2555
|
|
|
|
|
|
|
} |
|
2556
|
|
|
|
|
|
|
|
|
2557
|
5
|
50
|
|
|
|
52
|
if (B::Deparse::null($right)) { |
|
2558
|
|
|
|
|
|
|
# This branch occurs in 5.21.5 and earlier. |
|
2559
|
|
|
|
|
|
|
# A list repeat; count is inside left-side ex-list |
|
2560
|
0
|
|
|
|
|
0
|
$type = 'list repeat'; |
|
2561
|
|
|
|
|
|
|
|
|
2562
|
0
|
|
|
|
|
0
|
my $kid = $left->first->sibling; # skip pushmark |
|
2563
|
0
|
|
|
|
|
0
|
push @skipped_ops, $left->first, $kid; |
|
2564
|
0
|
|
|
|
|
0
|
$self->deparse_op_siblings(\@exprs, $kid, $op, 6); |
|
2565
|
0
|
|
|
|
|
0
|
$left_fmt = '(%C)'; |
|
2566
|
0
|
|
|
|
|
0
|
@args_spec = ([0, $#exprs, ', '], scalar(@exprs)); |
|
2567
|
|
|
|
|
|
|
} else { |
|
2568
|
5
|
|
|
|
|
15
|
$type = 'repeat'; |
|
2569
|
5
|
|
|
|
|
26
|
my $dolist = $op->private & OPpREPEAT_DOLIST; |
|
2570
|
5
|
100
|
|
|
|
26
|
push @exprs, $self->deparse_binop_left($op, $left, $dolist ? 1 : $prec); |
|
2571
|
5
|
|
|
|
|
10
|
$left_fmt = '%c'; |
|
2572
|
5
|
100
|
|
|
|
14
|
if ($dolist) { |
|
2573
|
1
|
|
|
|
|
2
|
$left_fmt = "(%c)"; |
|
2574
|
|
|
|
|
|
|
} |
|
2575
|
5
|
|
|
|
|
13
|
@args_spec = (0, 1); |
|
2576
|
|
|
|
|
|
|
} |
|
2577
|
5
|
|
|
|
|
21
|
push @exprs, $self->deparse_binop_right($op, $right, $prec); |
|
2578
|
5
|
|
|
|
|
17
|
my $opname = "x$eq"; |
|
2579
|
5
|
|
|
|
|
63
|
my $node = $self->info_from_template("$type $opname", |
|
2580
|
|
|
|
|
|
|
$op, "$left_fmt $opname %c", |
|
2581
|
|
|
|
|
|
|
\@args_spec, |
|
2582
|
|
|
|
|
|
|
\@exprs, |
|
2583
|
|
|
|
|
|
|
{maybe_parens => [$self, $cx, $prec], |
|
2584
|
|
|
|
|
|
|
other_ops => \@skipped_ops}); |
|
2585
|
|
|
|
|
|
|
|
|
2586
|
5
|
50
|
|
|
|
21
|
if (@skipped_ops) { |
|
2587
|
|
|
|
|
|
|
# if we have skipped ops like pushmark, we will use the position |
|
2588
|
|
|
|
|
|
|
# of the "x" as the part it represents. |
|
2589
|
0
|
|
|
|
|
0
|
my @new_ops; |
|
2590
|
0
|
|
|
|
|
0
|
my $str = $node->{text}; |
|
2591
|
0
|
|
|
|
|
0
|
my $right_text = "$opname " . $exprs[-1]->{text}; |
|
2592
|
0
|
|
|
|
|
0
|
my $start = rindex($str, $right_text); |
|
2593
|
0
|
|
|
|
|
0
|
my $position; |
|
2594
|
0
|
0
|
|
|
|
0
|
if ($start >= 0) { |
|
2595
|
0
|
|
|
|
|
0
|
$position = [$start, length($opname)]; |
|
2596
|
|
|
|
|
|
|
} else { |
|
2597
|
0
|
|
|
|
|
0
|
$position = [0, length($str)]; |
|
2598
|
|
|
|
|
|
|
} |
|
2599
|
0
|
|
|
|
|
0
|
my @skipped_nodes; |
|
2600
|
0
|
|
|
|
|
0
|
for my $skipped_op (@skipped_ops) { |
|
2601
|
0
|
|
|
|
|
0
|
my $new_op = $self->info_from_string($op->name, $skipped_op, $str, |
|
2602
|
|
|
|
|
|
|
{position => $position}); |
|
2603
|
0
|
|
|
|
|
0
|
push @new_ops, $new_op; |
|
2604
|
|
|
|
|
|
|
} |
|
2605
|
0
|
|
|
|
|
0
|
$node->{other_ops} = \@new_ops; |
|
2606
|
|
|
|
|
|
|
} |
|
2607
|
|
|
|
|
|
|
|
|
2608
|
5
|
|
|
|
|
21
|
return $node; |
|
2609
|
|
|
|
|
|
|
} |
|
2610
|
|
|
|
|
|
|
|
|
2611
|
|
|
|
|
|
|
sub stringify_older { |
|
2612
|
0
|
|
|
0
|
0
|
0
|
maybe_targmy(@_, \&dquote) |
|
2613
|
|
|
|
|
|
|
} |
|
2614
|
|
|
|
|
|
|
|
|
2615
|
|
|
|
|
|
|
# OP_STRINGIFY is a listop, but it only ever has one arg |
|
2616
|
|
|
|
|
|
|
sub stringify_newer { |
|
2617
|
0
|
|
|
0
|
0
|
0
|
my ($self, $op, $cx) = @_; |
|
2618
|
0
|
|
|
|
|
0
|
my $kid = $op->first->sibling; |
|
2619
|
0
|
|
|
|
|
0
|
my @other_ops = (); |
|
2620
|
0
|
|
0
|
|
|
0
|
while ($kid->name eq 'null' && !B::Deparse::null($kid->first)) { |
|
2621
|
0
|
|
|
|
|
0
|
push(@other_ops, $kid); |
|
2622
|
0
|
|
|
|
|
0
|
$kid = $kid->first; |
|
2623
|
|
|
|
|
|
|
} |
|
2624
|
0
|
|
|
|
|
0
|
my $info; |
|
2625
|
0
|
0
|
|
|
|
0
|
if ($kid->name =~ /^(?:const|padsv|rv2sv|av2arylen|gvsv|multideref |
|
2626
|
|
|
|
|
|
|
|aelemfast(?:_lex)?|[ah]elem|join|concat)\z/x) { |
|
2627
|
0
|
|
|
|
|
0
|
$info = maybe_targmy(@_, \&dquote); |
|
2628
|
|
|
|
|
|
|
} |
|
2629
|
|
|
|
|
|
|
else { |
|
2630
|
|
|
|
|
|
|
# Actually an optimised join. |
|
2631
|
0
|
|
|
|
|
0
|
my $info = listop(@_,"join"); |
|
2632
|
0
|
|
|
|
|
0
|
$info->{text} =~ s/join([( ])/join$1$self->{'ex_const'}, /; |
|
2633
|
|
|
|
|
|
|
} |
|
2634
|
0
|
|
|
|
|
0
|
push @{$info->{other_ops}}, @other_ops; |
|
|
0
|
|
|
|
|
0
|
|
|
2635
|
0
|
|
|
|
|
0
|
return $info; |
|
2636
|
|
|
|
|
|
|
} |
|
2637
|
|
|
|
|
|
|
|
|
2638
|
|
|
|
|
|
|
# Kind of silly, but we prefer, subst regexp flags joined together to |
|
2639
|
|
|
|
|
|
|
# make words. For example: s/a/b/xo => s/a/b/ox |
|
2640
|
|
|
|
|
|
|
|
|
2641
|
|
|
|
|
|
|
# oxime -- any of various compounds obtained chiefly by the action of |
|
2642
|
|
|
|
|
|
|
# hydroxylamine on aldehydes and ketones and characterized by the |
|
2643
|
|
|
|
|
|
|
# bivalent grouping C=NOH [Webster's Tenth] |
|
2644
|
|
|
|
|
|
|
|
|
2645
|
|
|
|
|
|
|
my %substwords; |
|
2646
|
|
|
|
|
|
|
map($substwords{join "", sort split //, $_} = $_, 'ego', 'egoism', 'em', |
|
2647
|
|
|
|
|
|
|
'es', 'ex', 'exes', 'gee', 'go', 'goes', 'ie', 'ism', 'iso', 'me', |
|
2648
|
|
|
|
|
|
|
'meese', 'meso', 'mig', 'mix', 'os', 'ox', 'oxime', 'see', 'seem', |
|
2649
|
|
|
|
|
|
|
'seg', 'sex', 'sig', 'six', 'smog', 'sog', 'some', 'xi', 'rogue', |
|
2650
|
|
|
|
|
|
|
'sir', 'rise', 'smore', 'more', 'seer', 'rome', 'gore', 'grim', 'grime', |
|
2651
|
|
|
|
|
|
|
'or', 'rose', 'rosie'); |
|
2652
|
|
|
|
|
|
|
|
|
2653
|
|
|
|
|
|
|
# FIXME 522 and 526 could probably be combined or common parts pulled out. |
|
2654
|
|
|
|
|
|
|
sub subst_older |
|
2655
|
|
|
|
|
|
|
{ |
|
2656
|
0
|
|
|
0
|
0
|
0
|
my($self, $op, $cx) = @_; |
|
2657
|
0
|
|
|
|
|
0
|
my $kid = $op->first; |
|
2658
|
0
|
|
|
|
|
0
|
my($binop, $var, $re, @other_ops) = ("", "", "", ()); |
|
2659
|
0
|
|
|
|
|
0
|
my ($repl, $repl_info); |
|
2660
|
|
|
|
|
|
|
|
|
2661
|
0
|
0
|
|
|
|
0
|
if ($op->flags & OPf_STACKED) { |
|
2662
|
0
|
|
|
|
|
0
|
$binop = 1; |
|
2663
|
0
|
|
|
|
|
0
|
$var = $self->deparse($kid, 20, $op); |
|
2664
|
0
|
|
|
|
|
0
|
$kid = $kid->sibling; |
|
2665
|
|
|
|
|
|
|
} |
|
2666
|
0
|
|
|
|
|
0
|
my $flags = ""; |
|
2667
|
0
|
|
|
|
|
0
|
my $pmflags = $op->pmflags; |
|
2668
|
0
|
0
|
|
|
|
0
|
if (B::Deparse::null($op->pmreplroot)) { |
|
2669
|
0
|
|
|
|
|
0
|
$repl = $kid; |
|
2670
|
0
|
|
|
|
|
0
|
$kid = $kid->sibling; |
|
2671
|
|
|
|
|
|
|
} else { |
|
2672
|
0
|
|
|
|
|
0
|
push @other_ops, $op->pmreplroot; |
|
2673
|
0
|
|
|
|
|
0
|
$repl = $op->pmreplroot->first; # skip substcont |
|
2674
|
|
|
|
|
|
|
} |
|
2675
|
0
|
|
|
|
|
0
|
while ($repl->name eq "entereval") { |
|
2676
|
0
|
|
|
|
|
0
|
push @other_ops, $repl; |
|
2677
|
0
|
|
|
|
|
0
|
$repl = $repl->first; |
|
2678
|
0
|
|
|
|
|
0
|
$flags .= "e"; |
|
2679
|
|
|
|
|
|
|
} |
|
2680
|
|
|
|
|
|
|
{ |
|
2681
|
0
|
|
|
|
|
0
|
local $self->{in_subst_repl} = 1; |
|
|
0
|
|
|
|
|
0
|
|
|
2682
|
0
|
0
|
|
|
|
0
|
if ($pmflags & PMf_EVAL) { |
|
2683
|
0
|
|
|
|
|
0
|
$repl_info = $self->deparse($repl->first, 0, $repl); |
|
2684
|
|
|
|
|
|
|
} else { |
|
2685
|
0
|
|
|
|
|
0
|
$repl_info = $self->dq($repl); |
|
2686
|
|
|
|
|
|
|
} |
|
2687
|
|
|
|
|
|
|
} |
|
2688
|
0
|
|
|
|
|
0
|
my $extended = ($pmflags & PMf_EXTENDED); |
|
2689
|
0
|
0
|
|
|
|
0
|
if (B::Deparse::null $kid) { |
|
2690
|
0
|
|
|
|
|
0
|
my $unbacked = B::Deparse::re_unback($op->precomp); |
|
2691
|
0
|
0
|
|
|
|
0
|
if ($extended) { |
|
2692
|
0
|
|
|
|
|
0
|
$re = B::Deparse::re_uninterp_extended(escape_extended_re($unbacked)); |
|
2693
|
|
|
|
|
|
|
} |
|
2694
|
|
|
|
|
|
|
else { |
|
2695
|
0
|
|
|
|
|
0
|
$re = B::Deparse::re_uninterp(B::Deparse::escape_str($unbacked)); |
|
2696
|
|
|
|
|
|
|
} |
|
2697
|
|
|
|
|
|
|
} else { |
|
2698
|
0
|
|
|
|
|
0
|
my ($re_info, $junk) = $self->regcomp($kid, 1, $extended); |
|
2699
|
0
|
|
|
|
|
0
|
$re = $re_info->{text}; |
|
2700
|
|
|
|
|
|
|
} |
|
2701
|
0
|
0
|
|
|
|
0
|
$flags .= "r" if $pmflags & PMf_NONDESTRUCT; |
|
2702
|
0
|
0
|
|
|
|
0
|
$flags .= "e" if $pmflags & PMf_EVAL; |
|
2703
|
0
|
|
|
|
|
0
|
$flags .= $self->re_flags($op); |
|
2704
|
0
|
|
|
|
|
0
|
$flags = join '', sort split //, $flags; |
|
2705
|
0
|
0
|
|
|
|
0
|
$flags = $substwords{$flags} if $substwords{$flags}; |
|
2706
|
0
|
|
|
|
|
0
|
my $core_s = $self->keyword("s"); # maybe CORE::s |
|
2707
|
|
|
|
|
|
|
|
|
2708
|
|
|
|
|
|
|
# FIXME: we need to attach the $repl_info someplace. |
|
2709
|
0
|
|
|
|
|
0
|
my $repl_text = $repl_info->{text}; |
|
2710
|
0
|
|
|
|
|
0
|
my $find_replace_re = double_delim($re, $repl_text); |
|
2711
|
0
|
|
|
|
|
0
|
my $opts = {}; |
|
2712
|
0
|
0
|
|
|
|
0
|
$opts->{other_ops} = \@other_ops if @other_ops; |
|
2713
|
0
|
0
|
|
|
|
0
|
if ($binop) { |
|
2714
|
0
|
|
|
|
|
0
|
return $self->info_from_template("=~ s///", $op, |
|
2715
|
|
|
|
|
|
|
"%c =~ ${core_s}%c$flags", |
|
2716
|
|
|
|
|
|
|
undef, |
|
2717
|
|
|
|
|
|
|
[$var, $find_replace_re], |
|
2718
|
|
|
|
|
|
|
{maybe_parens => [$self, $cx, 20]}); |
|
2719
|
|
|
|
|
|
|
} else { |
|
2720
|
0
|
|
|
|
|
0
|
return $self->info_from_string("s///", $op, "${core_s}${find_replace_re}$flags"); |
|
2721
|
|
|
|
|
|
|
} |
|
2722
|
0
|
|
|
|
|
0
|
Carp::confess("unhandled condition in pp_subst"); |
|
2723
|
|
|
|
|
|
|
} |
|
2724
|
|
|
|
|
|
|
|
|
2725
|
|
|
|
|
|
|
sub slice |
|
2726
|
|
|
|
|
|
|
{ |
|
2727
|
2
|
|
|
2
|
0
|
6
|
my ($self, $op, $cx, $left, $right, $regname, $padname) = @_; |
|
2728
|
2
|
|
|
|
|
3
|
my $last; |
|
2729
|
2
|
|
|
|
|
3
|
my(@elems, $kid, $array); |
|
2730
|
2
|
50
|
|
|
|
14
|
if (B::class($op) eq "LISTOP") { |
|
2731
|
2
|
|
|
|
|
9
|
$last = $op->last; |
|
2732
|
|
|
|
|
|
|
} else { |
|
2733
|
|
|
|
|
|
|
# ex-hslice inside delete() |
|
2734
|
0
|
|
|
|
|
0
|
for ($kid = $op->first; !B::Deparse::null $kid->sibling; $kid = $kid->sibling) { |
|
2735
|
0
|
|
|
|
|
0
|
$last = $kid; |
|
2736
|
|
|
|
|
|
|
} |
|
2737
|
|
|
|
|
|
|
} |
|
2738
|
2
|
|
|
|
|
9
|
$array = $last; |
|
2739
|
2
|
50
|
33
|
|
|
21
|
$array = $array->first |
|
2740
|
|
|
|
|
|
|
if $array->name eq $regname or $array->name eq "null"; |
|
2741
|
2
|
|
|
|
|
10
|
my $array_info = $self->elem_or_slice_array_name($array, $left, $padname, 0); |
|
2742
|
2
|
|
|
|
|
10
|
$kid = $op->first->sibling; # skip pushmark |
|
2743
|
|
|
|
|
|
|
|
|
2744
|
2
|
50
|
|
|
|
15
|
if ($kid->name eq "list") { |
|
2745
|
|
|
|
|
|
|
# FIXME: |
|
2746
|
|
|
|
|
|
|
# skip list, pushmark |
|
2747
|
0
|
|
|
|
|
0
|
$kid = $kid->first->sibling; |
|
2748
|
0
|
|
|
|
|
0
|
for (; !B::Deparse::null $kid; $kid = $kid->sibling) { |
|
2749
|
0
|
|
|
|
|
0
|
push @elems, $self->deparse($kid, 6, $op); |
|
2750
|
|
|
|
|
|
|
} |
|
2751
|
|
|
|
|
|
|
} else { |
|
2752
|
2
|
|
|
|
|
9
|
@elems = ($self->elem_or_slice_single_index($kid, $op)); |
|
2753
|
|
|
|
|
|
|
} |
|
2754
|
2
|
|
|
|
|
5
|
my $lead = '@'; |
|
2755
|
2
|
50
|
|
|
|
11
|
$lead = '%' if $op->name =~ /^kv/i; |
|
2756
|
2
|
|
|
|
|
7
|
my ($fmt, $args_spec); |
|
2757
|
2
|
|
|
|
|
0
|
my (@texts, $type); |
|
2758
|
2
|
50
|
|
|
|
4
|
if ($array_info) { |
|
2759
|
2
|
|
|
|
|
3
|
unshift @elems, $array_info; |
|
2760
|
2
|
|
|
|
|
6
|
$fmt = "${lead}%c$left%C$right"; |
|
2761
|
2
|
|
|
|
|
4
|
$args_spec = [0, [1, $#elems, ', ']]; |
|
2762
|
2
|
|
|
|
|
12
|
$type = "$lead$left .. $right"; |
|
2763
|
|
|
|
|
|
|
} else { |
|
2764
|
0
|
|
|
|
|
0
|
$fmt = "${lead}$left%C$right"; |
|
2765
|
0
|
|
|
|
|
0
|
$args_spec = [0, $#elems, ', ']; |
|
2766
|
0
|
|
|
|
|
0
|
$type = "${lead}$left .. $right"; |
|
2767
|
|
|
|
|
|
|
} |
|
2768
|
2
|
|
|
|
|
14
|
return $self->info_from_template($type, $op, $fmt, $args_spec, |
|
2769
|
|
|
|
|
|
|
\@elems), |
|
2770
|
|
|
|
|
|
|
} |
|
2771
|
|
|
|
|
|
|
|
|
2772
|
|
|
|
|
|
|
sub split |
|
2773
|
|
|
|
|
|
|
{ |
|
2774
|
0
|
|
|
0
|
0
|
0
|
my($self, $op, $cx) = @_; |
|
2775
|
0
|
|
|
|
|
0
|
my($kid, @exprs, $ary_info, $expr); |
|
2776
|
0
|
|
|
|
|
0
|
my $ary = ''; |
|
2777
|
0
|
|
|
|
|
0
|
my @body = (); |
|
2778
|
0
|
|
|
|
|
0
|
my @other_ops = (); |
|
2779
|
0
|
|
|
|
|
0
|
$kid = $op->first; |
|
2780
|
|
|
|
|
|
|
|
|
2781
|
|
|
|
|
|
|
# For our kid (an OP_PUSHRE), pmreplroot is never actually the |
|
2782
|
|
|
|
|
|
|
# root of a replacement; it's either empty, or abused to point to |
|
2783
|
|
|
|
|
|
|
# the GV for an array we split into (an optimization to save |
|
2784
|
|
|
|
|
|
|
# assignment overhead). Depending on whether we're using ithreads, |
|
2785
|
|
|
|
|
|
|
# this OP* holds either a GV* or a PADOFFSET. Luckily, B.xs |
|
2786
|
|
|
|
|
|
|
# figures out for us which it is. |
|
2787
|
0
|
|
|
|
|
0
|
my $replroot = $kid->pmreplroot; |
|
2788
|
0
|
|
|
|
|
0
|
my $gv = 0; |
|
2789
|
0
|
|
|
|
|
0
|
my $stacked = $op->flags & OPf_STACKED; |
|
2790
|
0
|
0
|
0
|
|
|
0
|
if (ref($replroot) eq "B::GV") { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
2791
|
0
|
|
|
|
|
0
|
$gv = $replroot; |
|
2792
|
|
|
|
|
|
|
} elsif (!ref($replroot) and $replroot > 0) { |
|
2793
|
0
|
|
|
|
|
0
|
$gv = $self->padval($replroot); |
|
2794
|
|
|
|
|
|
|
} elsif ($kid->targ) { |
|
2795
|
0
|
|
|
|
|
0
|
$ary = $self->padname($kid->targ) |
|
2796
|
|
|
|
|
|
|
} elsif ($stacked) { |
|
2797
|
0
|
|
|
|
|
0
|
$ary_info = $self->deparse($op->last, 7, $op); |
|
2798
|
0
|
|
|
|
|
0
|
push @body, $ary_info; |
|
2799
|
0
|
|
|
|
|
0
|
$ary = $ary_info->{text}; |
|
2800
|
|
|
|
|
|
|
} |
|
2801
|
0
|
0
|
|
|
|
0
|
$ary_info = $self->maybe_local(@_, |
|
2802
|
|
|
|
|
|
|
$self->stash_variable('@', |
|
2803
|
|
|
|
|
|
|
$self->gv_name($gv), |
|
2804
|
|
|
|
|
|
|
$cx)) |
|
2805
|
|
|
|
|
|
|
if $gv; |
|
2806
|
|
|
|
|
|
|
|
|
2807
|
|
|
|
|
|
|
# Skip the last kid when OPf_STACKED is set, since it is the array |
|
2808
|
|
|
|
|
|
|
# on the left. |
|
2809
|
0
|
0
|
|
|
|
0
|
for (; !B::Deparse::null($stacked ? $kid->sibling : $kid); |
|
2810
|
|
|
|
|
|
|
$kid = $kid->sibling) { |
|
2811
|
0
|
|
|
|
|
0
|
push @exprs, $self->deparse($kid, 6, $op); |
|
2812
|
|
|
|
|
|
|
} |
|
2813
|
|
|
|
|
|
|
|
|
2814
|
0
|
|
|
|
|
0
|
my $opts = {body => \@exprs}; |
|
2815
|
|
|
|
|
|
|
|
|
2816
|
0
|
|
|
|
|
0
|
my @args_texts = map $_->{text}, @exprs; |
|
2817
|
|
|
|
|
|
|
# handle special case of split(), and split(' ') that compiles to /\s+/ |
|
2818
|
|
|
|
|
|
|
# Under 5.10, the reflags may be undef if the split regexp isn't a constant |
|
2819
|
|
|
|
|
|
|
# Under 5.17.5-5.17.9, the special flag is on split itself. |
|
2820
|
0
|
|
|
|
|
0
|
$kid = $op->first; |
|
2821
|
0
|
0
|
|
|
|
0
|
if ( $op->flags & OPf_SPECIAL ) { |
|
2822
|
0
|
|
|
|
|
0
|
$exprs[0]->{text} = "' '"; |
|
2823
|
|
|
|
|
|
|
} |
|
2824
|
|
|
|
|
|
|
|
|
2825
|
0
|
|
|
|
|
0
|
my $sep = ''; |
|
2826
|
0
|
|
|
|
|
0
|
my $type; |
|
2827
|
|
|
|
|
|
|
my @expr_texts; |
|
2828
|
0
|
0
|
|
|
|
0
|
if ($ary) { |
|
2829
|
0
|
|
|
|
|
0
|
@expr_texts = ("$ary", '=', join(', ', @args_texts)); |
|
2830
|
0
|
|
|
|
|
0
|
$sep = ' '; |
|
2831
|
0
|
|
|
|
|
0
|
$type = 'split_array'; |
|
2832
|
0
|
|
|
|
|
0
|
$opts->{maybe_parens} = [$self, $cx, 7]; |
|
2833
|
|
|
|
|
|
|
} else { |
|
2834
|
0
|
|
|
|
|
0
|
@expr_texts = ('split', '(', join(', ', @args_texts), ')'); |
|
2835
|
0
|
|
|
|
|
0
|
$type = 'split'; |
|
2836
|
|
|
|
|
|
|
|
|
2837
|
|
|
|
|
|
|
} |
|
2838
|
0
|
|
|
|
|
0
|
return info_from_list($op, $self, \@expr_texts, $sep, $type, $opts); |
|
2839
|
|
|
|
|
|
|
} |
|
2840
|
|
|
|
|
|
|
|
|
2841
|
|
|
|
|
|
|
sub subst_newer |
|
2842
|
|
|
|
|
|
|
{ |
|
2843
|
18
|
|
|
18
|
0
|
30
|
my($self, $op, $cx) = @_; |
|
2844
|
18
|
|
|
|
|
55
|
my $kid = $op->first; |
|
2845
|
18
|
|
|
|
|
36
|
my($binop, $var, $re, @other_ops) = ("", "", "", ()); |
|
2846
|
18
|
|
|
|
|
22
|
my ($repl, $repl_info); |
|
2847
|
|
|
|
|
|
|
|
|
2848
|
18
|
50
|
|
|
|
76
|
if ($op->flags & OPf_STACKED) { |
|
|
|
50
|
|
|
|
|
|
|
2849
|
0
|
|
|
|
|
0
|
$binop = 1; |
|
2850
|
0
|
|
|
|
|
0
|
$var = $self->deparse($kid, 20, $op); |
|
2851
|
0
|
|
|
|
|
0
|
$kid = $kid->sibling; |
|
2852
|
|
|
|
|
|
|
} |
|
2853
|
|
|
|
|
|
|
elsif (my $targ = $op->targ) { |
|
2854
|
0
|
|
|
|
|
0
|
$binop = 1; |
|
2855
|
0
|
|
|
|
|
0
|
$var = $self->padname($targ); |
|
2856
|
|
|
|
|
|
|
} |
|
2857
|
18
|
|
|
|
|
22
|
my $flags = ""; |
|
2858
|
18
|
|
|
|
|
37
|
my $pmflags = $op->pmflags; |
|
2859
|
18
|
100
|
|
|
|
121
|
if (B::Deparse::null($op->pmreplroot)) { |
|
2860
|
14
|
|
|
|
|
21
|
$repl = $kid; |
|
2861
|
14
|
|
|
|
|
36
|
$kid = $kid->sibling; |
|
2862
|
|
|
|
|
|
|
} else { |
|
2863
|
4
|
|
|
|
|
15
|
push @other_ops, $op->pmreplroot; |
|
2864
|
4
|
|
|
|
|
14
|
$repl = $op->pmreplroot->first; # skip substcont |
|
2865
|
|
|
|
|
|
|
} |
|
2866
|
18
|
|
|
|
|
60
|
while ($repl->name eq "entereval") { |
|
2867
|
0
|
|
|
|
|
0
|
push @other_ops, $repl; |
|
2868
|
0
|
|
|
|
|
0
|
$repl = $repl->first; |
|
2869
|
0
|
|
|
|
|
0
|
$flags .= "e"; |
|
2870
|
|
|
|
|
|
|
} |
|
2871
|
|
|
|
|
|
|
{ |
|
2872
|
18
|
|
|
|
|
23
|
local $self->{in_subst_repl} = 1; |
|
|
18
|
|
|
|
|
43
|
|
|
2873
|
18
|
100
|
|
|
|
32
|
if ($pmflags & PMf_EVAL) { |
|
2874
|
4
|
|
|
|
|
25
|
$repl_info = $self->deparse($repl->first, 0, $repl); |
|
2875
|
|
|
|
|
|
|
} else { |
|
2876
|
14
|
|
|
|
|
61
|
$repl_info = $self->dq($repl); |
|
2877
|
|
|
|
|
|
|
} |
|
2878
|
|
|
|
|
|
|
} |
|
2879
|
18
|
50
|
|
|
|
199
|
if (not B::Deparse::null my $code_list = $op->code_list) { |
|
|
|
50
|
|
|
|
|
|
|
2880
|
0
|
|
|
|
|
0
|
$re = $self->code_list($code_list); |
|
2881
|
|
|
|
|
|
|
} elsif (B::Deparse::null $kid) { |
|
2882
|
18
|
|
|
|
|
1332
|
$re = B::Deparse::re_uninterp(B::Deparse::escape_re(B::Deparse::re_unback($op->precomp))); |
|
2883
|
|
|
|
|
|
|
} else { |
|
2884
|
0
|
|
|
|
|
0
|
my ($re_info, $junk) = $self->regcomp($kid, 1); |
|
2885
|
0
|
|
|
|
|
0
|
$re = $re_info->{text}; |
|
2886
|
|
|
|
|
|
|
} |
|
2887
|
18
|
100
|
|
|
|
68
|
$flags .= "r" if $pmflags & PMf_NONDESTRUCT; |
|
2888
|
18
|
100
|
|
|
|
41
|
$flags .= "e" if $pmflags & PMf_EVAL; |
|
2889
|
18
|
|
|
|
|
158
|
$flags .= $self->re_flags($op); |
|
2890
|
18
|
|
|
|
|
56
|
$flags = join '', sort split //, $flags; |
|
2891
|
18
|
50
|
|
|
|
46
|
$flags = $substwords{$flags} if $substwords{$flags}; |
|
2892
|
18
|
|
|
|
|
2140
|
my $core_s = $self->keyword("s"); # maybe CORE::s |
|
2893
|
|
|
|
|
|
|
|
|
2894
|
|
|
|
|
|
|
# FIXME: we need to attach the $repl_info someplace. |
|
2895
|
18
|
|
|
|
|
35
|
my $repl_text = $repl_info->{text}; |
|
2896
|
18
|
100
|
|
|
|
36
|
my $opts->{other_ops} = \@other_ops if @other_ops; |
|
2897
|
18
|
|
|
|
|
110
|
my $find_replace_re = double_delim($re, $repl_text); |
|
2898
|
|
|
|
|
|
|
|
|
2899
|
18
|
50
|
|
|
|
35
|
if ($binop) { |
|
2900
|
0
|
|
|
|
|
0
|
return $self->info_from_template("=~ s///", $op, |
|
2901
|
|
|
|
|
|
|
"%c =~ ${core_s}%c$flags", |
|
2902
|
|
|
|
|
|
|
undef, |
|
2903
|
|
|
|
|
|
|
[$var, $find_replace_re], |
|
2904
|
|
|
|
|
|
|
{maybe_parens => [$self, $cx, 20]}); |
|
2905
|
|
|
|
|
|
|
} else { |
|
2906
|
18
|
|
|
|
|
57
|
return $self->info_from_string("s///", $op, "${core_s}${find_replace_re}$flags"); |
|
2907
|
|
|
|
|
|
|
} |
|
2908
|
0
|
|
|
|
|
0
|
Carp::confess("unhandled condition in pp_subst"); |
|
2909
|
|
|
|
|
|
|
} |
|
2910
|
|
|
|
|
|
|
|
|
2911
|
|
|
|
|
|
|
# This handles the category of unary operators, e.g. alarm(), caller(), |
|
2912
|
|
|
|
|
|
|
# close().. |
|
2913
|
|
|
|
|
|
|
sub unop |
|
2914
|
|
|
|
|
|
|
{ |
|
2915
|
291
|
|
|
291
|
0
|
853
|
my($self, $op, $cx, $name, $nollafr) = @_; |
|
2916
|
291
|
|
|
|
|
421
|
my $kid; |
|
2917
|
291
|
|
|
|
|
595
|
my $opts = {}; |
|
2918
|
291
|
100
|
|
|
|
1154
|
if ($op->flags & B::OPf_KIDS) { |
|
2919
|
231
|
|
|
|
|
368
|
my $parent = $op; |
|
2920
|
231
|
|
|
|
|
778
|
$kid = $op->first; |
|
2921
|
231
|
50
|
|
|
|
564
|
if (not $name) { |
|
2922
|
|
|
|
|
|
|
# this deals with 'boolkeys' right now |
|
2923
|
0
|
|
|
|
|
0
|
my $kid_node = $self->deparse($kid, $cx, $parent); |
|
2924
|
0
|
|
|
|
|
0
|
$opts->{prev_expr} = $kid_node; |
|
2925
|
0
|
|
|
|
|
0
|
return $self->info_from_template("unop, see child", $op, "%c", |
|
2926
|
|
|
|
|
|
|
undef, [$kid_node], $opts); |
|
2927
|
|
|
|
|
|
|
} |
|
2928
|
231
|
|
|
|
|
394
|
my $builtinname = $name; |
|
2929
|
231
|
50
|
|
|
|
679
|
$builtinname =~ /^CORE::/ or $builtinname = "CORE::$name"; |
|
2930
|
231
|
100
|
100
|
|
|
3425
|
if (defined prototype($builtinname) |
|
|
|
|
100
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
2931
|
|
|
|
|
|
|
&& $builtinname ne 'CORE::readline' |
|
2932
|
|
|
|
|
|
|
&& prototype($builtinname) =~ /^;?\*/ |
|
2933
|
|
|
|
|
|
|
&& $kid->name eq "rv2gv") { |
|
2934
|
24
|
|
|
|
|
52
|
my $rv2gv = $kid; |
|
2935
|
24
|
|
|
|
|
39
|
$parent = $rv2gv; |
|
2936
|
24
|
|
|
|
|
74
|
$kid = $kid->first; |
|
2937
|
24
|
|
|
|
|
88
|
$opts->{other_ops} = [$rv2gv]; |
|
2938
|
|
|
|
|
|
|
} |
|
2939
|
|
|
|
|
|
|
|
|
2940
|
231
|
100
|
|
|
|
624
|
if ($nollafr) { |
|
2941
|
5
|
|
|
|
|
20
|
$kid = $self->deparse($kid, 16, $parent); |
|
2942
|
5
|
|
|
|
|
139
|
$opts->{maybe_parens} = [$self, $cx, 16], |
|
2943
|
|
|
|
|
|
|
my $fullname = $self->keyword($name); |
|
2944
|
5
|
|
|
|
|
52
|
return $self->info_from_template("unary operator $name noallafr", $op, |
|
2945
|
|
|
|
|
|
|
"$fullname %c", undef, [$kid], $opts); |
|
2946
|
|
|
|
|
|
|
} |
|
2947
|
226
|
|
|
|
|
798
|
return $self->maybe_parens_unop($name, $kid, $cx, $parent, $opts) |
|
2948
|
|
|
|
|
|
|
|
|
2949
|
|
|
|
|
|
|
} else { |
|
2950
|
60
|
|
|
|
|
248
|
$opts->{maybe_parens} = [$self, $cx, 16]; |
|
2951
|
60
|
|
|
|
|
3020
|
my $fullname = ($self->keyword($name)); |
|
2952
|
60
|
|
|
|
|
182
|
my $fmt = "$fullname"; |
|
2953
|
60
|
100
|
|
|
|
272
|
$fmt .= '()' if $op->flags & B::OPf_SPECIAL; |
|
2954
|
60
|
|
|
|
|
378
|
return $self->info_from_template("unary operator $name", $op, $fmt, |
|
2955
|
|
|
|
|
|
|
undef, [], $opts); |
|
2956
|
|
|
|
|
|
|
} |
|
2957
|
|
|
|
|
|
|
} |
|
2958
|
|
|
|
|
|
|
|
|
2959
|
|
|
|
|
|
|
# This handles category of symbolic prefix and postfix unary operators, |
|
2960
|
|
|
|
|
|
|
# e.g $x++, -r, +$x. |
|
2961
|
|
|
|
|
|
|
sub pfixop |
|
2962
|
|
|
|
|
|
|
{ |
|
2963
|
6
|
|
|
6
|
0
|
15
|
my $self = shift; |
|
2964
|
6
|
|
|
|
|
20
|
my($op, $cx, $operator, $prec, $flags) = (@_, 0); |
|
2965
|
6
|
|
|
|
|
41
|
my $operand = $self->deparse($op->first, $prec, $op); |
|
2966
|
6
|
|
|
|
|
23
|
my ($type, $fmt); |
|
2967
|
6
|
|
|
|
|
0
|
my @nodes; |
|
2968
|
6
|
50
|
66
|
|
|
46
|
if ($flags & POSTFIX) { |
|
|
|
50
|
|
|
|
|
|
|
2969
|
0
|
|
|
|
|
0
|
@nodes = ($operand, $operator); |
|
2970
|
0
|
|
|
|
|
0
|
$type = "prefix $operator"; |
|
2971
|
0
|
|
|
|
|
0
|
$fmt = "%c%c"; |
|
2972
|
|
|
|
|
|
|
} elsif ($operator eq '-' && $operand->{text} =~ /^[a-zA-Z](?!\w)/) { |
|
2973
|
|
|
|
|
|
|
# Add () around operator to disambiguate with filetest operator |
|
2974
|
0
|
|
|
|
|
0
|
@nodes = ($operator, $operand); |
|
2975
|
0
|
|
|
|
|
0
|
$type = "prefix non-filetest $operator"; |
|
2976
|
0
|
|
|
|
|
0
|
$fmt = "%c(%c)"; |
|
2977
|
|
|
|
|
|
|
} else { |
|
2978
|
6
|
|
|
|
|
20
|
@nodes = ($operator, $operand); |
|
2979
|
6
|
|
|
|
|
18
|
$type = "postfix $operator"; |
|
2980
|
6
|
|
|
|
|
14
|
$fmt = "%c%c"; |
|
2981
|
|
|
|
|
|
|
} |
|
2982
|
|
|
|
|
|
|
|
|
2983
|
6
|
|
|
|
|
40
|
return $self->info_from_template($type, $op, $fmt, [0, 1], |
|
2984
|
|
|
|
|
|
|
\@nodes, |
|
2985
|
|
|
|
|
|
|
{maybe_parens => [$self, $cx, $prec]}) ; |
|
2986
|
|
|
|
|
|
|
} |
|
2987
|
|
|
|
|
|
|
|
|
2988
|
|
|
|
|
|
|
# Produce an node for a range (".." or "..." op) |
|
2989
|
|
|
|
|
|
|
sub range { |
|
2990
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
|
2991
|
0
|
|
|
|
|
0
|
my ($op, $cx, $type) = @_; |
|
2992
|
0
|
|
|
|
|
0
|
my $left = $op->first; |
|
2993
|
0
|
|
|
|
|
0
|
my $right = $left->sibling; |
|
2994
|
0
|
|
|
|
|
0
|
$left = $self->deparse($left, 9, $op); |
|
2995
|
0
|
|
|
|
|
0
|
$right = $self->deparse($right, 9, $op); |
|
2996
|
0
|
|
|
|
|
0
|
return $self->info_from_template("range $type", $op, "%c${type}%c", |
|
2997
|
|
|
|
|
|
|
undef, [$left, $right], |
|
2998
|
|
|
|
|
|
|
{maybe_parens => [$self, $cx, 9]}); |
|
2999
|
|
|
|
|
|
|
} |
|
3000
|
|
|
|
|
|
|
|
|
3001
|
|
|
|
|
|
|
sub rv2x |
|
3002
|
|
|
|
|
|
|
{ |
|
3003
|
75
|
|
|
75
|
0
|
222
|
my($self, $op, $cx, $sigil) = @_; |
|
3004
|
75
|
50
|
33
|
|
|
850
|
if (B::class($op) eq 'NULL' || !$op->can("first")) { |
|
3005
|
0
|
|
|
|
|
0
|
carp("Unexpected op in pp_rv2x"); |
|
3006
|
0
|
|
|
|
|
0
|
return info_from_text($op, $self, 'XXX', 'bad_rv2x', {}); |
|
3007
|
|
|
|
|
|
|
} |
|
3008
|
75
|
|
|
|
|
175
|
my ($info, $kid_info); |
|
3009
|
75
|
|
|
|
|
329
|
my $kid = $op->first; |
|
3010
|
75
|
|
|
|
|
264
|
$kid_info = $self->deparse($kid, 0, $op); |
|
3011
|
75
|
50
|
|
|
|
478
|
if ($kid->name eq "gv") { |
|
|
|
0
|
|
|
|
|
|
|
3012
|
75
|
|
|
850
|
|
616
|
my $transform_fn = sub {$self->stash_variable($sigil, $self->info2str(shift), $cx)}; |
|
|
850
|
|
|
|
|
2418
|
|
|
3013
|
75
|
|
|
|
|
543
|
return $self->info_from_template("rv2x $sigil", undef, "%F", [[0, $transform_fn]], [$kid_info]) |
|
3014
|
|
|
|
|
|
|
} elsif (B::Deparse::is_scalar $kid) { |
|
3015
|
0
|
|
|
|
|
0
|
my $str = $self->info2str($kid_info); |
|
3016
|
0
|
|
|
|
|
0
|
my $fmt = '%c'; |
|
3017
|
0
|
|
|
|
|
0
|
my @args_spec = (0); |
|
3018
|
0
|
0
|
|
|
|
0
|
if ($str =~ /^\$([^\w\d])\z/) { |
|
3019
|
|
|
|
|
|
|
# "$$+" isn't a legal way to write the scalar dereference |
|
3020
|
|
|
|
|
|
|
# of $+, since the lexer can't tell you aren't trying to |
|
3021
|
|
|
|
|
|
|
# do something like "$$ + 1" to get one more than your |
|
3022
|
|
|
|
|
|
|
# PID. Either "${$+}" or "$${+}" are workable |
|
3023
|
|
|
|
|
|
|
# disambiguations, but if the programmer did the former, |
|
3024
|
|
|
|
|
|
|
# they'd be in the "else" clause below rather than here. |
|
3025
|
|
|
|
|
|
|
# It's not clear if this should somehow be unified with |
|
3026
|
|
|
|
|
|
|
# the code in dq and re_dq that also adds lexer |
|
3027
|
|
|
|
|
|
|
# disambiguation braces. |
|
3028
|
0
|
|
|
0
|
|
0
|
my $transform = sub { $_[0] =~ /^\$([^\w\d])\z/; '$' . "{$1}"}; |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
3029
|
0
|
|
|
|
|
0
|
$fmt = '%F'; |
|
3030
|
0
|
|
|
|
|
0
|
@args_spec = (0, $transform); |
|
3031
|
|
|
|
|
|
|
} |
|
3032
|
0
|
|
|
|
|
0
|
return $self->info_from_template("scalar $str", $op, $fmt, undef, \@args_spec, {}); |
|
3033
|
|
|
|
|
|
|
} else { |
|
3034
|
0
|
|
|
|
|
0
|
my $fmt = "$sigil\{%c\}"; |
|
3035
|
0
|
|
|
|
|
0
|
my $type = "rv2x: $sigil\{}"; |
|
3036
|
0
|
|
|
|
|
0
|
return $self->info_from_template($type, $op, $fmt, undef, [$kid_info]); |
|
3037
|
|
|
|
|
|
|
} |
|
3038
|
0
|
|
|
|
|
0
|
Carp::confess("unhandled condition in rv2x"); |
|
3039
|
|
|
|
|
|
|
} |
|
3040
|
|
|
|
|
|
|
|
|
3041
|
|
|
|
|
|
|
# Handle ops that can introduce blocks or scope. "while", "do", "until", and |
|
3042
|
|
|
|
|
|
|
# possibly "map", and "grep" are examples such things. |
|
3043
|
|
|
|
|
|
|
sub scopeop |
|
3044
|
|
|
|
|
|
|
{ |
|
3045
|
12
|
|
|
12
|
0
|
26
|
my($real_block, $self, $op, $cx) = @_; |
|
3046
|
12
|
|
|
|
|
15
|
my $kid; |
|
3047
|
|
|
|
|
|
|
my @kids; |
|
3048
|
|
|
|
|
|
|
|
|
3049
|
|
|
|
|
|
|
local(@$self{qw'curstash warnings hints hinthash'}) |
|
3050
|
12
|
100
|
|
|
|
53
|
= @$self{qw'curstash warnings hints hinthash'} if $real_block; |
|
3051
|
12
|
|
|
|
|
20
|
my @other_ops = (); |
|
3052
|
12
|
100
|
|
|
|
24
|
if ($real_block) { |
|
3053
|
7
|
|
|
|
|
23
|
push @other_ops, $op->first; |
|
3054
|
7
|
|
|
|
|
27
|
$kid = $op->first->sibling; # skip enter |
|
3055
|
7
|
50
|
|
|
|
72
|
if (B::Deparse::is_miniwhile($kid)) { |
|
3056
|
0
|
|
|
|
|
0
|
my $top = $kid->first; |
|
3057
|
0
|
|
|
|
|
0
|
my $name = $top->name; |
|
3058
|
0
|
0
|
|
|
|
0
|
if ($name eq "and") { |
|
|
|
0
|
|
|
|
|
|
|
3059
|
0
|
|
|
|
|
0
|
$name = $self->keyword("while"); |
|
3060
|
|
|
|
|
|
|
} elsif ($name eq "or") { |
|
3061
|
0
|
|
|
|
|
0
|
$name = $self->keyword("until"); |
|
3062
|
|
|
|
|
|
|
} else { # no conditional -> while 1 or until 0 |
|
3063
|
0
|
|
|
|
|
0
|
my $body = $self->deparse($top->first, 1, $top); |
|
3064
|
0
|
|
|
|
|
0
|
return $self->info_from_template("scopeop: $name 1", $op, |
|
3065
|
|
|
|
|
|
|
"%c while 1", undef, [$body], |
|
3066
|
|
|
|
|
|
|
{other_ops => \@other_ops}); |
|
3067
|
|
|
|
|
|
|
} |
|
3068
|
0
|
|
|
|
|
0
|
my $cond = $top->first; |
|
3069
|
0
|
|
|
|
|
0
|
push @other_ops, $cond->sibling; |
|
3070
|
0
|
|
|
|
|
0
|
my $body = $cond->sibling->first; # skip lineseq |
|
3071
|
0
|
|
|
|
|
0
|
my $cond_info = $self->deparse($cond, 1, $top); |
|
3072
|
0
|
|
|
|
|
0
|
my $body_info = $self->deparse($body, 1, $top); |
|
3073
|
0
|
|
|
|
|
0
|
return $self->info_from_template("scopeop: $name", |
|
3074
|
|
|
|
|
|
|
$op,"%c $name %c", |
|
3075
|
|
|
|
|
|
|
undef, [$body_info, $cond_info], |
|
3076
|
|
|
|
|
|
|
{other_ops => \@other_ops}); |
|
3077
|
|
|
|
|
|
|
} |
|
3078
|
|
|
|
|
|
|
} else { |
|
3079
|
5
|
|
|
|
|
15
|
$kid = $op->first; |
|
3080
|
|
|
|
|
|
|
} |
|
3081
|
12
|
|
|
|
|
72
|
for (; !B::Deparse::null($kid); $kid = $kid->sibling) { |
|
3082
|
27
|
|
|
|
|
154
|
push @kids, $kid; |
|
3083
|
|
|
|
|
|
|
} |
|
3084
|
12
|
|
|
|
|
19
|
my $node; |
|
3085
|
12
|
50
|
|
|
|
26
|
if ($cx > 0) { |
|
3086
|
|
|
|
|
|
|
# inside an expression, (a do {} while for lineseq) |
|
3087
|
0
|
|
|
|
|
0
|
my $body = $self->lineseq($op, 0, @kids); |
|
3088
|
0
|
|
|
|
|
0
|
my $text; |
|
3089
|
0
|
0
|
|
|
|
0
|
if (is_lexical_subs(@kids)) { |
|
3090
|
0
|
|
|
|
|
0
|
$node = $self->info_from_template("scoped do", $op, |
|
3091
|
|
|
|
|
|
|
'do {\n%+%c\n%-}', |
|
3092
|
|
|
|
|
|
|
[0], [$body]); |
|
3093
|
|
|
|
|
|
|
|
|
3094
|
|
|
|
|
|
|
} else { |
|
3095
|
0
|
|
|
|
|
0
|
$node = $self->info_from_template("scoped expression", $op, |
|
3096
|
|
|
|
|
|
|
'%c',[0], [$body]); |
|
3097
|
|
|
|
|
|
|
} |
|
3098
|
|
|
|
|
|
|
} else { |
|
3099
|
12
|
|
|
|
|
40
|
$node = $self->lineseq($op, $cx, @kids); |
|
3100
|
|
|
|
|
|
|
} |
|
3101
|
12
|
100
|
|
|
|
37
|
$node->{other_ops} = \@other_ops if @other_ops; |
|
3102
|
12
|
|
|
|
|
42
|
return $node; |
|
3103
|
|
|
|
|
|
|
} |
|
3104
|
|
|
|
|
|
|
|
|
3105
|
|
|
|
|
|
|
sub single_delim($$$$$) |
|
3106
|
|
|
|
|
|
|
{ |
|
3107
|
31
|
|
|
31
|
0
|
97
|
my($self, $op, $q, $default, $str) = @_; |
|
3108
|
|
|
|
|
|
|
|
|
3109
|
31
|
50
|
33
|
|
|
343
|
return $self->info_from_template("string $default .. $default (default)", $op, |
|
3110
|
|
|
|
|
|
|
"$default%c$default", [0], |
|
3111
|
|
|
|
|
|
|
[$str]) |
|
3112
|
|
|
|
|
|
|
if $default and index($str, $default) == -1; |
|
3113
|
0
|
|
|
|
|
|
my $coreq = $self->keyword($q); # maybe CORE::q |
|
3114
|
0
|
0
|
|
|
|
|
if ($q ne 'qr') { |
|
3115
|
0
|
|
|
|
|
|
(my $succeed, $str) = balanced_delim($str); |
|
3116
|
0
|
0
|
|
|
|
|
return $self->info_from_string("string $q", $op, "$coreq$str") |
|
3117
|
|
|
|
|
|
|
if $succeed; |
|
3118
|
|
|
|
|
|
|
} |
|
3119
|
0
|
|
|
|
|
|
for my $delim ('/', '"', '#') { |
|
3120
|
0
|
0
|
|
|
|
|
$self->info_from_string("string $q $delim$delim", $op, "qr$delim$str$delim") |
|
3121
|
|
|
|
|
|
|
if index($str, $delim) == -1; |
|
3122
|
|
|
|
|
|
|
} |
|
3123
|
0
|
0
|
|
|
|
|
if ($default) { |
|
3124
|
|
|
|
|
|
|
my $transform_fn = sub { |
|
3125
|
0
|
|
|
0
|
|
|
s/$_[0]/\\$_[0]/g; |
|
3126
|
0
|
|
|
|
|
|
return $_[0]; |
|
3127
|
0
|
|
|
|
|
|
}; |
|
3128
|
|
|
|
|
|
|
|
|
3129
|
0
|
|
|
|
|
|
return $self->info_from_template("string $q $default$default", |
|
3130
|
|
|
|
|
|
|
$op, "$default%F$default", |
|
3131
|
|
|
|
|
|
|
[[0, $transform_fn]], [$str]); |
|
3132
|
|
|
|
|
|
|
} else { |
|
3133
|
|
|
|
|
|
|
my $transform_fn = sub { |
|
3134
|
0
|
|
|
0
|
|
|
$_[0] =~ s[/][\\/]g; |
|
3135
|
0
|
|
|
|
|
|
return $_[0]; |
|
3136
|
0
|
|
|
|
|
|
}; |
|
3137
|
0
|
|
|
|
|
|
return $self->info_from_template("string $q //", |
|
3138
|
|
|
|
|
|
|
$op, "$coreq/%F/", |
|
3139
|
|
|
|
|
|
|
[[0, $transform_fn]], [$str]); |
|
3140
|
|
|
|
|
|
|
} |
|
3141
|
|
|
|
|
|
|
} |
|
3142
|
|
|
|
|
|
|
|
|
3143
|
|
|
|
|
|
|
# Demo code |
|
3144
|
|
|
|
|
|
|
unless(caller) { |
|
3145
|
|
|
|
|
|
|
; |
|
3146
|
|
|
|
|
|
|
} |
|
3147
|
|
|
|
|
|
|
|
|
3148
|
|
|
|
|
|
|
1; |