<commit_before>/*
Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
$Id$

=head1 NAME

objects.c - Class and object

=head1 DESCRIPTION

Handles class and object manipulation.

=head2 Functions

=over 4

=cut

*/

#define PARROT_IN_OBJECTS_C
#include "parrot/parrot.h"
#include <assert.h>

#include "objects.str"

static void* instantiate_py_object(Interp*, PMC*, void*);
extern void
parrot_py_set_vtable(Parrot_Interp interpreter, PMC* class);

static PMC *
clone_array(Parrot_Interp interpreter, PMC *source_array)
{
    PMC *new_array;
    INTVAL count;
    INTVAL i;

    count = VTABLE_elements(interpreter, source_array);
    /*
     * preserve type, we have OrderedHash and Array
     * XXX this doesn't preserve the keys of the ordered hash
     *     (but the keys aren't used -leo)
     */
    new_array = pmc_new(interpreter, source_array->vtable->base_type);
    VTABLE_set_integer_native(interpreter, new_array, count);
    for (i = 0; i < count; i++) {
        VTABLE_set_pmc_keyed_int(interpreter, new_array, i,
                VTABLE_get_pmc_keyed_int(interpreter, source_array, i));
    }
    return new_array;
}

/* Take the class and completely rebuild the atttribute stuff for
   it. Horribly destructive, and definitely not a good thing to do if
   there are instantiated objects for the class */
static void
rebuild_attrib_stuff(Parrot_Interp interpreter, PMC *class)
{
    INTVAL cur_offset = POD_FIRST_ATTRIB;
    SLOTTYPE *class_slots;
    PMC *attr_offset_hash;
    PMC *class_offset_hash;
    PMC *parent_array;
    PMC *a_parent_class;
    STRING *classname;
    INTVAL class_offset;
    INTVAL parent_class_count;

    class_slots = PMC_data(class);
    attr_offset_hash = pmc_new(interpreter, enum_class_OrderedHash);
    class_offset_hash = pmc_new(interpreter, enum_class_PerlHash);
    parent_array = get_attrib_num(class_slots, PCD_ALL_PARENTS);
    parent_class_count = VTABLE_elements(interpreter, parent_array);

    for (class_offset = 0; class_offset < parent_class_count; class_offset++) {
        INTVAL parent_attr_count;
        SLOTTYPE *parent_slots;
        PMC *parent_attrib_array;

        a_parent_class = VTABLE_get_pmc_keyed_int(interpreter,
                parent_array, class_offset);
        if (!PObj_is_class_TEST(a_parent_class)) {
            /* this Class inherits from a PMC -
             * no attributes there
             */
            break;
        }
        parent_slots = PMC_data(a_parent_class);
        parent_attrib_array = get_attrib_num(parent_slots,
                PCD_CLASS_ATTRIBUTES);
        parent_attr_count = VTABLE_elements(interpreter,
                parent_attrib_array);

        /* If there are any parent attributes, then go add the
           parent to this class' attribute info things */
        if (parent_attr_count) {
            STRING *parent_name;
            INTVAL parent_offset;
            STRING *partial_name;

            parent_name = VTABLE_get_string(interpreter,
                    get_attrib_num(parent_slots, PCD_CLASS_NAME));
            /* Note the current offset as where this class'
               attributes start */
            VTABLE_set_integer_keyed_str(interpreter,
                    class_offset_hash,
                    parent_name, cur_offset);
            partial_name = string_concat(interpreter, parent_name,
                    string_from_cstring(interpreter, "\0", 1),
                    0);
            for (parent_offset = 0; parent_offset < parent_attr_count;
                    parent_offset++) {
                STRING *attr_name;
                STRING *full_name;

                attr_name = VTABLE_get_string_keyed_int(interpreter,
                        parent_attrib_array, parent_offset);
                full_name = string_concat(interpreter, partial_name,
                        attr_name, 0);
                VTABLE_set_integer_keyed_str(interpreter, attr_offset_hash,
                        full_name, cur_offset++);
            }
        }

    }
    /* Now append our own. To make things easier, we make sure we
       always appear in the offset list, even if we don't have any
       attributes. That way the append code for adding attributes to a
       child class works better */
    classname = VTABLE_get_string(interpreter, get_attrib_num(class_slots,
                PCD_CLASS_NAME));
    VTABLE_set_integer_keyed_str(interpreter, class_offset_hash, classname,
            cur_offset);
    {
        PMC *attribs;
        INTVAL attr_count;

        attribs = get_attrib_num(class_slots, PCD_CLASS_ATTRIBUTES);
        attr_count = VTABLE_elements(interpreter, attribs);
        if (attr_count) {
            STRING *partial_name;
            INTVAL offset;

            partial_name = string_concat(interpreter, classname,
                    string_from_cstring(interpreter, "\0", 1),
                    0);
            for (offset = 0; offset < attr_count; offset++) {
                STRING *attr_name;
                STRING *full_name;

                attr_name = VTABLE_get_string_keyed_int(interpreter, attribs,
                        offset);
                full_name = string_concat(interpreter, partial_name,
                        attr_name, 0);
                VTABLE_set_integer_keyed_str(interpreter, attr_offset_hash,
                        full_name, cur_offset++);
            }
        }
    }

    /* And replace what was in there with the new ones */
    set_attrib_num(class_slots, PCD_ATTRIBUTES, attr_offset_hash);
    set_attrib_num(class_slots, PCD_ATTRIB_OFFS, class_offset_hash);
    /* And note the totals */
    ATTRIB_COUNT(class) = cur_offset - POD_FIRST_ATTRIB;
}

/*

=item C<static void create_deleg_pmc_vtable(Interp *, PMC *class, STRING *name)>

Create a vtable that dispatches either to the contained PMC in the first
attribute (deleg_pmc) or to an overridden method (delegate), depending
on the existance of the method for this class.

*/

static void
create_deleg_pmc_vtable(Interp *interpreter, PMC *class, STRING *class_name)
{
    PMC *vtable_pmc;
    VTABLE *vtable, *deleg_pmc_vtable, *delegate_vtable, *object_vtable;
    int i;
    const char *meth;
    STRING meth_str;
    union {
        const void * __c_ptr;
        void * __ptr;
    } __ptr_u;

    vtable_pmc = get_attrib_num((SLOTTYPE*)PMC_data(class),
            PCD_OBJECT_VTABLE);
    vtable = PMC_struct_val(vtable_pmc);
    deleg_pmc_vtable = Parrot_base_vtables[enum_class_deleg_pmc];
    object_vtable = Parrot_base_vtables[enum_class_ParrotObject];
    delegate_vtable = Parrot_base_vtables[enum_class_delegate];

    memset(&meth_str, 0, sizeof(meth_str));
    meth_str.representation = enum_stringrep_one;
    for (i = 0; (meth = Parrot_vtable_slot_names[i]); ++i) {
        if (!*meth)
            continue;
        meth_str.strstart = const_cast(meth);
        meth_str.strlen = meth_str.bufused = strlen(meth);<commit_msg>Add a missing =cut to API documentation.<commit_after>/*
Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
$Id$

=head1 NAME

objects.c - Class and object

=head1 DESCRIPTION

Handles class and object manipulation.

=head2 Functions

=over 4

=cut

*/

#define PARROT_IN_OBJECTS_C
#include "parrot/parrot.h"
#include <assert.h>

#include "objects.str"

static void* instantiate_py_object(Interp*, PMC*, void*);
extern void
parrot_py_set_vtable(Parrot_Interp interpreter, PMC* class);

static PMC *
clone_array(Parrot_Interp interpreter, PMC *source_array)
{
    PMC *new_array;
    INTVAL count;
    INTVAL i;

    count = VTABLE_elements(interpreter, source_array);
    /*
     * preserve type, we have OrderedHash and Array
     * XXX this doesn't preserve the keys of the ordered hash
     *     (but the keys aren't used -leo)
     */
    new_array = pmc_new(interpreter, source_array->vtable->base_type);
    VTABLE_set_integer_native(interpreter, new_array, count);
    for (i = 0; i < count; i++) {
        VTABLE_set_pmc_keyed_int(interpreter, new_array, i,
                VTABLE_get_pmc_keyed_int(interpreter, source_array, i));
    }
    return new_array;
}

/* Take the class and completely rebuild the atttribute stuff for
   it. Horribly destructive, and definitely not a good thing to do if
   there are instantiated objects for the class */
static void
rebuild_attrib_stuff(Parrot_Interp interpreter, PMC *class)
{
    INTVAL cur_offset = POD_FIRST_ATTRIB;
    SLOTTYPE *class_slots;
    PMC *attr_offset_hash;
    PMC *class_offset_hash;
    PMC *parent_array;
    PMC *a_parent_class;
    STRING *classname;
    INTVAL class_offset;
    INTVAL parent_class_count;

    class_slots = PMC_data(class);
    attr_offset_hash = pmc_new(interpreter, enum_class_OrderedHash);
    class_offset_hash = pmc_new(interpreter, enum_class_PerlHash);
    parent_array = get_attrib_num(class_slots, PCD_ALL_PARENTS);
    parent_class_count = VTABLE_elements(interpreter, parent_array);

    for (class_offset = 0; class_offset < parent_class_count; class_offset++) {
        INTVAL parent_attr_count;
        SLOTTYPE *parent_slots;
        PMC *parent_attrib_array;

        a_parent_class = VTABLE_get_pmc_keyed_int(interpreter,
                parent_array, class_offset);
        if (!PObj_is_class_TEST(a_parent_class)) {
            /* this Class inherits from a PMC -
             * no attributes there
             */
            break;
        }
        parent_slots = PMC_data(a_parent_class);
        parent_attrib_array = get_attrib_num(parent_slots,
                PCD_CLASS_ATTRIBUTES);
        parent_attr_count = VTABLE_elements(interpreter,
                parent_attrib_array);

        /* If there are any parent attributes, then go add the
           parent to this class' attribute info things */
        if (parent_attr_count) {
            STRING *parent_name;
            INTVAL parent_offset;
            STRING *partial_name;

            parent_name = VTABLE_get_string(interpreter,
                    get_attrib_num(parent_slots, PCD_CLASS_NAME));
            /* Note the current offset as where this class'
               attributes start */
            VTABLE_set_integer_keyed_str(interpreter,
                    class_offset_hash,
                    parent_name, cur_offset);
            partial_name = string_concat(interpreter, parent_name,
                    string_from_cstring(interpreter, "\0", 1),
                    0);
            for (parent_offset = 0; parent_offset < parent_attr_count;
                    parent_offset++) {
                STRING *attr_name;
                STRING *full_name;

                attr_name = VTABLE_get_string_keyed_int(interpreter,
                        parent_attrib_array, parent_offset);
                full_name = string_concat(interpreter, partial_name,
                        attr_name, 0);
                VTABLE_set_integer_keyed_str(interpreter, attr_offset_hash,
                        full_name, cur_offset++);
            }
        }

    }
    /* Now append our own. To make things easier, we make sure we
       always appear in the offset list, even if we don't have any
       attributes. That way the append code for adding attributes to a
       child class works better */
    classname = VTABLE_get_string(interpreter, get_attrib_num(class_slots,
                PCD_CLASS_NAME));
    VTABLE_set_integer_keyed_str(interpreter, class_offset_hash, classname,
            cur_offset);
    {
        PMC *attribs;
        INTVAL attr_count;

        attribs = get_attrib_num(class_slots, PCD_CLASS_ATTRIBUTES);
        attr_count = VTABLE_elements(interpreter, attribs);
        if (attr_count) {
            STRING *partial_name;
            INTVAL offset;

            partial_name = string_concat(interpreter, classname,
                    string_from_cstring(interpreter, "\0", 1),
                    0);
            for (offset = 0; offset < attr_count; offset++) {
                STRING *attr_name;
                STRING *full_name;

                attr_name = VTABLE_get_string_keyed_int(interpreter, attribs,
                        offset);
                full_name = string_concat(interpreter, partial_name,
                        attr_name, 0);
                VTABLE_set_integer_keyed_str(interpreter, attr_offset_hash,
                        full_name, cur_offset++);
            }
        }
    }

    /* And replace what was in there with the new ones */
    set_attrib_num(class_slots, PCD_ATTRIBUTES, attr_offset_hash);
    set_attrib_num(class_slots, PCD_ATTRIB_OFFS, class_offset_hash);
    /* And note the totals */
    ATTRIB_COUNT(class) = cur_offset - POD_FIRST_ATTRIB;
}

/*

=item C<static void create_deleg_pmc_vtable(Interp *, PMC *class, STRING *name)>

Create a vtable that dispatches either to the contained PMC in the first
attribute (deleg_pmc) or to an overridden method (delegate), depending
on the existance of the method for this class.

=cut

*/

static void
create_deleg_pmc_vtable(Interp *interpreter, PMC *class, STRING *class_name)
{
    PMC *vtable_pmc;
    VTABLE *vtable, *deleg_pmc_vtable, *delegate_vtable, *object_vtable;
    int i;
    const char *meth;
    STRING meth_str;
    union {
        const void * __c_ptr;
        void * __ptr;
    } __ptr_u;

    vtable_pmc = get_attrib_num((SLOTTYPE*)PMC_data(class),
            PCD_OBJECT_VTABLE);
    vtable = PMC_struct_val(vtable_pmc);
    deleg_pmc_vtable = Parrot_base_vtables[enum_class_deleg_pmc];
    object_vtable = Parrot_base_vtables[enum_class_ParrotObject];
    delegate_vtable = Parrot_base_vtables[enum_class_delegate];

    memset(&meth_str, 0, sizeof(meth_str));
    meth_str.representation = enum_stringrep_one;
    for (i = 0; (meth = Parrot_vtable_slot_names[i]); ++i) {
        if (!*meth)
            continue;
        meth_str.strstart = const_cast(meth);
        meth_str.strlen = meth_str.bufused = strlen(meth);
{'fraction_non_alphanumeric': 0.07651335204779386, 'fraction_numerical': 0.0037428921039372345, 'mean_word_length': 2.5717223650385606, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6385166', 'n_tokens_mistral': 4480, 'n_tokens_neox': 4345, 'n_words': 998}