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)>

Reply via email to