[PerlChina] Fwd: [perl #38346] [PATCH] Re: B::Deparse's bug?

y6cmE refile at gmail.com
Wed Feb 8 20:42:34 PST 2006

---------- Forwarded message ----------
From: Stephen McCamant via RT <perlbug-followup at perl.org>
Date: 2006-2-9 上午9:51
Subject: [perl #38346] [PATCH] Re: B::Deparse's bug?
To: refile at gmail.com

>>>>> "RS" == Robert Spier <rspier at pobox.com> writes:

RS> Perl5 Bug Summary

RS> New issues that have not been responded to yet
RS> 1 - 2 weeks old
RS> 38346 B::Deparse's bug?

I don't remember ever seeing this on p5p, perhaps because it was
sent to perlbug-admin instead of perlbug.

Here's a further-simplified test case:

% perl -MO=Deparse -e '$a ? $b = $c : $d = $e'
$a ? ($b = $c) : $d = $e;
% perl -MO=Deparse -e '$a ? $b = $c : $d = $e' | perl -c
Assignment to both a list and a scalar at - line 1, near "$e;"

I vaguely recall this issue coming up before, but maybe it was
somewhere else, or maybe it was just about how Perl parses and I never
thought to check what Deparse does. The precedence of ?: is a bit
weird because for the middle argument, the ? and the : act a bit like
parentheses: potentially, you could have a very low precedence
operator there without causing an ambiguity. For instance, the only
reasonable interpretation of:

$a ? $b or $c : $d


$a ? ($b or $c) : $d

even though "or" normally has lower precedence than ?:. However,
perl's grammar doesn't allow the unparenthesized "or" example: the
lowest precedence operators that can be in the middle of a ?: without
parens are assignments. I'm not sure how intentional this was, but it
seems pretty defensible on language design grounds, since mixing ?:
with low-precedence operators is error-prone and rarely necessary.

As for the current bug, Deparse is excessively conservative in adding
parentheses, applying the same rule to the middle arg as to the left
or right args. Alas, perl takes the parens as signifying a list,
leading to the error shown. The right fix appears to be to make
Deparse less conservative, as in the appended patch.

By the way, the original reporter may already know this, but in case
they don't and for the benefit of anyone else playing along at home,
the original example doesn't do what it looks like it's supposed to,
exactly because of a precedence problem. To demonstrate with Deparse:

% perl -MO=Deparse,-p -e '$a ? $b = $c : $d = $e'
(($a ? ($b = $c) : $d) = $e);

What the author of the code presumably meant was:

% perl -MO=Deparse,-p -e '$a ? $b = $c : ($d = $e)'
($a ? ($b = $c) : ($d = $e));

(especially since in the original example, $b and $d were the same

-- Stephen

--- perl-current/ext/B/B/Deparse.pm     2006-01-03 04:38:52.000000000 -0500
+++ perl at 26919/ext/B/B/Deparse.pm       2006-02-08 20:19:17.147191075 -0500
@@ -2504,7 +2504,7 @@ sub pp_cond_expr {
           (is_scope($false) || is_ifelse_cont($false))
           and $self->{'expand'} < 7) {
       $cond = $self->deparse($cond, 8);
-       $true = $self->deparse($true, 8);
+       $true = $self->deparse($true, 6);
       $false = $self->deparse($false, 8);
       return $self->maybe_parens("$cond ? $true : $false", $cx, 8);

呵呵,Perl 初学者,大家多多照顾!
-------------- next part --------------

More information about the China-pm mailing list