Leopold Toetsch wrote:
However, from <http://www.perl.com/pub/a/2004/04/16/a12.html?page=10>:
Whenever you make a call using subroutine call syntax, it's a candidate for multiple dispatch.
I read this to mean that the *caller* does nothing to distinguish between calls to single dispatch subroutines from multiple dispatch subroutines.
So... how does one determine at compile time which opcode to use?
This probably needs some clarification from Perl6 people. Anyway, if Parrot just gets:
foo(Px, Py, Pz)
there is no information, how many invocants are participating in MMD. So candidates for multiple dispatch must be declared somewhere.
$a.foo($b, $c) := foo($a, $b, $c)
Given the latter syntax, how does the compiler know when to emit a <callmethodcc "foo"> and when to emit a <call_MMD "foo">?
The compiler has to know it. E.g.
foo($a: $b, $c); # 1 invocant foo($a, $b: $c); # 2 MMD invocants
and as Parrot has to find a method depending on n MMD invocants, this information must be present at runtime. This leads to the assumption that we'll need an opcode
call_MMD "meth", n_invocants
and some changes in pdd03 as the current calling scheme doesn't have anything about argument order. I have described that in subject:
"MMD: more implications"
The only thing I am attempting to solve is the presumption that MMD calls can be detected at "compile time".
It's quite clear for infix operations like "add". For arbitrary subroutines the compiler has to know it, as outlined above.
Unless you can describe a mechanism which enables the callers to detect
at "compile" time whether they are invoking a MMD subroutine or not, this code needs to be either executed as a part of an VTABLE_invoke.
See above.
Again, I am not suggesting that the algorithm be made any "thinner", in fact, I am not suggesting any change to the algorithms that you have described. I am merely suggesting where the logic needs to be placed.
This is quite clear, IMHO. As said:
Px = Py + Pz
is a call to a MMD function, which is located by the described sequence of VTABLE_find_method and called. The dispatch happens at the opcode level. That's really the same as a "callmethodcc" opcode, which happens to have just one invocant. There is no difference between these to invocations except that "add" or "+" is a fancy shortcut for humans reading the source code. Above is exactly the same as:
Px = Py."__add"(Pz)
But as there are two invocants and we know that's and "add" operation, we have an optimized opcode for this kind of infix MMD operations like:
Px = call_MMD_2 "__add", Py, Pz
where Px is *created* by the opcode.
I'm just proposing this equivalence and a scheme to make it running.
And despite that it's looking like a "fat" method call, Parrot executes this sequence, if the "__add" isn't overloaded:
if (cache->type == (Py->vtable->base_type << 16|Pz->vtable->base_type) Px = (cache->function)(Py, Pz);
which is 30% faster then the current mmd_dispatch based opcode.
- Sam Ruby
leo