The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
/*
Copyright (C) 2001-2009, Parrot Foundation.

=head1 NAME

src/pmc/multisub.pmc - A container for multi-dispatched subs

=head1 DESCRIPTION

This class inherits from ResizablePMCArray and provides an Array of
Sub PMCs with the same short name, but different long names.

=head2 Functions

=over 4

=cut

*/

#include "pmc/pmc_callcontext.h"

/* HEADERIZER HFILE: none */
/* HEADERIZER BEGIN: static */
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */

static void check_is_valid_sub(PARROT_INTERP, ARGIN(PMC * sub))
        __attribute__nonnull__(1)
        __attribute__nonnull__(2);

#define ASSERT_ARGS_check_is_valid_sub __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
       PARROT_ASSERT_ARG(interp) \
    , PARROT_ASSERT_ARG(sub))
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
/* HEADERIZER END: static */

/*

=item C<static void check_is_valid_sub(PARROT_INTERP, PMC * sub)>

TK

=cut

*/

static void
check_is_valid_sub(PARROT_INTERP, ARGIN(PMC * sub))
{
    ASSERT_ARGS(check_is_valid_sub)
    STRING * const invokable_str = CONST_STRING(interp, "invokable");
    if (!VTABLE_does(interp, sub, invokable_str))
        Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
            "attempt to add non-invokable PMC");
}

pmclass MultiSub
    extends ResizablePMCArray
    auto_attrs
    provides array
    provides invokable {

    VTABLE STRING * get_string() {
        PMC * const sub0    = VTABLE_get_pmc_keyed_int(INTERP, SELF, 0);
        /*if (PMC_IS_NULL(sub0))
            return STRINGNULL;*/
        STRING * const name = VTABLE_get_string(INTERP, sub0);
        return name;
    }

    VTABLE void push_pmc(PMC *value) {
        check_is_valid_sub(INTERP, value);
        SUPER(value);
    }

    VTABLE void set_pmc_keyed_int(INTVAL key, PMC *value) {
        check_is_valid_sub(INTERP, value);
        SUPER(key, value);
    }

    VTABLE opcode_t *invoke(void *next) {
        PMC * const sig_obj = CONTEXT(INTERP)->current_sig;
        PMC * const func    = Parrot_mmd_sort_manhattan_by_sig_pmc(INTERP,
                SELF, sig_obj);

        if (PMC_IS_NULL(func))
            Parrot_ex_throw_from_c_args(INTERP, NULL, 1,
                    "No applicable candidates found to dispatch to for '%Ss'",
                    VTABLE_get_string(INTERP, SELF));
        return VTABLE_invoke(INTERP, func, next);
    }
}

/*

=back

=head1 SEE ALSO

F<src/multidispatch.c>,

=cut

*/

/*
 * Local variables:
 *   c-file-style: "parrot"
 * End:
 * vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
 */