in reply to Re: B::Deparse weirdness (parser weirdness!)
in thread B::Deparse weirdness

OK I wasn't sure if comparing do EXPR with print LIST was fair, so I tried something more similar with eval EXPR

sorry but that's really ridiculous, the priority of parens is handled the other way round.

$ perl -MO=Concise -e 'eval ($foo)->{bar};' 8 <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v:{ ->3 7 <2> helem vK/2 ->8 5 <1> rv2hv[t2] sKR/1 ->6 4 <1> entereval[t256] sK/1 ->5 - <1> ex-rv2sv sK/1 ->4 3 <#> gvsv[*foo] s ->4 6 <$> const[PV "bar"] s/BARE ->7 -e syntax OK $ perl -MO=Concise -e 'do ($foo)->{bar};' 9 <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v:{ ->3 8 <1> dofile vK/1 ->9 7 <2> helem sK/2 ->8 5 <1> rv2hv[t2] sKR/1 ->6 4 <1> rv2sv sKPM/DREFHV,1 ->5 3 <#> gv[*foo] s ->4 6 <$> const[PV "bar"] s/BARE ->7 -e syntax OK

I can't really blame B::Deparse for failing to guess this parser weirdness.

It's using heuristics to produce readable code without too many parens to group obvious precedence.

How are the authors supposed to known that do is special?

update

in hindsight it would be safer if B::Deparse was grouping complex LHS of the arrow OP into parens.

even if this is correct

$ perl -MO=Deparse -e '(eval $foo)->{bar};' eval($foo)->{'bar'};

nobody would mind getting this instead.

(eval($foo))->{'bar'};

Cheers Rolf

(addicted to the Perl Programming Language and ☆☆☆☆ :)

Replies are listed 'Best First'.
Re^3: B::Deparse weirdness (possible patch)
by LanX (Saint) on Oct 13, 2014 at 23:09 UTC
    > in hindsight it would be safer if B::Deparse was grouping complex LHS of the arrow OP into parens.

    here a possible patch to do this. It introduces a call to a new routine maybe_parens_lhs_arrow() into the return statement of elem().

    Complex LHS-> is determined by not starting with a sigil or paren.

    sub elem { my $self = shift; my ($op, $cx, $left, $right, $padname) = @_; my($array, $idx) = ($op->first, $op->first->sibling); $idx = $self->elem_or_slice_single_index($idx); unless ($array->name eq $padname) { # Maybe this has been fixed + $array = $array->first; # skip rv2av (or ex-rv2av in _53+) } if (my $array_name=$self->elem_or_slice_array_name ($array, $left, $padname, 1)) { return "\$" . $array_name . $left . $idx . $right; } else { # $x[20][3]{hi} or expr->[20] my $arrow = is_subscriptable($array) ? "" : "->"; return maybe_parens_lhs_arrow($self->deparse($array, 24), $arrow) . $left . $idx . $right; } } sub maybe_parens_lhs_arrow { my ($lhs, $arrow) = @_; return "($lhs)$arrow" if ($arrow eq "->" and $lhs !~ /^[$@%&(*]/); return "$lhs$arrow"; }

    Looks like a weird hack ... much like most of B::Deparse ! :)

    That's teh result then:

    $ perl -I. -MO=Deparse -e '(do $foo)->{$bar}' (do($foo))->{$bar}; -e syntax OK $ perl -I. -MO=Deparse -e '$foo->{$bar}' $$foo{$bar}; -e syntax OK

    Cheers Rolf

    (addicted to the Perl Programming Language and ☆☆☆☆ :)