src/multidispatch.c - Multimethod dispatch for binary opcode functions


This system is set up to handle type-based dispatching for binary (two argument) functions. This includes, though isn't necessarily limited to, binary operators such as addition or subtraction.


The MMD system is straightforward, and currently must be explicitly invoked, for example by a vtable function. (We reserve the right to use MMD in all circumstances, but currently do not).


For the purposes of the API, each MMD-able function is assigned a unique number which is used to find the correct function table. This is the func_num parameter in the following functions. While Parrot isn't restricted to a predefined set of functions, it does set things up so that all the binary vtable functions have a MMD table preinstalled for them, with default behaviour.

Remarks ^

binop_mmd_funcs->x and ->y are table sizes not highest type in table.

Functions ^

static void dump_mmd

RT #48260: Not yet documented!!!

funcptr_t get_mmd_dispatch_type

RT #48260: Not yet documented!!!

PMC *Parrot_mmd_find_multi_from_sig_obj

Collect a list of possible candidates for a given sub name and call signature. Rank the possible candidates by Manhattan Distance, and return the best matching candidate. The candidate list is cached in the CallSignature object, to allow for iterating through it.

Currently this only looks in the global "MULTI" namespace.

static void Parrot_mmd_ensure_writable

Make sure pmc is writable enough for function.


PMC *Parrot_build_sig_object_from_varargs

Take a varargs list, and convert it into a CallSignature PMC. The CallSignature stores the original short signature string, and an array of integer types to pass on to the multiple dispatch search.

void Parrot_mmd_multi_dispatch_from_c_args

Dispatch to a MultiSub, from a variable-sized list of C arguments. The multiple dispatch system will figure out which sub should be called based on the types of the arguments passed in.

Return arguments must be passed as a reference to the PMC, string, number, or integer, so the result can be set.

void mmd_add_function

Add a new binary MMD function to the list of functions the MMD system knows of. func_num is the number of the new function. function is ignored.

RT #45941 change this to a MMD register interface that takes a function *name*.


static void mmd_expand_x

Expands the function table in the X dimension to include new_x.


static void mmd_expand_y

Expands the function table in the Y direction.


void Parrot_mmd_register

Register a function funcptr for MMD function table func_num for classes left_type and right_type. The left and right types are INTVALs that represent the class ID numbers.

The function table must exist, but if it is too small, it will automatically be expanded.

Adding a new function to the table can be interestingly non-trivial, so we get to be tricky.

If the left or right types are larger than anything we've seen so far, it means that we have to expand the table. Making Y larger is simple -- just realloc with some more rows. Making X larger is less simple. In either case, we punt to other functions.

RT #45943 - Currently the MMD system doesn't handle inheritance and best match searching, as it assumes that all PMC types have no parent type. This can be considered a bug, and will be resolved at some point in the future.


void Parrot_mmd_register_sub

RT #48260: Not yet documented!!!


void mmd_destroy

Frees all the memory allocated used the MMD subsystem.


PMC *Parrot_mmd_find_multi_from_long_sig

Find the best candidate multi for a given sub name and signature. The signature is a string containing a comma-delimited list of type names.

Currently only searches the global MULTI namespace.

PMC *Parrot_MMD_search_default_infix

RT #48260: Not yet documented!!!


PMC *Parrot_mmd_sort_manhattan_by_sig_pmc

Given an array PMC (usually a MultiSub) and a CallSignature PMC sort the mmd candidates by their manhattan distance to the signature args.

PMC *Parrot_mmd_sort_manhattan

Given an array PMC (usually a MultiSub) sort the mmd candidates by their manhatten distance to the current args.

static PMC *Parrot_mmd_arg_tuple_func

Return a list of argument types. PMC arguments are taken from registers according to calling conventions.

static PMC *Parrot_mmd_search_default

Default implementation of MMD search. Search scopes for candidates, walk the class hierarchy, sort all candidates by their Manhattan distance, and return result

{{**DEPRECATE?? **}}

static void Parrot_mmd_search_classes

Search all the classes in all MultiSubs of the candidates cl and return a list of all candidates. start_at_parent is 0 to start at the class itself or 1 to search from the first parent class.

static INTVAL distance_cmp

RT #48260: Not yet documented!!!

static PMC *mmd_build_type_tuple_from_type_list

Construct a FixedIntegerArray of type numbers from an array of type names. Used for multiple dispatch.

static PMC *mmd_build_type_tuple_from_long_sig

Construct a FixedIntegerArray of type numbers from a comma-delimited string of type names. Used for multiple dispatch.

static PMC *mmd_cvt_to_types

Given a ResizablePMCArray PMC containing some form of type identifier (either the string name of a class or a PMC representing the type), resolves all type references to type IDs, if possible. If that's not possible, returns PMCNULL. In that case you can't dispatch to the multi variant with this type signature, as Parrot doesn't yet know about the respective types requested -- you have to register them first.

Otherwise, returns a ResizableIntegerArray PMC full of type IDs representing the signature of a multi variant to which you may be able to dispatch.


static UINTVAL mmd_distance

Create Manhattan Distance of sub pmc against given argument types. 0xffff is the maximum distance

static void Parrot_mmd_sort_candidates

Sort the candidate list cl by Manhattan Distance

static PMC *Parrot_mmd_search_scopes

Search all scopes for MMD candidates matching the arguments given in arg_tuple.

static int mmd_maybe_candidate

If the candidate pmc is a Sub PMC, push it on the candidate list and return TRUE to stop further search.

If the candidate is a MultiSub remember all matching Subs and return FALSE to continue searching outer scopes.

static int mmd_search_local

Search the current package namespace for matching candidates. Return TRUE if the MMD search should stop.

static void mmd_search_by_sig_obj

Search the namespace of the first argument to the sub call for matching candidates.

static void mmd_search_global

Search the builtin namespace for matching candidates.

static void mmd_add_multi_global

Create a MultiSub, or add a variant to an existing MultiSub. The MultiSub is stored in the global MULTI namespace.

static void mmd_add_multi_to_namespace

Create a MultiSub, or add a variant to an existing MultiSub. The MultiSub is added as a method to a class.

void Parrot_mmd_add_multi_from_long_sig

Create a MultiSub, or add a variant to an existing MultiSub. The MultiSub is stored in the global MULTI namespace.

void Parrot_mmd_add_multi_from_c_args

Create a MultiSub, or add a variant to an existing MultiSub. The MultiSub is stored in the specified namespace.

void Parrot_mmd_add_multi_list_from_c_args

Create a collection of multiple dispatch subs from a C structure of information. Iterate through the list of details passed in. For each entry create a MultiSub or add a variant to an existing MultiSub. MultiSubs are created in the global 'MULTI' namespace in the Parrot HLL.

Typically used to create all the multiple dispatch routines declared in a PMC from the PMC's class initialization function.