B-DeparseTree

 view release on metacpan or  search on metacpan

lib/B/DeparseTree/PPfns.pm  view on Meta::CPAN

    }
    if (@a == 1) {
	return $self->info_from_template('list const: one item',
					 $op, "(%c)", undef, [$a[0]]);
    }

    my @texts = map $_->{text}, @a;
    if ( @a > 2 and !grep(!/^-?\d+$/, @texts)) {
	# collapse a consecutive sequence like (-1,0,1,2) into a range like (-1..2)
	my $first = $texts[0];
	my $i = $first;
	return $self->info_from_template('list const ..', $op,
					 "%c..%c", undef,
					 [$a[0], $a[-1]],
					 {maybe_parens => [$self, $cx, 9]})
	    unless grep $i++ != $_, @texts;
    }
    return $self->info_from_template('list const, more than one item',
				     $op, "%C", [[0, $#a, ', ']], \@a,
				     {maybe_parens => [$self, $cx, $prec]});
}

# This handle list ops: "open", "pack", "return" ...
sub listop
{
    my($self, $op, $cx, $name, $kid, $nollafr) = @_;
    my(@exprs, @new_nodes, @skipped_ops);
    my $parens = ($cx >= 5) || $self->{'parens'};

    unless ($kid) {
	push @skipped_ops, $op->first;
	$kid = $op->first->sibling;
    }

    # If there are no arguments, add final parentheses (or parenthesize the
    # whole thing if the llafr does not apply) to account for cases like
    # (return)+1 or setpgrp()+1.  When the llafr does not apply, we use a
    # precedence of 6 (< comma), as "return, 1" does not need parentheses.
    if (B::Deparse::null $kid) {
	my $fullname = $self->keyword($name);
	my $text = $nollafr
	    ? $self->maybe_parens($fullname, $cx, 7)
	    : $fullname . '()' x (7 < $cx);
	return $self->info_from_string("listop $name", $op, $text);
    }
    my $first;
    my $fullname = $self->keyword($name);
    my $proto = prototype("CORE::$name");
    if (
	 (     (defined $proto && $proto =~ /^;?\*/)
	    || $name eq 'select' # select(F) doesn't have a proto
	 )
	 && $kid->name eq "rv2gv"
	 && !($kid->private & B::OPpLVAL_INTRO)
    ) {
	$first = $self->rv2gv_or_string($kid->first, $op);
    }
    else {
	$first = $self->deparse($kid, 6, $op);
    }
    if ($name eq "chmod" && $first->{text} =~ /^\d+$/) {
	my $transform_fn = sub {sprintf("%#o", $self->info2str(shift))};
	$first = $self->info_from_template("chmod octal", undef,
					   "%F", [[0, $transform_fn]],
					   [$first], {'relink_children' => [0]});
	push @new_nodes, $first;
    }

    # FIXME: fold this into a template
    $first->{text} = "+" + $first->{text}
	if not $parens and not $nollafr and substr($first->{text}, 0, 1) eq "(";

    push @exprs, $first;
    $kid = $kid->sibling;
    if (defined $proto && $proto =~ /^\*\*/ && $kid->name eq "rv2gv"
	&& !($kid->private & B::OPpLVAL_INTRO)) {
	$first = $self->rv2gv_or_string($kid->first, $op);
	push @exprs, $first;
	$kid = $kid->sibling;
    }

    $self->deparse_op_siblings(\@exprs, $kid, $op, 6);

    if ($name eq "reverse" && ($op->private & B::OPpREVERSE_INPLACE)) {
	my $fmt;
	my $type;
	if ($parens) {
	    $fmt = "%c = $fullname(%c)";
	    $type = "listop reverse ()"
	} else {
	    $fmt = "%c = $fullname(%c)";
	    $type = "listop reverse"
	}
	my @nodes = ($exprs[0], $exprs[0]);
	return $self->info_from_template($type, $op, $fmt, undef,
					 [$exprs[0], $exprs[0]]);
    }

    my $opts = {};
    my $type;
    my $fmt;

    if ($name =~ /^(system|exec)$/
	&& ($op->flags & B::OPf_STACKED)
	&& @exprs > 1)
    {
	# handle the "system(prog a1, a2, ...)" form
	# where there is no ', ' between the first two arguments.
	if ($parens && $nollafr) {
	    $fmt = "($fullname %c %C)";
	    $type = "listop ($fullname)";
	} elsif ($parens) {
	    $fmt = "$fullname(%c %C)";
	    $type = "listop $fullname()";
	} else {
	    $fmt = "$fullname %c %C";
	    $type = "listop $fullname";
	}
	return $self->info_from_template($type, $op, $fmt,
					 [0, [1, $#exprs, ', ']], \@exprs);

    }



( run in 0.588 second using v1.01-cache-2.11-cpan-39bf76dae61 )