parrotcode: Multiple Dispatch | |
Contents | Documentation |
docs/pdds/pdd27_multiple_dispatch.pod - Multiple Dispatch
This PDD defines Parrot's multiple dispatch system.
$Revision$
Multiple dispatch allows a single function name to be associated with several alternate implementations. It selects the alternate to execute for a particular call at runtime, based on the types of the arguments passed into the call. The selection process compares the arguments of the call and the types declared in the signatures of the alternates, as well as their inherited or composed parents, to find the best match.
A similar selection of alternates based on types at compile time is generally called overloading.
The aim of Parrot's multiple dispatch system is not to be an exact match to any one HLL, but to provide the features and tools needed to support multiple dispatch in a number of different HLLs.
Parrot has a single multiple dispatch system, used at the HLL level and internally. {{NOTE: I appreciate the history that led us to have two largely independent MMD systems, but it will cause problems down the road, if we don't fix it now.}}
The heart of the system is the MultiSub PMC. All multiple dispatch routines are MultiSub PMCs, subclasses of MultiSub, or polymorphic equivalents of MultiSub. Calls to multiple dispatch routines use the Parrot calling conventions.
A MultiSub stores a list of subroutines. When a MultiSub is invoked, it calls an MMD sorting routine to select the best candidate for the current arguments, and invokes that candidate.
A MultiSub can be used anywhere a Sub can be used. It can be stored in a namespace or as a method or vtable override in a class.
An alternate multiple dispatch matching algorithm may be plugged in by subclassing MultiSub and overriding invoke
.
MultiSub defines the following vtable functions in addition to the ones inherited from ResizablePMCArray.
Parrot_mmd_sort_candidate_list
from the public MMD API,
but may be changed to call Parrot_mmd_invoke
.The following attributes are used when declaring a MultiSub in PIR.
.sub mymultisub :multi(Integer, Integer)
:multi
attribute marks a subroutine or method as participating in multiple dispatch. .param pmc first :invocant
:invocant
, and must be contiguous. Subs that are not marked with :multi
may not mark parameters with :invocant
.These functions are the public interface to common multiple dispatch operations, and may be called from opcodes, vtable functions, or other C functions.
Parrot_PCCINVOKE
, but doesn't separate out the invocant before the signature since the call can have multiple invocants. A significant part of the code from Parrot_PCCINVOKE
can be factored out to helper routines used by both Parrot_PCCINVOKE
and Parrot_mmd_invoke
. void
Parrot_mmd_invoke(PARROT_INTERP, NOTNULL(STRING *sub_name),
ARGIN(const char *signature), ...)>
mmd_dispatch_v_pi()
.Parrot's basic opcodes are not multiple dispatch. They appear to be so, since a single opcode name may have multiple signatures. But, behind the scenes, this is essentially compile-time overloading. (Each different signature is actually a different opcode number, hidden behind the abstraction of a single name.)
Multiple dispatch is only used by a limited set of opcodes. These opcodes directly correspond to standard vtable functions. Multiple dispatch opcodes may take PMC, integer, float, or string arguments and return a PMC, integer, float, or string result.
Multiple dispatch opcodes are standard opcodes that internally call the Parrot_mmd_invoke
routine from the public MMD API.
{{NOTE: It is no longer necessary to name multisubs used for opcode dispatch using the "__" names.}}
Some PMCs call multiple dispatch routines from their vtable functions. ResizablePMCArray, for example, calls the multiple dispatch equality operation on each element of two arrays from the 'is_equal' vtable function.
Multiple dispatch calls from within vtable functions call the Parrot_mmd_invoke
routine from the public MMD API.
None.
docs/mmd.pod src/mmd.c src/pmc/multisub.pmc
|