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

Re: Can I OVERLOAD the assignment operator? Please???

Thread Previous | Thread Next
From:
Nicholas Clark
Date:
May 24, 2003 01:46
Subject:
Re: Can I OVERLOAD the assignment operator? Please???
Message ID:
20030524094555.W1149@plum.flirble.org
On Fri, May 23, 2003 at 08:31:00AM +0100, Nick Ing-Simmons wrote:
> Dan Sugalski <dan@sidhe.org> writes:
> >That's something I think you can't do, and arguably a bug. I'm pretty 
> >sure you can have tie magic, or overloading magic, but not both.
> 
> That is my recollection too.
> 
> I would quite like this fixed too - but it was tricky. I got 
> as far as tracing the control path once.  

I think that the problem is this - you can't have a tied variable return
an overloaded value and it do what you expect. Take pp_add
(before I bloated it) - quotes are from the 5.005_03 source which
I have somewhere handy:

PP(pp_add)
{
    djSP; dATARGET; tryAMAGICbin(add,opASSIGN); 
    {
      dPOPTOPnnrl_ul;
      SETn( left + right );
      RETURN;
    }
}

where the AMAGIC stuff is:

#define tryAMAGICbinW(meth,assign,set) STMT_START { \
          if (PL_amagic_generation) { \
            SV* tmpsv; \
            SV* right= *(sp); SV* left= *(sp-1);\
            if ((SvAMAGIC(left)||SvAMAGIC(right))&&\
                (tmpsv=amagic_call(left, \
                                   right, \
                                   CAT2(meth,_amg), \
                                   (assign)? AMGf_assign: 0))) {\
               SPAGAIN; \
               (void)POPs; set(tmpsv); RETURN; } \
          } \
        } STMT_END

#define tryAMAGICbin(meth,assign) tryAMAGICbinW(meth,assign,SETsv)
#define tryAMAGICbinSET(meth,assign) tryAMAGICbinW(meth,assign,SETs)


The problem, IIRC, is that the AMAGIC test for overloading is made at
the top. And this checks the flags on the tied variable (the container).
The tied variable isn't overloaded so the if doesn't fire.
Then dPOPTOPnnrl_ul hits, which calls SvNV() on values from the stack,
triggering the FETCH call on the tied variable. I think that that is
the mg_get in sv_2nv:

sv_2nv(register SV *sv)
{
    if (!sv)
        return 0.0;
    if (SvGMAGICAL(sv)) {
        mg_get(sv);


but even if that's not exactly the correct place, the upshot is that
by the return from SvNV happens the tied variable has returned an
overloaded value, but now there is no check on whether it's overloaded,
and whether we should jump back and do overloading.

Answers on a postcard as to how to add such logic without slowing the
world down (or getting into infinite loops) welcome.

Hopefully Alex Gough will correct me if I'm wrong.

Nicholas Clark

Thread Previous | Thread Next


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