a) As Sam says, in Python "y**z" is just shorthand for "y.__pow__(z)"--they will compile down to exactly the same thing (required for Python to behave correctly). Since __pow__ isn't "special", we don't need anything to support it that we wouldn't need for any other arbitrary method, say "y.elbowCanOpener(z)".
[snip]
So I don't think an op really gives us what we want. (Specifically, we could define a pow_p_p_p op, but then Python wouldn't use it for the case Sam brought up.) I'd apply the same argument to many of the other p_p_p ops that we have--they don't gives us what we need at the HLL level (though they may still be necessary for other uses).
It is my intent that Python *would* use this method. What is important isn't that y**z actually call y.__pow__(z), but that the two have the same effect.
Let's take a related example: y+z. I could make sure that each are PMCs, and then find the __add__ attribute, retrieve it, and then use it as a basis for a subroutine call, as the semantics of Python would seem to require. Or I could simply emit the add op.
How do I make these the same? I have a common base class for all python objects which defines an __add__ method thus:
METHOD PMC* __add__(PMC *value) { PMC * ret = pmc_new(INTERP, dynclass_PyObject); mmd_dispatch_v_ppp(INTERP, SELF, value, ret, MMD_ADD); return ret; }
... so, people who invoke the __add__ method explicitly get the same function done, albeit at a marginally higher cost.
Now to complete this, what I plan to do is to also implement all MMD/vtable operations at the PyObject level and have them call the corresponding Python methods. This will enable user level __add__ methods to be called.
Prior to calling the method, there will need to be a check to ensure that the method to be called was, in fact, overridden. If not, a type_error exception will be thrown.
- Sam Ruby