/* This Parrot-specific addition to the API is used to free an object. */ static void gc_free(PARROT_INTERP, PMC *obj) { P6opaqueREPRData *repr_data = (P6opaqueREPRData *)STABLE(obj)->REPR_data; if (repr_data->allocation_size) Parrot_gc_free_fixed_size_storage(interp, repr_data->allocation_size, PMC_data(obj)); else mem_sys_free(PMC_data(obj)); PMC_data(obj) = NULL; }
/* Clones the current object. This involves cloning the method and * attribute lists and copying the (immutable string) name. */ static PMC * repr_clone(PARROT_INTERP, PMC *to_clone) { KnowHOWREPRInstance *obj = mem_allocate_zeroed_typed(KnowHOWREPRInstance); obj->common.stable = STABLE_PMC(to_clone); obj->methods = VTABLE_clone(interp, ((KnowHOWREPRInstance *)PMC_data(to_clone))->methods); obj->attributes = VTABLE_clone(interp, ((KnowHOWREPRInstance *)PMC_data(to_clone))->attributes); obj->name = ((KnowHOWREPRInstance *)PMC_data(to_clone))->name; return wrap_object(interp, obj); }
/* This Parrot-specific addition to the API is used to free an object. */ static void gc_free(PARROT_INTERP, PMC *obj) { NFAInstance *nfa = (NFAInstance *)PMC_data(obj); INTVAL i; for (i = 0; i < nfa->body.num_states; i++) if (nfa->body.states[i]) mem_sys_free(nfa->body.states[i]); mem_sys_free(nfa->body.num_state_edges); mem_sys_free(nfa); PMC_data(obj) = NULL; }
/* Introspects the name. */ static void name(PARROT_INTERP, PMC *nci) { PMC * unused; PMC *capture = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp)); PMC *self = VTABLE_get_pmc_keyed_int(interp, capture, 0); STRING *name = ((KnowHOWREPRInstance *)PMC_data(self))->body.name; unused = Parrot_pcc_build_call_from_c_args(interp, capture, "S", name); }
/* Creates a new type with this HOW as its meta-object. */ static void new_type(PARROT_INTERP, PMC *nci) { PMC * unused; /* We first create a new HOW instance. */ PMC *capture = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp)); PMC *self = VTABLE_get_pmc_keyed_int(interp, capture, 0); PMC *HOW = REPR(self)->allocate(interp, STABLE(self)); /* See if we have a representation name; if not default to P6opaque. */ STRING *repr_name = VTABLE_exists_keyed_str(interp, capture, repr_str) ? VTABLE_get_string_keyed_str(interp, capture, repr_str) : p6opaque_str; /* Create a new type object of the desired REPR. (Note that we can't * default to KnowHOWREPR here, since it doesn't know how to actually * store attributes, it's just for bootstrapping knowhow's. */ REPROps *repr_to_use = REPR_get_by_name(interp, repr_name); PMC *type_object = repr_to_use->type_object_for(interp, HOW); /* See if we were given a name; put it into the meta-object if so. */ STRING *name = VTABLE_exists_keyed_str(interp, capture, name_str) ? VTABLE_get_string_keyed_str(interp, capture, name_str) : empty_str; REPR(HOW)->initialize(interp, STABLE(HOW), OBJECT_BODY(HOW)); ((KnowHOWREPRInstance *)PMC_data(HOW))->body.name = name; PARROT_GC_WRITE_BARRIER(interp, HOW); /* Set .WHO to an empty hash. */ STABLE(type_object)->WHO = Parrot_pmc_new(interp, enum_class_Hash); PARROT_GC_WRITE_BARRIER(interp, STABLE_PMC(type_object)); /* Put it into capture to act as return value. */ unused = Parrot_pcc_build_call_from_c_args(interp, capture, "P", type_object); }
/* Introspects the methods. For now just hand back real method table. */ static void methods(PARROT_INTERP, PMC *nci) { PMC * unused; PMC *capture = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp)); PMC *self = VTABLE_get_pmc_keyed_int(interp, capture, 0); PMC *meths = ((KnowHOWREPRInstance *)PMC_data(self))->body.methods; unused = Parrot_pcc_build_call_from_c_args(interp, capture, "P", meths); }
/* Checks if an attribute has been initialized. */ static INTVAL is_attribute_initialized(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint) { HashAttrStoreInstance *instance = (HashAttrStoreInstance *)PMC_data(obj); if (!instance->store) Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "Cannot access attributes in a type object"); return VTABLE_exists_keyed_str(interp, instance->store, name); }
/* Binds the given value to the specified attribute. */ static void bind_attribute(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint, PMC *value) { HashAttrStoreInstance *instance = (HashAttrStoreInstance *)PMC_data(obj); if (!instance->store) Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "Cannot access attributes in a type object"); VTABLE_set_pmc_keyed_str(interp, instance->store, name, value); }
/* Gets the current value for an attribute. */ static PMC * get_attribute(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint) { P6opaqueInstance *instance = (P6opaqueInstance *)PMC_data(obj); P6opaqueREPRData *repr_data = (P6opaqueREPRData *)STABLE(obj)->REPR_data; INTVAL slot; /* Ensure it is a defined object. */ if (!instance->spill) Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "Cannot access attributes in a type object"); /* Try the slot allocation first. */ slot = try_get_slot(interp, repr_data, class_handle, name); if (slot >= 0) { PMC *result = get_pmc_at_offset(instance, repr_data->attribute_offsets[slot]); if (result) { return result; } else { /* Maybe we know how to auto-viv it to a container. */ if (repr_data->auto_viv_values) { PMC *value = repr_data->auto_viv_values[slot]; if (value != NULL) { value = REPR(value)->clone(interp, value); set_pmc_at_offset(instance, repr_data->attribute_offsets[slot], value); return value; } } return PMCNULL; } } /* Otherwise, complain that the attribute doesn't exist. */ no_such_attribute(interp, "get", class_handle, name); }
/* This Parrot-specific addition to the API is used to mark an object. */ static void gc_mark(PARROT_INTERP, PMC *obj) { UninstantiableInstance *instance = (UninstantiableInstance *)PMC_data(obj); if (!PMC_IS_NULL(instance->common.stable)) Parrot_gc_mark_PMC_alive(interp, instance->common.stable); if (!PMC_IS_NULL(instance->common.sc)) Parrot_gc_mark_PMC_alive(interp, instance->common.sc); }
/* Clones the current object. */ static PMC * repr_clone(PARROT_INTERP, PMC *to_clone) { P6opaqueInstance *obj; P6opaqueREPRData *repr_data = (P6opaqueREPRData *)STABLE(to_clone)->REPR_data; if (defined(interp, to_clone)) { obj = (P6opaqueInstance *)Parrot_gc_allocate_fixed_size_storage(interp, repr_data->allocation_size); memcpy(obj, PMC_data(to_clone), repr_data->allocation_size); if (!PMC_IS_NULL(obj->spill)) obj->spill = VTABLE_clone(interp, obj->spill); } else { obj = mem_allocate_zeroed_typed(P6opaqueInstance); memcpy(obj, PMC_data(to_clone), sizeof(P6opaqueInstance)); } return wrap_object(interp, obj); }
/* This Parrot-specific addition to the API is used to mark an object. */ static void gc_mark(PARROT_INTERP, PMC *obj) { P6strInstance *instance = (P6strInstance *)PMC_data(obj); if (!PMC_IS_NULL(instance->common.stable)) Parrot_gc_mark_PMC_alive(interp, instance->common.stable); if (!PMC_IS_NULL(instance->common.sc)) Parrot_gc_mark_PMC_alive(interp, instance->common.sc); if (!STRING_IS_NULL(instance->value)) Parrot_gc_mark_STRING_alive(interp, instance->value); }
/* This Parrot-specific addition to the API is used to free an object. */ static void gc_free(PARROT_INTERP, PMC *obj) { P6opaqueREPRData *repr_data = (P6opaqueREPRData *)STABLE(obj)->REPR_data; INTVAL i; /* Cleanup any nested reprs that need it. */ if (repr_data->gc_cleanup_slots) { for (i = 0; repr_data->gc_cleanup_slots[i] >= 0; i++) { INTVAL offset = repr_data->attribute_offsets[repr_data->gc_cleanup_slots[i]]; STable *st = repr_data->flattened_stables[repr_data->gc_cleanup_slots[i]]; st->REPR->gc_cleanup(interp, st, (char *)OBJECT_BODY(obj) + offset); } } if (repr_data->allocation_size && !PObj_flag_TEST(private0, obj)) Parrot_gc_free_fixed_size_storage(interp, repr_data->allocation_size, PMC_data(obj)); else mem_sys_free(PMC_data(obj)); PMC_data(obj) = NULL; }
/* Clone. Clone object body and the attribute storage hash. */ static PMC * repr_clone(PARROT_INTERP, PMC *to_clone) { HashAttrStoreInstance *obj; /* Allocate and set up object instance. */ obj = (HashAttrStoreInstance *) Parrot_gc_allocate_fixed_size_storage(interp, sizeof(HashAttrStoreInstance)); obj->common.stable = STABLE_PMC(to_clone); obj->store = VTABLE_clone(interp, ((HashAttrStoreInstance *)PMC_data(to_clone))->store); return wrap_object(interp, obj); }
/* This Parrot-specific addition to the API is used to mark an object. */ static void gc_mark(PARROT_INTERP, PMC *obj) { HashAttrStoreInstance *instance = (HashAttrStoreInstance *)PMC_data(obj); /* Mark STable. */ if (!PMC_IS_NULL(instance->common.stable)) Parrot_gc_mark_PMC_alive(interp, instance->common.stable); /* Mark store */ if (!PMC_IS_NULL(instance->store)) Parrot_gc_mark_PMC_alive(interp, instance->store); }
/* This Parrot-specific addition to the API is used to mark an object. */ static void gc_mark(PARROT_INTERP, PMC *obj) { KnowHOWREPRInstance *instance = (KnowHOWREPRInstance *)PMC_data(obj); if (!PMC_IS_NULL(instance->common.stable)) Parrot_gc_mark_PMC_alive(interp, instance->common.stable); if (!PMC_IS_NULL(instance->common.sc)) Parrot_gc_mark_PMC_alive(interp, instance->common.sc); if (!PMC_IS_NULL(instance->methods)) Parrot_gc_mark_PMC_alive(interp, instance->methods); if (!PMC_IS_NULL(instance->attributes)) Parrot_gc_mark_PMC_alive(interp, instance->attributes); }
/* Used with boxing. Sets a string value, for representations that can hold * one. */ static void set_str(PARROT_INTERP, PMC *obj, STRING *value) { P6opaqueInstance *instance = (P6opaqueInstance *)PMC_data(obj); P6opaqueREPRData *repr_data = (P6opaqueREPRData *)STABLE(obj)->REPR_data; if (repr_data->unbox_str_offset) { set_str_at_offset(instance, repr_data->unbox_str_offset, value); } else { Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "This type cannot box a native string"); } }
/* Gets the list of possible candidates to dispatch too. */ static PMC *get_dispatchees(PARROT_INTERP, PMC *dispatcher) { if (!smo_id) smo_id = Parrot_pmc_get_type_str(interp, Parrot_str_new(interp, "SixModelObject", 0)); if (dispatcher->vtable->base_type == enum_class_Sub && PARROT_SUB(dispatcher)->multi_signature->vtable->base_type == smo_id) { NQP_Routine *r = (NQP_Routine *)PMC_data(PARROT_SUB(dispatcher)->multi_signature); return r->dispatchees; } else { Parrot_ex_throw_from_c_args(interp, 0, 1, "Could not find multi-dispatch list"); } }
/* Composes the meta-object. */ static void compose(PARROT_INTERP, PMC *nci) { PMC * unused; PMC *capture = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp)); PMC *self = VTABLE_get_pmc_keyed_int(interp, capture, 0); PMC *obj = VTABLE_get_pmc_keyed_int(interp, capture, 1); STABLE(obj)->method_cache = ((KnowHOWREPRInstance *)PMC_data(self))->body.methods; STABLE(obj)->mode_flags = METHOD_CACHE_AUTHORITATIVE; STABLE(obj)->type_check_cache_length = 1; STABLE(obj)->type_check_cache = (PMC **)mem_sys_allocate(sizeof(PMC *)); STABLE(obj)->type_check_cache[0] = obj; unused = Parrot_pcc_build_call_from_c_args(interp, capture, "P", obj); }
/* Finds a method. */ static void find_method(PARROT_INTERP, PMC *nci) { PMC * unused; /* Get methods table out of meta-object and look up method. */ PMC *capture = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp)); PMC *self = VTABLE_get_pmc_keyed_int(interp, capture, 0); PMC *methods = ((KnowHOWREPRInstance *)PMC_data(self))->body.methods; STRING *name = VTABLE_get_string_keyed_int(interp, capture, 2); PMC *method = VTABLE_get_pmc_keyed_str(interp, methods, name); /* Put into capture to act as return value. */ unused = Parrot_pcc_build_call_from_c_args(interp, capture, "P", method); }
/* Adds an attribute meta-object to the list. */ static void add_attribute(PARROT_INTERP, PMC *nci) { PMC * unused; /* Get attributes list out of meta-object. */ PMC *capture = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp)); PMC *self = VTABLE_get_pmc_keyed_int(interp, capture, 0); PMC *attrs = ((KnowHOWREPRInstance *)PMC_data(self))->body.attributes; /* Add meta-attribute to it. */ PMC *meta_attr = VTABLE_get_pmc_keyed_int(interp, capture, 2); VTABLE_push_pmc(interp, attrs, meta_attr); unused = Parrot_pcc_build_call_from_c_args(interp, capture, "P", meta_attr); }
/* This Parrot-specific addition to the API is used to mark an object. */ static void gc_mark(PARROT_INTERP, PMC *obj) { P6opaqueInstance *instance = (P6opaqueInstance *)PMC_data(obj); /* Mark STable and SC. */ if (!PMC_IS_NULL(instance->common.stable)) Parrot_gc_mark_PMC_alive(interp, instance->common.stable); if (!PMC_IS_NULL(instance->common.sc)) Parrot_gc_mark_PMC_alive(interp, instance->common.sc); /* If there's spill storage, mark that. */ if (!PMC_IS_NULL(instance->spill)) Parrot_gc_mark_PMC_alive(interp, instance->spill); /* Mark contained PMC and string attributes, provided this is a * real object. */ if (instance->spill) { P6opaqueREPRData *repr_data = (P6opaqueREPRData *)STABLE(obj)->REPR_data; INTVAL i; /* Mark PMCs. */ if (repr_data->gc_pmc_mark_offsets) { for (i = 0; i < repr_data->num_attributes; i++) { INTVAL offset = repr_data->gc_pmc_mark_offsets[i]; if (offset) { PMC *to_mark = get_pmc_at_offset(instance, offset); if (!PMC_IS_NULL(to_mark)) Parrot_gc_mark_PMC_alive(interp, to_mark); } else { break; } } } /* Mark strings. */ if (repr_data->gc_str_mark_offsets) { for (i = 0; i < repr_data->num_attributes; i++) { INTVAL offset = repr_data->gc_str_mark_offsets[i]; if (offset) { STRING *to_mark = get_str_at_offset(instance, offset); if (to_mark) Parrot_gc_mark_STRING_alive(interp, to_mark); } else { break; } } } } }
void * get_free_pmc(struct Parrot_Interp *interpreter, struct Small_Object_Pool *pool) { PMC *pmc = get_free_object(interpreter, pool); /* clear flags, set is_PMC_FLAG */ PObj_flags_SETTO(pmc, PObj_is_PMC_FLAG); #if ! PMC_DATA_IN_EXT PMC_data((PMC *)pmc) = NULL; #endif ((PMC *)pmc)->pmc_ext = NULL; /* TODO check PMCs init method, if they clear the cache */ return pmc; }
/* Composes the meta-object. */ static void compose(PARROT_INTERP, PMC *nci) { PMC *repr_info_hash, *repr_info, *type_info, *attr_list, *attr_iter, *unused; PMC *capture = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp)); PMC *self = VTABLE_get_pmc_keyed_int(interp, capture, 0); PMC *obj = VTABLE_get_pmc_keyed_int(interp, capture, 1); UNUSED(nci); /* Do REPR composition. */ repr_info = Parrot_pmc_new(interp, enum_class_ResizablePMCArray); type_info = Parrot_pmc_new(interp, enum_class_ResizablePMCArray); VTABLE_push_pmc(interp, repr_info, type_info); VTABLE_push_pmc(interp, type_info, obj); attr_list = Parrot_pmc_new(interp, enum_class_ResizablePMCArray); attr_iter = VTABLE_get_iter(interp, ((KnowHOWREPRInstance *)PMC_data(self))->body.attributes); while (VTABLE_get_bool(interp, attr_iter)) { PMC *attr = VTABLE_shift_pmc(interp, attr_iter); PMC *attr_hash = Parrot_pmc_new(interp, enum_class_Hash);; VTABLE_set_string_keyed_str(interp, attr_hash, name_str, REPR(attr)->box_funcs->get_str(interp, STABLE(attr), OBJECT_BODY(attr))); VTABLE_push_pmc(interp, attr_list, attr_hash); } VTABLE_push_pmc(interp, type_info, attr_list); VTABLE_push_pmc(interp, type_info, Parrot_pmc_new(interp, enum_class_ResizablePMCArray)); repr_info_hash = Parrot_pmc_new(interp, enum_class_Hash); VTABLE_set_pmc_keyed_str(interp, repr_info_hash, attribute_str, repr_info); REPR(obj)->compose(interp, STABLE(obj), repr_info_hash); /* Set up method and type caches. */ STABLE(obj)->method_cache = ((KnowHOWREPRInstance *)PMC_data(self))->body.methods; STABLE(obj)->mode_flags = METHOD_CACHE_AUTHORITATIVE; STABLE(obj)->type_check_cache_length = 1; STABLE(obj)->type_check_cache = (PMC **)mem_sys_allocate(sizeof(PMC *)); STABLE(obj)->type_check_cache[0] = obj; unused = Parrot_pcc_build_call_from_c_args(interp, capture, "P", obj); }
/* Adds a method. */ static void add_method(PARROT_INTERP, PMC *nci) { PMC * unused; /* Get methods table out of meta-object. */ PMC *capture = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp)); PMC *self = VTABLE_get_pmc_keyed_int(interp, capture, 0); PMC *methods = ((KnowHOWREPRInstance *)PMC_data(self))->body.methods; /* Get name and method to add. */ STRING *name = VTABLE_get_string_keyed_int(interp, capture, 2); PMC *method = VTABLE_get_pmc_keyed_int(interp, capture, 3); /* Add it, and return added method as result. */ VTABLE_set_pmc_keyed_str(interp, methods, name, method); unused = Parrot_pcc_build_call_from_c_args(interp, capture, "P", method); }
/* Used with boxing. Gets a string value, for representations that can hold * one. */ static STRING * get_str(PARROT_INTERP, PMC *obj) { P6opaqueInstance *instance = (P6opaqueInstance *)PMC_data(obj); P6opaqueREPRData *repr_data = (P6opaqueREPRData *)STABLE(obj)->REPR_data; if (repr_data->unbox_str_offset) { if (!instance->spill) { Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "Cannot unbox type object to a native string"); } return get_str_at_offset(instance, repr_data->unbox_str_offset); } else { Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "This type cannot unbox to a native string"); } }
/* Checks if an attribute has been initialized. */ static INTVAL is_attribute_initialized(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint) { P6opaqueInstance *instance = (P6opaqueInstance *)PMC_data(obj); P6opaqueREPRData *repr_data = (P6opaqueREPRData *)STABLE(obj)->REPR_data; INTVAL slot; if (!instance->spill) Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "Cannot access attributes in a type object"); slot = try_get_slot(interp, repr_data, class_handle, name); if (slot >= 0) return NULL != get_pmc_at_offset(instance, repr_data->attribute_offsets[slot]); else no_such_attribute(interp, "initializedness check", class_handle, name); }
PARROT_WARN_UNUSED_RESULT PARROT_CANNOT_RETURN_NULL static STRING* trace_class_name(PARROT_INTERP, ARGIN(const PMC* pmc)) { ASSERT_ARGS(trace_class_name) STRING *class_name; if (PObj_is_class_TEST(pmc)) { SLOTTYPE * const class_array = (SLOTTYPE *)PMC_data(pmc); PMC * const class_name_pmc = get_attrib_num(class_array, PCD_CLASS_NAME); class_name = VTABLE_get_string(interp, class_name_pmc); } else class_name = pmc->vtable->whoami; return class_name; }
static FLOATVAL get_attribute_num(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint) { P6opaqueInstance *instance = (P6opaqueInstance *)PMC_data(obj); P6opaqueREPRData *repr_data = (P6opaqueREPRData *)STABLE(obj)->REPR_data; INTVAL slot; /* Ensure it is a defined object. */ if (!instance->spill) Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "Cannot access attributes in a type object"); /* Try the slot allocation first. */ slot = try_get_slot(interp, repr_data, class_handle, name); if (slot >= 0) return get_num_at_offset(instance, repr_data->attribute_offsets[slot]); /* Otherwise, complain that the attribute doesn't exist. */ no_such_attribute(interp, "get", class_handle, name); }
static STRING * Rakudo_binding_arity_fail(PARROT_INTERP, PMC *params, INTVAL num_params, INTVAL num_pos_args, INTVAL too_many) { STRING *result; INTVAL arity = 0; INTVAL count = 0; INTVAL i; const char *whoz_up = too_many ? "Too many" : "Not enough"; /* Work out how many we could have been passed. */ for (i = 0; i < num_params; i++) { Rakudo_Parameter *param = (Rakudo_Parameter *)PMC_data( VTABLE_get_pmc_keyed_int(interp, params, i)); if (!PMC_IS_NULL(param->named_names)) continue; if (param->flags & SIG_ELEM_SLURPY_NAMED) continue; if (param->flags & SIG_ELEM_SLURPY_POS) { count = -1; } else if (param->flags & SIG_ELEM_IS_OPTIONAL) { count++; } else { count++; arity++; } } /* Now generate decent error. */ if (arity == count) result = Parrot_sprintf_c(interp, "%s positional parameters passed; got %d but expected %d", whoz_up, num_pos_args, arity); else if (count == -1) result = Parrot_sprintf_c(interp, "%s positional parameters passed; got %d but expected at least %d", whoz_up, num_pos_args, arity); else result = Parrot_sprintf_c(interp, "%s positional parameters passed; got %d but expected between %d and %d", whoz_up, num_pos_args, arity, count); return result; }