File Coverage

lib/B/DeparseTree/P526.pm
Criterion Covered Total %
statement 149 339 43.9
branch 65 196 33.1
condition 23 101 22.7
subroutine 28 36 77.7
pod 0 15 0.0
total 265 687 38.5


line stmt bran cond sub pod time code
1             # B::DeparseTree::P526.pm
2             # Copyright (c) 1998-2000, 2002, 2003, 2004, 2005, 2006 Stephen McCamant.
3             # Copyright (c) 2015, 2017, 2018 Rocky Bernstein
4             # All rights reserved.
5             # This module is free software; you can redistribute and/or modify
6             # it under the same terms as Perl itself.
7              
8             # This is based on the module B::Deparse (for perl 5.22) by Stephen McCamant.
9             # It has been extended save tree structure, and is addressible
10             # by opcode address.
11              
12             # B::Parse in turn is based on the module of the same name by Malcolm Beattie,
13             # but essentially none of his code remains.
14              
15 8     8   96 use v5.26;
  8         21  
16              
17 8     8   37 use rlib '../..';
  8         14  
  8         61  
18              
19             package B::DeparseTree::P526;
20 8     8   2510 use Carp;
  8         14  
  8         803  
21              
22 8         1595 use B qw(
23             CVf_METHOD
24             MDEREF_ACTION_MASK
25             MDEREF_AV_gvav_aelem
26             MDEREF_AV_gvsv_vivify_rv2av_aelem
27             MDEREF_AV_padav_aelem
28             MDEREF_AV_padsv_vivify_rv2av_aelem
29             MDEREF_AV_pop_rv2av_aelem
30             MDEREF_AV_vivify_rv2av_aelem
31             MDEREF_FLAG_last
32             MDEREF_HV_gvhv_helem
33             MDEREF_HV_gvsv_vivify_rv2hv_helem
34             MDEREF_HV_padhv_helem
35             MDEREF_HV_padsv_vivify_rv2hv_helem
36             MDEREF_HV_pop_rv2hv_helem
37             MDEREF_HV_vivify_rv2hv_helem
38             MDEREF_INDEX_MASK
39             MDEREF_INDEX_const
40             MDEREF_INDEX_gvsv
41             MDEREF_INDEX_none
42             MDEREF_INDEX_padsv
43             MDEREF_MASK
44             MDEREF_SHIFT
45             MDEREF_reload
46             OPf_KIDS
47             OPf_MOD
48             OPf_PARENS
49             OPf_REF
50             OPf_SPECIAL
51             OPf_STACKED
52             OPf_WANT
53             OPf_WANT_LIST
54             OPf_WANT_SCALAR
55             OPf_WANT_VOID
56             OPpCONST_BARE
57             OPpENTERSUB_AMPER
58             OPpEXISTS_SUB
59             OPpLVAL_INTRO
60             OPpMULTIDEREF_DELETE
61             OPpMULTIDEREF_EXISTS
62             OPpOUR_INTRO
63             OPpPADRANGE_COUNTSHIFT
64             OPpSLICE
65             OPpSORT_INTEGER
66             OPpSORT_NUMERIC
67             OPpSORT_REVERSE
68             OPpSPLIT_ASSIGN OPpSPLIT_LEX
69             OPpTARGET_MY
70             PADNAMEt_OUTER
71             PMf_CONTINUE
72             PMf_EVAL
73             PMf_EXTENDED
74             PMf_EXTENDED_MORE
75             PMf_FOLD
76             PMf_GLOBAL
77             PMf_KEEP
78             PMf_MULTILINE
79             PMf_ONCE
80             PMf_SINGLELINE
81             SVf_FAKE
82             SVf_ROK SVpad_OUR
83             SVpad_TYPED
84             SVs_RMG
85             SVs_SMG
86             class
87             main_cv
88             main_root
89             main_start
90             opnumber
91             perlstring
92             svref_2object
93 8     8   43 );
  8         13  
94              
95 8     8   4498 use B::DeparseTree::PPfns;
  8         19  
  8         2469  
96 8     8   63 use B::DeparseTree::SyntaxTree;
  8         13  
  8         650  
97 8     8   3969 use B::DeparseTree::PP;
  8         18  
  8         2490  
98 8     8   53 use B::Deparse;
  8         18  
  8         1326  
99              
100             # Copy unchanged functions from B::Deparse
101             *begin_is_use = *B::Deparse::begin_is_use;
102             *const_sv = *B::Deparse::const_sv;
103             *escape_re = *B::Deparse::escape_re;
104             *find_scope_st = *B::Deparse::find_scope_st;
105             *gv_name = *B::Deparse::gv_name;
106             *keyword = *B::Deparse::keyword;
107             *meth_pad_subs = *B::Deparse::pad_subs;
108             *meth_rclass_sv = *B::Deparse::meth_rclass_sv;
109             *meth_sv = *B::Deparse::meth_sv;
110             *padany = *B::Deparse::padany;
111             *padname = *B::Deparse::padname;
112             *padname_sv = *B::Deparse::padname_sv;
113             *padval = *B::Deparse::padval;
114             *re_flags = *B::Deparse::re_flags;
115             *stash_variable = *B::Deparse::stash_variable;
116             *stash_variable_name = *B::Deparse::stash_variable_name;
117             *tr_chr = *B::Deparse::tr_chr;
118              
119 8     8   48 use strict;
  8         14  
  8         301  
120 8     8   42 use vars qw/$AUTOLOAD/;
  8         14  
  8         327  
121 8     8   36 use warnings ();
  8         13  
  8         837  
122             require feature;
123              
124             our(@EXPORT, @ISA);
125             our $VERSION = '3.2.0';
126              
127             @ISA = qw(B::DeparseTree::PP);
128              
129             @EXPORT = qw(slice);
130              
131             BEGIN {
132             # List version-specific constants here.
133             # Easiest way to keep this code portable between version looks to
134             # be to fake up a dummy constant that will never actually be true.
135 8     8   37 foreach (qw(OPpSORT_INPLACE OPpSORT_DESCEND OPpITER_REVERSED OPpCONST_NOVER
136             OPpPAD_STATE PMf_SKIPWHITE RXf_SKIPWHITE
137             PMf_CHARSET PMf_KEEPCOPY PMf_NOCAPTURE CVf_ANONCONST
138             CVf_LOCKED OPpREVERSE_INPLACE OPpSUBSTR_REPL_FIRST
139             PMf_NONDESTRUCT OPpCONST_ARYBASE OPpEVAL_BYTES
140             OPpLVREF_TYPE OPpLVREF_SV OPpLVREF_AV OPpLVREF_HV
141             OPpLVREF_CV OPpLVREF_ELEM SVpad_STATE)) {
142 192         261 eval { B->import($_) };
  192         8335  
143 8     8   48 no strict 'refs';
  8         29  
  8         560  
144 192 100       285 *{$_} = sub () {0} unless *{$_}{CODE};
  24         89  
  192         1408  
145             }
146             }
147              
148 8     8   27 BEGIN { for (qw[ rv2sv aelem
149             rv2av rv2hv helem custom ]) {
150 48         2566 eval "sub OP_\U$_ () { " . opnumber($_) . "}"
151             }}
152              
153             # pp_padany -- does not exist after parsing
154              
155             sub AUTOLOAD {
156 0 0   0   0 if ($AUTOLOAD =~ s/^.*::pp_//) {
157 0         0 warn "unexpected OP_".uc $AUTOLOAD;
158 0 0       0 ($_[1]->type == OP_CUSTOM ? "CUSTOM ($AUTOLOAD)" : uc $AUTOLOAD);
159 0         0 return "XXX";
160             } else {
161 0         0 Carp::confess "Undefined subroutine $AUTOLOAD called";
162             }
163             }
164              
165       0     sub DESTROY {} # Do not AUTOLOAD
166              
167             # The BEGIN {} is used here because otherwise this code isn't executed
168             # when you run B::Deparse on itself.
169             my %globalnames;
170 8     8   266 BEGIN { map($globalnames{$_}++, "SIG", "STDIN", "STDOUT", "STDERR", "INC",
171             "ENV", "ARGV", "ARGVOUT", "_"); }
172              
173 8     8   45 { no strict 'refs'; *{"pp_r$_"} = *{"pp_$_"} for qw< keys each values >; }
  8         13  
  8         28381  
174              
175             # FIXME:
176             # Different in 5.20. Go over differences to see if okay in 5.20.
177             sub pp_chdir {
178 0     0 0 0 my ($self, $op, $cx) = @_;
179 0 0       0 if (($op->flags & (OPf_SPECIAL|OPf_KIDS)) == (OPf_SPECIAL|OPf_KIDS)) {
180 0         0 my $kw = $self->keyword("chdir");
181 0         0 my $kid = $self->const_sv($op->first)->PV;
182             my $code = $kw
183 0 0 0     0 . ($cx >= 16 || $self->{'parens'} ? "($kid)" : " $kid");
184 0     0   0 maybe_targmy(@_, sub { $_[3] }, $code);
  0         0  
185             } else {
186 0         0 maybe_targmy(@_, \&unop, "chdir")
187             }
188             }
189              
190             my @threadsv_names = B::threadsv_names;
191             sub pp_threadsv {
192 0     0 0 0 my $self = shift;
193 0         0 my($op, $cx) = @_;
194 0         0 return $self->maybe_local_str($op, $cx, "\$" . $threadsv_names[$op->targ]);
195             }
196              
197 0     0 0 0 sub pp_rv2sv { maybe_local_str(@_, rv2x(@_, "\$")) }
198 4     4 0 12 sub pp_rv2hv { maybe_local_str(@_, rv2x(@_, "%")) }
199 6     6 0 19 sub pp_rv2gv { maybe_local_str(@_, rv2x(@_, "*")) }
200              
201             # skip rv2av
202             sub pp_av2arylen {
203 32     32 0 41 my $self = shift;
204 32         50 my($op, $cx) = @_;
205 32 50       118 if ($op->first->name eq "padav") {
206 0         0 return $self->maybe_local_str($op, $cx, '$#' . $self->padany($op->first));
207             } else {
208 32         121 return $self->maybe_local_str($op, $cx,
209             $self->rv2x($op->first, $cx, '$#'));
210             }
211             }
212              
213             sub pp_rv2av {
214 33     33 0 48 my $self = shift;
215 33         61 my($op, $cx) = @_;
216 33         101 my $kid = $op->first;
217 33 50       127 if ($kid->name eq "const") { # constant list
218 0         0 my $av = $self->const_sv($kid);
219 0         0 return $self->list_const($kid, $cx, $av->ARRAY);
220             } else {
221 33         111 return $self->maybe_local_str($op, $cx,
222             $self->rv2x($op, $cx, "\@"));
223             }
224             }
225              
226             sub elem_or_slice_array_name
227             {
228 3     3 0 5 my $self = shift;
229 3         8 my ($array, $left, $padname, $allow_arrow) = @_;
230              
231 3 50 0     12 if ($array->name eq $padname) {
    0          
    0          
    0          
232 3         38 return $self->padany($array);
233             } elsif (B::Deparse::is_scope($array)) { # ${expr}[0]
234 0         0 return "{" . $self->deparse($array, 0) . "}";
235             } elsif ($array->name eq "gv") {
236 0 0       0 ($array, my $quoted) =
237             $self->stash_variable_name(
238             $left eq '[' ? '@' : '%', $self->gv_or_padgv($array)
239             );
240 0 0 0     0 if (!$allow_arrow && $quoted) {
241             # This cannot happen.
242 0         0 die "Invalid variable name $array for slice";
243             }
244 0 0       0 return $quoted ? "$array->" : $array;
245             } elsif (!$allow_arrow || B::Deparse::is_scalar $array) {
246             # $x[0], $$x[0], ...
247 0         0 return $self->deparse($array, 24)->{text};
248             } else {
249 0         0 return undef;
250             }
251             }
252              
253             sub elem_or_slice_single_index($$)
254             {
255 3     3 0 7 my ($self, $idx, $parent) = @_;
256              
257 3         11 my $idx_info = $self->deparse($idx, 1, $parent);
258 3         7 my $idx_str = $idx_info->{text};
259              
260             # Outer parens in an array index will confuse perl
261             # if we're interpolating in a regular expression, i.e.
262             # /$x$foo[(-1)]/ is *not* the same as /$x$foo[-1]/
263             #
264             # If $self->{parens}, then an initial '(' will
265             # definitely be paired with a final ')'. If
266             # !$self->{parens}, the misleading parens won't
267             # have been added in the first place.
268             #
269             # [You might think that we could get "(...)...(...)"
270             # where the initial and final parens do not match
271             # each other. But we can't, because the above would
272             # only happen if there's an infix binop between the
273             # two pairs of parens, and *that* means that the whole
274             # expression would be parenthesized as well.]
275             #
276 3 50       6 $idx_str =~ s/^\((.*)\)$/$1/ if $self->{'parens'};
277              
278             # Hash-element braces will autoquote a bareword inside themselves.
279             # We need to make sure that C<$hash{warn()}> doesn't come out as
280             # C<$hash{warn}>, which has a quite different meaning. Currently
281             # B::Deparse will always quote strings, even if the string was a
282             # bareword in the original (i.e. the OPpCONST_BARE flag is ignored
283             # for constant strings.) So we can cheat slightly here - if we see
284             # a bareword, we know that it is supposed to be a function call.
285             #
286 3         24 $idx_str =~ s/^([A-Za-z_]\w*)$/$1()/;
287              
288 3         16 return info_from_text($idx_info->{op}, $self, $idx_str,
289             'elem_or_slice_single_index',
290             {body => [$idx_info]});
291             }
292              
293             sub elem
294             {
295 0     0   0 my ($self, $op, $cx, $left, $right, $padname) = @_;
296 0         0 my($array, $idx) = ($op->first, $op->first->sibling);
297              
298 0         0 my $idx_info = $self->elem_or_slice_single_index($idx, $op);
299 0         0 my $opts = {body => [$idx_info]};
300              
301 0 0       0 unless ($array->name eq $padname) { # Maybe this has been fixed
302 0         0 $opts->{other_ops} = [$array];
303 0         0 $array = $array->first; # skip rv2av (or ex-rv2av in _53+)
304             }
305 0         0 my @texts = ();
306 0         0 my $info;
307 0         0 my $array_name=$self->elem_or_slice_array_name($array, $left, $padname, 1);
308 0 0       0 if ($array_name) {
309 0 0       0 if ($array_name !~ /->\z/) {
310 0 0       0 if ($array_name eq '#') {
311 0         0 $array_name = '${#}';
312             } else {
313 0         0 $array_name = '$' . $array_name ;
314             }
315             }
316 0         0 push @texts, $array_name;
317 0 0       0 push @texts, $left if $left;
318 0         0 push @texts, $idx_info->{text}, $right;
319 0         0 return info_from_list($op, $self, \@texts, '', 'elem', $opts)
320             } else {
321             # $x[20][3]{hi} or expr->[20]
322 0         0 my $type;
323 0         0 my $array_info = $self->deparse($array, 24, $op);
324 0         0 push @{$info->{body}}, $array_info;
  0         0  
325 0         0 @texts = ($array_info->{text});
326 0 0       0 if (B::Deparse::is_subscriptable($array)) {
327 0         0 push @texts, $left, $idx_info->{text}, $right;
328 0         0 $type = 'elem_no_arrow';
329             } else {
330 0         0 push @texts, '->', $left, $idx_info->{text}, $right;
331 0         0 $type = 'elem_arrow';
332             }
333 0         0 return info_from_list($op, $self, \@texts, '', $type, $opts);
334             }
335 0         0 Carp::confess("unhandled condition in elem");
336             }
337              
338             # a simplified version of elem_or_slice_array_name()
339             # for the use of pp_multideref
340              
341             sub multideref_var_name($$$)
342             {
343 7     7 0 13 my ($self, $gv, $is_hash) = @_;
344              
345 7 100       120 my ($name, $quoted) =
346             $self->stash_variable_name( $is_hash ? '%' : '@', $gv);
347 7 100       31 return $quoted ? "$name->"
    50          
348             : $name eq '#'
349             ? '${#}' # avoid ${#}[1] => $#[1]
350             : '$' . $name;
351             }
352              
353             sub pp_multideref
354             {
355 9     9 0 20 my($self, $op, $cx) = @_;
356 9         17 my @texts = ();
357              
358 9 100       55 if ($op->private & OPpMULTIDEREF_EXISTS) {
    100          
    50          
359 4         62 @texts = ($self->keyword("exists"), ' ');
360             }
361             elsif ($op->private & OPpMULTIDEREF_DELETE) {
362 4         64 @texts = ($self->keyword("delete"), ' ')
363             }
364             elsif ($op->private & OPpLVAL_INTRO) {
365 0         0 @texts = ($self->keyword("local"), ' ')
366             }
367              
368 9 50 33     80 if ($op->first && ($op->first->flags & OPf_KIDS)) {
369             # arbitrary initial expression, e.g. f(1,2,3)->[...]
370 0         0 my $first = $self->deparse($op->first, 24, $op);
371 0         0 push @texts, $first->{text};
372             }
373              
374 9         55 my @items = $op->aux_list($self->{curcv});
375 9         17 my $actions = shift @items;
376              
377 9         16 my $is_hash;
378 9         11 my $derefs = 0;
379              
380 9         12 while (1) {
381 9 50       23 if (($actions & MDEREF_ACTION_MASK) == MDEREF_reload) {
382 0         0 $actions = shift @items;
383 0         0 next;
384             }
385              
386             $is_hash = (
387 9   66     104 ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_pop_rv2hv_helem
388             || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_gvsv_vivify_rv2hv_helem
389             || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_padsv_vivify_rv2hv_helem
390             || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_vivify_rv2hv_helem
391             || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_padhv_helem
392             || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_gvhv_helem
393             );
394              
395 9 100 66     50 if ( ($actions & MDEREF_ACTION_MASK) == MDEREF_AV_padav_aelem
    50 66        
396             || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_padhv_helem)
397             {
398 2         4 $derefs = 1;
399 2         18 push @texts, '$' . substr($self->padname(shift @items), 1);
400             }
401             elsif ( ($actions & MDEREF_ACTION_MASK) == MDEREF_AV_gvav_aelem
402             || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_gvhv_helem)
403             {
404 7         12 $derefs = 1;
405 7         27 push @texts, $self->multideref_var_name(shift @items, $is_hash);
406             }
407             else {
408 0 0 0     0 if ( ($actions & MDEREF_ACTION_MASK) ==
    0 0        
    0 0        
409             MDEREF_AV_padsv_vivify_rv2av_aelem
410             || ($actions & MDEREF_ACTION_MASK) ==
411             MDEREF_HV_padsv_vivify_rv2hv_helem)
412             {
413 0         0 push @texts, $self->padname(shift @items);
414             }
415             elsif ( ($actions & MDEREF_ACTION_MASK) ==
416             MDEREF_AV_gvsv_vivify_rv2av_aelem
417             || ($actions & MDEREF_ACTION_MASK) ==
418             MDEREF_HV_gvsv_vivify_rv2hv_helem)
419             {
420 0         0 push @texts, $self->multideref_var_name(shift @items, $is_hash);
421             }
422             elsif ( ($actions & MDEREF_ACTION_MASK) ==
423             MDEREF_AV_pop_rv2av_aelem
424             || ($actions & MDEREF_ACTION_MASK) ==
425             MDEREF_HV_pop_rv2hv_helem)
426             {
427 0 0 0     0 if ( ($op->flags & OPf_KIDS)
      0        
      0        
      0        
      0        
428             && ( B::Deparse::_op_is_or_was($op->first, OP_RV2AV)
429             || B::Deparse::_op_is_or_was($op->first, OP_RV2HV))
430             && ($op->first->flags & OPf_KIDS)
431             && ( B::Deparse::_op_is_or_was($op->first->first, OP_AELEM)
432             || B::Deparse::_op_is_or_was($op->first->first, OP_HELEM))
433             )
434             {
435 0         0 $derefs++;
436             }
437             }
438              
439 0 0       0 push(@texts, '->') if !$derefs++;
440             }
441              
442              
443 9 50       30 if (($actions & MDEREF_INDEX_MASK) == MDEREF_INDEX_none) {
444 0         0 last;
445             }
446              
447 9 100       33 push(@texts, $is_hash ? '{' : '[');
448              
449 9 50       19 if (($actions & MDEREF_INDEX_MASK) == MDEREF_INDEX_const) {
    0          
    0          
450 9         13 my $key = shift @items;
451 9 100       16 if ($is_hash) {
452 5         19 push @texts, $self->const($key, $cx)->{text};
453             }
454             else {
455 4         8 push @texts, $key;
456             }
457             }
458             elsif (($actions & MDEREF_INDEX_MASK) == MDEREF_INDEX_padsv) {
459 0         0 push @texts, $self->padname(shift @items);
460             }
461             elsif (($actions & MDEREF_INDEX_MASK) == MDEREF_INDEX_gvsv) {
462 0         0 push @texts,('$' . ($self->stash_variable_name('$', shift @items))[0]);
463             }
464              
465 9 100       39 push(@texts, $is_hash ? '}' : ']');
466              
467 9 50       22 if ($actions & MDEREF_FLAG_last) {
468 9         21 last;
469             }
470 0         0 $actions >>= MDEREF_SHIFT;
471             }
472              
473 9         32 return info_from_list($op, $self, \@texts, '', 'multideref', {});
474             }
475              
476             # returns "&" and the argument bodies if the prototype doesn't match the args,
477             # or ("", $args_after_prototype_demunging) if it does.
478             sub check_proto {
479 1     1 0 3 my $self = shift;
480 1         2 my $op = shift;
481 1 50       4 return ('&', []) if $self->{'noproto'};
482 1         4 my($proto, @args) = @_;
483 1         2 my($arg, $real);
484 1         2 my $doneok = 0;
485 1         2 my @reals;
486             # An unbackslashed @ or % gobbles up the rest of the args
487 1         4 1 while $proto =~ s/(?
488 1         4 $proto =~ s/^\s*//;
489 1         4 while ($proto) {
490 4         14 $proto =~ s/^(\\?[\$\@&%*_]|\\\[[\$\@&%*]+\]|;)\s*//;
491 4         9 my $chr = $1;
492 4 50 33     26 if ($chr eq "") {
    100          
    50          
493 0 0       0 return ('&', []) if @args;
494             } elsif ($chr eq ";") {
495 1         3 $doneok = 1;
496             } elsif ($chr eq "@" or $chr eq "%") {
497 0         0 push @reals, map($self->deparse($_, 6), @args, $op);
498 0         0 @args = ();
499             } else {
500 3         4 $arg = shift @args;
501 3 100       8 last unless $arg;
502 2 50 33     6 if ($chr eq "\$" || $chr eq "_") {
    0          
    0          
    0          
503 2 50       12 if (B::Deparse::want_scalar $arg) {
504 2         6 push @reals, $self->deparse($arg, 6, $op);
505             } else {
506 0         0 return ('&', []);
507             }
508             } elsif ($chr eq "&") {
509 0 0       0 if ($arg->name =~ /^(s?refgen|undef)$/) {
510 0         0 push @reals, $self->deparse($arg, 6, $op);
511             } else {
512 0         0 return ('&', []);
513             }
514             } elsif ($chr eq "*") {
515 0 0 0     0 if ($arg->name =~ /^s?refgen$/
516             and $arg->first->first->name eq "rv2gv")
517             {
518 0         0 $real = $arg->first->first; # skip refgen, null
519 0 0       0 if ($real->first->name eq "gv") {
520 0         0 push @reals, $self->deparse($real, 6, $op);
521             } else {
522 0         0 push @reals, $self->deparse($real->first, 6, $op);
523             }
524             } else {
525 0         0 return ('&', []);
526             }
527             } elsif (substr($chr, 0, 1) eq "\\") {
528 0         0 $chr =~ tr/\\[]//d;
529 0 0 0     0 if ($arg->name =~ /^s?refgen$/ and
      0        
      0        
530             !B::Deparse::null($real = $arg->first) and
531             ($chr =~ /\$/ && B::Deparse::is_scalar($real->first)
532             or ($chr =~ /@/
533             && class($real->first->sibling) ne 'NULL'
534             && $real->first->sibling->name
535             =~ /^(rv2|pad)av$/)
536             or ($chr =~ /%/
537             && class($real->first->sibling) ne 'NULL'
538             && $real->first->sibling->name
539             =~ /^(rv2|pad)hv$/)
540             #or ($chr =~ /&/ # This doesn't work
541             # && $real->first->name eq "rv2cv")
542             or ($chr =~ /\*/
543             && $real->first->name eq "rv2gv")))
544             {
545 0         0 push @reals, $self->deparse($real, 6, $op);
546             } else {
547 0         0 return ('&', []);
548             }
549             }
550             }
551             }
552 1 50 33     4 return ('&', []) if $proto and !$doneok; # too few args and no ';'
553 1 50       3 return ('&', []) if @args; # too many args
554 1         12 return ('', \@reals);
555             }
556              
557             # Like dq(), but different
558             sub re_dq {
559 1     1 0 3 my $self = shift;
560 1         2 my ($op) = @_;
561 1         2 my ($re_dq_info, $fmt);
562              
563 1         4 my $type = $op->name;
564 1 50       14 if ($type eq "const") {
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
565 0 0       0 return '$[' if $op->private & OPpCONST_ARYBASE;
566 0         0 my $unbacked = B::Deparse::re_unback($self->const_sv($op)->as_string);
567 0         0 return B::Deparse::re_uninterp(escape_re($unbacked));
568             } elsif ($type eq "concat") {
569 0         0 my $first = $self->re_dq($op->first);
570 0         0 my $last = $self->re_dq($op->last);
571 0         0 return B::Deparse::re_dq_disambiguate($first, $last);
572             } elsif ($type eq "uc") {
573 0         0 $re_dq_info = $self->re_dq($op->first->sibling);
574 0         0 $fmt = '\U%c\E';
575 0         0 $type .= ' uc';
576             } elsif ($type eq "lc") {
577 0         0 $re_dq_info = $self->re_dq($op->first->sibling);
578 0         0 $fmt = '\L%c\E';
579 0         0 $type .= ' lc';
580             } elsif ($type eq "ucfirst") {
581 0         0 $re_dq_info = $self->re_dq($op->first->sibling);
582 0         0 $fmt = '\u%c';
583 0         0 $type .= ' ucfirst';
584             } elsif ($type eq "lcfirst") {
585 0         0 $re_dq_info = $self->re_dq($op->first->sibling);
586 0         0 $fmt = '\u%c';
587 0         0 $type .= ' lcfirst';
588             } elsif ($type eq "quotemeta") {
589 0         0 $re_dq_info = $self->re_dq($op->first->sibling);
590 0         0 $fmt = '\Q%c\E';
591 0         0 $type .= ' quotemeta';
592             } elsif ($type eq "fc") {
593 0         0 $re_dq_info = $self->re_dq($op->first->sibling);
594 0         0 $fmt = '\F%c\E';
595 0         0 $type .= ' fc';
596             } elsif ($type eq "join") {
597 0         0 return $self->deparse($op->last, 26); # was join($", @ary)
598             } else {
599 1         5 my $ret = $self->deparse($op, 26);
600 1 50       7 $ret =~ s/^\$([(|)])\z/\${$1}/ # $( $| $) need braces
601             or $ret =~ s/^\@([-+])\z/\@{$1}/; # @- @+ need braces
602 1         3 return $ret;
603             }
604 0         0 return $self->info_from_template($type, $op->first->sibling,
605             $fmt, [$re_dq_info], [0]);
606             }
607              
608             sub pure_string {
609 8     8 0 24 my ($self, $op) = @_;
610 8 50       46 return 0 if B::Deparse::null $op;
611 8         31 my $type = $op->name;
612              
613 8 50 33     249 if ($type eq 'const' || $type eq 'av2arylen') {
    50 33        
    50 33        
    50 66        
    50 66        
    100 33        
      33        
614 0         0 return 1;
615             }
616             elsif ($type =~ /^(?:[ul]c(first)?|fc)$/ || $type eq 'quotemeta') {
617 0         0 return $self->pure_string($op->first->sibling);
618             }
619             elsif ($type eq 'join') {
620 0         0 my $join_op = $op->first->sibling; # Skip pushmark
621 0 0 0     0 return 0 unless $join_op->name eq 'null' && $join_op->targ == OP_RV2SV;
622              
623 0         0 my $gvop = $join_op->first;
624 0 0       0 return 0 unless $gvop->name eq 'gvsv';
625 0 0       0 return 0 unless '"' eq $self->gv_name($self->gv_or_padgv($gvop));
626              
627 0 0       0 return 0 unless ${$join_op->sibling} eq ${$op->last};
  0         0  
  0         0  
628 0 0       0 return 0 unless $op->last->name =~ /^(?:[ah]slice|(?:rv2|pad)av)$/;
629             }
630             elsif ($type eq 'concat') {
631 0   0     0 return $self->pure_string($op->first)
632             && $self->pure_string($op->last);
633             }
634             elsif (B::Deparse::is_scalar($op) || $type =~ /^[ah]elem$/) {
635 0         0 return 1;
636             }
637             elsif ($type eq "null" and $op->can('first') and not B::Deparse::null $op->first and
638             ($op->first->name eq "null" and $op->first->can('first')
639             and not B::Deparse::null $op->first->first and
640             $op->first->first->name eq "aelemfast"
641             or
642             $op->first->name =~ /^aelemfast(?:_lex)?\z/
643             )) {
644 1         6 return 1;
645             }
646             else {
647 7         23 return 0;
648             }
649              
650 0         0 return 1;
651             }
652              
653             sub regcomp
654             {
655 5     5 0 12 my($self, $op, $cx, $extended) = @_;
656 5         7 my @other_ops = ();
657 5         15 my $kid = $op->first;
658 5 50       19 if ($kid->name eq "regcmaybe") {
659 0         0 push @other_ops, $kid;
660 0         0 $kid = $kid->first;
661             }
662 5 50       15 if ($kid->name eq "regcreset") {
663 0         0 push @other_ops, $kid;
664 0         0 $kid = $kid->first;
665             }
666 5 50 66     35 if ($kid->name eq "null" and !B::Deparse::null($kid->first)
      66        
667             and $kid->first->name eq 'pushmark') {
668 0         0 my $str = '';
669 0         0 push(@other_ops, $kid);
670 0         0 $kid = $kid->first->sibling;
671 0         0 my @body = ();
672 0         0 while (!B::Deparse::null($kid)) {
673 0         0 my $first = $str;
674 0         0 my $last = $self->re_dq($kid, $extended);
675 0         0 push @body, $last;
676 0         0 push(@other_ops, $kid);
677 0         0 $str = B::Deparse::re_dq_disambiguate($first,
678             $self->info2str($last));
679 0         0 $kid = $kid->sibling;
680             }
681 0         0 return (info_from_text($op, $self, $str, 'regcomp',
682             {other_ops => \@other_ops,
683             body => \@body}), 1);
684             }
685              
686 5 100       16 if ($self->pure_string($kid)) {
687 1         11 my $info = $self->re_dq($kid, $extended);
688 1 50       4 my @kid_ops = $info->{other_ops} ? @{$info->{other_ops}} : ();
  0         0  
689 1         2 push @other_ops, @kid_ops;
690 1         3 $info->{other_ops} = \@other_ops;
691 1         4 return ($info, 1);
692             }
693 4         13 return ($self->deparse($kid, $cx, $op), 0, $op);
694             }
695              
696             sub pp_split
697             {
698 0     0     my($self, $op, $cx) = @_;
699 0           my($kid, @exprs, $ary_info, $expr);
700 0           my $stacked = $op->flags & OPf_STACKED;
701 0           my $ary = '';
702 0           my @body = ();
703 0           my @other_ops = ();
704 0           $kid = $op->first;
705              
706 0           $kid = $op->first;
707 0 0         $kid = $kid->sibling if $kid->name eq 'regcomp';
708 0           for (; !B::Deparse::null($kid); $kid = $kid->sibling) {
709 0           push @exprs, $self->deparse($kid, 6, $op);
710             }
711              
712 0           unshift @exprs, $self->matchop($op, $cx, "m", "/");
713              
714 0 0         if ($op->private & OPpSPLIT_ASSIGN) {
715             # With C<@array = split(/pat/, str);>,
716             # array is stored in split's pmreplroot; either
717             # as an integer index into the pad (for a lexical array)
718             # or as GV for a package array (which will be a pad index
719             # on threaded builds)
720             # With my/our @array = split(/pat/, str), the array is instead
721             # accessed via an extra padav/rv2av op at the end of the
722             # split's kid ops.
723              
724 0 0         if ($stacked) {
725 0           $ary = pop @exprs;
726             }
727             else {
728 0 0         if ($op->private & OPpSPLIT_LEX) {
729 0           $ary = $self->padname($op->pmreplroot);
730             }
731             else {
732             # union with op_pmtargetoff, op_pmtargetgv
733 0           my $gv = $op->pmreplroot;
734 0 0         $gv = $self->padval($gv) if !ref($gv);
735 0           $ary = $self->maybe_local(@_,
736             $self->stash_variable('@',
737             $self->gv_name($gv),
738             $cx))
739             }
740 0 0         if ($op->private & OPpLVAL_INTRO) {
741 0 0         $ary = $op->private & OPpSPLIT_LEX ? "my $ary" : "local $ary";
742             }
743             }
744             }
745              
746 0           push @body, @exprs;
747 0           my $opts = {body => \@exprs};
748              
749             # handle special case of split(), and split(' ') that compiles to /\s+/
750 0 0 0       if (($op->reflags // 0) & RXf_SKIPWHITE()) {
751 0           my $expr0 = $exprs[0];
752 0           my $expr0b0 = $expr0->{body}[0];
753 0           my $bsep = $expr0b0->{sep};
754 0           my $sep = $expr0->{sep};
755 0           $expr0b0->{texts}[1] = ' ';
756             # substr($expr0b0->{text}, 1, 0) = ' ';
757 0           substr($expr0->{texts}[0], 1, 0) = ' ';
758 0           substr($expr0->{text}, 1, 0) = ' ';
759             }
760 0           my @args_texts = map $_->{text}, @exprs;
761              
762 0           my $sep = '';
763 0           my $type;
764             my @expr_texts;
765 0 0         if ($ary) {
766 0           @expr_texts = ("$ary", '=', join(', ', @args_texts));
767 0           $sep = ' ';
768 0           $type = 'split_array';
769 0           $opts->{maybe_parens} = [$self, $cx, 7];
770             } else {
771 0           @expr_texts = ('split', '(', join(', ', @args_texts), ')');
772 0           $type = 'split';
773              
774             }
775 0           return info_from_list($op, $self, \@expr_texts, $sep, $type, $opts);
776             }
777              
778             # Not in Perl 5.20 and presumably < 5.20. No harm in adding to 5.20?
779             *pp_ncomplement = *pp_complement;
780              
781             1;