Sam Ruby wrote:

Leopold Toetsch wrote:

Only function calls / returns may change the context. A simple opcode like get_repr isn't allowed to do that.

The question isn't about what opcodes are or are not allowed to do. The question is what VTABLE_* functions are or are not allowed to do. Can VTABLE_invoke change the context? How about VTABLE_get_string?

Well, I think it's all answered in the two quoted lines. C<invoke> can change the context, but the next opcode after invoke has again the original context, because of the function return restores the context.


All other methods aren't allowed to change the context.

If you look at the current delegate PMC, every VTABLE call is translated to a call of a method. Are such methods allowed to change the context?

The delegate vtables or MMD wrappers call a method. That returns with the passed in return continuation. So all the wrapped methods behave exactly as if an opcode would have done the job. So no.


If things invoked by runops are not allowed to change the context, then runops should throw an internal exception if the context changes.

Well, as already said, that would need a check for each opcode and we don't do that. It's like a C compiler should check the stack pointer after each execute hardware opcode.


On the other hand, if runops can't change the context, then why is runops_args careful to capture the context prior to calling runops?

C<runops> is a low-level function that awaits all properly setup. Around that are more function that e.g. create a return continuation and do argument or returnvalue passing. Just use one of these functions as delegate.c does.


Again, what are the rules?

Simple: plain opcodes don't change the context. A function call does, but the return has to restore the context. Ovleroading doesn't change anything here.


But before you implement more and more methods I'd rather have inheritance and method calling conventions fixed.

How I chose to invest my time is up to me.

Of course. You have promised a summary ;)

The reason why I am proceeding this way is that I found the previous discussions on topics like object, classes, and metaclasses to be frustrating. I want the next round to be based on specifics.

I was very specific. Parrot (or the runcore, the engine) does method dispatch (when all is fixed and adjusted).


  add Px, Py, Pz

is equivalent to a method call:

  Px = Py."__add"(Pz)

The class (of Py) is queried via VTABLE_find_method() if it "can" do the "add", which will eventually cause more find_method calls to find a matching or best suited MMD method. After the method is found, it'll be called, being it a C function or an overloaded piece of code.

That'll cost some cycles on the first execution of this one opcode. The next one on that bytecode location is running 30%-70% faster as the current static MMD lookup.

The signature of an overloaded function for above is

   .sub myadd
      .param left
      .param right
      ...
     .return(dest)
    .end

"myadd" can be added via add_method() to the class (as "__add") or Parrot picks up an existing "__add" in the appropriate namespace (which will call add_method()). A class system can provide it's own add_method/find_method pair or use Parrot's scheme.

The same basics holds for all overloadable operations, being it currently vtable or MMD methods.

I want to be able to point at a specific wrapper and ask the question: how could it be done better?

You need a wrapper, if the Parrot implementation of the method for that class isn't matching Python semantics, e.g. to adjust return results. Or you just install your own method, e.g. for "__repr". Almost all basic methematical, logical, bitwise, ... operations should just have a reasonable implementation in core, and all HLLs will just use that.


Parrot_PyClass_get_repr is one such wrapper. How could it be done better? If you make a specific suggestion there, I'll either adopt it or produce a test case as a counter example.

You'd need in pyclass.pmc:

  PMC* get_repr() {
     return  pmc_new_string( ... "<class ...>")
  }

A method that returns the string representation of a PyClass object.

That's not a wrapper but an implementation for one specific class. No wrapper for other classes or a dispatch through run_meth_fromc_args is needed.

Nothing more will be needed, *when* all is fixed:

* we return PMCs normally (other types are optimizations)
* the methods create new PMCs - no LHS PMC is passed in
* all overloadable MMDs and vtables are registered as NCI methods
like the current METHOD syntax in .pmc files.
* Parrot knows common type names (Integer, Float, String, Bool, ...) of the supported languages
* all dispatch is based on VTABLE_find_method


That's a simple scheme and should be well suited for all current target languages - IMHO.

- Sam Ruby

leo



Reply via email to