PARROT_EXPORT PARROT_CAN_RETURN_NULL PARROT_WARN_UNUSED_RESULT PMC * Parrot_oo_get_class(PARROT_INTERP, ARGIN(PMC *key)) { ASSERT_ARGS(Parrot_oo_get_class) PMC *classobj = PMCNULL; if (PMC_IS_NULL(key)) return PMCNULL; if (PObj_is_class_TEST(key)) classobj = key; else { /* Fast select of behavior based on type of the lookup key */ switch (key->vtable->base_type) { case enum_class_NameSpace: classobj = VTABLE_get_class(interp, key); break; case enum_class_String: case enum_class_Key: case enum_class_ResizableStringArray: { PMC * const hll_ns = VTABLE_get_pmc_keyed_int(interp, interp->HLL_namespace, Parrot_pcc_get_HLL(interp, CURRENT_CONTEXT(interp))); PMC * const ns = Parrot_ns_get_namespace_keyed(interp, hll_ns, key); if (!PMC_IS_NULL(ns)) classobj = VTABLE_get_class(interp, ns); } default: break; } } /* If the PMCProxy doesn't exist yet for the given key, we look up the type ID here and create a new one */ if (PMC_IS_NULL(classobj)) { INTVAL type; const INTVAL base_type = key->vtable->base_type; /* This is a hack! All PMCs should be able to be handled through a single codepath, and all of them should be able to avoid stringification because it's so imprecise. */ if (base_type == enum_class_Key || base_type == enum_class_ResizableStringArray || base_type == enum_class_String) type = Parrot_pmc_get_type(interp, key); else type = Parrot_pmc_get_type_str(interp, VTABLE_get_string(interp, key)); classobj = get_pmc_proxy(interp, type); } return classobj; }
PARROT_INLINE PARROT_CANNOT_RETURN_NULL PARROT_WARN_UNUSED_RESULT static PMC * get_pmc_proxy(PARROT_INTERP, INTVAL type) { ASSERT_ARGS(get_pmc_proxy) PMC * type_class; /* Check if not a PMC or invalid type number */ if (type > interp->n_vtable_max || type <= 0) return PMCNULL; type_class = interp->vtables[type]->pmc_class; if (type != enum_class_Class && type_class->vtable->base_type == enum_class_Class) { return type_class; } else { PMC * const parrot_hll = Parrot_ns_get_namespace_keyed_str(interp, interp->root_namespace, CONST_STRING(interp, "parrot")); PMC * const pmc_ns = Parrot_ns_make_namespace_keyed_str(interp, parrot_hll, interp->vtables[type]->whoami); PMC * proxy = VTABLE_get_class(interp, pmc_ns); /* Create proxy if not found */ if (PMC_IS_NULL(proxy)) { proxy = Parrot_pmc_new_init_int(interp, enum_class_PMCProxy, type); Parrot_pcc_invoke_method_from_c_args(interp, pmc_ns, CONST_STRING(interp, "set_class"), "P->", proxy); } return proxy; } }
/* Creates a Perl 6 object of the type given by C<classname> */ static PMC * Rakudo_binding_create(PARROT_INTERP, STRING *classname) { PMC *ns = Parrot_get_ctx_HLL_namespace(interp); PMC *class_ns = Parrot_ns_get_namespace_keyed_str(interp, ns, classname); PMC *class_obj = VTABLE_get_class(interp, class_ns); PMC *result = VTABLE_instantiate(interp, class_obj, PMCNULL); return result; }
/* Creates a Perl 6 Array. */ static PMC * Rakudo_binding_create_positional(PARROT_INTERP, PMC *rest, STRING *type_str) { static PMC *truepmc = NULL; PMC *hll_ns = Parrot_get_ctx_HLL_namespace(interp); PMC *arr_ns = Parrot_ns_get_namespace_keyed_str(interp, hll_ns, type_str); PMC *arr_class = VTABLE_get_class(interp, arr_ns); PMC *result = VTABLE_instantiate(interp, arr_class, PMCNULL); INTVAL type_id = pmc_type(interp, Parrot_str_new(interp, "P6opaque", 0)); result->vtable = interp->vtables[type_id]; if (!truepmc) truepmc = VTABLE_get_pmc_keyed_str(interp, hll_ns, Parrot_str_new(interp, "True", 0)); VTABLE_set_attr_str(interp, result, Parrot_str_new(interp, "$!flat", 0), truepmc); VTABLE_set_attr_str(interp, result, Parrot_str_new(interp, "@!rest", 0), rest); return result; }