Dan Sugalski wrote:

Separate op won't work for Python.  Consider:

  def f(x,y): return x+y
  print f(5,6)     # 11
  print f("a","b") # ab

Oh, sure it'd work, if you had an ADD_OR_CONCATENATE op with an appropriate MMD table. :)

Conceptually, "+" is not an op at all in Python, it is syntatic sugar for a method call. Consider:


  def f(x,y): return x+y

  class g:
    def __init__(self,value): self.value=value
    def __add__(self,value): return str(self.value)+str(value)

  print g(1)+1

CPython returns "11".

Still, the downside is that you'd like:

    a + b

to do the same thing no matter what language emitted the code. (Though arguably perl's + is the same as, say, a lisp +, but different from a VB/Python +, they just happen to have the same sigil)

I don't think that a substrate like Parrot should "take sides" on issues such as these. add_p_p_p is a function that takes as input two PMCs and produces another PMC. The data types of the output can't be reliably determined by the input. The underlying function performed is entirely dependent on the PMCs in question.


I would suggest that the responsibility of Parrot begins and ends with doing the appropriate MMD.

Also:

  def f(x,y): return x.__add__(y)
  print f(5,6)     # 11
  print f("a","b") # ab

In fact, it gets stranger. Methods can be detached from their classes and accessed as functions:

  print int.__add__(3,4)
  z="a".__add__
  print z("b")

Ah, I get stranger things than that with my breakfast cereal. (Which is one of the reasons I tend to have a bagel for breakfast, but that's neither here nor there) That's not actually a big problem, though it's something we'd *definitely* want to wedge into the code generator. (One of those places where dealing with the AST is a lot nicer than dealing with the bytecode)


With AST access, the z="a".__add__ would end up with code to check for an __add__ method and if found create an anonymous method closure PMC for z. Invoking z invokes the closure, sets up the object slot, and makes the method call as it ought. (Whether it should go search the hierarchy when bound or invoked is a separate thing)

Alternately, __add__ would simply be a attribute of the string PMC, with a value being the same closure which you describe. Ideally, the creation of this closure could be deferred until the attribute was actually retrieved.


Similarly, the add(PMC, PMC) function in PyObject should look for, and attempt to invoke, any such __add__ methods. That way, classes derived from PyObject could override "+" by providing an appropriate implementation of an __add__ method.

But actually, my recommendation is that we don't go that far yet. Yesterday, I coded up a number of python pmcs:

  pyboolean.pmc  pyfloat.pmc  pylist.pmc  pyobject.pmc  pytuple.pmc
  pydict.pmc     pyint.pmc    pynone.pmc  pystring.pmc

Actually, when I say "coded", all I did was copy some existing pmcs and made minimal changes (global renames, removed the checks for PARROT_PYTHON_MODE by making such paths the defaults, added some get_repr implementations, and some minor tweaks like making integers no longer promote to floats).

While I got a version of Pirate to work with these new classes, the result feels a bit like cheating. What I would like to do is to evolve this into a complete Python object model, focusing first on being a faithful implementation of Python, initially at the expense of interlanguage interop.

Seems like the right thing to do to me.

As I am doing this work, should I put this on my server some place? Check it in some place? Send it as patches?


- Sam Ruby

Reply via email to