/*
Copyright (C) 2001-2008, The Perl Foundation.
$Id: /mirror/trunk/src/pmc/default.pmc 35118 2009-01-07T03:34:47.066581Z allison  $

=head1 NAME

src/pmc/default.pmc - Abstract root class

=head1 DESCRIPTION

These are the vtable functions for the default PMC class.

All methods which are not defined here get a default implementation
generated from F<src/vtable.tbl> by F<tools/build/pmc2c.pl>.

=head2 Functions

=over 4

=cut

*/

#include "parrot/parrot.h"

#define INT2KEY(i, k) key_new_integer((i), (k))

/* undef 'interface' to keep MSVC happy */
#undef interface

/*

=item C<static STRING *caller(PARROT_INTERP, PMC *pmc)>

Returns a C string for the name of C<*pmc>.

=cut

*/

static STRING *
caller(PARROT_INTERP, PMC *pmc /*NULLOK*/)
{
    STRING * const null_str = CONST_STRING(interp, "(null)");

    return pmc && pmc->vtable && pmc->vtable->whoami
                ? VTABLE_name(interp, pmc) : null_str;
}

/*

=item C<static void cant_do_method(PARROT_INTERP, PMC *pmc,
                                   const char *methname)>

Throws an exception "$methname() not implemented in class '$class'", used by
all unimplemented messages.

=cut

*/

static void
cant_do_method(PARROT_INTERP, PMC *pmc /*NULLOK*/, const char *methname)
{
    Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_ILL_INHERIT,
            "%s() not implemented in class '%Ss'", methname,
            caller(interp, pmc));
}

/*

=item C<static INTVAL
check_set_std_props(PARROT_INTERP, PMC *pmc, STRING *key, PMC *value)>

Called from C<setprop()>.

Returns a true value if C<setprop()> can avoid actually setting a property
in the prophash. If it returns true, the property setting will be reflected
in a future call to C<propagate_std_props()>

=cut

*/

static INTVAL
check_set_std_props(PARROT_INTERP, PMC *pmc, STRING *key, PMC *value)
{
    /* the quick hack below cannot be used because the string could
       be constructed in an interpreter that is later destroyed */
#if  0
    /* RT #46659
     * a quick hack, to prevent freeing that string during DOD
     * triggered in t/pmc/pmc_62.t when configured with --gc=libc
     */
    static STRING *ro;
    if (!ro)
        ro = string_make(interp, "_ro", 3, "ascii",
            PObj_constant_FLAG|PObj_external_FLAG);
    if (!string_compare(interp, key, ro)) {
#else

    /*
     * s2 in string_compare is freed here
     */
    if (!string_compare(interp, key, CONST_STRING(interp, "_ro"))) {
#endif
        /* pmc should set/clear readonly */
        const INTVAL on = VTABLE_get_bool(interp, value);

        /* morph to Const/normal class or readonly class */
        /* RT #46661 warn when this fails? */
        if (on && (pmc->vtable->flags & VTABLE_HAS_CONST_TOO))
            pmc->vtable = interp->vtables[pmc->vtable->base_type + 1];
        else if (!on && (pmc->vtable->flags & (VTABLE_IS_CONST_FLAG)))
            VTABLE_morph(interp, pmc, pmc->vtable->base_type - 1);
        else if (on && (pmc->vtable->flags & VTABLE_HAS_READONLY_FLAG))
            pmc->vtable = pmc->vtable->ro_variant_vtable;
        else if (!on && (pmc->vtable->flags & VTABLE_IS_READONLY_FLAG)
                && pmc->vtable->ro_variant_vtable)
            pmc->vtable = pmc->vtable->ro_variant_vtable;
        else
            return 0;

        return 1;
    }

    return 0;
}

/*

=item C<static void
propagate_std_props(PARROT_INTERP, PMC *self, PMC *prop_hash)>

Set pending standard properties in C<prop_hash>.

=cut

*/

static void
propagate_std_props(PARROT_INTERP, PMC *self, PMC *prop_hash) {
    if (self->vtable->flags & (VTABLE_IS_CONST_FLAG | VTABLE_IS_READONLY_FLAG)){
        PMC * const pmc_true  = pmc_new(interp, enum_class_Integer);
        PMC_int_val(pmc_true) = 1;
        VTABLE_set_pmc_keyed_str(interp, prop_hash, CONST_STRING(interp, "_ro"), pmc_true);
    }
}

/*

=item C<static INTVAL
has_pending_std_props(PMC *self)>

Returns true if propagate_std_props() would create a non-empty prophash.

=cut

*/

static INTVAL
has_pending_std_props(PMC *self) {
    if (self->vtable->flags & (VTABLE_IS_CONST_FLAG | VTABLE_IS_READONLY_FLAG))
        return 1;
    else
        return 0;
}


/*

=item C<static PMC*
check_get_std_props(PARROT_INTERPeter, PMC *self, STRING *key)>

Checks if we can infer the value of C<key> property from C<self> without
looking at its prophash. Returns C<PMCNULL> if not, returns the value otherwise.

=cut
*/

static PMC*
check_get_std_props(PARROT_INTERP, PMC *self, STRING *key) {
    if ((self->vtable->flags & (VTABLE_IS_CONST_FLAG | VTABLE_IS_READONLY_FLAG))
        &&!string_compare(interp, key, CONST_STRING(interp, "_ro"))) {
        PMC * const ret_val  = pmc_new(interp, enum_class_Integer);
        PMC_int_val(ret_val) = 1;
        return ret_val;
    }
    else
        return PMCNULL;
}

/*

=item C<static PMC *
make_prop_hash(PARROT_INTERP, PMC *self)>

Create a property hash for C<self>. Returns the created hash. Inferred
properties will be added to the hash and it will be set as
C<PMC_metadata(self)>.

=cut

*/

static PMC*
make_prop_hash(PARROT_INTERP, PMC *self) {
    PMC *prop;

    if (!self->pmc_ext)
        add_pmc_ext(interp, self);

    PMC_metadata(self) = prop = pmc_new_noinit(interp, enum_class_Hash);
    GC_WRITE_BARRIER(interp, self, NULL, prop);
    VTABLE_init(interp, prop);
    propagate_std_props(interp, self, prop);
    return prop;
}

/*

=item C<static INTVAL
does_isa(PARROT_INTERP, STRING *method, STRING *what)>

Compares C<*method> and C<*what>.
Returns true (1) if B<method> is found in B<what>, false (0) otherwise.

=cut

*/

static INTVAL
does_isa(PARROT_INTERP, const STRING *method, const STRING *what)
{
    INTVAL  pos    = 0;
    INTVAL  length = string_length(interp, what);

    do {
        INTVAL len;
        INTVAL idx = string_str_index(interp, what, method, (INTVAL)pos);

        if (idx < 0)
            return 0;

        pos = idx;

        if (pos >= length)
            return 0;

        len = string_length(interp, method);

        if (pos && string_index(interp, what, pos - 1) != 32) {
            pos += len;
            continue;
        }

        if (pos + len < length && string_index(interp, what, pos + len) != 32) {
            pos += len;
            continue;
        }

        return 1;
    } while (1);
}

pmclass default abstract no_init {

/*

=back

=head2 Methods

=over 4

=item C<void init()>

Does nothing.

=cut

*/

    VTABLE void init() {
    }

/*

=item C<void init_pmc(PMC *initializer)>

With a null C<initializer>, calls C<init()>, else throws an exception.

=cut

*/

    VTABLE void init_pmc(PMC *initializer) {
        if (PMC_IS_NULL(initializer))
            SELF.init();
        else
            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_ILL_INHERIT,
                "init_pmc() not implemented in class '%Ss'",
                caller(interp, pmc));
    }

/*

=item C<PMC *instantiate(PMC *init)>

Default fallback. Creates a new PMC of the type of the class SELF and
calls init().

=cut

*/

    VTABLE PMC *instantiate(PMC *init) {
        const INTVAL type = VTABLE_type(INTERP, SELF);

        /* Ensure no looping, as pmc_new calls the instantiate vtable entry for
         * classes. */
        if (PObj_is_class_TEST(SELF))
            Parrot_ex_throw_from_c_args(interp, NULL, 1,
                    "All high-level classes should override instantiate");

        if (!PMC_IS_NULL(init))
            return pmc_new_init(INTERP, type, init);

        return pmc_new(INTERP, type);
    }

/*

=item C<void mark()>

Panics with a "no custom mark routine defined" error message.

=cut

*/

    VTABLE void mark() {
        PANIC(INTERP, "custom_mark flag set but no custom mark routine defined");
    }

/*

=item C<PMC *getprop(STRING *key)>

Returns the property for C<*key>. If no property is defined then the
NULL PMC is returned.

=cut

*/

    VTABLE PMC *getprop(STRING *key) {
        if (SELF->pmc_ext && PMC_metadata(SELF))
            return VTABLE_get_pmc_keyed_str(INTERP, PMC_metadata(SELF), key);
        else
            return check_get_std_props(interp, SELF, key);
    }

/*

=item C<void setprop(STRING *key, PMC *value)>

Sets the property for C<*key> to C<*value>.

=cut

*/

    VTABLE void setprop(STRING *key, PMC *value) {
        if (check_set_std_props(INTERP, SELF, key, value))
            return;

        if (SELF->pmc_ext && PMC_metadata(SELF)) {
            VTABLE_set_pmc_keyed_str(INTERP,
                PMC_metadata(SELF), key, value);
        }
        else {
            PMC * const prop = make_prop_hash(INTERP, SELF);

            VTABLE_set_pmc_keyed_str(INTERP, prop, key, value);
        }
    }

/*

=item C<void delprop(STRING *key)>

Deletes the property for C<*key>.

=cut

*/

    VTABLE void delprop(STRING *key) {
        if (SELF->pmc_ext && PMC_metadata(SELF))
            VTABLE_delete_keyed_str(INTERP, PMC_metadata(SELF), key);
    }

/*

=item C<PMC *getprops()>

Returns the PMC's properties or the NULL PMC if no properties exist.

=cut

*/

    VTABLE PMC *getprops() {
        if (!SELF->pmc_ext)
            add_pmc_ext(INTERP, SELF);

        if (!PMC_metadata(SELF)) {
            if (has_pending_std_props(SELF))
                return make_prop_hash(INTERP, SELF);
            else
                return PMCNULL;
        }

        return PMC_metadata(SELF);
    }

/*

=item C<INTVAL type()>

Returns the PMC's type.

=cut

*/

    VTABLE INTVAL type() {
        return SELF->vtable->base_type;
    }

/*

=item C<STRING *name()>

Returns the name of the PMC.

=cut

*/

    VTABLE STRING *name() {
        return SELF->vtable->whoami;
    }


/*

=item C<PMC *get_namespace>

Return the namespace for this PMC.

=item C<PMC *find_method(STRING *method_name)>

Looks up the method for C<*method_name> and returns it. If no method is
found then C<NULL> is returned.

=item C<void add_method(STRING *method_name, PMC *sub)>

Store the method as a global in the namespace of this class.

=cut

*/

    VTABLE PMC *get_namespace() {
        return SELF->vtable->_namespace;
    }


    VTABLE PMC *find_method(STRING *method_name) {
        return Parrot_find_method_with_cache(INTERP, SELF, method_name);
    }

    VTABLE void add_method(STRING *method_name, PMC *sub_pmc) {
        VTABLE_set_pmc_keyed_str(INTERP, SELF->vtable->_namespace,
                                 method_name, sub_pmc);
    }
/*

=item C<INTVAL get_integer_keyed_int(INTVAL key)>

Converts C<key> to a PMC key and returns the result of calling
C<get_integer_keyed()> with it.

=cut

*/

    VTABLE INTVAL get_integer_keyed_int(INTVAL key) {
        PMC *const r_key = INT2KEY(INTERP, key);
        return SELF.get_integer_keyed(r_key);
    }

/*

=item C<FLOATVAL get_number_keyed_int(INTVAL key)>

Converts C<key> to a PMC key and returns the result of calling
C<get_number_keyed()> with it.

=cut

*/

    VTABLE FLOATVAL get_number_keyed_int(INTVAL key) {
        PMC *const r_key = INT2KEY(INTERP, key);
        return SELF.get_number_keyed(r_key);
    }


/*

=item C<STRING *get_string_keyed_int(INTVAL key)>

Converts C<key> to a PMC key and returns the result of calling
C<get_string_keyed()> with it.

=cut

*/

    VTABLE STRING *get_string_keyed_int(INTVAL key) {
        PMC *const r_key = INT2KEY(INTERP, key);
        return SELF.get_string_keyed(r_key);
    }

/*

=item C<INTVAL elements_keyed_int(INTVAL key)>

Converts C<key> to a PMC key and returns the result of calling
C<elements_keyed()> with it.

=cut

*/

    INTVAL elements_keyed_int(INTVAL key) {
        PMC *const r_key = INT2KEY(INTERP, key);
        return SELF.elements_keyed(r_key);
    }


/*

=item C<PMC *get_pmc_keyed_int(INTVAL key)>

Converts C<key> to a PMC key and returns the result of calling
C<get_pmc_keyed()> with it.

=cut

*/

    VTABLE PMC *get_pmc_keyed_int(INTVAL key) {
        PMC *const r_key = INT2KEY(INTERP, key);
        return SELF.get_pmc_keyed(r_key);
    }

/*

=item C<void *get_pointer()>

Returns the address of the PMC.

=cut

*/

    VTABLE void *get_pointer() {
        return SELF;
    }

/*

=item C<INTVAL is_same(PMC *value)>

Returns whether the PMC is numerically equal to C<value>.

=cut

*/

    VTABLE INTVAL is_same(PMC *value) {
        return SELF == value;
    }

/*

=item C<void assign_pmc(PMC *value)>

=item C<void assign_string_native(PMC *value)>

Defaults fall back to C<set_pmc> and C<set_string_native>.

=cut

*/

    VTABLE void assign_pmc(PMC *value) {
        STRING * const undef = CONST_STRING(INTERP, "Undef");

        if (VTABLE_isa(INTERP, value, undef))
            pmc_reuse(INTERP, SELF, value->vtable->base_type, 0);
        else
            SELF.set_pmc(value);
    }

    VTABLE void assign_string_native(STRING *value) {
        SELF.set_string_native(value);
    }

/*

=item C<void morph(INTVAL type)>

Changes the PMC to a PMC of a new type

=cut

*/

    VTABLE void morph(INTVAL type) {
        pmc_reuse(INTERP, SELF, type, 0);
    }

/*

=item C<void set_integer_keyed_int(INTVAL key, INTVAL value)>

Converts C<key> to a PMC key and calls C<set_integer_keyed()> with it
and C<value>.

=cut

*/

    VTABLE void set_integer_keyed_int(INTVAL key, INTVAL value) {
        PMC *const r_key = INT2KEY(INTERP, key);
        SELF.set_integer_keyed(r_key, value);
    }

/*

=item C<void set_number_keyed_int(INTVAL key, FLOATVAL value)>

Converts C<key> to a PMC key and calls C<set_number_keyed()> with it
and C<value>.

=cut

*/

    VTABLE void set_number_keyed_int(INTVAL key, FLOATVAL value) {
        PMC *const r_key = INT2KEY(INTERP, key);
        SELF.set_number_keyed(r_key, value);
    }

/*

=item C<void set_string_keyed_int(INTVAL key, STRING *string)>

Converts C<key> to a PMC key and calls C<set_string_keyed()> with it
and C<value>.

=cut

*/

    VTABLE void set_string_keyed_int(INTVAL key, STRING *string) {
        PMC *const r_key = INT2KEY(INTERP, key);
        SELF.set_string_keyed(r_key, string);
    }

/*

=item C<void set_bool_keyed_int(INTVAL key, INTVAL value)>

Converts C<key> to a PMC key and calls C<set_bool_keyed()> with it
and C<value>.

=cut

*/

    void set_bool_keyed_int(INTVAL key, INTVAL value) {
        PMC *const r_key = INT2KEY(INTERP, key);
        SELF.set_bool_keyed(r_key, value);
    }

/*

=item C<void set_pmc_keyed_int(INTVAL key, PMC *value)>

Converts C<key> to a PMC key and calls C<set_pmc_keyed()> with it
and C<value>.

=cut

*/

    VTABLE void set_pmc_keyed_int(INTVAL key, PMC *value) {
        PMC *const r_key = INT2KEY(INTERP, key);
        SELF.set_pmc_keyed(r_key, value);
    }

/*

=item C<INTVAL is_equal(PMC *value)>

Default fallback. Performs a multiple dispatch call for 'is_equal'.

=cut

*/

    VTABLE INTVAL is_equal(PMC *value) {
        INTVAL retval;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "is_equal", "PP->I", SELF, value, &retval);

        return retval;
    }

/*

=item C<INTVAL is_equal_num(PMC *value)>

Default fallback. Performs a multiple dispatch call for 'is_equal_num'.

=cut

*/

    VTABLE INTVAL is_equal_num(PMC *value) {
        INTVAL retval;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "is_equal_num", "PP->I", SELF, value, &retval);

        return retval;
    }

/*

=item C<INTVAL is_equal_string(PMC *value)>

Default fallback. Performs a multiple dispatch call for 'is_equal'.

=cut

*/

    VTABLE INTVAL is_equal_string(PMC *value) {
        INTVAL retval;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "is_equal_string", "PP->I", SELF, value, &retval);

        return retval;
    }

/*

=item C<INTVAL exists_keyed_int(INTVAL key)>

Converts C<key> to a PMC key and returns the result of calling
C<exists_keyed()> with it.

=cut

*/

    VTABLE INTVAL exists_keyed_int(INTVAL key) {
        PMC *const r_key = INT2KEY(INTERP, key);
        return SELF.exists_keyed(r_key);
    }

/*

=item C<INTVAL defined()>

Returns true.

=cut

*/

    VTABLE INTVAL defined() {
        return 1;
    }

/*

=item C<INTVAL defined_keyed_int(INTVAL key)>

Converts C<key> to a PMC key and returns the result of calling
C<defined_keyed()> with it.

=cut

*/

    VTABLE INTVAL defined_keyed_int(INTVAL key) {
        PMC *const r_key = INT2KEY(INTERP, key);
        return SELF.defined_keyed(r_key);
    }

/*

=item C<void delete_keyed_int(INTVAL key)>

Converts C<key> to a PMC key and calls C<delete_keyed()> with it.

=cut

*/

    VTABLE void delete_keyed_int(INTVAL key) {
        PMC *const r_key = INT2KEY(INTERP, key);
        SELF.delete_keyed(r_key);
    }

/*

=item C<PMC *nextkey_keyed_int(INTVAL key, INTVAL w)>

Converts C<key> to a PMC key and returns the result of calling
C<nextkey_keyed()> with it.

=cut

*/

    VTABLE PMC *nextkey_keyed_int(INTVAL key, INTVAL w) {
        PMC *const r_key = INT2KEY(INTERP, key);
        return SELF.nextkey_keyed(r_key, w);
    }

/*

=item C<INTVAL can(STRING *method)>

Reports whether the PMC "can" perform C<method>.
If the PMC implements the vtable function C<method>,
true (1) is returned; otherwise, false (0) is returned.

=cut

*/

    VTABLE INTVAL can(STRING *method) {
        return !PMC_IS_NULL(VTABLE_find_method(INTERP, SELF, method));
    }

/*

=item C<INTVAL does(STRING *interface)>

Reports whether the PMC "does" perform C<interface>.
If the interface C<interface> is found in the PMC's interface list,
true (1) is returned; otherwise, false (0) is returned.

=cut

*/

    VTABLE INTVAL does(STRING *_interface) {
        return does_isa(INTERP, _interface, SELF->vtable->provides_str);
    }

/*

=item C<INTVAL does_pmc(PMC *role)>

Reports whether the PMC "does" the C<role>.

=cut

*/

    INTVAL does_pmc(PMC *role) {
        /* No C-level roles yet. */
        return 0;
    }

/*

=item C<INTVAL isa_pmc(PMC *_class)>

Reports whether the PMC "isa" C<_class>.
If the class C<_class> is found in the PMC's class hierarchy,
true (1) is returned; otherwise, false (0) is returned.

=cut

*/

    VTABLE INTVAL isa_pmc(PMC *lookup) {
        if (PMC_IS_NULL(lookup))
            return 0;

        /* RT #46665 - walk mro */
        return parrot_hash_exists(INTERP, SELF->vtable->isa_hash,
                (void *)VTABLE_get_string(interp, lookup));
    }

/*

=item C<INTVAL isa(STRING *_class)>

Reports whether the PMC "isa" C<_class>.
If the class C<_class> is found in the PMC's class hierarchy,
true (1) is returned; otherwise, false (0) is returned.

=cut

*/

    VTABLE INTVAL isa(STRING *_class) {
        /* RT #46665 - walk mro */
        return parrot_hash_exists(INTERP, SELF->vtable->isa_hash,
                    (void *)_class);
    }

/*

=item C<PMC *inspect_str(STRING *what)>

Provides introspection of a specific piece of information about the PMC.

=cut

*/

    PMC *inspect_str(STRING *name) {
        if (string_equal(interp, name, CONST_STRING(interp, "flags")) == 0) {
            PMC *found = pmc_new(interp, enum_class_Integer);
            VTABLE_set_integer_native(interp, found,
                    (INTVAL)PObj_get_FLAGS(SELF));
            return found;
        }
        else if (string_equal(interp, name, CONST_STRING(interp, "mro")) == 0) {
            return VTABLE_clone(interp, SELF->vtable->mro);
        }
        else
            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
                "Unknown introspection value '%S'", name);
    }

/*

=item C<PMC *inspect()>

Returns a Hash describing the class, with key/value pairs as described in
inspect_str.

=cut

*/
    PMC *inspect() {
        PMC    *metadata           = pmc_new(interp, enum_class_Hash);
        STRING * const flags_str   = CONST_STRING(interp, "flags");

        VTABLE_set_pmc_keyed_str(interp, metadata, flags_str,
            VTABLE_inspect_str(interp, SELF, flags_str));

        return metadata;
    }

/*

=item C<PMC *get_class()>

Returns SELF. A PMC is its own class.

=item C<PMC *get_attr_str(STRING *attr)>

Look for NCI methods and properties.

=cut

*/
    VTABLE PMC *get_class() {
        PMC *ns     = VTABLE_get_namespace(interp, SELF);
        PMC *_class = PMCNULL;

        if (!PMC_IS_NULL(ns))
            _class = VTABLE_get_class(interp, ns);

        if (PMC_IS_NULL(_class)) {
            INTVAL type      = VTABLE_type(interp, SELF);
            PMC   *type_num  = pmc_new(interp, enum_class_Integer);
            VTABLE_set_integer_native(interp, type_num, type);
            return pmc_new_init(interp, enum_class_PMCProxy, type_num);
        }

        return _class;

    }

    VTABLE PMC *get_attr_str(STRING *name) {
        PMC *p = VTABLE_find_method(INTERP, SELF, name);

        if (PMC_IS_NULL(p))
            return PMCNULL;

        if (VTABLE_isa(INTERP, p, CONST_STRING(INTERP, "NCI"))) {
            PMC * const bound_meth = VTABLE_clone(INTERP, p);
            bound_meth->vtable     = interp->vtables[enum_class_Bound_NCI];
            VTABLE_set_pmc(INTERP, bound_meth, SELF);

            return bound_meth;
        }
        else if (p->vtable->base_type == enum_class_MultiSub) {
            PMC * const bound_meth      = pmc_new(INTERP, enum_class_Bound_NCI);
            VTABLE_set_pmc(INTERP, bound_meth, SELF);
            PMC_struct_val(bound_meth)  = p;
            PObj_get_FLAGS(bound_meth) |= PObj_private0_FLAG;

            return bound_meth;
        }

        /* RT #46671 bound user functions */
        return p;
    }

/*

=item C<PMC *get_attr_keyed(PMC *key, STRING *name)>

Default version of keyed attribute lookups. Discards the key and does a lookup
by the string name passed in.

=item C<void set_attr_keyed(PMC *key, STRING *name, PMC *value)>

Default version of keyed attribute set. Discards the key and does a set by
the string name passed in.

=cut

*/
    VTABLE PMC *get_attr_keyed(PMC *key, STRING *name) {
        return VTABLE_get_attr_str(INTERP, SELF, name);
    }

    VTABLE void set_attr_keyed(PMC *key, STRING *name, PMC *value) {
        VTABLE_set_attr_str(INTERP, SELF, name, value);
    }

/*

=item C<void add_parent(PMC *parent)>

Add class C<parent> to the list of our parents.

=cut

*/

    VTABLE void add_parent(PMC *parent) {
        if (!PObj_is_class_TEST(SELF))
            Parrot_ex_throw_from_c_args(interp, NULL, 1,
                "Only classes can be subclassed");

        Parrot_ex_throw_from_c_args(interp, NULL, 1,
                "All classes should override add_parent");
    }

/*

=item C<void visit(visit_info *info)>

Used by DOD to mark the PMC.

=cut

*/

    VTABLE void visit(visit_info *info) {
        /* default - mark prop hash */
        if (SELF->pmc_ext && PMC_metadata(SELF) &&
            info->extra_flags != EXTRA_IS_PROP_HASH) {
            info->extra_flags = EXTRA_IS_PROP_HASH;
            info->extra       = PMC_metadata(SELF);

            /* place escape mark */
            (info->visit_pmc_now)(INTERP, SELF, info);

            /* place and the prop hash */
            (info->visit_pmc_now)(INTERP, PMC_metadata(SELF), info);
        }
    }

/*

=item C<PMC* clone()>

Clones this PMC.  By default, this just does a freeze and thaw.

=cut

*/

    VTABLE PMC* clone() {
        return Parrot_thaw(interp, Parrot_freeze(interp, SELF));
    }

/*

=item C<void freeze(visit_info *info)>

Does nothing.

=cut

*/

    VTABLE void freeze(visit_info *info) {
        /* default - no action */
    }

/*

=item C<void thaw(visit_info *info)>

Initializes the PMC during unarchiving.

=cut

*/

    VTABLE void thaw(visit_info *info) {
        /* default - initialize the PMC */
        if (info->extra_flags == EXTRA_IS_PROP_HASH) {
            if (!SELF->pmc_ext)
                add_pmc_ext(INTERP, SELF);

            info->thaw_ptr  = &PMC_metadata(SELF);
            info->container = SELF;

            (info->visit_pmc_now)(INTERP, PMC_metadata(SELF), info);
        }
        else
            SELF.init();
    }

/*

=item C<void thawfinish(visit_info *info)>

Does nothing.

=cut

*/

    void thawfinish(visit_info *info) {
        /* default - no action */
    }

/*

=item C<PMC *add(PMC *value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'add'.

=cut

*/

    VTABLE PMC *add(PMC *value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "add", "PPP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *add_int(INTVAL value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'add_int'.

=cut

*/

    VTABLE PMC *add_int(INTVAL value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "add_int", "PIP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *add_float(FLOATVAL value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'add_float'.

=cut

*/

    VTABLE PMC *add_float(FLOATVAL value, PMC *dest) {
        dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));

        VTABLE_set_number_native(INTERP, dest,
                SELF.get_number() + value);
        return dest;
    }

/*

=item C<void i_add(PMC *value)>

Default fallback. Performs a multiple dispatch call for 'i_add'.

=cut

*/

    VTABLE void i_add(PMC *value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_add", "PP", SELF, value);
    }

/*

=item C<void i_add_int(INTVAL value)>

Default fallback. Performs a multiple dispatch call for 'i_add_int'.

=cut

*/

    VTABLE void i_add_int(INTVAL value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_add_int", "PI", SELF, value);
    }

/*

=item C<void i_add_float(FLOATVAL value)>

Default fallback. Performs a multiple dispatch call for 'i_add_float'.

=cut

*/

    VTABLE void i_add_float(FLOATVAL value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_add_float", "PN", SELF, value);
    }

/*

=item C<PMC *subtract(PMC *value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'subtract'.

=cut

*/

    VTABLE PMC *subtract(PMC *value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "subtract", "PPP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *subtract_int(INTVAL value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'subtract_int'.

=cut

*/

    VTABLE PMC *subtract_int(INTVAL value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "subtract_int", "PIP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *subtract_float(FLOATVAL value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'subtract_float'.

=cut

*/

    VTABLE PMC *subtract_float(FLOATVAL value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "subtract_float", "PNP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<void i_subtract(PMC *value)>

Default fallback. Performs a multiple dispatch call for 'i_subtract'.

=cut

*/

    VTABLE void i_subtract(PMC *value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_subtract", "PP", SELF, value);
    }

/*

=item C<void i_subtract_int(INTVAL value)>

Default fallback. Performs a multiple dispatch call for 'i_subtract_int'.

=cut

*/

    VTABLE void i_subtract_int(INTVAL value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_subtract_int", "PI", SELF, value);
    }

/*

=item C<void i_subtract_float(FLOATVAL value)>

Default fallback. Performs a multiple dispatch call for 'i_subtract_float'.

=cut

*/

    VTABLE void i_subtract_float(FLOATVAL value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_subtract_float", "PN", SELF, value);
    }

/*

=item C<PMC *multiply(PMC *value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'multiply'.

=cut

*/

    VTABLE PMC *multiply(PMC *value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "multiply", "PPP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *multiply_int(INTVAL value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'multiply_int'.

=cut

*/

    VTABLE PMC *multiply_int(INTVAL value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "multiply_int", "PIP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *multiply_float(FLOATVAL value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'multiply_float'.

=cut

*/

    VTABLE PMC *multiply_float(FLOATVAL value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "multiply_float", "PNP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<void i_multiply(PMC *value)>

Default fallback. Performs a multiple dispatch call for 'i_multiply'.

=cut

*/

    VTABLE void i_multiply(PMC *value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_multiply", "PP", SELF, value);
    }

/*

=item C<void i_multiply_int(INTVAL value)>

Default fallback. Performs a multiple dispatch call for 'i_multiply_int'.

=cut

*/

    VTABLE void i_multiply_int(INTVAL value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_multiply_int", "PI", SELF, value);
    }

/*

=item C<void i_multiply_float(FLOATVAL value)>

Default fallback. Performs a multiple dispatch call for 'i_multiply_float'.

=cut

*/

    VTABLE void i_multiply_float(FLOATVAL value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_multiply_float", "PN", SELF, value);
    }

/*

=item C<PMC *divide(PMC *value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'divide'.

=cut

*/

    VTABLE PMC *divide(PMC *value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "divide", "PPP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *divide_int(INTVAL value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'divide_int'.

=cut

*/

    VTABLE PMC *divide_int(INTVAL value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "divide_int", "PIP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *divide_float(FLOATVAL value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'divide_float'.

=cut

*/

    VTABLE PMC *divide_float(FLOATVAL value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "divide_float", "PNP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<void i_divide(PMC *value)>

Default fallback. Performs a multiple dispatch call for 'i_divide'.

=cut

*/

    VTABLE void i_divide(PMC *value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_divide", "PP", SELF, value);
    }

/*

=item C<void i_divide_int(INTVAL value)>

Default fallback. Performs a multiple dispatch call for 'i_divide_int'.

=cut

*/

    VTABLE void i_divide_int(INTVAL value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_divide_int", "PI", SELF, value);
    }

/*

=item C<void i_divide_float(FLOATVAL value)>

Default fallback. Performs a multiple dispatch call for 'i_divide_float'.

=cut

*/

    VTABLE void i_divide_float(FLOATVAL value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_divide_float", "PN", SELF, value);
    }

/*

=item C<PMC *floor_divide(PMC *value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'floor_divide'.

=cut

*/

    VTABLE PMC *floor_divide(PMC *value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "floor_divide", "PPP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *floor_divide_int(INTVAL value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'floor_divide_int'.

=cut

*/

    VTABLE PMC *floor_divide_int(INTVAL value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "floor_divide_int", "PIP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *floor_divide_float(FLOATVAL value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'floor_divide_float'.

=cut

*/

    VTABLE PMC *floor_divide_float(FLOATVAL value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "floor_divide_float", "PNP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<void i_floor_divide(PMC *value)>

Default fallback. Performs a multiple dispatch call for 'i_floor_divide'.

=cut

*/

    VTABLE void i_floor_divide(PMC *value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_floor_divide", "PP", SELF, value);
    }

/*

=item C<void i_floor_divide_int(INTVAL value)>

Default fallback. Performs a multiple dispatch call for 'i_floor_divide_int'.

=cut

*/

    VTABLE void i_floor_divide_int(INTVAL value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_floor_divide_int", "PI", SELF, value);
    }

/*

=item C<void i_floor_divide_float(FLOATVAL value)>

Default fallback. Performs a multiple dispatch call for 'i_floor_divide_float'.

=cut

*/

    VTABLE void i_floor_divide_float(FLOATVAL value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_floor_divide_float", "PN", SELF, value);
    }

/*

=item C<PMC *modulus(PMC *value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'modulus'.

=cut

*/

    VTABLE PMC *modulus(PMC *value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "modulus", "PPP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *modulus_int(INTVAL value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'modulus_int'.

=cut

*/

    VTABLE PMC *modulus_int(INTVAL value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "modulus_int", "PIP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *modulus_float(FLOATVAL value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'modulus_float'.

=cut

*/

    VTABLE PMC *modulus_float(FLOATVAL value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "modulus_float", "PNP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<void i_modulus(PMC *value)>

Default fallback. Performs a multiple dispatch call for 'i_modulus'.

=cut

*/

    VTABLE void i_modulus(PMC *value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_modulus", "PP", SELF, value);
    }

/*

=item C<void i_modulus_int(INTVAL value)>

Default fallback. Performs a multiple dispatch call for 'i_modulus_int'.

=cut

*/

    VTABLE void i_modulus_int(INTVAL value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_modulus_int", "PI", SELF, value);
    }

/*

=item C<void i_modulus_float(FLOATVAL value)>

Default fallback. Performs a multiple dispatch call for 'i_modulus_float'.

=cut

*/

    VTABLE void i_modulus_float(FLOATVAL value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_modulus_float", "PN", SELF, value);
    }

/*

=item C<PMC *pow(PMC *value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'pow'.

=cut

*/

    VTABLE PMC *pow(PMC *value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "pow", "PPP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *pow_int(INTVAL value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'pow_int'.

=cut

*/

    VTABLE PMC *pow_int(INTVAL value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "pow_int", "PIP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *pow_float(FLOATVAL value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'pow_float'.

=cut

*/

    VTABLE PMC *pow_float(FLOATVAL value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "pow_float", "PNP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<void i_pow(PMC *value)>

Default fallback. Performs a multiple dispatch call for 'i_pow'.

=cut

*/

    VTABLE void i_pow(PMC *value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_pow", "PP", SELF, value);
    }

/*

=item C<void i_pow_int(INTVAL value)>

Default fallback. Performs a multiple dispatch call for 'i_pow_int'.

=cut

*/

    VTABLE void i_pow_int(INTVAL value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_pow_int", "PI", SELF, value);
    }

/*

=item C<void i_pow_float(FLOATVAL value)>

Default fallback. Performs a multiple dispatch call for 'i_pow_float'.

=cut

*/

    VTABLE void i_pow_float(FLOATVAL value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_pow_float", "PN", SELF, value);
    }

/*

=item C<PMC *bitwise_or(PMC *value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'bitwise_or'.

=cut

*/

    VTABLE PMC *bitwise_or(PMC *value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "bitwise_or", "PPP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *bitwise_or_int(INTVAL value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'bitwise_or_int'.

=cut

*/

    VTABLE PMC *bitwise_or_int(INTVAL value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "bitwise_or_int", "PIP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<void i_bitwise_or(PMC *value)>

Default fallback. Performs a multiple dispatch call for 'i_bitwise_or'.

=cut

*/

    VTABLE void i_bitwise_or(PMC *value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_bitwise_or", "PP", SELF, value);
    }

/*

=item C<void i_bitwise_or_int(INTVAL value)>

Default fallback. Performs a multiple dispatch call for 'i_bitwise_or_int'.

=cut

*/

    VTABLE void i_bitwise_or_int(INTVAL value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_bitwise_or_int", "PI", SELF, value);
    }

/*

=item C<PMC *bitwise_and(PMC *value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'bitwise_and'.

=cut

*/

    VTABLE PMC *bitwise_and(PMC *value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "bitwise_and", "PPP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *bitwise_and_int(INTVAL value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'bitwise_and_int'.

=cut

*/

    VTABLE PMC *bitwise_and_int(INTVAL value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "bitwise_and_int", "PIP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<void i_bitwise_and(PMC *value)>

Default fallback. Performs a multiple dispatch call for 'i_bitwise_and'.

=cut

*/

    VTABLE void i_bitwise_and(PMC *value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_bitwise_and", "PP", SELF, value);
    }

/*

=item C<void i_bitwise_and_int(INTVAL value)>

Default fallback. Performs a multiple dispatch call for 'i_bitwise_and_int'.

=cut

*/

    VTABLE void i_bitwise_and_int(INTVAL value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_bitwise_and_int", "PI", SELF, value);
    }

/*

=item C<PMC *bitwise_xor(PMC *value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'bitwise_xor'.

=cut

*/

    VTABLE PMC *bitwise_xor(PMC *value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "bitwise_xor", "PPP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *bitwise_xor_int(INTVAL value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'bitwise_xor_int'.

=cut

*/

    VTABLE PMC *bitwise_xor_int(INTVAL value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "bitwise_xor_int", "PIP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<void i_bitwise_xor(PMC *value)>

Default fallback. Performs a multiple dispatch call for 'i_bitwise_xor'.

=cut

*/

    VTABLE void i_bitwise_xor(PMC *value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_bitwise_xor", "PP", SELF, value);
    }

/*

=item C<void i_bitwise_xor_int(INTVAL value)>

Default fallback. Performs a multiple dispatch call for 'i_bitwise_xor_int'.

=cut

*/

    VTABLE void i_bitwise_xor_int(INTVAL value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_bitwise_xor_int", "PI", SELF, value);
    }

/*

=item C<PMC *bitwise_ors(PMC *value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'bitwise_ors'.

=cut

*/

    VTABLE PMC *bitwise_ors(PMC *value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "bitwise_ors", "PPP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *bitwise_ors_str(STRING *value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'bitwise_ors_str'.

=cut

*/

    VTABLE PMC *bitwise_ors_str(STRING *value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "bitwise_ors_str", "PSP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<void i_bitwise_ors(PMC *value)>

Default fallback. Performs a multiple dispatch call for 'i_bitwise_ors'.

=cut

*/

    VTABLE void i_bitwise_ors(PMC *value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_bitwise_ors", "PP", SELF, value);
    }

/*

=item C<void i_bitwise_ors_str(STRING *value)>

Default fallback. Performs a multiple dispatch call for 'i_bitwise_ors_str'.

=cut

*/

    VTABLE void i_bitwise_ors_str(STRING *value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_bitwise_ors_str", "PS", SELF, value);
    }

/*

=item C<PMC *bitwise_ands(PMC *value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'bitwise_ands'.

=cut

*/

    VTABLE PMC *bitwise_ands(PMC *value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "bitwise_ands", "PPP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *bitwise_ands_str(STRING *value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'bitwise_ands_str'.

=cut

*/

    VTABLE PMC *bitwise_ands_str(STRING *value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "bitwise_ands_str", "PSP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<void i_bitwise_ands(PMC *value)>

Default fallback. Performs a multiple dispatch call for 'i_bitwise_ands'.

=cut

*/

    VTABLE void i_bitwise_ands(PMC *value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_bitwise_ands", "PP", SELF, value);
    }

/*

=item C<void i_bitwise_ands_str(STRING *value)>

Default fallback. Performs a multiple dispatch call for 'i_bitwise_ands_str'.

=cut

*/

    VTABLE void i_bitwise_ands_str(STRING *value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_bitwise_ands_str", "PS", SELF, value);
    }

/*

=item C<PMC *bitwise_xors(PMC *value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'bitwise_xors'.

=cut

*/

    VTABLE PMC *bitwise_xors(PMC *value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "bitwise_xors", "PPP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *bitwise_xors_str(STRING *value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'bitwise_xors_str'.

=cut

*/

    VTABLE PMC *bitwise_xors_str(STRING *value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "bitwise_xors_str", "PSP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<void i_bitwise_xors(PMC *value)>

Default fallback. Performs a multiple dispatch call for 'i_bitwise_xors'.

=cut

*/

    VTABLE void i_bitwise_xors(PMC *value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_bitwise_xors", "PP", SELF, value);
    }

/*

=item C<void i_bitwise_xors_str(STRING *value)>

Default fallback. Performs a multiple dispatch call for 'i_bitwise_xors_str'.

=cut

*/

    VTABLE void i_bitwise_xors_str(STRING *value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_bitwise_xors_str", "PS", SELF, value);
    }

/*

=item C<PMC *bitwise_shl(PMC *value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'bitwise_shl'.

=cut

*/

    VTABLE PMC *bitwise_shl(PMC *value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "bitwise_shl", "PPP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *bitwise_shl_int(INTVAL value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'bitwise_shl_int'.

=cut

*/

    VTABLE PMC *bitwise_shl_int(INTVAL value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "bitwise_shl_int", "PIP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<void i_bitwise_shl(PMC *value)>

Default fallback. Performs a multiple dispatch call for 'i_bitwise_shl'.

=cut

*/

    VTABLE void i_bitwise_shl(PMC *value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_bitwise_shl", "PP", SELF, value);
    }

/*

=item C<void i_bitwise_shl_int(INTVAL value)>

Default fallback. Performs a multiple dispatch call for 'i_bitwise_shl_int'.

=cut

*/

    VTABLE void i_bitwise_shl_int(INTVAL value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_bitwise_shl_int", "PI", SELF, value);
    }

/*

=item C<PMC *bitwise_shr(PMC *value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'bitwise_shr'.

=cut

*/

    VTABLE PMC *bitwise_shr(PMC *value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "bitwise_shr", "PPP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *bitwise_shr_int(INTVAL value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'bitwise_shr_int'.

=cut

*/

    VTABLE PMC *bitwise_shr_int(INTVAL value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "bitwise_shr_int", "PIP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<void i_bitwise_shr(PMC *value)>

Default fallback. Performs a multiple dispatch call for 'i_bitwise_shr'.

=cut

*/

    VTABLE void i_bitwise_shr(PMC *value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_bitwise_shr", "PP", SELF, value);
    }

/*

=item C<void i_bitwise_shr_int(INTVAL value)>

Default fallback. Performs a multiple dispatch call for 'i_bitwise_shr_int'.

=cut

*/

    VTABLE void i_bitwise_shr_int(INTVAL value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_bitwise_shr_int", "PI", SELF, value);
    }

/*

=item C<PMC *bitwise_lsr(PMC *value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'bitwise_lsr'.

=cut

*/

    VTABLE PMC *bitwise_lsr(PMC *value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "bitwise_lsr", "PPP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *bitwise_lsr_int(INTVAL value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'bitwise_lsr_int'.

=cut

*/

    VTABLE PMC *bitwise_lsr_int(INTVAL value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "bitwise_lsr_int", "PIP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<void i_bitwise_lsr(PMC *value)>

Default fallback. Performs a multiple dispatch call for 'i_bitwise_lsr'.

=cut

*/

    VTABLE void i_bitwise_lsr(PMC *value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_bitwise_lsr", "PP", SELF, value);
    }

/*

=item C<void i_bitwise_lsr_int(INTVAL value)>

Default fallback. Performs a multiple dispatch call for 'i_bitwise_lsr_int'.

=cut

*/

    VTABLE void i_bitwise_lsr_int(INTVAL value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_bitwise_lsr_int", "PI", SELF, value);
    }

/*

=item C<INTVAL cmp(PMC *value)>

Default fallback. Performs a multiple dispatch call for 'cmp'.

=cut

*/

    VTABLE INTVAL cmp(PMC *value) {
        INTVAL retval;

        /* Don't multidispatch if you've got two pointers to the same PMC. They
         * are equal. */
        if (SELF == value)
            return 0;

        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "cmp", "PP->I", SELF, value, &retval);

        return retval;
    }

/*

=item C<INTVAL cmp_num(PMC *value)>

Default fallback. Performs a multiple dispatch call for 'cmp_num'.

=cut

*/

    VTABLE INTVAL cmp_num(PMC *value) {
        INTVAL retval;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "cmp_num", "PP->I", SELF, value, &retval);

        return retval;
    }

/*

=item C<INTVAL cmp_string(PMC *value)>

Default fallback. Performs a multiple dispatch call for 'cmp_string'.

=cut

*/

    VTABLE INTVAL cmp_string(PMC *value) {
        INTVAL retval;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "cmp_string", "PP->I", SELF, value, &retval);

        return retval;
    }

/*

=item C<PMC *cmp_pmc(PMC *value)>

Default fallback. Performs a multiple dispatch call for 'cmp_pmc'.

=cut

*/

    VTABLE PMC *cmp_pmc(PMC *value) {
        PMC *retval;

        /* Don't multidispatch if you've got two pointers to the same PMC. They
         * are equal. */
        if (SELF == value)
            return 0;

        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "cmp_pmc", "PP->P", SELF, value, &retval);

        return retval;
    }
/*

=item C<PMC *logical_or(PMC *value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'logical_or'.

=cut

*/

    VTABLE PMC *logical_or(PMC *value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "logical_or", "PPP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *logical_and(PMC *value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'logical_and'.

=cut

*/

    VTABLE PMC *logical_and(PMC *value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "logical_and", "PPP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *logical_xor(PMC *value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'logical_xor'.

=cut

*/

    VTABLE PMC *logical_xor(PMC *value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "logical_xor", "PPP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *concatenate(PMC *value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'concatenate'.

=cut

*/

    VTABLE PMC *concatenate(PMC *value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "concatenate", "PPP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *concatenate_str(STRING *value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'concatenate_str'.

=cut

*/

    VTABLE PMC *concatenate_str(STRING *value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "concatenate_str", "PSP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<void i_concatenate(PMC *value)>

Default fallback. Performs a multiple dispatch call for 'i_concatenate'.

=cut

*/

    VTABLE void i_concatenate(PMC *value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_concatenate", "PP", SELF, value);
    }

/*

=item C<void i_concatenate_str(STRING *value)>

Default fallback. Performs a multiple dispatch call for 'i_concatenate_str'.

=cut

*/

    VTABLE void i_concatenate_str(STRING *value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_concatenate_str", "PS", SELF, value);
    }

/*

=item C<PMC *repeat(PMC *value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'repeat'.

=cut

*/

    VTABLE PMC *repeat(PMC *value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "repeat", "PPP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<PMC *repeat_int(INTVAL value, PMC *dest)>

Default fallback. Performs a multiple dispatch call for 'repeat_int'.

=cut

*/

    VTABLE PMC *repeat_int(INTVAL value, PMC *dest) {
        PMC *result = PMCNULL;
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "repeat_int", "PIP->P", SELF, value, dest, &result);
        return result;
    }

/*

=item C<void i_repeat(PMC *value)>

Default fallback. Performs a multiple dispatch call for 'i_repeat'.

=cut

*/

    VTABLE void i_repeat(PMC *value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_repeat", "PP", SELF, value);
    }

/*

=item C<void i_repeat_int(INTVAL value)>

Default fallback. Performs a multiple dispatch call for 'i_repeat_int'.

=cut

*/

    VTABLE void i_repeat_int(INTVAL value) {
        Parrot_mmd_multi_dispatch_from_c_args(interp,
                "i_repeat_int", "PI", SELF, value);
    }
}

/*

=back

=cut

*/

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