Ejemplo n.º 1
0
Archivo: embed.c Proyecto: gitpan/ponie
static void
setup_argv(struct Parrot_Interp *interpreter, int argc, char ** argv)
{
    INTVAL i;
    PMC *userargv;

    if (Interp_flags_TEST(interpreter, PARROT_DEBUG_FLAG)) {
        PIO_eprintf(interpreter,
                "*** Parrot VM: Setting up ARGV array in P5.  Current argc: %d ***\n",
                argc);
    }

    userargv = pmc_new_noinit(interpreter, enum_class_SArray);
    /* immediately anchor pmc to root set */
    interpreter->pmc_reg.registers[5] = userargv;
    VTABLE_set_pmc_keyed_int(interpreter, interpreter->iglobals,
            (INTVAL)IGLOBALS_ARGV_LIST, userargv);
    VTABLE_init(interpreter, userargv);
    VTABLE_set_integer_native(interpreter, userargv, argc);

    for (i = 0; i < argc; i++) {
        /* Run through argv, adding everything to @ARGS. */
        STRING *arg = string_make(interpreter, argv[i], strlen(argv[i]),
                                  0, PObj_external_FLAG, 0);

        if (Interp_flags_TEST(interpreter, PARROT_DEBUG_FLAG)) {
            PIO_eprintf(interpreter, "\t%vd: %s\n", i, argv[i]);
        }

        VTABLE_push_string(interpreter, userargv, arg);
    }
}
Ejemplo n.º 2
0
/* can't really use xsubpp here... */
extern
XS(blizkost_callable_trampoline)
{
#ifdef dVAR
    dVAR;
#endif
    dXSARGS;
    PMC *callable;
    blizkost_nexus *nexus;
    int i;
    PMC *args, *posret, *namret;

    blizkost_get_bound_pmc(my_perl, &nexus, (SV *)cv, &callable);

    if (nexus->dying)
        exit_fatal(1, "Attempted reentry of Parrot code during global destruction");

    PERL_UNUSED_VAR(ax);
    SP -= items;
    PUTBACK;

    args = Parrot_pmc_new_init_int(nexus->parrot_interp, enum_class_ResizablePMCArray, items);
    for (i = 0; i < items; i++) {
        SV *svarg = ST(i);
        PMC *pmcarg = blizkost_wrap_sv(nexus, svarg);
        VTABLE_set_pmc_keyed_int(nexus->parrot_interp, args, i, pmcarg);
    }

    Parrot_pcc_invoke_sub_from_c_args(nexus->parrot_interp, callable,
            "Pf->PsPsn", args, &posret, &namret);

    blizkost_slurpy_to_stack(nexus, posret, namret);

    SPAGAIN;
}
Ejemplo n.º 3
0
PARROT_EXPORT
void
Parrot_set_executable_name(PARROT_INTERP, Parrot_String name)
{
    PMC * const name_pmc = pmc_new(interp, enum_class_String);
    VTABLE_set_string_native(interp, name_pmc, name);
    VTABLE_set_pmc_keyed_int(interp, interp->iglobals, IGLOBALS_EXECUTABLE,
        name_pmc);
}
Ejemplo n.º 4
0
/* Sets up a very simple attribute meta-object. Just supports having a
 * name, and even uses the P6str representation to store it, so that's
 * really all that it supports. */
PMC * SixModelObject_setup_knowhow_attribute(PARROT_INTERP, PMC *sc, PMC *knowhow) {
    PMC *old_ctx, *cappy, *meth, *knowhow_attr, *how;
    
    /* Create a new KnowHOWAttribute type using P6str repr.. */
    meth = STABLE(knowhow)->find_method(interp, knowhow,
        Parrot_str_new_constant(interp, "new_type"), NO_HINT);
    old_ctx = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
    cappy   = Parrot_pmc_new(interp, enum_class_CallContext);
    VTABLE_push_pmc(interp, cappy, knowhow);
    VTABLE_set_string_keyed_str(interp, cappy, name_str,
        Parrot_str_new_constant(interp, "KnowHOWAttribute"));
    VTABLE_set_string_keyed_str(interp, cappy, repr_str,
        Parrot_str_new_constant(interp, "P6str"));
    Parrot_pcc_invoke_from_sig_object(interp, meth, cappy);
    cappy = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
    Parrot_pcc_set_signature(interp, CURRENT_CONTEXT(interp), old_ctx);
    knowhow_attr = VTABLE_get_pmc_keyed_int(interp, cappy, 0);
    how = STABLE(knowhow_attr)->HOW;
    
    /* Add new method. */
    meth = STABLE(how)->find_method(interp, how,
        Parrot_str_new_constant(interp, "add_method"), NO_HINT);
    cappy   = Parrot_pmc_new(interp, enum_class_CallContext);
    VTABLE_push_pmc(interp, cappy, how);
    VTABLE_push_pmc(interp, cappy, knowhow_attr);
    VTABLE_push_string(interp, cappy, Parrot_str_new_constant(interp, "new"));
    VTABLE_push_pmc(interp, cappy, wrap_c(interp, F2DPTR(attr_new)));
    Parrot_pcc_invoke_from_sig_object(interp, meth, cappy);
    Parrot_pcc_set_signature(interp, CURRENT_CONTEXT(interp), old_ctx);
    
    /* Add name method. */
    cappy   = Parrot_pmc_new(interp, enum_class_CallContext);
    VTABLE_push_pmc(interp, cappy, how);
    VTABLE_push_pmc(interp, cappy, knowhow_attr);
    VTABLE_push_string(interp, cappy, name_str);
    VTABLE_push_pmc(interp, cappy, wrap_c(interp, F2DPTR(attr_name)));
    Parrot_pcc_invoke_from_sig_object(interp, meth, cappy);
    Parrot_pcc_set_signature(interp, CURRENT_CONTEXT(interp), old_ctx);
    
    /* Compose. */
    meth = STABLE(knowhow)->find_method(interp, how,
        Parrot_str_new_constant(interp, "compose"), NO_HINT);
    cappy   = Parrot_pmc_new(interp, enum_class_CallContext);
    VTABLE_push_pmc(interp, cappy, how);
    VTABLE_push_pmc(interp, cappy, knowhow_attr);
    Parrot_pcc_invoke_from_sig_object(interp, meth, cappy);
    Parrot_pcc_set_signature(interp, CURRENT_CONTEXT(interp), old_ctx);
    
    /* Associate the created object with the intial core serialization
     * context. */
    VTABLE_set_pmc_keyed_int(interp, sc, 2, knowhow_attr);
    SC_PMC(knowhow_attr) = sc;
    STABLE(knowhow_attr)->sc = sc;
    
    return knowhow_attr;
}
Ejemplo n.º 5
0
/* Takes an STable and adds it to this SC's root set, and installs a
 * reposession entry. */
void SC_repossess_stable(PARROT_INTERP, PMC *target_sc, PMC *orig_sc, PMC *st_pmc) {
    PMC *rep_indexes, *rep_scs;
    
    /* Add to root set. */
    PMC    *stables;
    INTVAL  new_slot;
    GETATTR_SerializationContext_root_stables(interp, target_sc, stables);
    new_slot = VTABLE_elements(interp, stables);
    VTABLE_set_pmc_keyed_int(interp, stables, new_slot, st_pmc);
    
    /* Add repossession entry. */
    GETATTR_SerializationContext_rep_indexes(interp, target_sc, rep_indexes);
    GETATTR_SerializationContext_rep_scs(interp, target_sc, rep_scs);
    VTABLE_push_integer(interp, rep_indexes, (new_slot << 1) | 1);
    VTABLE_push_pmc(interp, rep_scs, orig_sc);
}
Ejemplo n.º 6
0
/* This function gets shared with perl6.ops for the perl6_parcel_from_rpa op. */
PMC *
Rakudo_binding_parcel_from_rpa(PARROT_INTERP, PMC *rpa, PMC *fill) {
    PMC *type = Rakudo_types_parcel_get();
    PMC *parcel = REPR(type)->allocate(interp, STABLE(type));
    VTABLE_set_attr_keyed(interp, parcel, type, STORAGE_str, rpa);

    if (!PMC_IS_NULL(fill)) {
        INTVAL elems = VTABLE_elements(interp, rpa);
        INTVAL i;
        for (i = 0; i < elems; i++) {
            if (PMC_IS_NULL(VTABLE_get_pmc_keyed_int(interp, rpa, i)))
                VTABLE_set_pmc_keyed_int(interp, rpa, i, fill);
        }
    }

    return parcel;
}
Ejemplo n.º 7
0
static void
parrot_set_config_hash_interpreter(PARROT_INTERP)
{
    ASSERT_ARGS(parrot_set_config_hash_interpreter)
    PMC *iglobals = interp->iglobals;

    PMC *config_hash = NULL;

    if (parrot_config_size_stored > 1) {
        STRING * const config_string =
            Parrot_str_new_init(interp,
                               (const char *)parrot_config_stored, parrot_config_size_stored,
                               Parrot_default_encoding_ptr,
                               PObj_external_FLAG|PObj_constant_FLAG);

        config_hash = Parrot_thaw(interp, config_string);
    }
    else {
        config_hash = Parrot_pmc_new(interp, enum_class_Hash);
    }

    VTABLE_set_pmc_keyed_int(interp, iglobals,
                             (INTVAL) IGLOBALS_CONFIG_HASH, config_hash);
}
Ejemplo n.º 8
0
/* Bootstraps the KnowHOW. This is were things "bottom out" in the meta-model
 * so it's a tad loopy. Basically, we create a KnowHOW type object. We then
 * create an instance from that and add a bunch of methods to it. Returns the
 * bootstrapped object. */
PMC * SixModelObject_bootstrap_knowhow(PARROT_INTERP, PMC *sc) {
    /* Create our KnowHOW type object. Note we don't have a HOW just yet, so
     * pass in null. */
    REPROps *REPR        = REPR_get_by_name(interp, Parrot_str_new_constant(interp, "KnowHOWREPR"));
    PMC     *knowhow_pmc = REPR->type_object_for(interp, PMCNULL);

    /* We create a KnowHOW instance that can describe itself. This means
     * .HOW.HOW.HOW.HOW etc will always return that, which closes the model
     * up. Also pull out its underlying struct. */
    PMC *knowhow_how_pmc = REPR->allocate(interp, NULL);
    KnowHOWREPRInstance *knowhow_how = (KnowHOWREPRInstance *)PMC_data(knowhow_how_pmc);

    /* Need to give the knowhow_how a twiddled STable with a different
     * dispatcher, so things bottom out. */
    PMC *st_copy = create_stable(interp, REPR, knowhow_how_pmc);
    STABLE_STRUCT(st_copy)->WHAT = knowhow_pmc;
    STABLE_STRUCT(st_copy)->find_method = bottom_find_method;
    knowhow_how->common.stable = st_copy;

    /* Add various methods to the KnowHOW's HOW. */
    knowhow_how->body.methods = Parrot_pmc_new(interp, enum_class_Hash);
    knowhow_how->body.attributes = Parrot_pmc_new(interp, enum_class_ResizablePMCArray);
    VTABLE_set_pmc_keyed_str(interp, knowhow_how->body.methods,
        Parrot_str_new_constant(interp, "new_type"),
        wrap_c(interp, F2DPTR(new_type)));
    VTABLE_set_pmc_keyed_str(interp, knowhow_how->body.methods,
        Parrot_str_new_constant(interp, "find_method"),
        wrap_c(interp, F2DPTR(find_method)));
    VTABLE_set_pmc_keyed_str(interp, knowhow_how->body.methods,
        Parrot_str_new_constant(interp, "add_method"),
        wrap_c(interp, F2DPTR(add_method)));
    VTABLE_set_pmc_keyed_str(interp, knowhow_how->body.methods,
        Parrot_str_new_constant(interp, "add_attribute"),
        wrap_c(interp, F2DPTR(add_attribute)));
    VTABLE_set_pmc_keyed_str(interp, knowhow_how->body.methods,
        Parrot_str_new_constant(interp, "compose"),
        wrap_c(interp, F2DPTR(compose)));
    VTABLE_set_pmc_keyed_str(interp, knowhow_how->body.methods,
        Parrot_str_new_constant(interp, "parents"),
        wrap_c(interp, F2DPTR(parents)));
    VTABLE_set_pmc_keyed_str(interp, knowhow_how->body.methods,
        Parrot_str_new_constant(interp, "attributes"),
        wrap_c(interp, F2DPTR(attributes)));
    VTABLE_set_pmc_keyed_str(interp, knowhow_how->body.methods,
        Parrot_str_new_constant(interp, "methods"),
        wrap_c(interp, F2DPTR(methods)));
    VTABLE_set_pmc_keyed_str(interp, knowhow_how->body.methods,
        Parrot_str_new_constant(interp, "mro"),
        wrap_c(interp, F2DPTR(mro)));
    VTABLE_set_pmc_keyed_str(interp, knowhow_how->body.methods,
        Parrot_str_new_constant(interp, "name"),
        wrap_c(interp, F2DPTR(name)));

    /* Set name KnowHOW for the KnowHOW's HOW. */
    knowhow_how->body.name = Parrot_str_new_constant(interp, "KnowHOW");

    /* Set this built up HOW as the KnowHOW's HOW. */
    STABLE(knowhow_pmc)->HOW = knowhow_how_pmc;
    
    /* Give it an authoritative method cache. */
    STABLE(knowhow_pmc)->method_cache = knowhow_how->body.methods;
    STABLE(knowhow_pmc)->mode_flags   = METHOD_CACHE_AUTHORITATIVE;

    /* Set up some string constants that the methods here use. */
    repr_str     = Parrot_str_new_constant(interp, "repr");
    name_str     = Parrot_str_new_constant(interp, "name");
    empty_str    = Parrot_str_new_constant(interp, "");
    p6opaque_str = Parrot_str_new_constant(interp, "P6opaque");

    /* Associate the created objects with the intial core serialization
     * context. */
    VTABLE_set_pmc_keyed_int(interp, sc, 0, knowhow_pmc);
    SC_PMC(knowhow_pmc) = sc;
    VTABLE_set_pmc_keyed_int(interp, sc, 1, knowhow_how_pmc);
    SC_PMC(knowhow_how_pmc) = sc;
    STABLE(knowhow_pmc)->sc = sc;
    STABLE(knowhow_how_pmc)->sc = sc;

    return knowhow_pmc;
}
Ejemplo n.º 9
0
void
parrot_init_library_paths(PARROT_INTERP)
{
    ASSERT_ARGS(parrot_init_library_paths)
    PMC    *paths;
    STRING *entry;
    STRING *versionlib      = NULL;
    STRING *builddir        = NULL;
    PMC * const iglobals    = interp->iglobals;
    PMC * const config_hash = VTABLE_get_pmc_keyed_int(interp, iglobals,
                                (INTVAL)IGLOBALS_CONFIG_HASH);

    /* create the lib_paths array */
    PMC * const lib_paths   = Parrot_pmc_new_init_int(interp,
            enum_class_FixedPMCArray, PARROT_LIB_PATH_SIZE);
    VTABLE_set_pmc_keyed_int(interp, iglobals,
            IGLOBALS_LIB_PATHS, lib_paths);

    if (VTABLE_elements(interp, config_hash)) {
        STRING * const libkey      = CONST_STRING(interp, "libdir");
        STRING * const verkey      = CONST_STRING(interp, "versiondir");
        STRING * const builddirkey = CONST_STRING(interp, "build_dir");
        STRING * const installed   = CONST_STRING(interp, "installed");

        versionlib = VTABLE_get_string_keyed_str(interp, config_hash, libkey);
        entry      = VTABLE_get_string_keyed_str(interp, config_hash, verkey);
        versionlib = Parrot_str_concat(interp, versionlib, entry);

        if (!VTABLE_get_integer_keyed_str(interp, config_hash, installed))
            builddir = VTABLE_get_string_keyed_str(interp,
                                config_hash, builddirkey);
    }

    /* each is an array of strings */
    /* define include paths */
    paths = Parrot_pmc_new(interp, enum_class_ResizableStringArray);
    VTABLE_set_pmc_keyed_int(interp, lib_paths,
            PARROT_LIB_PATH_INCLUDE, paths);
    { /* EXPERIMENTAL: add include path from environment */
        const char *envvar = Parrot_getenv(interp,
                                           Parrot_str_new_constant(interp, "PARROT_INCLUDE"));
        if (envvar != NULL  && envvar[0]) {
            entry = Parrot_str_new(interp, envvar, 0);
            VTABLE_push_string(interp, paths, entry);
        }
    }
    if (!STRING_IS_NULL(builddir)) {
        entry = Parrot_str_concat(interp, builddir, CONST_STRING(interp, "/"));
        VTABLE_push_string(interp, paths, entry);
        entry = Parrot_str_concat(interp, builddir, CONST_STRING(interp, "/runtime/parrot/include/"));
        VTABLE_push_string(interp, paths, entry);
    }
    entry = CONST_STRING(interp, "./");
    VTABLE_push_string(interp, paths, entry);
    if (!STRING_IS_NULL(versionlib)) {
        entry = Parrot_str_concat(interp, versionlib, CONST_STRING(interp, "/include/"));
        VTABLE_push_string(interp, paths, entry);
    }

    /* define library paths */
    paths = Parrot_pmc_new(interp, enum_class_ResizableStringArray);
    VTABLE_set_pmc_keyed_int(interp, lib_paths,
            PARROT_LIB_PATH_LIBRARY, paths);
    { /* EXPERIMENTAL: add library path from environment */
        const char *envvar = Parrot_getenv(interp,
                                           Parrot_str_new_constant(interp, "PARROT_LIBRARY"));
        if (envvar != NULL && envvar[0]) {
            entry = Parrot_str_new(interp, envvar, 0);
            VTABLE_push_string(interp, paths, entry);
        }
    }
    if (!STRING_IS_NULL(builddir)) {
        entry = Parrot_str_concat(interp, builddir, CONST_STRING(interp, "/runtime/parrot/library/"));
        VTABLE_push_string(interp, paths, entry);
    }
    entry = CONST_STRING(interp, "./");
    VTABLE_push_string(interp, paths, entry);
    if (!STRING_IS_NULL(versionlib)) {
        entry = Parrot_str_concat(interp, versionlib, CONST_STRING(interp, "/library/"));
        VTABLE_push_string(interp, paths, entry);
    }

    /* define languages paths */
    paths = Parrot_pmc_new(interp, enum_class_ResizableStringArray);
    VTABLE_set_pmc_keyed_int(interp, lib_paths,
            PARROT_LIB_PATH_LANG, paths);
    if (!STRING_IS_NULL(builddir)) {
        entry = Parrot_str_concat(interp, builddir, CONST_STRING(interp, "/runtime/parrot/languages/"));
        VTABLE_push_string(interp, paths, entry);
    }
    entry = CONST_STRING(interp, "./");
    VTABLE_push_string(interp, paths, entry);
    if (!STRING_IS_NULL(versionlib)) {
        entry = Parrot_str_concat(interp, versionlib, CONST_STRING(interp, "/languages/"));
        VTABLE_push_string(interp, paths, entry);
    }

    /* define dynext paths */
    paths = Parrot_pmc_new(interp, enum_class_ResizableStringArray);
    VTABLE_set_pmc_keyed_int(interp, lib_paths,
            PARROT_LIB_PATH_DYNEXT, paths);
    if (!STRING_IS_NULL(builddir)) {
        entry = Parrot_str_concat(interp, builddir, CONST_STRING(interp, "/runtime/parrot/dynext/"));
        VTABLE_push_string(interp, paths, entry);
    }
    entry = CONST_STRING(interp, "dynext/");
    VTABLE_push_string(interp, paths, entry);
    if (!STRING_IS_NULL(versionlib)) {
        entry = Parrot_str_concat(interp, versionlib, CONST_STRING(interp, "/dynext/"));
        VTABLE_push_string(interp, paths, entry);
    }

    /* shared exts */
    paths = Parrot_pmc_new(interp, enum_class_ResizableStringArray);
    VTABLE_set_pmc_keyed_int(interp, lib_paths,
            PARROT_LIB_DYN_EXTS, paths);
    /* no CONST_STRING here - the c2str.pl preprocessor needs "real strs" */
    entry = Parrot_str_new_constant(interp, PARROT_LOAD_EXT);
    VTABLE_push_string(interp, paths, entry);
    /* OS/X has .dylib and .bundle */
    if (!STREQ(PARROT_LOAD_EXT, PARROT_SHARE_EXT)) {
        entry = Parrot_str_new_constant(interp, PARROT_SHARE_EXT);
        VTABLE_push_string(interp, paths, entry);
    }

#ifdef PARROT_PLATFORM_LIB_PATH_INIT_HOOK
    PARROT_PLATFORM_LIB_PATH_INIT_HOOK(interp, lib_paths);
#endif
}
Ejemplo n.º 10
0
/* Adds a code ref to an SC. */
void SC_set_code(PARROT_INTERP, PMC *sc, INTVAL idx, PMC *code) {
    PMC *codes;
    GETATTR_SerializationContext_root_codes(interp, sc, codes);
    VTABLE_set_pmc_keyed_int(interp, codes, idx, code);
}
Ejemplo n.º 11
0
void
parrot_init_library_paths(PARROT_INTERP)
{
    ASSERT_ARGS(parrot_init_library_paths)
    PMC    *paths;
    STRING *entry;
    PMC * const iglobals    = interp->iglobals;

    /* create the lib_paths array */
    PMC * const lib_paths   = Parrot_pmc_new_init_int(interp,
            enum_class_FixedPMCArray, PARROT_LIB_PATH_SIZE);
    VTABLE_set_pmc_keyed_int(interp, iglobals,
            IGLOBALS_LIB_PATHS, lib_paths);

    /* each is an array of strings */
    /* define include paths */
    paths = Parrot_pmc_new(interp, enum_class_ResizableStringArray);
    VTABLE_set_pmc_keyed_int(interp, lib_paths,
            PARROT_LIB_PATH_INCLUDE, paths);
    { /* EXPERIMENTAL: add include path from environment */
        STRING *envvar = Parrot_getenv(interp, CONST_STRING(interp, "PARROT_INCLUDE"));
        Parrot_warn_experimental(interp, "PARROT_INCLUDE environment variable is experimental");
        if (!STRING_IS_NULL(envvar) && !STRING_IS_EMPTY(envvar))
            VTABLE_push_string(interp, paths, envvar);
    }
    entry = CONST_STRING(interp, "./");
    VTABLE_push_string(interp, paths, entry);

    /* define library paths */
    paths = Parrot_pmc_new(interp, enum_class_ResizableStringArray);
    VTABLE_set_pmc_keyed_int(interp, lib_paths,
            PARROT_LIB_PATH_LIBRARY, paths);
    { /* EXPERIMENTAL: add library path from environment */
        STRING *envvar = Parrot_getenv(interp, CONST_STRING(interp, "PARROT_LIBRARY"));
        Parrot_warn_experimental(interp, "PARROT_LIBRARY environment variable is experimental");
        if (!STRING_IS_NULL(envvar) && !STRING_IS_EMPTY(envvar))
            VTABLE_push_string(interp, paths, envvar);
    }
    entry = CONST_STRING(interp, "./");
    VTABLE_push_string(interp, paths, entry);

    /* define languages paths */
    paths = Parrot_pmc_new(interp, enum_class_ResizableStringArray);
    VTABLE_set_pmc_keyed_int(interp, lib_paths,
            PARROT_LIB_PATH_LANG, paths);
    entry = CONST_STRING(interp, "./");
    VTABLE_push_string(interp, paths, entry);

    /* define dynext paths */
    paths = Parrot_pmc_new(interp, enum_class_ResizableStringArray);
    VTABLE_set_pmc_keyed_int(interp, lib_paths,
            PARROT_LIB_PATH_DYNEXT, paths);
    entry = CONST_STRING(interp, "dynext/");
    VTABLE_push_string(interp, paths, entry);

    /* shared exts */
    paths = Parrot_pmc_new(interp, enum_class_ResizableStringArray);
    VTABLE_set_pmc_keyed_int(interp, lib_paths,
            PARROT_LIB_DYN_EXTS, paths);
    /* no CONST_STRING here - the c2str.pl preprocessor needs "real strs" */
    entry = Parrot_str_new_constant(interp, PARROT_LOAD_EXT);
    VTABLE_push_string(interp, paths, entry);
    /* OS/X has .dylib and .bundle */
    if (!STREQ(PARROT_LOAD_EXT, PARROT_SHARE_EXT)) {
        entry = Parrot_str_new_constant(interp, PARROT_SHARE_EXT);
        VTABLE_push_string(interp, paths, entry);
    }

#ifdef PARROT_PLATFORM_LIB_PATH_INIT_HOOK
    PARROT_PLATFORM_LIB_PATH_INIT_HOOK(interp, lib_paths);
#endif
}
Ejemplo n.º 12
0
Archivo: oo.c Proyecto: ashgti/parrot
PARROT_CANNOT_RETURN_NULL
PMC *
Parrot_oo_clone_object(PARROT_INTERP, ARGIN(PMC *pmc), ARGMOD_NULLOK(PMC *dest))
{
    ASSERT_ARGS(Parrot_oo_clone_object)
    Parrot_Object_attributes *obj = PARROT_OBJECT(pmc);
    Parrot_Object_attributes *cloned_guts;
    Parrot_Class_attributes  *_class;
    PMC                      *cloned;
    INTVAL                    num_classes;
    INTVAL                    i, num_attrs;

    if (!PMC_IS_NULL(dest)) {
        cloned = dest;
    }
    else {
        cloned = Parrot_pmc_new_noinit(interp, enum_class_Object);
    }

    _class = PARROT_CLASS(obj->_class);
    PARROT_ASSERT(_class);
    num_classes = VTABLE_elements(interp, _class->all_parents);

    /* Set custom GC mark and destroy on the object. */
    PObj_custom_mark_SET(cloned);
    PObj_custom_destroy_SET(cloned);

    /* Flag that it is an object */
    PObj_is_object_SET(cloned);

    /* Now clone attributes list.class. */
    cloned_guts               = (Parrot_Object_attributes *) PMC_data(cloned);
    cloned_guts->_class       = obj->_class;
    cloned_guts->attrib_store = VTABLE_clone(interp, obj->attrib_store);
    num_attrs                 = VTABLE_elements(interp, cloned_guts->attrib_store);
    for (i = 0; i < num_attrs; ++i) {
        PMC * const to_clone = VTABLE_get_pmc_keyed_int(interp, cloned_guts->attrib_store, i);
        if (!PMC_IS_NULL(to_clone)) {
            VTABLE_set_pmc_keyed_int(interp, cloned_guts->attrib_store, i,
                    VTABLE_clone(interp, to_clone));
        }
    }

    /* Some of the attributes may have been the PMCs providing storage for any
     * PMCs we inherited from; also need to clone those. */
    if (CLASS_has_alien_parents_TEST(obj->_class)) {
        int j;
        /* Locate any PMC parents. */
        for (j = 0; j < num_classes; ++j) {
            PMC * const cur_class = VTABLE_get_pmc_keyed_int(interp, _class->all_parents, j);
            if (cur_class->vtable->base_type == enum_class_PMCProxy) {
                /* Clone this PMC too. */
                STRING * const proxy = CONST_STRING(interp, "proxy");
                VTABLE_set_attr_keyed(interp, cloned, cur_class, proxy,
                    VTABLE_clone(interp,
                        VTABLE_get_attr_keyed(interp, cloned, cur_class, proxy)));
            }
        }
    }

    /* And we have ourselves a clone. */
    return cloned;
}