File Coverage

lib/B/DeparseTree/PPfns.pm
Criterion Covered Total %
statement 803 1562 51.4
branch 301 684 44.0
condition 203 394 51.5
subroutine 68 97 70.1
pod 0 68 0.0
total 1375 2805 49.0


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;