Leopold Toetsch wrote:

Sam Ruby <[EMAIL PROTECTED]> wrote:

Leopold Toetsch wrote:

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.

Ok. But that would imply that HLL interoperbility isn't really possible. Or just at a minimal surface level. But see below.

I don't believe that to be the case. If a Perl subroutine were to call a Python function and pass a PerlInt as a parameter, the receiving function should expect to be able to do addition via tha "+" operator, but should not be expect to find an "__add__" method on such objects. Instead, and if they cared to, they could explicitly call the "__add" method provided.


The reverse should also be true, if Python function were to call a Perl subroutine and pass a PyInt as a parameter, the receiving subroutine should expect to be able to do addition via the "+" operator, but not expect to find an "__add" method on such objects. Instead, and if they cared to, they could explicitly call the "__add__" method provided.

I would consider that significant interoperability with only minimal restrictions.

While the Python people aren't stopping to talk about the clearness of
their language, nothing is clear and explicit, when it comes to overloading
or metaclasses.

Please don't do that. I am not trying to extoll the virtues of Python, merely trying to implement it.


Anyway, IMHO, "class.__add__ = foo" or your example manipulating
"class.__dict__" (another special attribute name!) is the point, where
you can install Parrot semantics WRT method overloading.

Hold that thought. I'll answer this below.

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

We both know that's a simplification :) You've to install the methods of course ...

Again, it can't be done exclusively at translation time. It needs to be done at runtime. And if it is done at runtime, it need not be done at translation time at all. More below.


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.

The "class.__dict__" dictionary is special. Setting an "__add__" key too. The combined meaning is overloading. The different signature is a problem, yes - I've already mentioned that. And Parrot's "__add" method is not hypothetical :-)

$ grep __add t/pmc/object*.t

Here I'll apologize for being unclear. Yes, there is code in the existing object class in support of Perl's S06. What's hypothetical is the presumption that all languages will adopt Perl 6's naming convention for methods.


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.

Does it matter if the name is actually reserved? The meaning is important.

It does matter. Python classes are dictionaries of objects, some of which may be functions. You may extract objects from that dictionary and access them later. The "meaning" in such a scenario is not apparent until well after all interaction with the compile and runtime dictionaries is over.


... 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'd say, if you define an '__add__' method with 16 arguments, Python will throw an exception, if you try to use C<+> with an object of that class:

If I define an __add__ method with 16 arguments, Python will not throw an exception.


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.

Why? And how do you find your class then:

  c = C()
             ...
  3          22 LOAD_NAME                1 (C)
             25 CALL_FUNCTION            0

$pirate -d c.py ... find_lex $P0, 'C' $P1=$P0() store_lex -1, 'c', $P1

The important part isn't simply in which hash a given class name is looked up in, but that classes themselves in Python are transient objects subject to garbage collection.

... Where methods are properties
that can be added simply by calling the equivalent of set_pmc_keyed.

Nah. Methods aren't properties, but ...

No? Try the following:

   x = "abcdef".find
   print x('c')

The "set_pmc_keyed" on "__dict__" (or an equivalent setattribute call)
of your type system is responsible to create Parrot semantics for method
calls :-)

If this is done at runtime, the it need not be done at compile time.

However, it doesn't stop here. Just like methods can be added dynamically by name at runtime, they can be accessed dynamically by name. That means that all method lookups will need to be preceeded by a hash lookup. An not just on Python objects, but *all* objects.

That's why I object to characterizations like "dynamic dispatch is 30% faster than...". What will ultimately result if it is mandated that all languages adopt Perl6's semantics is that an ADDITIONAL dynamic dispatch will be required to make non-Perl6 functions work.

 - - -

The alternative is to treat C<__add> and C<__add__> as characterists that some languages chose to place on their objects, and outside the scope of the standard behaviors that Parrot provides. All such existing behavior moves from src/objects.c and src/global.c and classes/*.pmc to dynclass/perl*.pmc and/or dynclass/py*.pmc as appropriate.

Internally, Parrot will define a large but finite set of methods. One pair of such methods, C<find_method> and <invoke> are provided for languages to define their own behaviors. The namespaces for the two sets of methods is purposefully kept separate.

PerlScalar's implementation of the add will know about how to implement Perl 6's multi sub *infix. PyObject won't, but it will know about Python's __meta__ and __init_class__.

Users of languages built on Parrot should expect things like C<+> and C<[]> and iterators to work, but when they wander off into language specific territory, they will need to utilize mechanisms based on find_method and knowledge of names of the methods that they are trying to call.

- Sam Ruby

Reply via email to