develooper Front page | perl.perl5.porters | Postings from May 2008

Re: [perl #51408] prototypes sneakily break :lvalue subs

Thread Previous
From:
Rafael Garcia-Suarez
Date:
May 28, 2008 01:34
Subject:
Re: [perl #51408] prototypes sneakily break :lvalue subs
Message ID:
b77c1dce0805280134h3a201e1fj7d34b2e8a48577be@mail.gmail.com
2008/3/4 via RT l. mai @ web. de <perlbug-followup@perl.org>:
> My real problem is related to lvalue subroutines and prototypes.
> Consider the following code:
>
>  sub f :lvalue { $_ }
>
> With this, I'd expect to be able to use f() anywhere I can use $_,
> modulo weird things like indirect object syntax. But code like ...
>
>  my $ref = \f();
>  $$ref = 1;
>
> ... works and sets $_ to 1. Let's combine this with pass-by-alias:
>
>  sub f :lvalue { $_ }
>  sub g { $_[0] = 1 }
>  g(f());
>
> This code binds g's $_[0] to $_ and sets $_ to 1, as expected.
> However:
>
>  sub f :lvalue { $_ }
>  sub g ($) { $_[0] = 1 }
>  g(f());
>
> This code does nothing. The ($) prototype on g causes $_ to be
> passed by (temporary) value, and (per our initial observation)
> this kind of thing silently fails. g($_) works as expected, though,
> so there's something weird going on.
> Apparently the perl compiler simply inserts scalar()s in calls to
> g. This works fine for simple variables but breaks lvalue subs.

It doesn't insert scalar() calls, but indeed calls f in scalar context
(instead of list context as in the unprototyped case).

$ diff -u <(bleadperl -MO=Concise -e 'sub g;g(f())' 2>&1) <(bleadperl
-MO=Concise -e 'sub g($);g(f())' 2>&1)
--- /dev/fd/63	2008-05-28 10:26:06.651464655 +0200
+++ /dev/fd/62	2008-05-28 10:26:06.653628112 +0200
@@ -5,8 +5,8 @@
 8     <1> entersub[t2] vKS/TARG,1 ->9
 -        <1> ex-list K ->8
 3           <0> pushmark s ->4
-6           <1> entersub[t1] lKMS/NO(),TARG,INARGS,1 ->7
--              <1> ex-list lK ->6
+6           <1> entersub[t1] sKMS/NO(),TARG,INARGS,1 ->7
+-              <1> ex-list sK ->6
 4                 <0> pushmark s ->5
 -                 <1> ex-rv2cv sK ->-
 5                    <$> gv(*f) s/EARLYCV ->6

However, lvalue subs work in some scalar contexts:

$ bleadperl -MO=Concise -E 'sub f:lvalue{$x};$y=(f()=2);say$x'
e  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 47 -e:1) v:%,{ ->3
9     <2> sassign vKS/2 ->a
7        <2> sassign sKPS/2 ->8
3           <$> const(IV 2) s ->4
6           <1> entersub[t1] sKRMS*/NO(),TARG,1 ->7
-              <1> ex-list sK ->6
4                 <0> pushmark s ->5
-                 <1> ex-rv2cv sK ->-
5                    <$> gv(*f) s ->6
-        <1> ex-rv2sv sKRM*/1 ->9
8           <$> gvsv(*y) s ->9
a     <;> nextstate(main 47 -e:1) v:%,{ ->b
d     <@> say vK ->e
b        <0> pushmark s ->c
-        <1> ex-rv2sv sK/1 ->d
c           <$> gvsv(*x) s ->d
-e syntax OK
$ bleadperl -E 'sub f:lvalue{$x};$y=(f()=2);say$x'
2

I wonder if it's a simple question of fiddling with the entersub flags.

Thread Previous


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About