On Wednesday 13 June 2007 16:54:54 Jonathan Worthington wrote: > Yes, I'd like to see this. I did the groundwork for it already, by > refactoring the NameSpace PMC so that there is a place to hang such a > thing off now (just add it to the underlying struct), though I was doing > it so there was a slot to hang the class that the namespace maps to > from. So it shouldn't be too much work to do this.
It wasn't. This patch is a lot nicer. All tests pass. They pass more quickly too. I still dislike the named lookup in find_vtable_meth_ns(), but I couldn't find all of the places that could assign vtable methods to a namespace to make sure they all set the vtable flag appropriately. If someone else were to fix that, find_vtable_meth_ns() could become: return VTABLE_get_pmc_keyed_int(interp, ns, vtable_index); I wouldn't hate that either. > Note that PDD15 classes don't lookup non-vtable methods in namespaces > anymore, and I think the same will go for vtable methods. With PMCProxy > now existing, I suspect we can do the same for non-vtable methods of > PMCs too... So all of this pain will just go away? That's handy. -- c
=== compilers/imcc/pbc.c ================================================================== --- compilers/imcc/pbc.c (revision 4015) +++ compilers/imcc/pbc.c (local) @@ -782,8 +782,6 @@ else sub->multi_signature = NULL; - Parrot_store_sub_in_namespace(interp, sub_pmc); - if (unit->is_vtable_method == 1) { /* Work out the name of the vtable method. */ if (unit->vtable_name != NULL) @@ -808,6 +806,8 @@ sub->vtable_index = vtable_index; } + Parrot_store_sub_in_namespace(interp, sub_pmc); + pfc->type = PFC_PMC; pfc->u.key = sub_pmc; unit->sub_pmc = sub_pmc; === src/objects.c ================================================================== --- src/objects.c (revision 4015) +++ src/objects.c (local) @@ -81,28 +81,30 @@ static PMC* find_vtable_meth_ns(Interp *interp, PMC *ns, INTVAL vtable_index) { - const INTVAL k = VTABLE_elements(interp, ns); - PMC * const key = VTABLE_nextkey_keyed(interp, key_new(interp), ns, - ITERATE_FROM_START); + PMC *res = VTABLE_get_pmc_keyed_int(interp, ns, vtable_index); - const char * const meth = Parrot_vtable_slot_names[vtable_index]; - STRING * const meth_str = string_from_cstring(interp, meth, strlen(meth)); + if (! PMC_IS_NULL(res)) + return res; + else { + const char * const meth = Parrot_vtable_slot_names[vtable_index]; - int j; + STRING *meth_str = string_from_cstring(interp, meth, 0); + res = VTABLE_get_pmc_keyed_str(interp, ns, meth_str); - for (j = 0; j < k; ++j) { - STRING * const ns_key = (STRING *)parrot_hash_get_idx(interp, - (Hash *)PMC_struct_val(ns), key); - PMC * const res = VTABLE_get_pmc_keyed_str(interp, ns, ns_key); + if ( ! PMC_IS_NULL(res) + && VTABLE_isa(interp, res, CONST_STRING(interp, "Sub"))) + return res; + else { + meth_str = string_from_cstring(interp, meth + 2, 0); + res = VTABLE_get_pmc_keyed_str(interp, ns, meth_str); - /* success if matching vtable index or double-underscored name */ - if (res->vtable->base_type == enum_class_Sub && - (PMC_sub(res)->vtable_index == vtable_index || - string_compare(interp, meth_str, ns_key) == 0)) - return res; + if ( ! PMC_IS_NULL(res) + && VTABLE_isa(interp, res, CONST_STRING(interp, "Sub"))) + return res; + } + + return PMCNULL; } - - return PMCNULL; } /* === src/pmc/namespace.pmc ================================================================== --- src/pmc/namespace.pmc (revision 4015) +++ src/pmc/namespace.pmc (local) @@ -52,11 +52,12 @@ /* We store extra information about the namespace in a struct, which we will * hang off the PMC_data slot. */ typedef struct Parrot_NSInfo { - STRING *name; /* Name of this namespace part. */ - PMC *_class; /* The class or role attached to this namespace. */ + STRING *name; /* Name of this namespace part. */ + PMC *_class; /* The class or role attached to this namespace. */ + PMC *vtable; } Parrot_NSInfo; -/* Macro for easy access to the namespcae info. */ +/* Macro for easy access to the namespace info. */ #define PARROT_NSINFO(o) ((Parrot_NSInfo *) PMC_data(o)) @@ -74,9 +75,10 @@ */ void init() { - SUPER(); /* _struct_val := Hash */ - PMC_pmc_val(SELF) = NULL; /* parent */ - PMC_data(SELF) = mem_allocate_zeroed_typed(Parrot_NSInfo); + SUPER(); /* _struct_val := Hash */ + PMC_pmc_val(SELF) = NULL; /* parent */ + PMC_data(SELF) = mem_allocate_zeroed_typed(Parrot_NSInfo); + PARROT_NSINFO(SELF)->vtable = PMCNULL; } /* @@ -97,6 +99,8 @@ pobject_lives(INTERP, (PObj*)nsinfo->name); if (nsinfo->_class) pobject_lives(INTERP, (PObj*)nsinfo->_class); + if (nsinfo->vtable) + pobject_lives(INTERP, (PObj*)nsinfo->vtable); } /* @@ -132,7 +136,7 @@ Return the given namespace or PMCNULL. C<key> is either an array of strings, or a possibly nested key. -=item C<PMC* get_pmc_keyed_str(PMC *key)> +=item C<PMC* get_pmc_keyed_str(STRING *key)> Return the given namespace item or PMCNULL. If the named item is either a NameSpace or a var, the NameSpace is returned. @@ -198,6 +202,19 @@ VTABLE_set_pmc_keyed_int(INTERP, new_tuple, NS_slot_var_sub, value); b->value = new_tuple; } + + if (value->vtable->base_type == enum_class_Sub) { + Parrot_NSInfo *nsinfo = PARROT_NSINFO(SELF); + PMC *vtable = nsinfo->vtable; + Parrot_sub *sub = PMC_sub(value); + + if (PMC_IS_NULL(vtable)) + nsinfo->vtable = vtable = pmc_new(interp, enum_class_Hash); + + if (sub->vtable_index != -1) + VTABLE_set_pmc_keyed_int(INTERP, vtable, + sub->vtable_index, value); + } } void set_pmc_keyed(PMC *key, PMC *value) { @@ -263,6 +280,16 @@ return PMCNULL; } + PMC* get_pmc_keyed_int(INTVAL key) { + Parrot_NSInfo *nsinfo = PARROT_NSINFO(SELF); + PMC *vtable = nsinfo->vtable; + + if (PMC_IS_NULL(vtable)) + return PMCNULL; + + return VTABLE_get_pmc_keyed_int(interp, vtable, key); + } + /* =item C<void* get_pointer_keyed_str(STRING *key)>