1/*
2Copyright (C) 2001-2014, Parrot Foundation.
3
4=head1 NAME
5
6src/pmc/multisub.pmc - MultiSub PMC
7
8=head1 DESCRIPTION
9
10A container for multi-dispatched subs.
11
12This class inherits from ResizablePMCArray and provides an Array of
13Sub PMCs with the same short name, but different long names.
14
15=head2 Functions
16
17=over 4
18
19=cut
20
21*/
22
23#include "pmc/pmc_callcontext.h"
24
25/* HEADERIZER HFILE: none */
26/* HEADERIZER BEGIN: static */
27/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
28
29static void check_is_valid_sub(PARROT_INTERP, ARGIN(PMC * sub))
30        __attribute__nonnull__(1)
31        __attribute__nonnull__(2);
32
33#define ASSERT_ARGS_check_is_valid_sub __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
34       PARROT_ASSERT_ARG(interp) \
35    , PARROT_ASSERT_ARG(sub))
36/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
37/* HEADERIZER END: static */
38
39/*
40
41=item C<static void check_is_valid_sub(PARROT_INTERP, PMC * sub)>
42
43TK
44
45=cut
46
47*/
48
49static void
50check_is_valid_sub(PARROT_INTERP, ARGIN(PMC * sub))
51{
52    ASSERT_ARGS(check_is_valid_sub)
53    STRING * const invokable_str = CONST_STRING(interp, "invokable");
54    if (!VTABLE_does(interp, sub, invokable_str))
55        Parrot_ex_throw_from_c_noargs(interp, EXCEPTION_INVALID_OPERATION,
56            "attempt to add non-invokable PMC");
57}
58
59pmclass MultiSub
60    extends ResizablePMCArray
61    auto_attrs
62    provides array
63    provides invokable {
64
65    VTABLE STRING * get_string() :no_wb {
66        PMC * const sub0    = VTABLE_get_pmc_keyed_int(INTERP, SELF, 0);
67        /*if (PMC_IS_NULL(sub0))
68            return STRINGNULL;*/
69        STRING * const name = VTABLE_get_string(INTERP, sub0);
70        return name;
71    }
72
73    VTABLE void push_pmc(PMC *value) :manual_wb {
74        check_is_valid_sub(INTERP, value);
75        SUPER(value);
76    }
77
78    VTABLE void set_pmc_keyed_int(INTVAL key, PMC *value) :manual_wb {
79        check_is_valid_sub(INTERP, value);
80        SUPER(key, value);
81    }
82
83    VTABLE opcode_t *invoke(void *next) :no_wb {
84        PMC * const sig_obj = CONTEXT(INTERP)->current_sig;
85        PMC * const func    = Parrot_mmd_sort_manhattan_by_sig_pmc(INTERP,
86                SELF, sig_obj);
87
88        if (PMC_IS_NULL(func))
89            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_METHOD_NOT_FOUND,
90                    "No applicable candidates found to dispatch to for '%Ss'",
91                    VTABLE_get_string(INTERP, SELF));
92        return VTABLE_invoke(INTERP, func, next);
93    }
94}
95
96/*
97
98=back
99
100=head1 SEE ALSO
101
102F<src/multidispatch.c>,
103
104=cut
105
106*/
107
108/*
109 * Local variables:
110 *   c-file-style: "parrot"
111 * End:
112 * vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
113 */
114