File Coverage

lib/B/DeparseTree/P526.pm
Criterion Covered Total %
statement 235 523 44.9
branch 77 254 30.3
condition 30 122 24.5
subroutine 43 64 67.1
pod 0 40 0.0
total 385 1003 38.3


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 3     3   38 use v5.26;
  3         9  
16              
17 3     3   13 use rlib '../..';
  3         4  
  3         21  
18              
19             package B::DeparseTree::P526;
20 3     3   893 use Carp;
  3         5  
  3         294  
21              
22 3         680 use B qw(class main_root main_start main_cv svref_2object opnumber perlstring
23             OPf_KIDS OPf_REF OPf_STACKED OPf_SPECIAL OPf_MOD OPf_PARENS
24             OPf_WANT OPf_WANT_VOID OPf_WANT_SCALAR OPf_WANT_LIST
25             OPpEXISTS_SUB OPpSORT_NUMERIC OPpSORT_INTEGER
26             OPpLVAL_INTRO OPpOUR_INTRO OPpENTERSUB_AMPER OPpSLICE OPpCONST_BARE
27             OPpSORT_REVERSE OPpMULTIDEREF_EXISTS OPpMULTIDEREF_DELETE
28             OPpTARGET_MY
29             PADNAMEt_OUTER
30             PMf_KEEP PMf_GLOBAL PMf_CONTINUE PMf_EVAL PMf_ONCE
31             PMf_MULTILINE PMf_SINGLELINE PMf_FOLD PMf_EXTENDED PMf_EXTENDED_MORE
32             SVf_ROK SVpad_OUR SVf_FAKE SVs_RMG SVs_SMG
33             SVpad_TYPED
34             CVf_METHOD
35             MDEREF_ACTION_MASK
36             MDEREF_AV_gvav_aelem
37             MDEREF_AV_gvsv_vivify_rv2av_aelem
38             MDEREF_AV_padav_aelem
39             MDEREF_AV_padsv_vivify_rv2av_aelem
40             MDEREF_AV_pop_rv2av_aelem
41             MDEREF_AV_vivify_rv2av_aelem
42             MDEREF_FLAG_last
43             MDEREF_HV_gvhv_helem
44             MDEREF_HV_gvsv_vivify_rv2hv_helem
45             MDEREF_HV_padhv_helem
46             MDEREF_HV_padsv_vivify_rv2hv_helem
47             MDEREF_HV_pop_rv2hv_helem
48             MDEREF_HV_vivify_rv2hv_helem
49             MDEREF_INDEX_MASK
50             MDEREF_INDEX_const
51             MDEREF_INDEX_gvsv
52             MDEREF_INDEX_none
53             MDEREF_INDEX_padsv
54             MDEREF_MASK
55             MDEREF_SHIFT
56             MDEREF_reload
57             OPpPADRANGE_COUNTSHIFT
58             OPpSPLIT_ASSIGN OPpSPLIT_LEX
59 3     3   15 );
  3         4  
60              
61 3     3   1693 use B::DeparseTree::PPfns;
  3         8  
  3         799  
62 3     3   24 use B::DeparseTree::SyntaxTree;
  3         4  
  3         257  
63 3     3   1419 use B::DeparseTree::PP;
  3         37  
  3         1461  
64 3     3   20 use B::Deparse;
  3         4  
  3         386  
65              
66             # Copy unchanged functions from B::Deparse
67             *begin_is_use = *B::Deparse::begin_is_use;
68             *const_sv = *B::Deparse::const_sv;
69             *escape_re = *B::Deparse::escape_re;
70             *find_scope_st = *B::Deparse::find_scope_st;
71             *gv_name = *B::Deparse::gv_name;
72             *keyword = *B::Deparse::keyword;
73             *meth_pad_subs = *B::Deparse::pad_subs;
74             *meth_rclass_sv = *B::Deparse::meth_rclass_sv;
75             *meth_sv = *B::Deparse::meth_sv;
76             *padany = *B::Deparse::padany;
77             *padname = *B::Deparse::padname;
78             *padname_sv = *B::Deparse::padname_sv;
79             *padval = *B::Deparse::padval;
80             *re_flags = *B::Deparse::re_flags;
81             *stash_variable = *B::Deparse::stash_variable;
82             *stash_variable_name = *B::Deparse::stash_variable_name;
83             *tr_chr = *B::Deparse::tr_chr;
84              
85 3     3   16 use strict;
  3         4  
  3         66  
86 3     3   12 use vars qw/$AUTOLOAD/;
  3         4  
  3         128  
87 3     3   13 use warnings ();
  3         4  
  3         290  
88             require feature;
89              
90             our(@EXPORT, @ISA);
91             our $VERSION = '3.2.0';
92              
93             @ISA = qw(Exporter B::DeparseTree::PP);
94              
95             @EXPORT = qw(slice);
96              
97             BEGIN {
98             # List version-specific constants here.
99             # Easiest way to keep this code portable between version looks to
100             # be to fake up a dummy constant that will never actually be true.
101 3     3   10 foreach (qw(OPpSORT_INPLACE OPpSORT_DESCEND OPpITER_REVERSED OPpCONST_NOVER
102             OPpPAD_STATE PMf_SKIPWHITE RXf_SKIPWHITE
103             PMf_CHARSET PMf_KEEPCOPY PMf_NOCAPTURE CVf_ANONCONST
104             CVf_LOCKED OPpREVERSE_INPLACE OPpSUBSTR_REPL_FIRST
105             PMf_NONDESTRUCT OPpCONST_ARYBASE OPpEVAL_BYTES
106             OPpLVREF_TYPE OPpLVREF_SV OPpLVREF_AV OPpLVREF_HV
107             OPpLVREF_CV OPpLVREF_ELEM SVpad_STATE)) {
108 72         99 eval { B->import($_) };
  72         2895  
109 3     3   17 no strict 'refs';
  3         4  
  3         200  
110 72 100       106 *{$_} = sub () {0} unless *{$_}{CODE};
  9         37  
  72         581  
111             }
112             }
113              
114 3     3   11 BEGIN { for (qw[ rv2sv aelem
115             rv2av rv2hv helem custom ]) {
116 18         1088 eval "sub OP_\U$_ () { " . opnumber($_) . "}"
117             }}
118              
119             # pp_padany -- does not exist after parsing
120              
121             sub AUTOLOAD {
122 0 0   0   0 if ($AUTOLOAD =~ s/^.*::pp_//) {
123 0         0 warn "unexpected OP_".uc $AUTOLOAD;
124 0 0       0 ($_[1]->type == OP_CUSTOM ? "CUSTOM ($AUTOLOAD)" : uc $AUTOLOAD);
125 0         0 return "XXX";
126             } else {
127 0         0 Carp::confess "Undefined subroutine $AUTOLOAD called";
128             }
129             }
130              
131       0     sub DESTROY {} # Do not AUTOLOAD
132              
133             # The BEGIN {} is used here because otherwise this code isn't executed
134             # when you run B::Deparse on itself.
135             my %globalnames;
136 3     3   91 BEGIN { map($globalnames{$_}++, "SIG", "STDIN", "STDOUT", "STDERR", "INC",
137             "ENV", "ARGV", "ARGVOUT", "_"); }
138              
139 3     3   23 { no strict 'refs'; *{"pp_r$_"} = *{"pp_$_"} for qw< keys each values >; }
  3         11  
  3         16751  
140              
141             # FIXME:
142             # Different in 5.20. Go over differences to see if okay in 5.20.
143             sub pp_chdir {
144 0     0 0 0 my ($self, $op, $cx) = @_;
145 0 0       0 if (($op->flags & (OPf_SPECIAL|OPf_KIDS)) == (OPf_SPECIAL|OPf_KIDS)) {
146 0         0 my $kw = $self->keyword("chdir");
147 0         0 my $kid = $self->const_sv($op->first)->PV;
148             my $code = $kw
149 0 0 0     0 . ($cx >= 16 || $self->{'parens'} ? "($kid)" : " $kid");
150 0     0   0 maybe_targmy(@_, sub { $_[3] }, $code);
  0         0  
151             } else {
152 0         0 maybe_targmy(@_, \&unop, "chdir")
153             }
154             }
155              
156             sub pp_readline {
157 6     6 0 10 my $self = shift;
158 6         11 my($op, $cx) = @_;
159 6         40 my $kid = $op->first;
160 6 50       30 $kid = $kid->first if $kid->name eq "rv2gv"; # <$fh>
161 6 50 66     70 if (B::Deparse::is_scalar($kid)
      33        
162             and $op->flags & OPf_SPECIAL
163             and $self->deparse($kid, 1) eq 'ARGV') {
164 0         0 my $body = [$self->deparse($kid, 1, $op)];
165 0         0 return info_from_list($op, $self, ['<', $body->[0]{text}, '>'], '',
166             'readline_scalar', {body=>$body});
167             }
168 6         25 return $self->unop($op, $cx, "readline");
169             }
170              
171             sub pp_rcatline {
172 0     0 0 0 my $self = shift;
173 0         0 my($op) = @_;
174 0         0 return info_from_list($op, $self, ["<", $self->gv_name($self->gv_or_padgv($op)), ">"],
175             '', 'rcatline', {});
176             }
177              
178             sub pp_smartmatch {
179 0     0 0 0 my ($self, $op, $cx) = @_;
180 0 0       0 if ($op->flags & OPf_SPECIAL) {
181 0         0 return $self->deparse($op->last, $cx, $op);
182             }
183             else {
184 0         0 binop(@_, "~~", 14);
185             }
186             }
187              
188             sub bin_info_join($$$$$$$) {
189 6     6 0 11 my ($self, $op, $lhs, $rhs, $mid, $sep, $type) = @_;
190 6         20 my $texts = [$lhs->{text}, $mid, $rhs->{text}];
191 6         28 return info_from_list($op, $self, $texts, ' ', $type, {})
192             }
193              
194             sub bin_info_join_maybe_parens($$$$$$$$$) {
195 6     6 0 19 my ($self, $op, $lhs, $rhs, $mid, $sep, $cx, $prec, $type) = @_;
196 6         16 my $info = bin_info_join($self, $op, $lhs, $rhs, $mid, $sep, $type);
197 6         28 $info->{text} = $self->maybe_parens($info->{text}, $cx, $prec);
198 6         22 return $info;
199             }
200              
201             sub for_loop {
202 0     0 0 0 my $self = shift;
203 0         0 my($op, $cx, $parent) = @_;
204 0         0 my $init = $self->deparse($op, 1, $parent);
205 0         0 my $s = $op->sibling;
206 0 0       0 my $ll = $s->name eq "unstack" ? $s->sibling : $s->first->sibling;
207 0         0 return $self->loop_common($ll, $cx, $init);
208             }
209              
210             sub pp_padsv {
211 4120     4120 0 5102 my $self = shift;
212 4120         6367 my($op, $cx, $forbid_parens) = @_;
213 4120         40145 return $self->maybe_my($op, $cx, $self->padname($op->targ),
214             $forbid_parens);
215             }
216              
217             my @threadsv_names = B::threadsv_names;
218             sub pp_threadsv {
219 0     0 0 0 my $self = shift;
220 0         0 my($op, $cx) = @_;
221 0         0 return $self->maybe_local_str($op, $cx, "\$" . $threadsv_names[$op->targ]);
222             }
223              
224             sub gv_or_padgv {
225 2282     2282 0 3184 my $self = shift;
226 2282         2648 my $op = shift;
227 2282 50       10865 if (class($op) eq "PADOP") {
228 0         0 return $self->padval($op->padix);
229             } else { # class($op) eq "SVOP"
230 2282         9271 return $op->gv;
231             }
232             }
233              
234             sub pp_aelemfast_lex
235             {
236 2     2 0 9 my($self, $op, $cx) = @_;
237 2         28 my $name = $self->padname($op->targ);
238 2         16 $name =~ s/^@/\$/;
239 2         17 return info_from_list($op, $self, [$name, "[", ($op->private + $self->{'arybase'}), "]"],
240             '', 'pp_aelemfast_lex', {});
241             }
242              
243             sub pp_aelemfast
244             {
245 1     1 0 4 my($self, $op, $cx) = @_;
246             # optimised PADAV, pre 5.15
247 1 50       6 return $self->pp_aelemfast_lex(@_) if ($op->flags & OPf_SPECIAL);
248              
249 1         5 my $gv = $self->gv_or_padgv($op);
250 1         16 my($name,$quoted) = $self->stash_variable_name('@',$gv);
251 1 50       5 $name = $quoted ? "$name->" : '$' . $name;
252 1         5 my $i = $op->private;
253 1 50       4 $i -= 256 if $i > 127;
254 1         10 return info_from_list($op, $self, [$name, "[", ($op->private + $self->{'arybase'}), "]"],
255             '', 'pp_aelemfast', {});
256             }
257              
258 0     0 0 0 sub pp_rv2sv { maybe_local_str(@_, rv2x(@_, "\$")) }
259 10     10 0 45 sub pp_rv2hv { maybe_local_str(@_, rv2x(@_, "%")) }
260 3     3 0 11 sub pp_rv2gv { maybe_local_str(@_, rv2x(@_, "*")) }
261              
262             # skip rv2av
263             sub pp_av2arylen {
264 32     32 0 52 my $self = shift;
265 32         51 my($op, $cx) = @_;
266 32 50       142 if ($op->first->name eq "padav") {
267 0         0 return $self->maybe_local_str($op, $cx, '$#' . $self->padany($op->first));
268             } else {
269 32         124 return $self->maybe_local_str($op, $cx,
270             $self->rv2x($op->first, $cx, '$#'));
271             }
272             }
273              
274             sub list_const($$$) {
275 0     0 0 0 my $self = shift;
276 0         0 my($op, $cx, @list) = @_;
277 0         0 my @a = map $self->const($_, 6), @list;
278 0         0 my @texts = $self->map_texts(\@a);
279 0         0 my $type = 'list_const';
280 0         0 my $prec = 6;
281 0 0 0     0 if (@texts == 0) {
    0          
    0          
282 0         0 return info_from_list($op, $self, ['(', ')'], '', 'list_const_null', {});
283             } elsif (@texts == 1) {
284 0         0 return info_from_text($op, $self, $texts[0], 'list_const_one',
285             {body => \@a});
286             } elsif ( @texts > 2 and !grep(!/^-?\d+$/, @texts)) {
287             # collapse (-1,0,1,2) into (-1..2)
288 0         0 my ($s, $e) = @texts[0,-1];
289 0         0 my $i = $s;
290 0 0       0 unless (grep $i++ != $_, @texts) {
291 0         0 @texts = ($s, '..', $e);
292 0         0 $type = 'list_const_range';
293 0         0 $prec = 9;
294             }
295             }
296 0         0 return info_from_list($op, $self, \@texts, '', $type,
297             {maybe_parens => [$self, $cx, $prec]});
298             }
299              
300             sub pp_rv2av {
301 33     33 0 55 my $self = shift;
302 33         68 my($op, $cx) = @_;
303 33         109 my $kid = $op->first;
304 33 50       133 if ($kid->name eq "const") { # constant list
305 0         0 my $av = $self->const_sv($kid);
306 0         0 return $self->list_const($kid, $cx, $av->ARRAY);
307             } else {
308 33         164 return $self->maybe_local_str($op, $cx,
309             $self->rv2x($op, $cx, "\@"));
310             }
311             }
312              
313             sub elem_or_slice_array_name
314             {
315 3     3 0 8 my $self = shift;
316 3         7 my ($array, $left, $padname, $allow_arrow) = @_;
317              
318 3 50 0     15 if ($array->name eq $padname) {
    0          
    0          
    0          
319 3         45 return $self->padany($array);
320             } elsif (B::Deparse::is_scope($array)) { # ${expr}[0]
321 0         0 return "{" . $self->deparse($array, 0) . "}";
322             } elsif ($array->name eq "gv") {
323 0 0       0 ($array, my $quoted) =
324             $self->stash_variable_name(
325             $left eq '[' ? '@' : '%', $self->gv_or_padgv($array)
326             );
327 0 0 0     0 if (!$allow_arrow && $quoted) {
328             # This cannot happen.
329 0         0 die "Invalid variable name $array for slice";
330             }
331 0 0       0 return $quoted ? "$array->" : $array;
332             } elsif (!$allow_arrow || B::Deparse::is_scalar $array) {
333             # $x[0], $$x[0], ...
334 0         0 return $self->deparse($array, 24)->{text};
335             } else {
336 0         0 return undef;
337             }
338             }
339              
340             sub elem_or_slice_single_index($$)
341             {
342 3     3 0 7 my ($self, $idx, $parent) = @_;
343              
344 3         10 my $idx_info = $self->deparse($idx, 1, $parent);
345 3         6 my $idx_str = $idx_info->{text};
346              
347             # Outer parens in an array index will confuse perl
348             # if we're interpolating in a regular expression, i.e.
349             # /$x$foo[(-1)]/ is *not* the same as /$x$foo[-1]/
350             #
351             # If $self->{parens}, then an initial '(' will
352             # definitely be paired with a final ')'. If
353             # !$self->{parens}, the misleading parens won't
354             # have been added in the first place.
355             #
356             # [You might think that we could get "(...)...(...)"
357             # where the initial and final parens do not match
358             # each other. But we can't, because the above would
359             # only happen if there's an infix binop between the
360             # two pairs of parens, and *that* means that the whole
361             # expression would be parenthesized as well.]
362             #
363 3 50       9 $idx_str =~ s/^\((.*)\)$/$1/ if $self->{'parens'};
364              
365             # Hash-element braces will autoquote a bareword inside themselves.
366             # We need to make sure that C<$hash{warn()}> doesn't come out as
367             # C<$hash{warn}>, which has a quite different meaning. Currently
368             # B::Deparse will always quote strings, even if the string was a
369             # bareword in the original (i.e. the OPpCONST_BARE flag is ignored
370             # for constant strings.) So we can cheat slightly here - if we see
371             # a bareword, we know that it is supposed to be a function call.
372             #
373 3         17 $idx_str =~ s/^([A-Za-z_]\w*)$/$1()/;
374              
375 3         15 return info_from_text($idx_info->{op}, $self, $idx_str,
376             'elem_or_slice_single_index',
377             {body => [$idx_info]});
378             }
379              
380             sub elem
381             {
382 0     0   0 my ($self, $op, $cx, $left, $right, $padname) = @_;
383 0         0 my($array, $idx) = ($op->first, $op->first->sibling);
384              
385 0         0 my $idx_info = $self->elem_or_slice_single_index($idx, $op);
386 0         0 my $opts = {body => [$idx_info]};
387              
388 0 0       0 unless ($array->name eq $padname) { # Maybe this has been fixed
389 0         0 $opts->{other_ops} = [$array];
390 0         0 $array = $array->first; # skip rv2av (or ex-rv2av in _53+)
391             }
392 0         0 my @texts = ();
393 0         0 my $info;
394 0         0 my $array_name=$self->elem_or_slice_array_name($array, $left, $padname, 1);
395 0 0       0 if ($array_name) {
396 0 0       0 if ($array_name !~ /->\z/) {
397 0 0       0 if ($array_name eq '#') {
398 0         0 $array_name = '${#}';
399             } else {
400 0         0 $array_name = '$' . $array_name ;
401             }
402             }
403 0         0 push @texts, $array_name;
404 0 0       0 push @texts, $left if $left;
405 0         0 push @texts, $idx_info->{text}, $right;
406 0         0 return info_from_list($op, $self, \@texts, '', 'elem', $opts)
407             } else {
408             # $x[20][3]{hi} or expr->[20]
409 0         0 my $type;
410 0         0 my $array_info = $self->deparse($array, 24, $op);
411 0         0 push @{$info->{body}}, $array_info;
  0         0  
412 0         0 @texts = ($array_info->{text});
413 0 0       0 if (is_subscriptable($array)) {
414 0         0 push @texts, $left, $idx_info->{text}, $right;
415 0         0 $type = 'elem_no_arrow';
416             } else {
417 0         0 push @texts, '->', $left, $idx_info->{text}, $right;
418 0         0 $type = 'elem_arrow';
419             }
420 0         0 return info_from_list($op, $self, \@texts, '', $type, $opts);
421             }
422 0         0 Carp::confess("unhandled condition in elem");
423             }
424              
425             # a simplified version of elem_or_slice_array_name()
426             # for the use of pp_multideref
427              
428             sub multideref_var_name($$$)
429             {
430 7     7 0 21 my ($self, $gv, $is_hash) = @_;
431              
432 7 100       150 my ($name, $quoted) =
433             $self->stash_variable_name( $is_hash ? '%' : '@', $gv);
434 7 100       37 return $quoted ? "$name->"
    50          
435             : $name eq '#'
436             ? '${#}' # avoid ${#}[1] => $#[1]
437             : '$' . $name;
438             }
439              
440             sub pp_multideref
441             {
442 9     9 0 21 my($self, $op, $cx) = @_;
443 9         21 my @texts = ();
444              
445 9 100       65 if ($op->private & OPpMULTIDEREF_EXISTS) {
    100          
    50          
446 4         669 @texts = ($self->keyword("exists"), ' ');
447             }
448             elsif ($op->private & OPpMULTIDEREF_DELETE) {
449 4         577 @texts = ($self->keyword("delete"), ' ')
450             }
451             elsif ($op->private & OPpLVAL_INTRO) {
452 0         0 @texts = ($self->keyword("local"), ' ')
453             }
454              
455 9 50 33     112 if ($op->first && ($op->first->flags & OPf_KIDS)) {
456             # arbitrary initial expression, e.g. f(1,2,3)->[...]
457 0         0 my $first = $self->deparse($op->first, 24, $op);
458 0         0 push @texts, $first->{text};
459             }
460              
461 9         66 my @items = $op->aux_list($self->{curcv});
462 9         30 my $actions = shift @items;
463              
464 9         11 my $is_hash;
465 9         15 my $derefs = 0;
466              
467 9         35 while (1) {
468 9 50       27 if (($actions & MDEREF_ACTION_MASK) == MDEREF_reload) {
469 0         0 $actions = shift @items;
470 0         0 next;
471             }
472              
473             $is_hash = (
474 9   66     86 ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_pop_rv2hv_helem
475             || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_gvsv_vivify_rv2hv_helem
476             || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_padsv_vivify_rv2hv_helem
477             || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_vivify_rv2hv_helem
478             || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_padhv_helem
479             || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_gvhv_helem
480             );
481              
482 9 100 66     70 if ( ($actions & MDEREF_ACTION_MASK) == MDEREF_AV_padav_aelem
    50 66        
483             || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_padhv_helem)
484             {
485 2         5 $derefs = 1;
486 2         22 push @texts, '$' . substr($self->padname(shift @items), 1);
487             }
488             elsif ( ($actions & MDEREF_ACTION_MASK) == MDEREF_AV_gvav_aelem
489             || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_gvhv_helem)
490             {
491 7         12 $derefs = 1;
492 7         42 push @texts, $self->multideref_var_name(shift @items, $is_hash);
493             }
494             else {
495 0 0 0     0 if ( ($actions & MDEREF_ACTION_MASK) ==
    0 0        
    0 0        
496             MDEREF_AV_padsv_vivify_rv2av_aelem
497             || ($actions & MDEREF_ACTION_MASK) ==
498             MDEREF_HV_padsv_vivify_rv2hv_helem)
499             {
500 0         0 push @texts, $self->padname(shift @items);
501             }
502             elsif ( ($actions & MDEREF_ACTION_MASK) ==
503             MDEREF_AV_gvsv_vivify_rv2av_aelem
504             || ($actions & MDEREF_ACTION_MASK) ==
505             MDEREF_HV_gvsv_vivify_rv2hv_helem)
506             {
507 0         0 push @texts, $self->multideref_var_name(shift @items, $is_hash);
508             }
509             elsif ( ($actions & MDEREF_ACTION_MASK) ==
510             MDEREF_AV_pop_rv2av_aelem
511             || ($actions & MDEREF_ACTION_MASK) ==
512             MDEREF_HV_pop_rv2hv_helem)
513             {
514 0 0 0     0 if ( ($op->flags & OPf_KIDS)
      0        
      0        
      0        
      0        
515             && ( B::Deparse::_op_is_or_was($op->first, OP_RV2AV)
516             || B::Deparse::_op_is_or_was($op->first, OP_RV2HV))
517             && ($op->first->flags & OPf_KIDS)
518             && ( B::Deparse::_op_is_or_was($op->first->first, OP_AELEM)
519             || B::Deparse::_op_is_or_was($op->first->first, OP_HELEM))
520             )
521             {
522 0         0 $derefs++;
523             }
524             }
525              
526 0 0       0 push(@texts, '->') if !$derefs++;
527             }
528              
529              
530 9 50       31 if (($actions & MDEREF_INDEX_MASK) == MDEREF_INDEX_none) {
531 0         0 last;
532             }
533              
534 9 100       23 push(@texts, $is_hash ? '{' : '[');
535              
536 9 50       18 if (($actions & MDEREF_INDEX_MASK) == MDEREF_INDEX_const) {
    0          
    0          
537 9         21 my $key = shift @items;
538 9 100       51 if ($is_hash) {
539 5         35 push @texts, $self->const($key, $cx)->{text};
540             }
541             else {
542 4         9 push @texts, $key;
543             }
544             }
545             elsif (($actions & MDEREF_INDEX_MASK) == MDEREF_INDEX_padsv) {
546 0         0 push @texts, $self->padname(shift @items);
547             }
548             elsif (($actions & MDEREF_INDEX_MASK) == MDEREF_INDEX_gvsv) {
549 0         0 push @texts,('$' . ($self->stash_variable_name('$', shift @items))[0]);
550             }
551              
552 9 100       34 push(@texts, $is_hash ? '}' : ']');
553              
554 9 50       21 if ($actions & MDEREF_FLAG_last) {
555 9         16 last;
556             }
557 0         0 $actions >>= MDEREF_SHIFT;
558             }
559              
560 9         33 return info_from_list($op, $self, \@texts, '', 'multideref', {});
561             }
562              
563             sub pp_gelem
564             {
565 0     0 0 0 my($self, $op, $cx) = @_;
566 0         0 my($glob, $part) = ($op->first, $op->last);
567 0         0 $glob = $glob->first; # skip rv2gv
568 0 0       0 $glob = $glob->first if $glob->name eq "rv2gv"; # this one's a bug
569 0         0 my $scope = B::Deparse::is_scope($glob);
570 0         0 $glob = $self->deparse($glob, 0);
571 0         0 $part = $self->deparse($part, 1);
572 0 0       0 return "*" . ($scope ? "{$glob}" : $glob) . "{$part}";
573             }
574              
575             sub pp_lslice
576             {
577 1     1 0 3 my ($self, $op, $cs) = @_;
578 1         6 my $idx = $op->first;
579 1         5 my $list = $op->last;
580 1         2 my(@elems, $kid);
581 1         4 my $list_info = $self->deparse($list, 1, $op);
582 1         3 my $idx_info = $self->deparse($idx, 1, $op);
583 1         19 return info_from_list($op, $self, ['(', $list_info->{text}, ')', '[', $idx_info->{text}, ']'],
584             '', 'lslice', {body=>[$list_info, $idx_info]});
585             }
586              
587             sub _method
588             {
589 2     2   5 my($self, $op, $cx) = @_;
590 2         8 my @other_ops = ($op->first);
591 2         19 my $kid = $op->first->sibling; # skip pushmark
592 2         5 my($meth, $obj, @exprs);
593 2 50 33     9 if ($kid->name eq "list" and B::Deparse::want_list $kid) {
594             # When an indirect object isn't a bareword but the args are in
595             # parens, the parens aren't part of the method syntax (the LLAFR
596             # doesn't apply), but they make a list with OPf_PARENS set that
597             # doesn't get flattened by the append_elem that adds the method,
598             # making a (object, arg1, arg2, ...) list where the object
599             # usually is. This can be distinguished from
600             # '($obj, $arg1, $arg2)->meth()' (which is legal if $arg2 is an
601             # object) because in the later the list is in scalar context
602             # as the left side of -> always is, while in the former
603             # the list is in list context as method arguments always are.
604             # (Good thing there aren't method prototypes!)
605 0         0 $meth = $kid->sibling;
606 0         0 push @other_ops, $kid->first;
607 0         0 $kid = $kid->first->sibling; # skip pushmark
608 0         0 $obj = $kid;
609 0         0 $kid = $kid->sibling;
610 0         0 for (; not B::Deparse::null $kid; $kid = $kid->sibling) {
611 0         0 push @exprs, $kid;
612             }
613             } else {
614 2         3 $obj = $kid;
615 2         7 $kid = $kid->sibling;
616 2   66     22 for (; !B::Deparse::null ($kid->sibling) && $kid->name!~/^method(?:_named)?\z/;
617             $kid = $kid->sibling) {
618 1         10 push @exprs, $kid
619             }
620 2         4 $meth = $kid;
621             }
622              
623 2 50       9 if ($meth->name eq "method_named") {
    0          
    0          
    0          
624 2         17 $meth = $self->meth_sv($meth)->PV;
625             } elsif ($meth->name eq "method_super") {
626 0         0 $meth = "SUPER::".$self->meth_sv($meth)->PV;
627             } elsif ($meth->name eq "method_redir") {
628 0         0 $meth = $self->meth_rclass_sv($meth)->PV.'::'.$self->meth_sv($meth)->PV;
629             } elsif ($meth->name eq "method_redir_super") {
630 0         0 $meth = $self->meth_rclass_sv($meth)->PV.'::SUPER::'.
631             $self->meth_sv($meth)->PV;
632             } else {
633 0         0 $meth = $meth->first;
634 0 0       0 if ($meth->name eq "const") {
635             # As of 5.005_58, this case is probably obsoleted by the
636             # method_named case above
637 0         0 $meth = $self->const_sv($meth)->PV; # needs to be bare
638             }
639             }
640              
641             return {
642 2         17 method => $meth,
643             variable_method => ref($meth),
644             object => $obj,
645             args => \@exprs,
646             other_ops => \@other_ops
647             }, $cx;
648             }
649              
650             sub e_method {
651 2     2 0 4 my ($self, $op, $minfo, $cx) = @_;
652 2         8 my $obj = $self->deparse($minfo->{object}, 24, $op);
653 2         5 my @body = ($obj);
654 2         4 my $other_ops = $minfo->{other_ops};
655              
656 2         4 my $meth = $minfo->{method};
657 2         11 my $meth_info;
658 2 50       5 if ($minfo->{variable_method}) {
659 0         0 $meth_info = $self->deparse($meth, 1, $op);
660 0         0 push @body, $meth_info;
661             }
662 2         4 my @args = map { $self->deparse($_, 6, $op) } @{$minfo->{args}};
  1         4  
  2         5  
663 2         6 push @body, @args;
664 2         5 my @args_texts = map $_->{text}, @args;
665 2         5 my $args = join(", ", @args_texts);
666              
667 2         6 my $opts = {body => \@body, other_ops => $other_ops};
668 2         3 my @texts = ();
669 2         4 my $type;
670              
671 2 50 33     13 if ($minfo->{object}->name eq 'scope' && B::Deparse::want_list $minfo->{object}) {
672             # method { $object }
673             # This must be deparsed this way to preserve list context
674             # of $object.
675 0         0 my $need_paren = $cx >= 6;
676 0 0       0 if ($need_paren) {
677 0         0 @texts = ('(', $meth, substr($obj,2),
678             $args, ')');
679 0         0 $type = 'e_method_list_paren';
680             } else {
681 0         0 @texts = ($meth, substr($obj,2), $args);
682 0         0 $type = 'e_method_list';
683             }
684 0         0 return info_from_list($op, $self, \@texts, '', $type, $opts);
685             }
686 2 100       7 if (length $args) {
687 1         5 @texts = ($obj->{text}, '->', $meth, '(', $args, ')');
688 1         2 $type = 'e_method_args';
689             } else {
690 1         4 @texts = ($obj->{text}, '->', $meth);
691 1         3 $type = 'e_method_null';
692             }
693 2         6 return info_from_list($op, $self, \@texts, '', $type, $opts);
694             }
695              
696             # returns "&" and the argument bodies if the prototype doesn't match the args,
697             # or ("", $args_after_prototype_demunging) if it does.
698             sub check_proto {
699 1     1 0 3 my $self = shift;
700 1         11 my $op = shift;
701 1 50       5 return ('&', []) if $self->{'noproto'};
702 1         3 my($proto, @args) = @_;
703 1         3 my($arg, $real);
704 1         3 my $doneok = 0;
705 1         2 my @reals;
706             # An unbackslashed @ or % gobbles up the rest of the args
707 1         6 1 while $proto =~ s/(?
708 1         5 $proto =~ s/^\s*//;
709 1         3 while ($proto) {
710 4         16 $proto =~ s/^(\\?[\$\@&%*_]|\\\[[\$\@&%*]+\]|;)\s*//;
711 4         10 my $chr = $1;
712 4 50 33     19 if ($chr eq "") {
    100          
    50          
713 0 0       0 return ('&', []) if @args;
714             } elsif ($chr eq ";") {
715 1         3 $doneok = 1;
716             } elsif ($chr eq "@" or $chr eq "%") {
717 0         0 push @reals, map($self->deparse($_, 6), @args, $op);
718 0         0 @args = ();
719             } else {
720 3         4 $arg = shift @args;
721 3 100       7 last unless $arg;
722 2 50 33     7 if ($chr eq "\$" || $chr eq "_") {
    0          
    0          
    0          
723 2 50       14 if (B::Deparse::want_scalar $arg) {
724 2         8 push @reals, $self->deparse($arg, 6, $op);
725             } else {
726 0         0 return ('&', []);
727             }
728             } elsif ($chr eq "&") {
729 0 0       0 if ($arg->name =~ /^(s?refgen|undef)$/) {
730 0         0 push @reals, $self->deparse($arg, 6, $op);
731             } else {
732 0         0 return ('&', []);
733             }
734             } elsif ($chr eq "*") {
735 0 0 0     0 if ($arg->name =~ /^s?refgen$/
736             and $arg->first->first->name eq "rv2gv")
737             {
738 0         0 $real = $arg->first->first; # skip refgen, null
739 0 0       0 if ($real->first->name eq "gv") {
740 0         0 push @reals, $self->deparse($real, 6, $op);
741             } else {
742 0         0 push @reals, $self->deparse($real->first, 6, $op);
743             }
744             } else {
745 0         0 return ('&', []);
746             }
747             } elsif (substr($chr, 0, 1) eq "\\") {
748 0         0 $chr =~ tr/\\[]//d;
749 0 0 0     0 if ($arg->name =~ /^s?refgen$/ and
      0        
      0        
750             !B::Deparse::null($real = $arg->first) and
751             ($chr =~ /\$/ && B::Deparse::is_scalar($real->first)
752             or ($chr =~ /@/
753             && class($real->first->sibling) ne 'NULL'
754             && $real->first->sibling->name
755             =~ /^(rv2|pad)av$/)
756             or ($chr =~ /%/
757             && class($real->first->sibling) ne 'NULL'
758             && $real->first->sibling->name
759             =~ /^(rv2|pad)hv$/)
760             #or ($chr =~ /&/ # This doesn't work
761             # && $real->first->name eq "rv2cv")
762             or ($chr =~ /\*/
763             && $real->first->name eq "rv2gv")))
764             {
765 0         0 push @reals, $self->deparse($real, 6, $op);
766             } else {
767 0         0 return ('&', []);
768             }
769             }
770             }
771             }
772 1 50 33     4 return ('&', []) if $proto and !$doneok; # too few args and no ';'
773 1 50       3 return ('&', []) if @args; # too many args
774 1         4 return ('', \@reals);
775             }
776              
777 4     4 0 19 sub pp_enterwrite { unop(@_, "write") }
778              
779             # Split a floating point number into an integer mantissa and a binary
780             # exponent. Assumes you've already made sure the number isn't zero or
781             # some weird infinity or NaN.
782             sub split_float {
783 0     0 0 0 my($f) = @_;
784 0         0 my $exponent = 0;
785 0 0       0 if ($f == int($f)) {
786 0         0 while ($f % 2 == 0) {
787 0         0 $f /= 2;
788 0         0 $exponent++;
789             }
790             } else {
791 0         0 while ($f != int($f)) {
792 0         0 $f *= 2;
793 0         0 $exponent--;
794             }
795             }
796 0         0 my $mantissa = sprintf("%.0f", $f);
797 0         0 return ($mantissa, $exponent);
798             }
799              
800             # OP_STRINGIFY is a listop, but it only ever has one arg
801             sub pp_stringify {
802 0     0 0 0 my ($self, $op, $cx) = @_;
803 0         0 my $kid = $op->first->sibling;
804 0         0 my @other_ops = ();
805 0   0     0 while ($kid->name eq 'null' && !B::Deparse::null($kid->first)) {
806 0         0 push(@other_ops, $kid);
807 0         0 $kid = $kid->first;
808             }
809 0         0 my $info;
810 0 0       0 if ($kid->name =~ /^(?:const|padsv|rv2sv|av2arylen|gvsv|multideref
811             |aelemfast(?:_lex)?|[ah]elem|join|concat)\z/x) {
812 0         0 $info = maybe_targmy(@_, \&dquote);
813             }
814             else {
815             # Actually an optimised join.
816 0         0 my $info = listop(@_,"join");
817 0         0 $info->{text} =~ s/join([( ])/join$1$self->{'ex_const'}, /;
818             }
819 0         0 push @{$info->{other_ops}}, @other_ops;
  0         0  
820 0         0 return $info;
821             }
822              
823              
824             # Like dq(), but different
825             sub re_dq {
826 1     1 0 2 my $self = shift;
827 1         3 my ($op) = @_;
828 1         2 my ($re_dq_info, $fmt);
829              
830 1         4 my $type = $op->name;
831 1 50       14 if ($type eq "const") {
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
832 0 0       0 return '$[' if $op->private & OPpCONST_ARYBASE;
833 0         0 my $unbacked = B::Deparse::re_unback($self->const_sv($op)->as_string);
834 0         0 return B::Deparse::re_uninterp(escape_re($unbacked));
835             } elsif ($type eq "concat") {
836 0         0 my $first = $self->re_dq($op->first);
837 0         0 my $last = $self->re_dq($op->last);
838 0         0 return B::Deparse::re_dq_disambiguate($first, $last);
839             } elsif ($type eq "uc") {
840 0         0 $re_dq_info = $self->re_dq($op->first->sibling);
841 0         0 $fmt = '\U%c\E';
842 0         0 $type .= ' uc';
843             } elsif ($type eq "lc") {
844 0         0 $re_dq_info = $self->re_dq($op->first->sibling);
845 0         0 $fmt = '\L%c\E';
846 0         0 $type .= ' lc';
847             } elsif ($type eq "ucfirst") {
848 0         0 $re_dq_info = $self->re_dq($op->first->sibling);
849 0         0 $fmt = '\u%c';
850 0         0 $type .= ' ucfirst';
851             } elsif ($type eq "lcfirst") {
852 0         0 $re_dq_info = $self->re_dq($op->first->sibling);
853 0         0 $fmt = '\u%c';
854 0         0 $type .= ' lcfirst';
855             } elsif ($type eq "quotemeta") {
856 0         0 $re_dq_info = $self->re_dq($op->first->sibling);
857 0         0 $fmt = '\Q%c\E';
858 0         0 $type .= ' quotemeta';
859             } elsif ($type eq "fc") {
860 0         0 $re_dq_info = $self->re_dq($op->first->sibling);
861 0         0 $fmt = '\F%c\E';
862 0         0 $type .= ' fc';
863             } elsif ($type eq "join") {
864 0         0 return $self->deparse($op->last, 26); # was join($", @ary)
865             } else {
866 1         5 my $ret = $self->deparse($op, 26);
867 1 50       6 $ret =~ s/^\$([(|)])\z/\${$1}/ # $( $| $) need braces
868             or $ret =~ s/^\@([-+])\z/\@{$1}/; # @- @+ need braces
869 1         3 return $ret;
870             }
871 0         0 return $self->info_from_template($type, $op->first->sibling,
872             $fmt, [$re_dq_info], [0]);
873             }
874              
875             sub pure_string {
876 8     8 0 17 my ($self, $op) = @_;
877 8 50       60 return 0 if B::Deparse::null $op;
878 8         32 my $type = $op->name;
879              
880 8 50 33     241 if ($type eq 'const' || $type eq 'av2arylen') {
    50 33        
    50 33        
    50 66        
    50 66        
    100 33        
      33        
881 0         0 return 1;
882             }
883             elsif ($type =~ /^(?:[ul]c(first)?|fc)$/ || $type eq 'quotemeta') {
884 0         0 return $self->pure_string($op->first->sibling);
885             }
886             elsif ($type eq 'join') {
887 0         0 my $join_op = $op->first->sibling; # Skip pushmark
888 0 0 0     0 return 0 unless $join_op->name eq 'null' && $join_op->targ == OP_RV2SV;
889              
890 0         0 my $gvop = $join_op->first;
891 0 0       0 return 0 unless $gvop->name eq 'gvsv';
892 0 0       0 return 0 unless '"' eq $self->gv_name($self->gv_or_padgv($gvop));
893              
894 0 0       0 return 0 unless ${$join_op->sibling} eq ${$op->last};
  0         0  
  0         0  
895 0 0       0 return 0 unless $op->last->name =~ /^(?:[ah]slice|(?:rv2|pad)av)$/;
896             }
897             elsif ($type eq 'concat') {
898 0   0     0 return $self->pure_string($op->first)
899             && $self->pure_string($op->last);
900             }
901             elsif (B::Deparse::is_scalar($op) || $type =~ /^[ah]elem$/) {
902 0         0 return 1;
903             }
904             elsif ($type eq "null" and $op->can('first') and not B::Deparse::null $op->first and
905             ($op->first->name eq "null" and $op->first->can('first')
906             and not B::Deparse::null $op->first->first and
907             $op->first->first->name eq "aelemfast"
908             or
909             $op->first->name =~ /^aelemfast(?:_lex)?\z/
910             )) {
911 1         5 return 1;
912             }
913             else {
914 7         29 return 0;
915             }
916              
917 0         0 return 1;
918             }
919              
920             sub regcomp
921             {
922 5     5 0 11 my($self, $op, $cx, $extended) = @_;
923 5         7 my @other_ops = ();
924 5         16 my $kid = $op->first;
925 5 50       22 if ($kid->name eq "regcmaybe") {
926 0         0 push @other_ops, $kid;
927 0         0 $kid = $kid->first;
928             }
929 5 50       33 if ($kid->name eq "regcreset") {
930 0         0 push @other_ops, $kid;
931 0         0 $kid = $kid->first;
932             }
933 5 50 66     63 if ($kid->name eq "null" and !B::Deparse::null($kid->first)
      66        
934             and $kid->first->name eq 'pushmark') {
935 0         0 my $str = '';
936 0         0 push(@other_ops, $kid);
937 0         0 $kid = $kid->first->sibling;
938 0         0 my @body = ();
939 0         0 while (!B::Deparse::null($kid)) {
940 0         0 my $first = $str;
941 0         0 my $last = $self->re_dq($kid, $extended);
942 0         0 push @body, $last;
943 0         0 push(@other_ops, $kid);
944 0         0 $str = B::Deparse::re_dq_disambiguate($first,
945             $self->info2str($last));
946 0         0 $kid = $kid->sibling;
947             }
948 0         0 return (info_from_text($op, $self, $str, 'regcomp',
949             {other_ops => \@other_ops,
950             body => \@body}), 1);
951             }
952              
953 5 100       22 if ($self->pure_string($kid)) {
954 1         8 my $info = $self->re_dq($kid, $extended);
955 1 50       3 my @kid_ops = $info->{other_ops} ? @{$info->{other_ops}} : ();
  0         0  
956 1         3 push @other_ops, @kid_ops;
957 1         2 $info->{other_ops} = \@other_ops;
958 1         4 return ($info, 1);
959             }
960 4         15 return ($self->deparse($kid, $cx, $op), 0, $op);
961             }
962              
963             # osmic acid -- see osmium tetroxide
964              
965 6     6 0 24 sub pp_match { matchop(@_, "m", "/") }
966 0     0 0   sub pp_pushre { matchop(@_, "m", "/") }
967 0     0 0   sub pp_qr { matchop(@_, "qr", "") }
968              
969             sub pp_split
970             {
971 0     0 0   my($self, $op, $cx) = @_;
972 0           my($kid, @exprs, $ary_info, $expr);
973 0           my $stacked = $op->flags & OPf_STACKED;
974 0           my $ary = '';
975 0           my @body = ();
976 0           my @other_ops = ();
977 0           $kid = $op->first;
978              
979 0           $kid = $op->first;
980 0 0         $kid = $kid->sibling if $kid->name eq 'regcomp';
981 0           for (; !B::Deparse::null($kid); $kid = $kid->sibling) {
982 0           push @exprs, $self->deparse($kid, 6, $op);
983             }
984              
985 0           unshift @exprs, $self->matchop($op, $cx, "m", "/");
986              
987 0 0         if ($op->private & OPpSPLIT_ASSIGN) {
988             # With C<@array = split(/pat/, str);>,
989             # array is stored in split's pmreplroot; either
990             # as an integer index into the pad (for a lexical array)
991             # or as GV for a package array (which will be a pad index
992             # on threaded builds)
993             # With my/our @array = split(/pat/, str), the array is instead
994             # accessed via an extra padav/rv2av op at the end of the
995             # split's kid ops.
996              
997 0 0         if ($stacked) {
998 0           $ary = pop @exprs;
999             }
1000             else {
1001 0 0         if ($op->private & OPpSPLIT_LEX) {
1002 0           $ary = $self->padname($op->pmreplroot);
1003             }
1004             else {
1005             # union with op_pmtargetoff, op_pmtargetgv
1006 0           my $gv = $op->pmreplroot;
1007 0 0         $gv = $self->padval($gv) if !ref($gv);
1008 0           $ary = $self->maybe_local(@_,
1009             $self->stash_variable('@',
1010             $self->gv_name($gv),
1011             $cx))
1012             }
1013 0 0         if ($op->private & OPpLVAL_INTRO) {
1014 0 0         $ary = $op->private & OPpSPLIT_LEX ? "my $ary" : "local $ary";
1015             }
1016             }
1017             }
1018              
1019 0           push @body, @exprs;
1020 0           my $opts = {body => \@exprs};
1021              
1022             # handle special case of split(), and split(' ') that compiles to /\s+/
1023 0 0 0       if (($op->reflags // 0) & RXf_SKIPWHITE()) {
1024 0           my $expr0 = $exprs[0];
1025 0           my $expr0b0 = $expr0->{body}[0];
1026 0           my $bsep = $expr0b0->{sep};
1027 0           my $sep = $expr0->{sep};
1028 0           $expr0b0->{texts}[1] = ' ';
1029             # substr($expr0b0->{text}, 1, 0) = ' ';
1030 0           substr($expr0->{texts}[0], 1, 0) = ' ';
1031 0           substr($expr0->{text}, 1, 0) = ' ';
1032             }
1033 0           my @args_texts = map $_->{text}, @exprs;
1034              
1035 0           my $sep = '';
1036 0           my $type;
1037             my @expr_texts;
1038 0 0         if ($ary) {
1039 0           @expr_texts = ("$ary", '=', join(', ', @args_texts));
1040 0           $sep = ' ';
1041 0           $type = 'split_array';
1042 0           $opts->{maybe_parens} = [$self, $cx, 7];
1043             } else {
1044 0           @expr_texts = ('split', '(', join(', ', @args_texts), ')');
1045 0           $type = 'split';
1046              
1047             }
1048 0           return info_from_list($op, $self, \@expr_texts, $sep, $type, $opts);
1049             }
1050              
1051             # Kind of silly, but we prefer, subst regexp flags joined together to
1052             # make words. For example: s/a/b/xo => s/a/b/ox
1053              
1054             # oxime -- any of various compounds obtained chiefly by the action of
1055             # hydroxylamine on aldehydes and ketones and characterized by the
1056             # bivalent grouping C=NOH [Webster's Tenth]
1057              
1058             unless (caller) {
1059             eval "use Data::Printer;";
1060              
1061             eval {
1062             sub fib($) {
1063             my $x = shift;
1064             return 1 if $x <= 1;
1065             return(fib($x-1) + fib($x-2))
1066             }
1067             sub baz {
1068 3     3   34 no strict;
  3         8  
  3         919  
1069             CORE::wait;
1070             }
1071             };
1072              
1073             # use B::Deparse;
1074             # my $deparse_old = B::Deparse->new("-l", "-sC");
1075             # print $deparse_old->coderef2text(\&baz);
1076             # exit 1;
1077             my $deparse = __PACKAGE__->new("-l", "-c", "-sC");
1078             my $info = $deparse->coderef2info(\&baz);
1079             import Data::Printer colored => 0;
1080             Data::Printer::p($info);
1081             print "\n", '=' x 30, "\n";
1082             # print $deparse->($deparse->deparse_subname('fib')->{text});
1083             # print "\n", '=' x 30, "\n";
1084             # print "\n", '-' x 30, "\n";
1085             while (my($key, $value) = each %{$deparse->{optree}}) {
1086             my $parent_op_name = 'undef';
1087             if ($value->{parent}) {
1088             my $parent = $deparse->{optree}{$value->{parent}};
1089             $parent_op_name = $parent->{op}->name if $parent->{op};
1090             }
1091             printf("0x%x %s/%s of %s |\n%s",
1092             $key, $value->{op}->name, $value->{type},
1093             $parent_op_name, $deparse->indent($value->{text}));
1094             printf " ## line %s\n", $value->{cop} ? $value->{cop}->line : 'undef';
1095             print '-' x 30, "\n";
1096             }
1097             }
1098              
1099             # Not in Perl 5.20 and presumably < 5.20. No harm in adding to 5.20?
1100             *pp_ncomplement = *pp_complement;
1101 0     0 0   sub pp_scomplement { maybe_targmy(@_, \&pfixop, "~.", 21) }
1102              
1103             unless (caller) {
1104             eval "use Data::Printer;";
1105              
1106             eval {
1107             our($Fileparse_fstype);
1108             sub fib($) {
1109 0     0 0   my $x = shift;
1110 0 0         return 1 if $x <= 1;
1111 0           return(fib($x-1) + fib($x-2))
1112             }
1113             sub fileparse {
1114 3     3   21 no strict;
  3         7  
  3         215  
1115             # my($fullname,@suffices) = @_;
1116              
1117 0     0 0   my $tail = '';
1118 0           $tail = $1 . $tail;
1119              
1120             # Ensure taint is propagated from the path to its pieces.
1121 0           $tail .= $taint;
1122 0 0         wantarray ? ($basename .= $taint, $dirpath .= $taint, $tail)
1123             : ($basename .= $taint);
1124             }
1125             sub baz {
1126 3     3   16 no strict;
  3         6  
  3         773  
1127 0 0   0 0   if ($basename =~ s/$pat//s) {
1128             }
1129             }
1130             };
1131              
1132             my $deparse = __PACKAGE__->new("-l", "-c");
1133             my $info = $deparse->coderef2info(\&fileparse);
1134             # my $info = $deparse->coderef2info(\&baz);
1135             import Data::Printer colored => 0;
1136             Data::Printer::p($info);
1137             print "\n", '=' x 30, "\n";
1138             # print $deparse->indent($deparse->deparse_subname('fib')->{text});
1139             # print "\n", '=' x 30, "\n";
1140             # print "\n", '-' x 30, "\n";
1141             while (my($key, $value) = each %{$deparse->{optree}}) {
1142             my $parent_op_name = 'undef';
1143             if ($value->{parent}) {
1144             my $parent = $deparse->{optree}{$value->{parent}};
1145             $parent_op_name = $parent->{op}->name if $parent->{op};
1146             }
1147             if (eval{$value->{op}->name}) {
1148             printf("0x%x %s/%s of %s |\n%s",
1149             $key, $value->{op}->name, $value->{type},
1150             $parent_op_name, $deparse->{text});
1151             } else {
1152             printf("0x%x %s of %s |\n",
1153             $key, $value->{type},
1154             $parent_op_name);
1155             }
1156             printf " ## line %s\n", $value->{cop} ? $value->{cop}->line : 'undef';
1157             print '-' x 30, "\n";
1158             }
1159             # use B::Deparse;
1160             # my $deparse_old = B::Deparse->new("-l", "-sC");
1161             # print $deparse_old->coderef2text(\&baz);
1162             }
1163              
1164             1;