Leopold Toetsch <[EMAIL PROTECTED]> wrote:

[ fullquote ]

> A recent discussion with Sam has shown that the current calling
> conventions for overloaded operators don't match Python semantics (nor
> Perl6 when I interpret S06 and S13 correctly).

> The difference is that Parrot is passing in the destination argument
> while these languages are returning the operator result.

> E.g.

> def myadd(self, r):
>      return self - r

> class I(int):
>      __add__ = myadd

> i = I(44)
> print i, i + 2

> Parrot is expecting and calling a subroutine like:

>    .sub __add
>      .param left
>      .param right
>      .param dest
>     ...
>    .end

> and it's run in void context. This calling convention matches the "add"
> opcode, where the destination argument has to exist. But it's not suited
> for HLLs as the HLL compiler can't track the subroutine usage back to
> overloading and adjust the emitted code.

> A short-term solution would be to evaluate the return result (if the
> function returns something) and assign that value to the "dest" argument.

> Parrot would call

>    .sub __add
>       .param left
>       .param right
>       .param dest       # HLL can use it or create a temp
>       ...
>       .return(temp)     # or .return (dest) if HLL knows about dest
>     .end

> while this is still a bit sub-optimal because of the additional temp,
> the HLL might create, it would at least match the semantics.

> A more radical change would be to just adapt these opcodes to create an
> appropriate PMC with the result.

Thinking more about that it seems that we don't have much chance to keep
the current scheme that the destination is passed in.

a Python snippet:

def myadd(self, r):
    return I(self.v - r)

class I(object):
    __add__ = myadd
    def __init__(self, v):
        self.v = v
    def __repr__(self):
        return "I(%d)" % self.v


i = I(44)
j = i + 2
k = j + 2
print i, j, k

The "add" opcode is overloaded and returns a new object of class "I".
The current scheme is:

  $P0 = new Undef
  $P0 = add i, 2

*If* the HLL compiler can somehow make a connection between the "myadd"
function as an overloaded "add" opcode, it could try to morph the passed
in destination argument. The whole morph code is bulky and slow,
changing one PMC into an arbitrary different one needs deallocating the
old one (what happens with finalizers?) and constructing a new one in
place.

But I doubt that a compiler can track such a usage (myadd could be in a
different file and imported). That means we are pre-constructing a LHS
PMC for nothing with all implications on GC and performance.

Second: looking at pmc.c:pmc_reuse() the code isn't able to and can't
never return a singleton as the result of an operation, because that
would mean to change the address of the argument, where only it's
pointer is passed.

> Comments?
> leo

leo

Reply via email to