Leopold Toetsch wrote:

Sam Ruby <[EMAIL PROTECTED]> wrote:

Leopold Toetsch wrote:

My philosophy is simple: things without test cases tend not not get
fixed, and when fixed, tend not to stay fixed.

There is of course a test case. I have mentioned it at least 20 times ;) t/op/gc_13.imc - currently using lexicals.

$ parrot t/op/gc_13.imc 3 * 5 == 15!

What's broken?

I am worried about Parrot trying to establish common public names for
common functions.  Many of the examples you gave did not include the
prerequisite double underscores.  For example: "sub", "imag", "eof".

Ah ok. Sorry. "__subtract". OTOH some might be that common and the usage is the same in all languages that we might use that common name. But that's probably not worth the effort. So yes, we should establish the notion that all methods follow that convention.

Cool.

Re: VTABLES... I disagree with you on this one.  Prematurely mapping an
operation to a string is a premature pessimization.

Except that we are doing that already. Please read through classes/delegate.c. The problem is that this scheme doesn't work for MMD of real objects.

I don't know enough to have an informed opinion yet on MMD.  But
__set_integer_native is not a MMD operation.  It already is efficiently
dispatched to the correct method.

For PMCs yes. For objects not efficiently and only with a separate delegate meta-class.

The current delegation internals are not likely a good match for languages like Python or Ruby. I see such languages as implementing their own semantics for classes, and Parrot limiting its knowledge to methods like findmeth and invoke.


... What do we benefit from the premature
pessimisation of mapping this to a string?

Well, method names happen to be strings ;)

Using the table below, at the moment, there are exactly zero strings materialized and/or compared against during the execution of vtable/PMC methods. To the extent that these are represent common operations, this can be significant from a performance perspective.


Anyway, I'll try to summarize our current method dispatch scheme:

               vtable            MMD              NCI method
 -------------------------------------------------------------
 opcode        set P0, 4         add P0, P1, P2   io."__eof"()
 -------------------------------------------------------------
 PMC           pmc->vtable->..   mmd_dispatch_*   callmethod
 object        delegate.c          1)             callmethod
 object(PMC)   deleg_pmc.c         1)             callmethod

NCI methods are working, the method lookup is dynamic, inheritance
works.

MMD inheritance is totally static (set up during PMC compilation).
PMCs dispatch with the mmd_dispatch_* functions in ops/*.ops.
1) overloading a MMD infix operation needs the mmdvtregister opcode, but
this does not effect any class inheritance and it's just for the given
two types.
Multi-dimensional MD is not implemented.

For vtables objects and objects derived from PMCs use two helper classes
that bridge the dynamic inheritance of objects to the static inheritance
in PMCs. This doesn't support runtime overloading of methods that
defaulted to the PMC method.

Looking at 5 different schemes that work for ~50% of the cases can -
well - make one pessimistic ;)

I'm proposing that *internally* (implementation detail ...) one scheme
should be enough. Again: the opcodes don't change.

I don't think that there can be a single dynamic mechanism that works for all languages, let alone one that works for Parrot internals too.


For starters, "findmeth" is a method. One that merits its own VTABLE entry (otherwise, how would you find it?). Others that map cleanly onto existing language syntax also can benefit from such optimizations.

MMD might help out with mutiple language interop, but Python as currently designed doesn't need any such facility.

The vtable method set_integer_native clearly maps to a real method that

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

can be either inherited or be provided by the user. This doesn't work
for MMD functions.

Again, set_integer_native is not an MMD function?

__set_integer_native is a vtable method.

Cool.

No. I'm not ditching lexical pads at all. They are of course needed. The
top pad is in the registers. Outer pads are looked up as usual.

I guess I don't understand.  I guess it is time for a test case.  ;-)
How would the following work if the top pad is in registers?

The top pad is always the currently executing one.

  var = 1
  def g():
    global var
    var = 2

  print "before", var
  g()
  print "after", var

It's obviously up to the "global" to do the right thing. My impression (I don't have more Python knowledge ;) is, that "global" refers to the outermost lexical pad in the main module.

Such behavior is the default for perl5:

  my $var = 1;
  sub g {
    $var = 2;
  }

As there is no "my $var" in the inner pad, that's just a C<find_lex> opcode. It follows the C<prev> pointer to the outer pad and finds in the lexical hash the "$var" which maps to a position in the register store of the outer pad.

"my ($a, $b)" in the innermost pad (in sub g) would map directly to
registers as "my $var" maps to a register in "main" (in the outer pad).

It's the same as currently, except that we have now a separate array
that holds the lexicals. I was just mapping that array into the
preserved area of registers, which would make this area of course
variable-sized with the nice benefit that "my int $i" also works (we
don't have natural int lexicals currently).

I asked my question poorly, and I think you answered it, but the important point is that subroutines can change the lexical variables of their callers - enough so that either a second level of indirection is required (such as Dan recently indicated is that plans for Perl6 and Ruby), or subroutines will need to refetch lexicals after a subroutine call.


- Sam Ruby

Reply via email to