develooper Front page | perl.perl5.porters | Postings from February 2000

Re: [PATCH 5.5.660] improved semantics for assign to pseudohash

From:
John Tobey
Date:
February 28, 2000 06:32
Subject:
Re: [PATCH 5.5.660] improved semantics for assign to pseudohash
Message ID:
m12PRDt-000FPKC@feynman.localnet
> Date: Mon, 28 Feb 2000 05:58:36 -0500
> From: Michael G Schwern <schwern@pobox.com>
> 
> I was more curious about this particular statement:
> 
>         kid = ((LISTOP*)cBINOPo->op_first->op_sibling)->op_last;
> 
> Ops are still something of a blackbox to me.  I think I've figured it
> out myself, but could you walk me through it?  I kind of understand
> what it does, just not why.

Run "perl -MO=Terse -e '%x=()'" or "perl -Dx -ce '%x=()'" to see the
tree structure we're stepping around in.

    BINOP (0x81718c8) aassign [2]          == o
        UNOP (0x8171880) null [141]        == cBINOPo->op_first
            OP (0x81718a8) pushmark
            OP (0x8171818) stub
        UNOP (0x8171838) null [141]        == cBINOPo->op_first->op_sibling
            OP (0x8171860) pushmark
            UNOP (0x8170fd8) rv2hv [1]     == ((LISTOP*)...)->op_last
                SVOP (0x8173020) gv  GV (0x8100dfc) *x

> > > BTW Does it handle (%$ph, @a) = @list; and (@a, %$ph) = @list; and
> > > ($a, %$ph) = @list properly?
> > 
> > No, yes, and yes, I think.  Perl_ck_aassign needs to be changed so
> > that it looks at the first hash-or-array on the left side instead of
> > simply the last element as it does now.
> 
> Okay, I've made some progress.  I altered Perl_ck_aassign:
> 
> Perl_ck_aassign(pTHX_ OP *o)
> {
>     OP *kid;
>     for( kid = ((LISTOP*)cBINOPo->op_first->op_sibling)->op_first;
>          kid;
>          kid = kid->op_sibling
>        )
>     {
>         if (kid->op_type == OP_RV2HV || kid->op_type == OP_PADHV)
>             o->op_flags |= OPf_SPECIAL;
>     }
>     return o;
> }
> 
> Walk through everything on the left hand side of the assignment, not
> just the first.  This should nail all combinations of (EXPR, %$avhv) =
> @list and (%$avhv, EXPR) = @list;  Hope its not overkill.

Hmmm.  By using a single flag (OPf_SPECIAL) in the AASSIGN op, we lose
the chance to specify for each child on the left-hand side whether it
uses the hash syntax or not.  Therefore, this approach will always get
something wrong when a combination of @ and % expressions is assigned
to.  My proposal (to look only at the first non-scalar) would have
meant that

    (@extra, %$avhv) = EXPR;

wiped the fields hash from %$avhv.  Perhaps this is an okay
compromise, since we can say "don't do that".  A correct fix, I guess,
would be to have pp_aassign keep a pointer to the LHS kid ops and test
each one that's of type SVt_PVAV for hashness.

> @extra = qw(whatever and stuff);
> %$avhv = ();
> (%$avhv, @extra) = (foo => 42, pants => 53, bar => "HIKE!");
> print "not " unless "@$avhv[1..3]" eq '42 HIKE! 53' and @extra == 0;
> print "ok 27\n";
> 
> In 27 @extra is coming out with ('whatever') instead of being cleared.
> I originally thought it was being misinterpreted as a pseudohash, thus
> element 0 wouldn't be cleared, but its not.  When it gets to
> aassign(), for some odd reason relem is "whatever".  I have no idea
> why.  Other than that little glitch it works.  (@foo, @bar) = @list;
> doesn't show the same behavior.

I don't know how relem got to be 'whatever', but the fact $extra[0]
survives is consistent with your change in Perl_ck_aassign().

> %$avhv = ();
> (@extra, %$avhv) = (foo => 42, pants => 53, bar => "HIKE!");
> print "not " unless ref $avhv[0] eq 'HASH' and @extra == 6;
> print "ok 28\n";
> 
> In 28 %$avhv is getting completely cleared.  I figure there's some
> sort of optimization that's screwing with it and still does the naive
> case, treating it as an array.  aassign() it still treating it as a
> pseudohash, but the time it gets there its completely cleared.  I
> didn't see anything obvious in the peephole and nothing is calling
> av_clear() that I can see (except to set @ARGV).

I would expect @extra to keep its first element here, too.  Does it?
If not, is OPf_SPECIAL actually set?

-- 
John Tobey, late nite hacker <jtobey@john-edwin-tobey.org>
\\\                                                               ///
]]]             With enough bugs, all eyes are shallow.           [[[
///                                                               \\\



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