Leopold Toetsch wrote:

Good. Now Evil Leo (who can't program in Python ;) writes some piece of code like this:

$ cat m.py
class M(type):
    def __new__(meta, name, base, vars):
        cls = type.__new__(meta, name, base, vars)
        cls.__add__ = myadd
        return cls

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

I = M('Int', (int,), {})

i = I(5)
print i
print i + 2

$ python m.py
5
42

What this means is that the __add__ method will not be directly used for
either PyInt or PyString objects

Well, and that's not true, IMHO. See above. It has to be part of Parrot's method dispatch. What if your translator just sees the last 3 lines of the code and M is in some lib? That implies that you either can't translate to "$P0 = $P1 + $P2", or that you just translate or alias "__add__" to Parrot's "__add" and let Parrot fiddle around to find the correct method.

Here's the part that you snipped that addresses that question:

  > And there is a piece that I haven't written yet that will do the
  > reverse: if MMD_ADD is called on a PyObject that has not provided
  > such behavior, then an any __add__ method provided needs to be
  > called.

* the method is returning a new PMC. This doesn't follow the signature
 of Parrot infix MMD operations.

Here I do think you are misunderstanding.  The __add__ method with
precisely that signature and semantics is defined by the Python language
specification.  It is (somewhat rarely) used directly, and therefore
must be supported exactly that way.

| __add__(...) | x.__add__(y) <==> x+y

Parrot semantics are that the destination exists. But having a look at
above "myadd", we probably have to adjust the calling conventions for
overloaded infix operators, i.e. return the destination value. Or
provide both schemes ... dunno.

Since you provided an Evil Leo sample, let me provide an Evil Sam sample:

  d = {
    "__init__": lambda self,x: setattr(self, "value", x),
    "__add__":  lambda self,x: str(self.value) + str(x.value)
  }

  def dict2class(d):
    class c: pass
    c.__dict__.update(d)
    return c

  c = dict2class(d)

  a=c(2)
  b=c(3)
  print a+b

Things to note:
  1) classes which are created every time a function is called
  2) classes are thin wrappers over a dictionary object

Now, given the above sample, let's revisit the statement that "The Python translator needs just a translation table for the common core methods."

How, exactly, would that be done? Given that the method name is simply a string... used as a key in dictionary... with a different parameter signature than the hypothetical Parrot __add method.

That's why I say:

In the general case, looking for "reserved" method names at "compile"
time doesn't work.

"__add__" is reserved in Python and corresponds directly to "__add" in
Parrot. I don't think that doesn't work.

__add__ is *not* reserved in Python. There just is some syntatic sugar that provide a shorthand for certain signatures. I am free to define __add__ methods that have zero or sixteen arguments. I won't be able to call such methods with the convenient shorthand, but other than that, they should work.


I personally don't think that performance considerations should be out
of bounds in these discussions

I've already shown that it's possible to go with fully dynamic dispatch *and* 30% faster for MMD and 70% faster for overloaded operations. First correct and complete, then speed considerations.

Neither of which match Python semantics. We are going to need a system where classes are anonymous, not global. Where methods are properties that can be added simply by calling the equivalent of set_pmc_keyed.


- Sam Ruby

Reply via email to