Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Re: B::Deparse weirdness (parser weirdness!)

by LanX (Saint)
on Oct 13, 2014 at 11:35 UTC ( [id://1103614]=note: print w/replies, xml ) Need Help??


in reply to B::Deparse weirdness

Rephrased:

B::Deparse thinks (and I expected) that parens have priority to capture function arguments and that

do('foo')->{'bar'};

is analogous to

(do 'foo') -> {bar}

but the weird parser rather sees

do ('foo' -> {bar})

see the difference in priority of parens around arguments by comparing print() vs do()

lanx@nc10-ubuntu:/tmp$ 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 # do file 7 <2> helem sK/2 ->8 # hash-elem returns fi +le 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 lanx@nc10-ubuntu:/tmp$ perl -MO=Concise, -e 'print ($foo)->{bar};' 9 <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v:{ ->3 8 <2> helem vK/2 ->9 # hash-element 6 <1> rv2hv[t2] sKR/1 ->7 5 <@> print sK ->6 # print returns hashre +f 3 <0> pushmark s ->4 - <1> ex-rv2sv sK/1 ->5 4 <#> gvsv[*foo] s ->5 7 <$> const[PV "bar"] s/BARE ->8 -e syntax OK

just remember the common trap when people try writing something like

 print (caller)[5]

$ perl -c -e 'print (caller)[5]' syntax error at -e line 1, near ")[" -e had compilation errors.

while

$ perl -c -e 'do (L,I,S,T)[5]' -e syntax OK

Cheers Rolf

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

Replies are listed 'Best First'.
Re^2: B::Deparse weirdness (parser weirdness!)
by LanX (Saint) on Oct 13, 2014 at 12:42 UTC
    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 ☆☆☆☆ :)

      > 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 ☆☆☆☆ :)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1103614]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (6)
As of 2024-03-28 23:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found