/*
Copyright (C) 2001-2008, The Perl Foundation.
$Id: /mirror/trunk/src/pmc/multisub.pmc 34095 2008-12-18T09:19:52.213267Z chromatic  $

=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 "parrot/parrot.h"


pmclass MultiSub extends ResizablePMCArray need_ext provides array {

    void push_pmc(PMC *value) {
        STRING * const _sub = CONST_STRING(interp, "Sub");
        STRING * const _nci = CONST_STRING(interp, "NCI");

        if (!VTABLE_isa(interp, value, _sub)
        &&  !VTABLE_isa(interp, value, _nci))
            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
                    "attempt to push non Sub PMC");

        SUPER(value);
    }

    VTABLE void set_pmc_keyed_int(INTVAL key, PMC *value) {
        STRING *_sub = CONST_STRING(interp, "Sub");
        if (!VTABLE_isa(interp, value, _sub))
            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
                    "attempt to set non Sub PMC");
        SUPER(key, value);
    }

    VTABLE void set_integer_keyed_int(INTVAL key, INTVAL value) {
        Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
                "attempt to set non Sub PMC");
    }

    VTABLE void set_string_keyed_int(INTVAL key, STRING *value) {
        Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
                "attempt to set non Sub PMC");
    }

    VTABLE void set_number_keyed_int(INTVAL key, FLOATVAL value) {
        Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
                "attempt to set non Sub PMC");
    }

    VTABLE opcode_t *invoke(void *next) {
        PMC * const func = Parrot_mmd_sort_manhattan(interp, SELF);

        if (PMC_IS_NULL(func))
            Parrot_ex_throw_from_c_args(INTERP, NULL, 1, "No applicable methods.\n");

        return VTABLE_invoke(INTERP, func, next);
    }

    VTABLE PMC *get_iter() {
        PMC * const sub = Parrot_mmd_sort_manhattan(INTERP, SELF);

        if (PMC_IS_NULL(sub))
            Parrot_ex_throw_from_c_args(INTERP, NULL, 1, "No applicable methods.\n");
        return SUPER();
    }

    /* I don't really know how to implement these if they need something
       special, so I'll sort the sub list and defer processing to the
       ResizablePMCArray's VTABLE methods of the same names. Hopefully we
       don't need anything beyond that. */
    VTABLE PMC *get_pmc_keyed(PMC *key) {
        PMC *sub = Parrot_mmd_sort_manhattan(INTERP, SELF);
        if (PMC_IS_NULL(sub))
            Parrot_ex_throw_from_c_args(INTERP, NULL, 1, "No applicable methods.\n");
        return SUPER(key);
    }

    VTABLE PMC *get_pmc_keyed_string(STRING *s) {
        PMC *sub = Parrot_mmd_sort_manhattan(INTERP, SELF);
        if (PMC_IS_NULL(sub))
            Parrot_ex_throw_from_c_args(INTERP, NULL, 1, "No applicable methods.\n");
        return SUPER(s);
    }

    /* get_iter method should take one of two inputs: either an array of
       arguments, or a string with a whitespace delimited function signature
       (N, I, S, P). It should sort the argument list according to closeness
       to this input argument list and return an iterator over that list. */

    METHOD PMC *get_iter(PMC *args) {
        STRING * const _array  = CONST_STRING(interp, "Array");
        STRING * const _string = CONST_STRING(interp, "String");

        if (VTABLE_isa(INTERP, args, _array)){
            /* TODO: What goes here? */
        }
        else if (VTABLE_isa(INTERP, args, _string)) {
            STRING * const s = VTABLE_get_string(INTERP, args);
            /* TODO: What goes here? */
        }
        else
            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
                    "attempt to call get_iter method with invalid arg type.\n");
    }
}

/*

=back

=head1 SEE ALSO

F<src/multidispatch.c>,
F<$perl6/doc/trunk/design/apo/A12.pod>,
F<$perl6/doc/trunk/design/syn/S12.pod>

=head1 HISTORY

Initial version                  - leo 14.03.2005

=cut

*/

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