Index: src/pmc/class.pmc =================================================================== --- src/pmc/class.pmc (版本 43124) +++ src/pmc/class.pmc (工作副本) @@ -99,21 +99,25 @@ PMC *cache, int cur_index) { /* The attribute metadata hash. */ - Parrot_Class_attributes * const class_info = PARROT_CLASS(cur_class); - PMC * const attribs = class_info->attrib_metadata; - PMC * const iter = VTABLE_get_iter(interp, attribs); + PMC *attrib_metadata, *iter; + /* Build a string representing the fully qualified class name. */ /* Retrieve the fully qualified class name for the class. */ - STRING * const fq_class = VTABLE_get_string(interp, cur_class); - PMC * const class_cache = pmc_new(interp, enum_class_Hash); + PMC * const class_cache = pmc_new(interp, enum_class_Hash); + STRING * const fq_class = VTABLE_get_string(interp, cur_class); + VTABLE_set_pmc_keyed_str(interp, cache, fq_class, class_cache); + GETATTR_Class_attrib_metadata(interp, cur_class, attrib_metadata); + + iter = VTABLE_get_iter(interp, attrib_metadata); + /* Iterate over the attributes. */ while (VTABLE_get_bool(interp, iter)) { /* Get attribute. */ PMC * const cur_attrib = VTABLE_get_pmc_keyed_str(interp, - attribs, VTABLE_shift_string(interp, iter)); + attrib_metadata, VTABLE_shift_string(interp, iter)); /* Get attribute name and append it to the key. */ STRING * const name_str = CONST_STRING(interp, "name"); @@ -134,22 +138,24 @@ /* This function builds the attribute index (table to map class name and * attribute name to an index) for the current class. */ static void -build_attrib_index(PARROT_INTERP, PMC *self) +build_attrib_index(PARROT_INTERP, PMC *SELF) { - Parrot_Class_attributes * const _class = PARROT_CLASS(self); - int cur_index = 0; - PMC * const attrib_index = pmc_new(interp, enum_class_Hash); - PMC * const cache = pmc_new(interp, enum_class_Hash); - const int num_classes = VTABLE_elements(interp, _class->all_parents); - int i; + int i, num_classes, cur_index = 0; + PMC *all_parents; + PMC * const attrib_index = pmc_new(interp, enum_class_Hash); + PMC * const cache = pmc_new(interp, enum_class_Hash); + + GETATTR_Class_all_parents(interp, SELF, all_parents); + num_classes =VTABLE_elements(interp, all_parents); + /* Go over the list of all parents to construct the attribute index. */ for (i = 0; i < num_classes; i++) { /* Get the class and check that it respects the standard class interface * (if not we don't know how it stores its attributes, so we'll have to * delegate the lookup). */ PMC * const cur_class = VTABLE_get_pmc_keyed_int(interp, - _class->all_parents, i); + all_parents, i); if (PObj_is_class_TEST(cur_class)) cur_index = cache_class_attribs(interp, cur_class, @@ -157,36 +163,36 @@ } /* Store built attribute index and invalidate cache. */ - _class->attrib_index = attrib_index; - _class->attrib_cache = cache; + SETATTR_Class_attrib_index(interp, SELF, attrib_index); + SETATTR_Class_attrib_cache(interp, SELF, cache); } + /* Takes a hash and initializes the class based on it. */ static void -init_class_from_hash(PARROT_INTERP, PMC *self, PMC *info) +init_class_from_hash(PARROT_INTERP, PMC *SELF, PMC *info) { - Parrot_Class_attributes * const _class = PARROT_CLASS(self); STRING * const name_str = CONST_STRING(interp, "name"); STRING * const parents_str = CONST_STRING(interp, "parents"); STRING * const methods_str = CONST_STRING(interp, "methods"); STRING * const roles_str = CONST_STRING(interp, "roles"); STRING * const attrs_str = CONST_STRING(interp, "attributes"); - PMC *old_ns; - STRING *resolve_method_str; + STRING *resolve_method_str; + PMC *old_namespace, *new_namespace; /* Ensure we actually have some initialization info. */ if (PMC_IS_NULL(info)) return; /* Take a copy of the current namespace the class is attached to. */ - old_ns = _class->_namespace; + GETATTR_Class__namespace(interp, SELF, old_namespace); /* Check if we have a name/namespace. */ if (VTABLE_exists_keyed_str(interp, info, name_str)) { + INTVAL type_num; STRING *new_name; - PMC *new_namespace; + VTABLE *new_vtable; + PMC *all_parents; PMC *name_arg = VTABLE_get_pmc_keyed_str(interp, info, name_str); - VTABLE *new_vtable; - INTVAL type_num; /* If we were passed a namespace PMC, set the namespace attribute * directly. Otherwise, lookup or create the appropriate namespace. */ @@ -213,61 +219,70 @@ Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "Failed to set name for class."); - _class->_namespace = new_namespace; - _class->name = new_name; + /* Set new name/namespace to SELF */ + SETATTR_Class_name(interp, SELF, new_name); + SETATTR_Class__namespace(interp, SELF, new_namespace); /* At this point we know the class isn't anonymous */ - CLASS_is_anon_CLEAR(self); + CLASS_is_anon_CLEAR(SELF); /* Register a type number for the class. */ type_num = Parrot_oo_register_type(interp, name_arg, new_namespace); + SETATTR_Class_id(interp, SELF, type_num); + + GETATTR_Class_all_parents(interp, SELF, all_parents); + /* Link the type number with the class's vtable. */ - new_vtable = Parrot_clone_vtable(interp, self->vtable); + new_vtable = Parrot_clone_vtable(interp, SELF->vtable); + new_vtable->pmc_class = SELF; new_vtable->base_type = type_num; - new_vtable->pmc_class = self; - new_vtable->whoami = VTABLE_get_string(interp, self); - new_vtable->mro = _class->all_parents; + new_vtable->mro = all_parents; + new_vtable->whoami = VTABLE_get_string(interp, SELF); new_vtable->ro_variant_vtable = - Parrot_clone_vtable(interp, self->vtable->ro_variant_vtable); + Parrot_clone_vtable(interp, SELF->vtable->ro_variant_vtable); /* Store the class's vtable in the global table */ interp->vtables[type_num] = new_vtable; - - _class->id = type_num; + } else { + /* no new namespace, so use the old one */ + new_namespace = old_namespace; } /* If we were attached to a namespace and are now attached to a new one, * need to unset ourselves in the old namespace. */ - if (!PMC_IS_NULL(old_ns) && _class->_namespace != old_ns) - Parrot_pcc_invoke_method_from_c_args(interp, old_ns, CONST_STRING(interp, "set_class"), "P->", PMCNULL); + if (!PMC_IS_NULL(old_namespace) && new_namespace != old_namespace) { + STRING * const set_class_str = CONST_STRING(interp, "set_class"); + Parrot_pcc_invoke_method_from_c_args(interp, + old_namespace, set_class_str, "P->", PMCNULL); + } /* Link namespace to this class, if there is one. */ - if (!PMC_IS_NULL(_class->_namespace)) { + if (!PMC_IS_NULL(new_namespace)) { STRING * const set_class_str = CONST_STRING(interp, "set_class"); - Parrot_pcc_invoke_method_from_c_args(interp, _class->_namespace, set_class_str, "P->", - self); + Parrot_pcc_invoke_method_from_c_args(interp, + new_namespace, set_class_str, "P->", SELF); } /* Initialize resolve_method. */ resolve_method_str = CONST_STRING(interp, "resolve_method"); if (VTABLE_exists_keyed_str(interp, info, resolve_method_str)) { /* Set it. */ - _class->resolve_method = - VTABLE_get_pmc_keyed_str(interp, info, resolve_method_str); + SETATTR_Class_resolve_method(interp, SELF, + VTABLE_get_pmc_keyed_str(interp, info, resolve_method_str)); } /* Initialize parents, if we have any. */ if (VTABLE_exists_keyed_str(interp, info, parents_str)) { /* Loop over parents array and add them. */ PMC * const parent_list = VTABLE_get_pmc_keyed_str(interp, info, - parents_str); + parents_str); const int parent_count = VTABLE_elements(interp, parent_list); int i; for (i = 0; i < parent_count; i++) - VTABLE_add_parent(interp, self, + VTABLE_add_parent(interp, SELF, VTABLE_get_pmc_keyed_int(interp, parent_list, i)); } @@ -280,7 +295,7 @@ int i; for (i = 0; i < role_count; i++) - VTABLE_add_role(interp, self, + VTABLE_add_role(interp, SELF, VTABLE_get_pmc_keyed_int(interp, role_list, i)); } @@ -288,14 +303,14 @@ if (VTABLE_exists_keyed_str(interp, info, attrs_str)) { /* Loop over attributes array and add them. */ PMC * const attrs_name_list = VTABLE_get_pmc_keyed_str(interp, info, - attrs_str); + attrs_str); const int attrib_count = VTABLE_elements(interp, attrs_name_list); int i; for (i = 0; i < attrib_count; i++) { STRING * const attr_name = VTABLE_get_string_keyed_int(interp, attrs_name_list, i); - VTABLE_add_attribute(interp, self, attr_name, PMCNULL); + VTABLE_add_attribute(interp, SELF, attr_name, PMCNULL); } } @@ -303,7 +318,7 @@ if (VTABLE_exists_keyed_str(interp, info, methods_str)) { /* Get the methods hash. */ PMC * const methods = VTABLE_get_pmc_keyed_str(interp, info, - methods_str); + methods_str); /* Iterate over the list of methods. */ PMC * const iter = VTABLE_get_iter(interp, methods); @@ -312,13 +327,13 @@ /* Add the method. */ STRING * const method_name = VTABLE_shift_string(interp, iter); PMC * const method_pmc = VTABLE_get_pmc_keyed_str(interp, - methods, method_name); - VTABLE_add_method(interp, self, method_name, method_pmc); + methods, method_name); + VTABLE_add_method(interp, SELF, method_name, method_pmc); } } /* Extract any methods from the namespace */ - Parrot_oo_extract_methods_from_namespace(interp, self, _class->_namespace); + Parrot_oo_extract_methods_from_namespace(interp, SELF, new_namespace); } static void @@ -331,12 +346,12 @@ for (; parent_index >= 0; parent_index--) { PMC *meth; PMC * const parent = VTABLE_get_pmc_keyed_int(interp, - all_parents, parent_index); + all_parents, parent_index); /* PMCProxy parents store an instance to delegate to */ if (parent->vtable->base_type == enum_class_PMCProxy) { - PMC *proxy = VTABLE_instantiate(interp, parent, PMCNULL); - STRING *proxy_str = CONST_STRING(interp, "proxy"); + PMC * const proxy = VTABLE_instantiate(interp, parent, PMCNULL); + STRING * const proxy_str = CONST_STRING(interp, "proxy"); VTABLE_set_attr_keyed(interp, object, parent, proxy_str, proxy); } @@ -391,14 +406,19 @@ static STRING * make_class_name(PARROT_INTERP, PMC *SELF) { - Parrot_Class_attributes * const _class = PARROT_CLASS(SELF); - PMC * const _namespace = _class->_namespace; + PMC *_namespace; + STRING *name; + GETATTR_Class__namespace(interp, SELF, _namespace); + if (!PMC_IS_NULL(_namespace)) { - if (_class->fullname) - return _class->fullname; + STRING *fullname; + + GETATTR_Class_fullname(interp, SELF, fullname); + + if (fullname) + return fullname; else { - /* Call the 'get_name' method on the class's associated * namespace to retrieve a fully qualified list of names, then * join the list with a semicolon. */ @@ -407,13 +427,18 @@ if (!PMC_IS_NULL(names)) /* remove the HLL namespace name */ VTABLE_shift_string(interp, names); - _class->fullname = Parrot_str_join(interp, CONST_STRING(interp, ";"), names); - return _class->fullname; + + fullname = Parrot_str_join(interp, CONST_STRING(interp, ";"), names); + + SETATTR_Class_fullname(interp, SELF, fullname); + + return fullname; } } + /* Otherwise, copy the stored string name of the class. */ + GETATTR_Class_name(interp, SELF, name); - /* Otherwise, copy the stored string name of the class. */ - return _class->name; + return name; } /* calculates the C3 method resolution order for this class. C3 is the @@ -424,26 +449,31 @@ static void calculate_mro(PARROT_INTERP, PMC *SELF, INTVAL num_parents) { - Parrot_Class_attributes * const _class = PARROT_CLASS(SELF); + PMC *mro; /* SELF is already on the all_parents */ if (num_parents == 0) return; if (num_parents == 1) { - STRING * const ap = CONST_STRING(interp, "all_parents"); - PMC * const parent = VTABLE_get_pmc_keyed_int(interp, - _class->parents, 0); - PMC * const parent_mro = VTABLE_inspect_str(interp, parent, ap); - PMC * const mro = VTABLE_clone(interp, parent_mro); + PMC *parent, *parents; + STRING * const ap = CONST_STRING(interp, "all_parents"); + + GETATTR_Class_parents(interp, SELF, parents); + + parent = VTABLE_get_pmc_keyed_int(interp, parents, 0); + mro = VTABLE_clone(interp, + VTABLE_inspect_str(interp, parent, ap)); VTABLE_unshift_pmc(interp, mro, SELF); - _class->all_parents = mro; + SETATTR_Class_all_parents(interp, SELF, mro);; } - else - _class->all_parents = Parrot_ComputeMRO_C3(interp, SELF); + else { + mro = Parrot_ComputeMRO_C3(interp, SELF); + SETATTR_Class_all_parents(interp, SELF, mro); + } if (!CLASS_is_anon_TEST(SELF)) - interp->vtables[VTABLE_type(interp, SELF)]->mro = _class->all_parents; + interp->vtables[VTABLE_type(interp, SELF)]->mro = mro; } /* @@ -459,25 +489,24 @@ */ pmclass Class auto_attrs { + ATTR INTVAL id; /* The type number of the PMC. */ + ATTR INTVAL instantiated; /* Any instantiations since last modification? */ + ATTR STRING *name; /* The name of the class. */ + ATTR STRING *fullname; /* The name of the class. */ + ATTR PMC *_namespace; /* The namespace it's linked to, if any. */ + ATTR PMC *parents; /* Immediate parent classes. */ + ATTR PMC *all_parents; /* Cached list of ourself and all parents, in MRO order. */ + ATTR PMC *roles; /* An array of roles. */ + ATTR PMC *methods; /* Hash of method names to methods in this class. */ + ATTR PMC *vtable_overrides; /* Hash of Parrot v-table methods we override. */ + ATTR PMC *attrib_metadata; /* Hash of attributes in this class to hashes of metadata. */ + ATTR PMC *attrib_index; /* Lookup table for attributes in this and parents. */ + ATTR PMC *attrib_cache; /* Cache of visible attrib names to indexes. */ + ATTR PMC *resolve_method; /* List of method names the class provides to resolve + * conflicts with methods from roles. */ + ATTR PMC *parent_overrides; + ATTR PMC *meth_cache; - ATTR INTVAL id; /* The type number of the PMC. */ - ATTR STRING *name; /* The name of the class. */ - ATTR STRING *fullname; /* The name of the class. */ - ATTR PMC *_namespace; /* The namespace it's linked to, if any. */ - ATTR INTVAL instantiated; /* Any instantiations since last modification? */ - ATTR PMC *parents; /* Immediate parent classes. */ - ATTR PMC *all_parents; /* Cached list of ourself and all parents, in MRO order. */ - ATTR PMC *roles; /* An array of roles. */ - ATTR PMC *methods; /* Hash of method names to methods in this class. */ - ATTR PMC *vtable_overrides; /* Hash of Parrot v-table methods we override. */ - ATTR PMC *attrib_metadata; /* Hash of attributes in this class to hashes of metadata. */ - ATTR PMC *attrib_index; /* Lookup table for attributes in this and parents. */ - ATTR PMC *attrib_cache; /* Cache of visible attrib names to indexes. */ - ATTR PMC *resolve_method; /* List of method names the class provides to resolve - * conflicts with methods from roles. */ - ATTR PMC *parent_overrides; - ATTR PMC *meth_cache; - /* =item C @@ -495,30 +524,33 @@ */ VTABLE void init() { - Parrot_Class_attributes * const _class = - (Parrot_Class_attributes *) PMC_data(SELF); + PMC * const all_parents = pmc_new(INTERP, enum_class_ResizablePMCArray); /* Set flag for custom GC mark. */ PObj_custom_mark_SET(SELF); /* Set up the object. */ - _class->name = CONST_STRING(interp, ""); - _class->_namespace = PMCNULL; - _class->parents = pmc_new(interp, enum_class_ResizablePMCArray); - _class->all_parents = pmc_new(interp, enum_class_ResizablePMCArray); - _class->roles = pmc_new(interp, enum_class_ResizablePMCArray); - _class->methods = pmc_new(interp, enum_class_Hash); - _class->attrib_metadata = pmc_new(interp, enum_class_Hash); - _class->attrib_index = PMCNULL; - _class->attrib_cache = PMCNULL; - _class->meth_cache = PMCNULL; - _class->resolve_method = pmc_new(interp, enum_class_ResizablePMCArray); + SET_ATTR_name(INTERP, SELF, CONST_STRING(INTERP, "")); + SET_ATTR__namespace(INTERP, SELF, PMCNULL); - _class->vtable_overrides = pmc_new(interp, enum_class_Hash); - _class->parent_overrides = pmc_new(interp, enum_class_Hash); + SET_ATTR_parents(INTERP, SELF, pmc_new(INTERP, enum_class_ResizablePMCArray)); + SET_ATTR_all_parents(INTERP, SELF, all_parents); + SET_ATTR_roles(INTERP, SELF, pmc_new(INTERP, enum_class_ResizablePMCArray)); + SET_ATTR_methods(INTERP, SELF, pmc_new(INTERP, enum_class_Hash)); + + SET_ATTR_attrib_metadata(INTERP, SELF, pmc_new(INTERP, enum_class_Hash)); + SET_ATTR_attrib_index(INTERP, SELF, PMCNULL); + SET_ATTR_attrib_cache(INTERP, SELF, PMCNULL); + + SET_ATTR_meth_cache(INTERP, SELF, PMCNULL); + SET_ATTR_resolve_method(INTERP, SELF, pmc_new(INTERP, enum_class_ResizablePMCArray)); + + SET_ATTR_vtable_overrides(INTERP, SELF, pmc_new(INTERP, enum_class_Hash)); + SET_ATTR_parent_overrides(INTERP, SELF, pmc_new(INTERP, enum_class_Hash)); + /* We put ourself on the all parents list. */ - VTABLE_push_pmc(interp, _class->all_parents, SELF); + VTABLE_push_pmc(INTERP, all_parents, SELF); /* We are a class. */ PObj_is_class_SET(SELF); @@ -529,11 +561,11 @@ VTABLE void init_pmc(PMC *init_data) { PMC *arg; - const INTVAL arg_type = VTABLE_type(interp, init_data); - STRING * const name_str = CONST_STRING(interp, "name"); + const INTVAL arg_type = VTABLE_type(INTERP, init_data); + STRING * const name_str = CONST_STRING(INTERP, "name"); /* Set up the object. */ - SELF.init(); + STATICSELF.init(); /* fast attempt to determine init_data type */ switch (arg_type) { @@ -542,8 +574,8 @@ case enum_class_ResizableStringArray: case enum_class_NameSpace: /* set only the name property */ - arg = pmc_new(interp, enum_class_Hash); - VTABLE_set_pmc_keyed_str(interp, arg, name_str, init_data); + arg = pmc_new(INTERP, enum_class_Hash); + VTABLE_set_pmc_keyed_str(INTERP, arg, name_str, init_data); break; case enum_class_Hash: @@ -552,15 +584,15 @@ /* slow attempt to determine init_data type */ default: - if (VTABLE_isa(interp, init_data, CONST_STRING(interp, "String")) - || VTABLE_isa(interp, init_data, CONST_STRING(interp, "Key")) - || VTABLE_isa(interp, init_data, CONST_STRING(interp, "ResizableStringArray"))) { + if (VTABLE_isa(INTERP, init_data, CONST_STRING(INTERP, "String")) + || VTABLE_isa(INTERP, init_data, CONST_STRING(INTERP, "Key")) + || VTABLE_isa(INTERP, init_data, CONST_STRING(INTERP, "ResizableStringArray"))) { /* set only the name property */ - arg = pmc_new(interp, enum_class_Hash); - VTABLE_set_pmc_keyed_str(interp, arg, name_str, init_data); + arg = pmc_new(INTERP, enum_class_Hash); + VTABLE_set_pmc_keyed_str(INTERP, arg, name_str, init_data); } - if (VTABLE_isa(interp, init_data, CONST_STRING(interp, "Hash"))) + if (VTABLE_isa(INTERP, init_data, CONST_STRING(INTERP, "Hash"))) arg = init_data; else Parrot_ex_throw_from_c_args(INTERP, NULL, @@ -570,7 +602,7 @@ } /* Initialize the class with the supplied data. */ - init_class_from_hash(interp, SELF, arg); + init_class_from_hash(INTERP, SELF, arg); } /* @@ -584,7 +616,7 @@ */ VTABLE STRING *get_string() { - return Parrot_str_copy(interp, make_class_name(interp, SELF)); + return Parrot_str_copy(INTERP, make_class_name(INTERP, SELF)); } /* @@ -598,21 +630,53 @@ */ VTABLE void mark() { - Parrot_Class_attributes * const _class = PARROT_CLASS(SELF); - Parrot_gc_mark_STRING_alive(interp, _class->name); - Parrot_gc_mark_STRING_alive(interp, _class->fullname); - Parrot_gc_mark_PMC_alive(interp, _class->_namespace); - Parrot_gc_mark_PMC_alive(interp, _class->parents); - Parrot_gc_mark_PMC_alive(interp, _class->all_parents); - Parrot_gc_mark_PMC_alive(interp, _class->roles); - Parrot_gc_mark_PMC_alive(interp, _class->methods); - Parrot_gc_mark_PMC_alive(interp, _class->vtable_overrides); - Parrot_gc_mark_PMC_alive(interp, _class->parent_overrides); - Parrot_gc_mark_PMC_alive(interp, _class->attrib_metadata); - Parrot_gc_mark_PMC_alive(interp, _class->attrib_index); - Parrot_gc_mark_PMC_alive(interp, _class->attrib_cache); - Parrot_gc_mark_PMC_alive(interp, _class->resolve_method); - Parrot_gc_mark_PMC_alive(interp, _class->meth_cache); + STRING *tmp_name; + PMC *tmp; + + if (!PMC_data(SELF)) + return; + + GET_ATTR_name(INTERP, SELF, tmp_name); + Parrot_gc_mark_STRING_alive(INTERP, tmp_name); + + GET_ATTR_fullname(INTERP, SELF, tmp_name); + Parrot_gc_mark_STRING_alive(INTERP, tmp_name); + + GET_ATTR__namespace(INTERP, SELF, tmp); + Parrot_gc_mark_PMC_alive(INTERP, tmp); + + GET_ATTR_parents(INTERP, SELF, tmp); + Parrot_gc_mark_PMC_alive(INTERP, tmp); + + GET_ATTR_all_parents(INTERP, SELF, tmp); + Parrot_gc_mark_PMC_alive(INTERP, tmp); + + GET_ATTR_roles(INTERP, SELF, tmp); + Parrot_gc_mark_PMC_alive(INTERP, tmp); + + GET_ATTR_methods(INTERP, SELF, tmp); + Parrot_gc_mark_PMC_alive(INTERP, tmp); + + GET_ATTR_vtable_overrides(INTERP, SELF, tmp); + Parrot_gc_mark_PMC_alive(INTERP, tmp); + + GET_ATTR_parent_overrides(INTERP, SELF, tmp); + Parrot_gc_mark_PMC_alive(INTERP, tmp); + + GET_ATTR_attrib_metadata(INTERP, SELF, tmp); + Parrot_gc_mark_PMC_alive(INTERP, tmp); + + GET_ATTR_attrib_index(INTERP, SELF, tmp); + Parrot_gc_mark_PMC_alive(INTERP, tmp); + + GET_ATTR_attrib_cache(INTERP, SELF, tmp); + Parrot_gc_mark_PMC_alive(INTERP, tmp); + + GET_ATTR_resolve_method(INTERP, SELF, tmp); + Parrot_gc_mark_PMC_alive(INTERP, tmp); + + GET_ATTR_meth_cache(INTERP, SELF, tmp); + Parrot_gc_mark_PMC_alive(INTERP, tmp); } @@ -630,29 +694,33 @@ */ VTABLE void add_attribute(STRING *name, PMC *type) { - Parrot_Class_attributes * const _class = PARROT_CLASS(SELF); - PMC * const new_attribute = pmc_new(interp, enum_class_Hash); + INTVAL instantiated; + PMC *attrib_metadata; + PMC * const new_attribute = pmc_new(INTERP, enum_class_Hash); + GET_ATTR_instantiated(INTERP, SELF, instantiated); + /* If we've been instantiated already, not allowed. */ - if (_class->instantiated) - Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, + if (instantiated) + Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, "Modifications to classes are not allowed after instantiation."); + GET_ATTR_attrib_metadata(INTERP, SELF, attrib_metadata); + /* If we already have an attribute of this name, it's an error. */ - if (VTABLE_exists_keyed_str(interp, _class->attrib_metadata, name)) - Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, + if (VTABLE_exists_keyed_str(INTERP, attrib_metadata, name)) + Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, "Attribute '%Ss' already exists in '%Ss'.", name, VTABLE_get_string(INTERP, SELF)); /* Set name and type. */ - VTABLE_set_string_keyed_str(interp, new_attribute, CONST_STRING(interp, "name"), name); + VTABLE_set_string_keyed_str(INTERP, new_attribute, CONST_STRING(INTERP, "name"), name); if (!PMC_IS_NULL(type)) - VTABLE_set_pmc_keyed_str(interp, new_attribute, CONST_STRING(interp, "type"), type); + VTABLE_set_pmc_keyed_str(INTERP, new_attribute, CONST_STRING(INTERP, "type"), type); /* Enter the attribute in the attrib_metadata table. */ - VTABLE_set_pmc_keyed_str(interp, _class->attrib_metadata, name, - new_attribute); + VTABLE_set_pmc_keyed_str(INTERP, attrib_metadata, name, new_attribute); } /* @@ -668,23 +736,28 @@ */ VTABLE void remove_attribute(STRING *name) { - Parrot_Class_attributes * const _class = PARROT_CLASS(SELF); + INTVAL instantiated; + PMC *attrib_metadata; + GET_ATTR_instantiated(INTERP, SELF, instantiated); + /* If we've been instantiated already, not allowed. */ - if (_class->instantiated) - Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, + if (instantiated) + Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, "Modifications to classes are not allowed after instantiation."); + GET_ATTR_attrib_metadata(INTERP, SELF, attrib_metadata); + /* If we don't have an attribute of this name, it's an error. */ - if (!VTABLE_exists_keyed_str(interp, _class->attrib_metadata, name)) - Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, + if (!VTABLE_exists_keyed_str(INTERP, attrib_metadata, name)) + Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, "Attribute '%Ss' cannot be removed, does not exist in '%Ss'.", name, VTABLE_get_string(INTERP, SELF)); /* Remove the attribute from the attrib_metadata table. */ - VTABLE_delete_keyed_str(interp, _class->attrib_metadata, name); + VTABLE_delete_keyed_str(INTERP, attrib_metadata, name); - build_attrib_index(interp, SELF); + build_attrib_index(INTERP, SELF); } /* @@ -697,23 +770,25 @@ */ VTABLE void add_method(STRING *name, PMC *sub) { - Parrot_Class_attributes * const _class = PARROT_CLASS(SELF); - PMC * const method = - VTABLE_get_pmc_keyed_str(interp, _class->methods, name); + PMC *methods, *method; + GET_ATTR_methods(INTERP, SELF, methods); + + method = VTABLE_get_pmc_keyed_str(INTERP, methods, name); + /* If we have already added a method with this name... */ if (!PMC_IS_NULL(method)) { if (method == sub) return; - Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, + Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, "A method named '%S' already exists in class '%S'. " "It may have been supplied by a role.", - name, VTABLE_get_string(interp, SELF)); + name, VTABLE_get_string(INTERP, SELF)); } /* Enter it into the table. */ - VTABLE_set_pmc_keyed_str(interp, _class->methods, name, sub); + VTABLE_set_pmc_keyed_str(INTERP, methods, name, sub); } /* @@ -726,13 +801,16 @@ */ VTABLE void remove_method(STRING *name) { - Parrot_Class_attributes * const _class = PARROT_CLASS(SELF); - if (VTABLE_exists_keyed_str(interp, _class->methods, name)) - VTABLE_delete_keyed_str(interp, _class->methods, name); + PMC *methods; + + GET_ATTR_methods(INTERP, SELF, methods); + + if (VTABLE_exists_keyed_str(INTERP, methods, name)) + VTABLE_delete_keyed_str(INTERP, methods, name); else - Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, + Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, "No method named '%S' to remove in class '%S'.", - name, VTABLE_get_string(interp, SELF)); + name, VTABLE_get_string(INTERP, SELF)); } /* @@ -745,30 +823,32 @@ */ VTABLE void add_vtable_override(STRING *name, PMC *sub) { - Parrot_Class_attributes * const _class = PARROT_CLASS(SELF); - PMC * const vtable = - VTABLE_get_pmc_keyed_str(interp, _class->vtable_overrides, name); + PMC *vtable_overrides, *vtable; + GET_ATTR_vtable_overrides(INTERP, SELF, vtable_overrides); + + vtable = VTABLE_get_pmc_keyed_str(INTERP, vtable_overrides, name); + /* If we have already added a vtable override with this name... */ if (!PMC_IS_NULL(vtable)) { if (vtable == sub) return; - Parrot_ex_throw_from_c_args(interp, NULL, + Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, "A vtable override named '%S' already exists in class '%S'. " "It may have been supplied by a role.", - name, VTABLE_get_string(interp, SELF)); + name, VTABLE_get_string(INTERP, SELF)); } /* Check that the name is actually valid as a vtable override */ - if (Parrot_get_vtable_index(interp, name) == -1) - Parrot_ex_throw_from_c_args(interp, NULL, + if (Parrot_get_vtable_index(INTERP, name) == -1) + Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_METHOD_NOT_FOUND, "'%S' is not a valid vtable function name.", name); /* Add it to vtable methods list. */ - VTABLE_set_pmc_keyed_str(interp, _class->vtable_overrides, name, sub); + VTABLE_set_pmc_keyed_str(INTERP, vtable_overrides, name, sub); } /* @@ -781,64 +861,71 @@ */ VTABLE void add_parent(PMC *parent) { - Parrot_Class_attributes * const _class = PARROT_CLASS(SELF); - int parent_count, index; + int parent_count, index; + INTVAL instantiated; + PMC *parents, *all_parents; + GET_ATTR_instantiated(INTERP, SELF, instantiated); + /* If we've been instantiated already, not allowed. */ - if (_class->instantiated) - Parrot_ex_throw_from_c_args(interp, NULL, + if (instantiated) + Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, "Modifications to classes are not allowed after instantiation."); /* Ensure it really is a class. */ if (!PObj_is_class_TEST(parent)) - Parrot_ex_throw_from_c_args(interp, NULL, + Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, "Parent isn't a Class."); /* Check is not self */ if (parent == SELF) - Parrot_ex_throw_from_c_args(interp, NULL, + Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, "Can't be own parent"); + GET_ATTR_parents(INTERP, SELF, parents); + /* get number of direct parents */ - parent_count = VTABLE_elements(interp, _class->parents); + parent_count = VTABLE_elements(INTERP, parents); /* iterate over all direct parents, check whether this class already has * the parent being added. */ for (index = 0; index < parent_count; index++) { /* get the next parent */ - PMC * const current_parent = VTABLE_get_pmc_keyed_int(interp, - _class->parents, index); + PMC * const current_parent = VTABLE_get_pmc_keyed_int(INTERP, + parents, index); /* throw an exception if we already have this parent */ if (current_parent == parent) - Parrot_ex_throw_from_c_args(interp, NULL, + Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, "The class '%S' already has a parent class '%S'. " "It may have been supplied by a role.", - VTABLE_get_string(interp, SELF), - VTABLE_get_string(interp, parent)); + VTABLE_get_string(INTERP, SELF), + VTABLE_get_string(INTERP, parent)); } + GET_ATTR_all_parents(INTERP, parent, all_parents); + /* Check that none of the parents is self */ - parent_count = VTABLE_elements(interp, PARROT_CLASS(parent)->all_parents); + parent_count = VTABLE_elements(INTERP, all_parents); for (index = 0; index < parent_count; index++) { /* get the next parent */ - PMC * const current_parent = VTABLE_get_pmc_keyed_int(interp, - PARROT_CLASS(parent)->all_parents, index); + PMC * const current_parent = VTABLE_get_pmc_keyed_int(INTERP, + all_parents, index); if (current_parent == SELF) - Parrot_ex_throw_from_c_args(interp, NULL, + Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, "Loop in class hierarchy: '%S' is an ancestor of '%S'.", - VTABLE_get_string(interp, SELF), - VTABLE_get_string(interp, parent)); + VTABLE_get_string(INTERP, SELF), + VTABLE_get_string(INTERP, parent)); } /* Add to the lists of our immediate parents and all parents. */ - VTABLE_push_pmc(interp, _class->parents, parent); - calculate_mro(interp, SELF, parent_count + 1); + VTABLE_push_pmc(INTERP, parents, parent); + calculate_mro(INTERP, SELF, parent_count + 1); } /* @@ -853,39 +940,44 @@ */ VTABLE void remove_parent(PMC *parent) { - Parrot_Class_attributes * const _class = PARROT_CLASS(SELF); - int parent_count, index; + int parent_count, index; + INTVAL instantiated; + PMC *parents, *all_parents; + GET_ATTR_instantiated(INTERP, SELF, instantiated); + /* If we've been instantiated already, not allowed. */ - if (_class->instantiated) - Parrot_ex_throw_from_c_args(interp, NULL, + if (instantiated) + Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, "Modifications to classes are not allowed after instantiation."); /* Ensure it really is a class. */ if (!PObj_is_class_TEST(parent)) - Parrot_ex_throw_from_c_args(interp, NULL, + Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, "Parent isn't a Class."); + GET_ATTR_parents(INTERP, SELF, parents); + /* get number of direct parents */ - parent_count = VTABLE_elements(interp, _class->parents); + parent_count = VTABLE_elements(INTERP, parents); /* iterate over all direct parents, looking for the parent to remove */ for (index = 0; index < parent_count; index++) { /* get the next parent */ - PMC * const current_parent = VTABLE_get_pmc_keyed_int(interp, - _class->parents, index); + PMC * const current_parent = VTABLE_get_pmc_keyed_int(INTERP, + parents, index); if (current_parent == parent) break; } if (index >= parent_count) - Parrot_ex_throw_from_c_args(interp, NULL, + Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, "Can't remove_parent: is not a parent."); - VTABLE_delete_keyed_int(interp, _class->parents, index); - calculate_mro(interp, SELF, parent_count - 1); + VTABLE_delete_keyed_int(INTERP, parents, index); + calculate_mro(INTERP, SELF, parent_count - 1); } /* @@ -899,12 +991,16 @@ */ VTABLE void add_role(PMC *role) { - const Parrot_Class_attributes * const _class = PARROT_CLASS(SELF); + PMC *resolve_method, *methods, *roles; + GET_ATTR_resolve_method(INTERP, SELF, resolve_method); + GET_ATTR_methods(INTERP, SELF, methods); + GET_ATTR_roles(INTERP, SELF, roles); + /* Do the composition. */ - Parrot_ComposeRole(interp, role, - _class->resolve_method, !PMC_IS_NULL(_class->resolve_method), - PMCNULL, 0, _class->methods, _class->roles); + Parrot_ComposeRole(INTERP, role, + resolve_method, !PMC_IS_NULL(resolve_method), + PMCNULL, 0, methods, roles); } /* @@ -948,51 +1044,58 @@ */ VTABLE PMC *inspect_str(STRING *what) { - Parrot_Class_attributes * const _class = PARROT_CLASS(SELF); - /* What should we return? */ PMC *found; - if (Parrot_str_equal(interp, what, CONST_STRING(interp, "attributes"))) { - found = _class->attrib_metadata; + if (Parrot_str_equal(INTERP, what, CONST_STRING(INTERP, "attributes"))) { + GET_ATTR_attrib_metadata(INTERP, SELF, found); } - else if (Parrot_str_equal(interp, what, CONST_STRING(interp, "parents"))) { - found = _class->parents; + else if (Parrot_str_equal(INTERP, what, CONST_STRING(INTERP, "parents"))) { + GET_ATTR_parents(INTERP, SELF, found); } - else if (Parrot_str_equal(interp, what, CONST_STRING(interp, "name"))) { - found = pmc_new(interp, enum_class_String); - VTABLE_set_string_native(interp, found, _class->name); + else if (Parrot_str_equal(INTERP, what, CONST_STRING(INTERP, "name"))) { + STRING *name; + + GET_ATTR_name(INTERP, SELF, name); + + found = pmc_new(INTERP, enum_class_String); + VTABLE_set_string_native(INTERP, found, name); } - else if (Parrot_str_equal(interp, what, CONST_STRING(interp, "id"))) { - found = pmc_new(interp, enum_class_Integer); - VTABLE_set_integer_native(interp, found, _class->id); + else if (Parrot_str_equal(INTERP, what, CONST_STRING(INTERP, "id"))) { + INTVAL id; + GET_ATTR_id(INTERP, SELF, id); + + found = pmc_new(INTERP, enum_class_Integer); + VTABLE_set_integer_native(INTERP, found, id); } - else if (Parrot_str_equal(interp, what, CONST_STRING(interp, "namespace"))) { + else if (Parrot_str_equal(INTERP, what, CONST_STRING(INTERP, "namespace"))) { + GET_ATTR__namespace(INTERP, SELF, found); + /* Should not clone this. */ - return _class->_namespace; + return found; } - else if (Parrot_str_equal(interp, what, CONST_STRING(interp, "attrib_index"))) { - found = _class->attrib_index; + else if (Parrot_str_equal(INTERP, what, CONST_STRING(INTERP, "attrib_index"))) { + GET_ATTR_attrib_index(INTERP, SELF, found); } - else if (Parrot_str_equal(interp, what, CONST_STRING(interp, "methods"))) { - found = _class->methods; + else if (Parrot_str_equal(INTERP, what, CONST_STRING(INTERP, "methods"))) { + GET_ATTR_methods(INTERP, SELF, found); } - else if (Parrot_str_equal(interp, what, CONST_STRING(interp, "vtable_overrides"))) { - found = _class->vtable_overrides; + else if (Parrot_str_equal(INTERP, what, CONST_STRING(INTERP, "vtable_overrides"))) { + GET_ATTR_vtable_overrides(INTERP, SELF, found); } - else if (Parrot_str_equal(interp, what, CONST_STRING(interp, "all_parents"))) { - found = _class->all_parents; + else if (Parrot_str_equal(INTERP, what, CONST_STRING(INTERP, "all_parents"))) { + GET_ATTR_all_parents(INTERP, SELF, found); } - else if (Parrot_str_equal(interp, what, CONST_STRING(interp, "roles"))) { - found = _class->roles; + else if (Parrot_str_equal(INTERP, what, CONST_STRING(INTERP, "roles"))) { + GET_ATTR_roles(INTERP, SELF, found); } - else if (Parrot_str_equal(interp, what, CONST_STRING(interp, "flags"))) { - found = pmc_new(interp, enum_class_Integer); - VTABLE_set_integer_native(interp, found, + else if (Parrot_str_equal(INTERP, what, CONST_STRING(INTERP, "flags"))) { + found = pmc_new(INTERP, enum_class_Integer); + VTABLE_set_integer_native(INTERP, found, (INTVAL)PObj_get_FLAGS(SELF)); } else - Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, + Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, "Unknown introspection value '%S'", what); /* return found value */ @@ -1002,18 +1105,18 @@ if (found->vtable->base_type == enum_class_Hash) { /* for Hash return values, create and return a shallow * clone because the VTABLE_clone does a deep clone */ - PMC * const hash = pmc_new(interp, enum_class_Hash); - PMC * const iter = VTABLE_get_iter(interp, found); - while (VTABLE_get_bool(interp, iter)) { - STRING * const key = VTABLE_shift_string(interp, iter); - PMC * const value = VTABLE_get_pmc_keyed_str(interp, found, key); - VTABLE_set_pmc_keyed_str(interp, hash, key, value); + PMC * const hash = pmc_new(INTERP, enum_class_Hash); + PMC * const iter = VTABLE_get_iter(INTERP, found); + while (VTABLE_get_bool(INTERP, iter)) { + STRING * const key = VTABLE_shift_string(INTERP, iter); + PMC * const value = VTABLE_get_pmc_keyed_str(INTERP, found, key); + VTABLE_set_pmc_keyed_str(INTERP, hash, key, value); } return hash; } - return VTABLE_clone(interp, found); + return VTABLE_clone(INTERP, found); } /* @@ -1029,35 +1132,35 @@ VTABLE PMC *inspect() { /* Create a hash, then use inspect_str to get all of the data to * fill it up with. */ - PMC * const metadata = pmc_new(interp, enum_class_Hash); - STRING * const name_str = CONST_STRING(interp, "name"); - STRING * const ns_str = CONST_STRING(interp, "namespace"); - STRING * const attrs_str = CONST_STRING(interp, "attributes"); - STRING * const meths_str = CONST_STRING(interp, "methods"); - STRING * const parents_str = CONST_STRING(interp, "parents"); - STRING * const roles_str = CONST_STRING(interp, "roles"); - STRING * const flags_str = CONST_STRING(interp, "flags"); + PMC * const metadata = pmc_new(INTERP, enum_class_Hash); + STRING * const name_str = CONST_STRING(INTERP, "name"); + STRING * const ns_str = CONST_STRING(INTERP, "namespace"); + STRING * const attrs_str = CONST_STRING(INTERP, "attributes"); + STRING * const meths_str = CONST_STRING(INTERP, "methods"); + STRING * const parents_str = CONST_STRING(INTERP, "parents"); + STRING * const roles_str = CONST_STRING(INTERP, "roles"); + STRING * const flags_str = CONST_STRING(INTERP, "flags"); - VTABLE_set_pmc_keyed_str(interp, metadata, name_str, - VTABLE_inspect_str(interp, SELF, name_str)); + VTABLE_set_pmc_keyed_str(INTERP, metadata, name_str, + VTABLE_inspect_str(INTERP, SELF, name_str)); - VTABLE_set_pmc_keyed_str(interp, metadata, ns_str, - VTABLE_inspect_str(interp, SELF, ns_str)); + VTABLE_set_pmc_keyed_str(INTERP, metadata, ns_str, + VTABLE_inspect_str(INTERP, SELF, ns_str)); - VTABLE_set_pmc_keyed_str(interp, metadata, attrs_str, - VTABLE_inspect_str(interp, SELF, attrs_str)); + VTABLE_set_pmc_keyed_str(INTERP, metadata, attrs_str, + VTABLE_inspect_str(INTERP, SELF, attrs_str)); - VTABLE_set_pmc_keyed_str(interp, metadata, meths_str, - VTABLE_inspect_str(interp, SELF, meths_str)); + VTABLE_set_pmc_keyed_str(INTERP, metadata, meths_str, + VTABLE_inspect_str(INTERP, SELF, meths_str)); - VTABLE_set_pmc_keyed_str(interp, metadata, parents_str, - VTABLE_inspect_str(interp, SELF, parents_str)); + VTABLE_set_pmc_keyed_str(INTERP, metadata, parents_str, + VTABLE_inspect_str(INTERP, SELF, parents_str)); - VTABLE_set_pmc_keyed_str(interp, metadata, roles_str, - VTABLE_inspect_str(interp, SELF, roles_str)); + VTABLE_set_pmc_keyed_str(INTERP, metadata, roles_str, + VTABLE_inspect_str(INTERP, SELF, roles_str)); - VTABLE_set_pmc_keyed_str(interp, metadata, flags_str, - VTABLE_inspect_str(interp, SELF, flags_str)); + VTABLE_set_pmc_keyed_str(INTERP, metadata, flags_str, + VTABLE_inspect_str(INTERP, SELF, flags_str)); return metadata; } @@ -1074,32 +1177,34 @@ */ VTABLE PMC *clone() { - Parrot_Class_attributes * const _class = PARROT_CLASS(SELF); + PMC *parents, *roles, *methods, *vtable_overrides; + PMC *parent_overrides, *attrib_metadata, *resolve_method; /* Create the new class PMC, of the same type of this one (we may * have been subclassed). */ - PMC * const copy = SUPER(); + PMC * const copy = SUPER(); + GET_ATTR_parents(INTERP, SELF, parents); + GET_ATTR_roles(INTERP, SELF, roles); + GET_ATTR_methods(INTERP, SELF, methods); + GET_ATTR_vtable_overrides(INTERP, SELF, vtable_overrides); + GET_ATTR_parent_overrides(INTERP, SELF, parent_overrides); + GET_ATTR_attrib_metadata(INTERP, SELF, attrib_metadata); + GET_ATTR_resolve_method(INTERP, SELF, resolve_method); + /* Clone parents, roles, methods, attributes and resolve data. We do * not copy name/namespace related stuff (need anonymous clone) or * stuff that gets computed on the first instantiation. */ + SET_ATTR_name(INTERP, copy, CONST_STRING(INTERP, "")); + SET_ATTR__namespace(INTERP, copy, PMCNULL); + SET_ATTR_parents(INTERP, copy, VTABLE_clone(INTERP, parents)); + SET_ATTR_roles(INTERP, copy, VTABLE_clone(INTERP, roles)); + SET_ATTR_methods(INTERP, copy, VTABLE_clone(INTERP, methods)); + SET_ATTR_vtable_overrides(INTERP, copy, VTABLE_clone(INTERP, vtable_overrides)); + SET_ATTR_parent_overrides(INTERP, copy, VTABLE_clone(INTERP, parent_overrides)); + SET_ATTR_attrib_metadata(INTERP, copy, VTABLE_clone(INTERP, attrib_metadata)); + SET_ATTR_resolve_method(INTERP, copy, VTABLE_clone(INTERP, resolve_method)); - Parrot_Class_attributes * const new_class = PARROT_CLASS(copy); - - new_class->name = CONST_STRING(interp, ""); - new_class->_namespace = PMCNULL; - new_class->parents = VTABLE_clone(interp, _class->parents); - new_class->roles = VTABLE_clone(interp, _class->roles); - new_class->methods = VTABLE_clone(interp, _class->methods); - new_class->vtable_overrides = VTABLE_clone(interp, - _class->vtable_overrides); - new_class->parent_overrides = VTABLE_clone(interp, - _class->parent_overrides); - new_class->attrib_metadata = VTABLE_clone(interp, - _class->attrib_metadata); - new_class->resolve_method = VTABLE_clone(interp, - _class->resolve_method); - /* Return cloned class. */ return copy; } @@ -1119,9 +1224,9 @@ VTABLE PMC *clone_pmc(PMC *args) { /* Do the standard clone. */ - PMC * const copy = SELF.clone(); + PMC * const copy = STATICSELF.clone(); - init_class_from_hash(interp, copy, args); + init_class_from_hash(INTERP, copy, args); return copy; } @@ -1137,46 +1242,57 @@ */ VTABLE PMC *instantiate(PMC *init) { - Parrot_Class_attributes * const _class = PARROT_CLASS(SELF); - PMC *object; + INTVAL instantiated; + PMC *object, *all_parents; + GET_ATTR_instantiated(INTERP, SELF, instantiated); + GET_ATTR_all_parents(INTERP, SELF, all_parents); + /* If we've not been instantiated before... */ - if (!_class->instantiated) { + if (!instantiated) { + int i, resolve_count; + INTVAL num_parents, mro_length; + PMC *resolve_method, *parents, *methods, *attrib_index; + const INTVAL cur_hll = Parrot_pcc_get_HLL(INTERP, CURRENT_CONTEXT(interp)); + + GET_ATTR_parents(INTERP, SELF, parents); + GET_ATTR_methods(INTERP, SELF, methods); + GET_ATTR_resolve_method(INTERP, SELF, resolve_method); + /* Check that we have all methods listed in resolve list. */ - const int resolve_count = VTABLE_elements(interp, - _class->resolve_method); - const INTVAL cur_hll = Parrot_pcc_get_HLL(interp, CURRENT_CONTEXT(interp)); - const INTVAL num_parents = VTABLE_elements(interp, _class->parents); - INTVAL mro_length; - int i; + resolve_count = VTABLE_elements(INTERP, resolve_method); + num_parents = VTABLE_elements(INTERP, parents); + /* don't use HLL mappings for internal-only data */ - Parrot_pcc_set_HLL(interp, CURRENT_CONTEXT(interp), 0); + Parrot_pcc_set_HLL(INTERP, CURRENT_CONTEXT(interp), 0); for (i = 0; i < resolve_count; i++) { STRING * const check_meth = - VTABLE_get_string_keyed_int(interp, _class->resolve_method, i); - if (!VTABLE_exists_keyed_str(interp, _class->methods, check_meth)) - Parrot_ex_throw_from_c_args(interp, NULL, + VTABLE_get_string_keyed_int(INTERP, resolve_method, i); + if (!VTABLE_exists_keyed_str(INTERP, methods, check_meth)) + Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_METHOD_NOT_FOUND, "The method '%S' was named " "in the resolve list, but not supplied", check_meth); } /* Build full parents list. * TT #1256: Need pluggable MRO, for now always do C3. */ - calculate_mro(interp, SELF, num_parents); - build_attrib_index(interp, SELF); + calculate_mro(INTERP, SELF, num_parents); + build_attrib_index(INTERP, SELF); - if (PMC_IS_NULL(_class->attrib_index)) + GET_ATTR_attrib_index(INTERP, SELF, attrib_index); + + if (PMC_IS_NULL(attrib_index)) return PMCNULL; /* See if we have any parents from other universes and if so set a * flag stating so. */ - mro_length = VTABLE_elements(interp, _class->all_parents); + mro_length = VTABLE_elements(INTERP, all_parents); for (i = 0; i < mro_length; i++) { - PMC * const class_check = VTABLE_get_pmc_keyed_int(interp, - _class->all_parents, i); + PMC * const class_check = VTABLE_get_pmc_keyed_int(INTERP, + all_parents, i); if (class_check->vtable->base_type != enum_class_Class) { /* Found one; that's enough. */ CLASS_has_alien_parents_SET(SELF); @@ -1184,14 +1300,14 @@ } } - Parrot_pcc_set_HLL(interp, CURRENT_CONTEXT(interp), cur_hll); + Parrot_pcc_set_HLL(INTERP, CURRENT_CONTEXT(interp), cur_hll); } /* Set instantiated flag. */ - _class->instantiated = 1; + SET_ATTR_instantiated(INTERP, SELF, 1); /* Create object. */ - object = pmc_new_noinit(interp, enum_class_Object); + object = pmc_new_noinit(INTERP, enum_class_Object); /* Set custom GC mark and destroy on the object. */ PObj_custom_mark_destroy_SETALL(object); @@ -1204,31 +1320,30 @@ /* TODO: this has been changed in order to use auto_attrs in the * Object PMC. Needs to be redone in a cleaner way. */ { - Parrot_Object_attributes * const objattr = - PMC_data_typed(object, Parrot_Object_attributes *); + Parrot_Object_attributes * const objattr = PARROT_OBJECT(object); objattr->_class = SELF; - objattr->attrib_store = pmc_new(interp, enum_class_ResizablePMCArray); + objattr->attrib_store = pmc_new(INTERP, enum_class_ResizablePMCArray); } if (!PMC_IS_NULL(init)) { /* Initialize attributes with the supplied values. */ - PMC * const iter = VTABLE_get_iter(interp, init); + PMC * const iter = VTABLE_get_iter(INTERP, init); - while (VTABLE_get_bool(interp, iter)) { - STRING * const name = VTABLE_shift_string(interp, iter); - PMC * const value = VTABLE_get_pmc_keyed_str(interp, init, + while (VTABLE_get_bool(INTERP, iter)) { + STRING * const name = VTABLE_shift_string(INTERP, iter); + PMC * const value = VTABLE_get_pmc_keyed_str(INTERP, init, name); /* Set the attribute. */ - VTABLE_set_attr_str(interp, object, name, value); + VTABLE_set_attr_str(INTERP, object, name, value); } /* Check for overrides on the init_pmc vtable function */ - initialize_parents_pmc(interp, object, _class->all_parents, init); + initialize_parents_pmc(INTERP, object, all_parents, init); } else /* Check for overrides on the init vtable function */ - initialize_parents(interp, object, _class->all_parents); + initialize_parents(INTERP, object, all_parents); return object; } @@ -1245,9 +1360,8 @@ */ VTABLE INTVAL isa_pmc(PMC *lookup) { - Parrot_Class_attributes * const _class = PARROT_CLASS(SELF); - PMC *classobj; - INTVAL i, num_classes; + INTVAL i, num_classes; + PMC *classobj, *parents; if (PMC_IS_NULL(lookup)) return 0; @@ -1255,13 +1369,13 @@ if (PObj_is_class_TEST(lookup) && lookup == SELF) return 1; - classobj = Parrot_oo_get_class(interp, lookup); + classobj = Parrot_oo_get_class(INTERP, lookup); if (PMC_IS_NULL(classobj)) return 0; /* Check if the class object is the same as self's class object */ - if (VTABLE_is_same(interp, SELF, classobj)) + if (VTABLE_is_same(INTERP, SELF, classobj)) return 1; /* this is effectively what the default PMC's isa_pmc does @@ -1269,26 +1383,28 @@ * only in these two, very specific and common cases */ if (classobj->vtable->base_type == enum_class_Class || classobj->vtable->base_type == enum_class_PMCProxy) { - STRING *classname = make_class_name(interp, classobj); + STRING * const classname = make_class_name(INTERP, classobj); - if (Parrot_str_equal(interp, SELF->vtable->whoami, classname)) + if (Parrot_str_equal(INTERP, SELF->vtable->whoami, classname)) return 1; if (SELF->vtable->isa_hash - && parrot_hash_exists(interp, SELF->vtable->isa_hash, + && parrot_hash_exists(INTERP, SELF->vtable->isa_hash, (void *)classname)) return 1; } + GET_ATTR_parents(INTERP, SELF, parents); + /* Iterate over all the parents and check if they respond true * for 'isa' on the original comparison. */ - num_classes = VTABLE_elements(interp, _class->parents); + num_classes = VTABLE_elements(INTERP, parents); for (i = 0; i < num_classes; i++) { - PMC * const cur_class = VTABLE_get_pmc_keyed_int(interp, - _class->parents, i); + PMC * const cur_class = VTABLE_get_pmc_keyed_int(INTERP, + parents, i); - if (VTABLE_isa_pmc(interp, cur_class, lookup)) + if (VTABLE_isa_pmc(INTERP, cur_class, lookup)) return 1; } @@ -1309,10 +1425,10 @@ PMC *want_class; /* hard-code this one exception right away */ - if (Parrot_str_equal(interp, classname, CONST_STRING(interp, "Class"))) + if (Parrot_str_equal(INTERP, classname, CONST_STRING(INTERP, "Class"))) return 1; - want_class = Parrot_oo_get_class_str(interp, classname); + want_class = Parrot_oo_get_class_str(INTERP, classname); if (PMC_IS_NULL(want_class)) return 0; @@ -1320,7 +1436,7 @@ if (SELF == want_class) return 1; - return VTABLE_isa_pmc(interp, SELF, want_class); + return VTABLE_isa_pmc(INTERP, SELF, want_class); } /* @@ -1333,35 +1449,38 @@ */ VTABLE INTVAL does(STRING *role_name) { - Parrot_Class_attributes * const _class = PARROT_CLASS(SELF); - PMC * const role_list = _class->roles; INTVAL i, count; + PMC *roles, *parents; - if (!role_list) + GET_ATTR_roles(INTERP, SELF, roles); + + if (!roles) return 0; - count = VTABLE_elements(interp, role_list); + count = VTABLE_elements(INTERP, roles); for (i = 0; i < count; i++) { - PMC * const role = VTABLE_get_pmc_keyed_int(interp, role_list, i); + PMC * const role = VTABLE_get_pmc_keyed_int(INTERP, roles, i); - if (VTABLE_does(interp, role, role_name)) + if (VTABLE_does(INTERP, role, role_name)) return 1; } + GET_ATTR_parents(INTERP, SELF, parents); + /* Iterate over all the parents and check if they respond true * for 'does' on the original comparison. */ - count = VTABLE_elements(interp, _class->parents); + count = VTABLE_elements(INTERP, parents); for (i = 0; i < count; i++) { - PMC * const cur_class = VTABLE_get_pmc_keyed_int(interp, - _class->parents, i); + PMC * const cur_class = VTABLE_get_pmc_keyed_int(INTERP, + parents, i); - if (VTABLE_does(interp, cur_class, role_name)) + if (VTABLE_does(INTERP, cur_class, role_name)) return 1; } - return VTABLE_isa(interp, SELF, role_name); + return VTABLE_isa(INTERP, SELF, role_name); } /* @@ -1374,34 +1493,37 @@ */ VTABLE INTVAL does_pmc(PMC *role) { - Parrot_Class_attributes * const _class = PARROT_CLASS(SELF); - PMC * const role_list = _class->roles; INTVAL i, role_count, count; + PMC *roles, *parents; - if (!role_list) + GET_ATTR_roles(INTERP, SELF, roles); + + if (!roles) return 0; - role_count = VTABLE_elements(interp, role_list); + role_count = VTABLE_elements(INTERP, role); for (i = 0; i < role_count; i++) { - PMC * const test_role = VTABLE_get_pmc_keyed_int(interp, role_list, i); - if (VTABLE_does_pmc(interp, test_role, role)) + PMC * const test_role = VTABLE_get_pmc_keyed_int(INTERP, roles, i); + if (VTABLE_does_pmc(INTERP, test_role, role)) return 1; } + GET_ATTR_parents(INTERP, SELF, parents); + /* Iterate over all the parents and check if they respond true * for 'does' on the original comparison. */ - count = VTABLE_elements(interp, _class->parents); + count = VTABLE_elements(INTERP, parents); for (i = 0; i < count; i++) { - PMC * const cur_class = VTABLE_get_pmc_keyed_int(interp, - _class->parents, i); + PMC * const cur_class = VTABLE_get_pmc_keyed_int(INTERP, + parents, i); - if (VTABLE_does_pmc(interp, cur_class, role)) + if (VTABLE_does_pmc(INTERP, cur_class, role)) return 1; } - return VTABLE_isa_pmc(interp, SELF, role); + return VTABLE_isa_pmc(INTERP, SELF, role); } /* @@ -1415,8 +1537,11 @@ */ VTABLE INTVAL type() { - Parrot_Class_attributes * const _class = PARROT_CLASS(SELF); - return _class->id; + INTVAL id; + + GET_ATTR_id(INTERP, SELF, id); + + return id; } /* @@ -1477,22 +1602,28 @@ */ VTABLE void freeze(visit_info *info) { - IMAGE_IO * const io = info->image_io; - Parrot_Class_attributes * const class_data = PARROT_CLASS(SELF); - STRING *serial_namespace = CONST_STRING(interp, ""); + INTVAL id; + PMC *_namespace; + STRING *name; + STRING *serial_namespace = CONST_STRING(INTERP, ""); + IMAGE_IO * const io = info->image_io; + GET_ATTR_id(INTERP, SELF, id); + GET_ATTR_name(INTERP, SELF, name); + GET_ATTR__namespace(INTERP, SELF, _namespace); + /* 1) freeze class id */ - VTABLE_push_integer(INTERP, io, class_data->id); + VTABLE_push_integer(INTERP, io, id); /* 2) freeze class name */ - VTABLE_push_string(INTERP, io, class_data->name); + VTABLE_push_string(INTERP, io, name); /* 3) serialize namespace name, including HLL */ - if (!PMC_IS_NULL(class_data->_namespace)) { - PMC * const names = Parrot_ns_get_name(interp, - class_data->_namespace); + if (!PMC_IS_NULL(_namespace)) { + PMC * const names = Parrot_ns_get_name(INTERP, + _namespace); if (!PMC_IS_NULL(names)) - serial_namespace = Parrot_str_join(interp, CONST_STRING(interp, ";"), names); + serial_namespace = Parrot_str_join(INTERP, CONST_STRING(INTERP, ";"), names); } VTABLE_push_string(INTERP, io, serial_namespace); } @@ -1526,31 +1657,31 @@ /* 3) deserialize namespace name, including HLL */ STRING * const serial_namespace = VTABLE_shift_string(INTERP, io); - STRING * const semicolon_str = CONST_STRING(INTERP, ";"); - PMC * const namespace_array = - Parrot_str_split(INTERP, semicolon_str, serial_namespace); - PMC *ns = Parrot_get_namespace_keyed(interp, + STRING * const semicolon_str = CONST_STRING(INTERP, ";"); + PMC * const namespace_array = + Parrot_str_split(INTERP, semicolon_str, serial_namespace); + PMC *ns = Parrot_get_namespace_keyed(INTERP, INTERP->root_namespace, namespace_array); /* If the namespace doesn't exist, we create it, and initialize * ourselves in it */ if (PMC_IS_NULL(ns)) { - ns = Parrot_make_namespace_keyed(interp, + ns = Parrot_make_namespace_keyed(INTERP, INTERP->root_namespace, namespace_array); - SELF.init_pmc(ns); + STATICSELF.init_pmc(ns); } /* If the namespace exists already, we point to it, but otherwise * act as an anonymous class. */ else { - SELF.init(); - PARROT_CLASS(SELF)->_namespace = ns; + STATICSELF.init(); + SET_ATTR__namespace(INTERP, SELF, ns); } + /* Set the class's id the frozen id */ + SET_ATTR_id(INTERP, SELF, id); + /* Set the class's short name to the frozen name */ - PARROT_CLASS(SELF)->name = name; - - /* Set the class's id the frozen id */ - PARROT_CLASS(SELF)->id = id; + SET_ATTR_name(INTERP, SELF, name); } } @@ -1567,7 +1698,11 @@ */ VTABLE INTVAL get_integer() { - return PARROT_CLASS(SELF)->id; + INTVAL id; + + GET_ATTR_id(INTERP, SELF, id); + + return id; } /* @@ -1581,15 +1716,14 @@ */ VTABLE void thawfinish(visit_info *info) { - Parrot_Class_attributes * const _class = PARROT_CLASS(SELF); UNUSED(info) /* Recalculate full MRO from thawed parents */ - _class->all_parents = Parrot_ComputeMRO_C3(interp, SELF); - _class->parent_overrides = pmc_new(interp, enum_class_Hash); + SET_ATTR_all_parents(INTERP, SELF, Parrot_ComputeMRO_C3(INTERP, SELF)); + SET_ATTR_parent_overrides(INTERP, SELF, pmc_new(INTERP, enum_class_Hash)); /* Rebuild attribute index from thawed attribute metadata */ - build_attrib_index(interp, SELF); + build_attrib_index(INTERP, SELF); } /* ********************************************************************** @@ -1608,20 +1742,20 @@ */ METHOD name(STRING *name :optional, int has_name :opt_flag) { - Parrot_Class_attributes * const _class = PARROT_CLASS(SELF); STRING *ret_name; if (has_name) { /* We'll build a hash just containing the name, then give this to * init_class_from_hash - saves some code duplication. */ - PMC * const naming_hash = pmc_new(interp, enum_class_Hash); - STRING * const name_str = CONST_STRING(interp, "name"); + PMC * const naming_hash = pmc_new(INTERP, enum_class_Hash); + STRING * const name_str = CONST_STRING(INTERP, "name"); - VTABLE_set_string_keyed_str(interp, naming_hash, name_str, name); - init_class_from_hash(interp, SELF, naming_hash); + VTABLE_set_string_keyed_str(INTERP, naming_hash, name_str, name); + init_class_from_hash(INTERP, SELF, naming_hash); } - ret_name = _class->name; + GET_ATTR_name(INTERP, SELF, ret_name); + RETURN(STRING *ret_name); } @@ -1635,10 +1769,13 @@ */ METHOD get_namespace(PMC *_namespace :optional, int has_name :opt_flag) { - Parrot_Class_attributes * const _class = PARROT_CLASS(SELF); - PMC * const ret_namespace = _class->_namespace; + PMC * ret_namespace; + UNUSED(_namespace); UNUSED(has_name); + + GET_ATTR__namespace(INTERP, SELF, ret_namespace); + RETURN(PMC *ret_namespace); } @@ -1653,14 +1790,14 @@ */ METHOD resolve_method(PMC *resolve_list :optional, int has_list :opt_flag) { - Parrot_Class_attributes * const _class = PARROT_CLASS(SELF); PMC *ret_list; /* Store list. */ if (has_list) - _class->resolve_method = resolve_list; + SET_ATTR_resolve_method(INTERP, SELF, resolve_list); - ret_list = _class->resolve_method; + GET_ATTR_resolve_method(INTERP, SELF, ret_list); + RETURN(PMC *ret_list); } @@ -1678,9 +1815,9 @@ /* Check if any arguments are in the slurpy hash, don't pass an empty * hash to instantiate */ PMC * const obj = - VTABLE_elements(interp, args) > 0 - ? VTABLE_instantiate(interp, SELF, args) - : VTABLE_instantiate(interp, SELF, PMCNULL); + VTABLE_elements(INTERP, args) > 0 + ? VTABLE_instantiate(INTERP, SELF, args) + : VTABLE_instantiate(INTERP, SELF, PMCNULL); RETURN(PMC *obj); } @@ -1696,7 +1833,7 @@ */ METHOD attributes() { - STRING * const attr_str = CONST_STRING(interp, "attributes"); + STRING * const attr_str = CONST_STRING(INTERP, "attributes"); PMC * const ret_attrib_metadata = SELF.inspect_str(attr_str); RETURN(PMC *ret_attrib_metadata); @@ -1727,7 +1864,7 @@ */ METHOD methods() { - PMC * const ret_methods = SELF.inspect_str(CONST_STRING(interp, "methods")); + PMC * const ret_methods = SELF.inspect_str(CONST_STRING(INTERP, "methods")); RETURN(PMC *ret_methods); } @@ -1757,7 +1894,7 @@ */ METHOD add_vtable_override(STRING *name, PMC *sub) { - VTABLE_add_vtable_override(interp, SELF, name, sub); + SELF.add_vtable_override(name, sub); } /* @@ -1770,7 +1907,7 @@ */ METHOD remove_method(STRING *name) { - VTABLE_remove_method(interp, SELF, name); + SELF.remove_method(name); } /* @@ -1784,21 +1921,26 @@ */ METHOD find_method(STRING *name) { - Parrot_Class_attributes * const _class = PARROT_CLASS(SELF); - int i; + int i, num_classes; + PMC *all_parents; + GET_ATTR_all_parents(INTERP, SELF , all_parents); + /* Walk and search. One day, we'll use the cache first. */ - const int num_classes = VTABLE_elements(interp, _class->all_parents); + num_classes = VTABLE_elements(INTERP, all_parents); for (i = 0; i < num_classes; i++) { + PMC *methods; + /* Get the class and see if it has the method. */ PMC * const cur_class = - VTABLE_get_pmc_keyed_int(interp, _class->all_parents, i); - const Parrot_Class_attributes * const class_info = PARROT_CLASS(cur_class); + VTABLE_get_pmc_keyed_int(INTERP, all_parents, i); + GET_ATTR_methods(INTERP, cur_class, methods); + /* Found it! */ - if (VTABLE_exists_keyed_str(interp, class_info->methods, name)) { - PMC * const ret = VTABLE_get_pmc_keyed_str(interp, class_info->methods, name); + if (VTABLE_exists_keyed_str(INTERP, methods, name)) { + PMC * const ret = VTABLE_get_pmc_keyed_str(INTERP, methods, name); RETURN(PMC *ret); } } @@ -1816,7 +1958,7 @@ */ METHOD parents() { - PMC * const ret_parents = SELF.inspect_str(CONST_STRING(interp, "parents")); + PMC * const ret_parents = SELF.inspect_str(CONST_STRING(INTERP, "parents")); RETURN(PMC *ret_parents); } @@ -1844,7 +1986,7 @@ */ METHOD roles() { - PMC * const ret_roles = SELF.inspect_str(CONST_STRING(interp, "roles")); + PMC * const ret_roles = SELF.inspect_str(CONST_STRING(INTERP, "roles")); RETURN(PMC *ret_roles); } @@ -1860,37 +2002,39 @@ */ METHOD add_role(PMC *role, - PMC *exclude_method :optional :named("exclude_method"), - int has_exclude_method :opt_flag, - PMC *alias_method :optional :named("alias_method"), - int has_alias_method :opt_flag) { + PMC *exclude_method :optional :named("exclude_method"), + int has_exclude_method :opt_flag, + PMC *alias_method :optional :named("alias_method"), + int has_alias_method :opt_flag) { + PMC *resolve_method, *methods, *roles; - Parrot_Class_attributes * const _class = PARROT_CLASS(SELF); + GET_ATTR_resolve_method(INTERP, SELF, resolve_method); + GET_ATTR_methods(INTERP, SELF, methods); + GET_ATTR_roles(INTERP, SELF, roles); /* Add everything on the resolve list to the exclude list; if we have * no exclude list, pass along the resolve list in its place if it has * any methods listed in it. */ if (!has_exclude_method) { - if (VTABLE_elements(interp, _class->resolve_method) != 0) { - exclude_method = _class->resolve_method; + if (VTABLE_elements(INTERP, resolve_method) != 0) { + exclude_method = resolve_method; has_exclude_method = 1; } } else { - const int resolve_count = VTABLE_elements(interp, _class->resolve_method); + const int resolve_count = VTABLE_elements(INTERP, resolve_method); int i; for (i = 0; i < resolve_count; i++) { - STRING * const meth_name = VTABLE_get_string_keyed_int(interp, - _class->resolve_method, i); - VTABLE_push_string(interp, exclude_method, meth_name); + STRING * const meth_name = VTABLE_get_string_keyed_int(INTERP, + resolve_method, i); + VTABLE_push_string(INTERP, exclude_method, meth_name); } } /* Do the composition. */ - Parrot_ComposeRole(interp, role, exclude_method, has_exclude_method, - alias_method, has_alias_method, - _class->methods, _class->roles); + Parrot_ComposeRole(INTERP, role, exclude_method, has_exclude_method, + alias_method, has_alias_method, methods, roles); } /* @@ -1942,7 +2086,7 @@ */ METHOD does(STRING *role_name) { - const INTVAL does = VTABLE_does(interp, SELF, role_name); + const INTVAL does = VTABLE_does(INTERP, SELF, role_name); RETURN(INTVAL does); }