Author: leo
Date: Sun Mar 12 05:52:21 2006
New Revision: 11873

Modified:
   trunk/src/global.c
   trunk/src/pmc/namespace.pmc

Log:
Namespaces 17 - implement set_pmc_keyed with complex keys

* create chained namespaces as needed
* refactor store_sub_in_namespace()
* always store a Sub's namespace_stash, when Subs are created


Modified: trunk/src/global.c
==============================================================================
--- trunk/src/global.c  (original)
+++ trunk/src/global.c  Sun Mar 12 05:52:21 2006
@@ -232,52 +232,69 @@
 }
 
 static void
-store_sub_in_namespace(Parrot_Interp interpreter, PMC* sub_pmc,
-        PMC *namespace, STRING *sub_name)
+store_sub(Interp *interpreter, STRING *class,
+        STRING *globalname, PMC *pmc)
 {
     PMC *globals = interpreter->stash_hash;
-    INTVAL type, class_type;
+    PMC *stash;
+    if (class) {
+        stash = Parrot_global_namespace(interpreter, globals, class);
+    }
+    else
+        stash = globals;  /*  TODO current */
+    VTABLE_set_pmc_keyed_str(interpreter, stash, globalname, pmc);
+    Parrot_invalidate_method_cache(interpreter, class, globalname);
+    /* MultiSub isa R*PMCArray and doesn't have a PMC_sub structure 
+     * MultiSub could also contain subs from various namespaces,
+     * that it doesn't make much sense, to associate a namespace
+     * a multi.
+     *
+     */
+    if (pmc->vtable->base_type != enum_class_MultiSub)
+        PMC_sub(pmc)->namespace_stash = stash;
+}
 
-#if DEBUG_GLOBAL
-    fprintf(stderr, "PMC_CONST: store_global: name '%s' ns %s\n",
-            (char*)sub_name->strstart,
-            namespace ? (char*)PMC_str_val(namespace)->strstart : "(none)");
-#endif
+static void
+store_sub_p(Interp *interpreter, PMC *namespace,
+        STRING *globalname, PMC *pmc)
+{
+    PMC *globals = interpreter->stash_hash;
+    PMC *stash;
+    stash = VTABLE_get_pmc_keyed(interpreter, globals, namespace);
+    if (!stash || stash->vtable->base_type != enum_class_NameSpace) {
+        stash = pmc_new(interpreter, enum_class_NameSpace);
+        VTABLE_set_pmc_keyed(interpreter, globals, namespace, stash);
+    }
+    VTABLE_set_pmc_keyed_str(interpreter, stash, globalname, pmc);
+    /* MultiSub isa R*PMCArray and doesn't have a PMC_sub structure */
+    if (pmc->vtable->base_type != enum_class_MultiSub)
+        PMC_sub(pmc)->namespace_stash = stash;
+}
+
+static void
+store_sub_in_namespace(Parrot_Interp interpreter, PMC* sub_pmc,
+        PMC *namespace, STRING *sub_name)
+{
     /*
      * namespace is either s String or a Key PMC or NULL
      */
     if (PMC_IS_NULL(namespace)) {
 global_ns:
         /* XXX store relative - not absolute */
-        Parrot_store_global(interpreter, NULL, sub_name, sub_pmc);
+        store_sub(interpreter, NULL, sub_name, sub_pmc);
     }
     else {
         STRING *names;
-        PMC * stash = NULL, *part;
-
-        type = namespace->vtable->base_type;
+        INTVAL type = namespace->vtable->base_type;
         switch (type) {
             case enum_class_String:
                 names = PMC_str_val(namespace);
                 if (!string_length(interpreter, names))
                     goto global_ns;
-                Parrot_store_global(interpreter, names, sub_name, sub_pmc);
+                store_sub(interpreter, names, sub_name, sub_pmc);
                 break;
             case enum_class_Key:
-                part = namespace;
-                /*
-                 * a nested key can't be handled by add_method
-                 */
-                for (; part; part = PMC_data(part)) {
-                    STRING *s = key_string(interpreter, part);
-#if TRACE_PACKFILE_PMC
-                    PIO_printf(interpreter, "key part %Ss\n", s);
-#endif
-                    stash = Parrot_global_namespace(interpreter, globals, s);
-                    globals = stash;
-                }
-                VTABLE_set_pmc_keyed_str(interpreter, stash, sub_name, 
sub_pmc);
-                PMC_sub(sub_pmc)->namespace_stash = stash;
+                store_sub_p(interpreter, namespace, sub_name, sub_pmc);
                 break;
             default:
                 internal_exception(1, "Unhandled namespace constant");

Modified: trunk/src/pmc/namespace.pmc
==============================================================================
--- trunk/src/pmc/namespace.pmc (original)
+++ trunk/src/pmc/namespace.pmc Sun Mar 12 05:52:21 2006
@@ -168,13 +168,47 @@
     }
 
     void set_pmc_keyed(PMC *key, PMC *value) {
-        switch (PObj_get_FLAGS(key) & KEY_type_FLAGS) {
-            case KEY_string_FLAG:
-                SELF.set_pmc_keyed_str(key_string(INTERP, key), value);
-                if (!key_next(INTERP, key))
+        PMC *ns = SELF, *next;
+        STRING *part;
+        INTVAL i, n;
+        if (key->vtable->base_type == enum_class_Key) {
+            while (1) {
+                part = key_string(INTERP, key);
+                key = key_next(INTERP, key);
+                next = VTABLE_get_pmc_keyed_str(INTERP, ns, part);
+                if (key) {
+                    if (!next || 
+                            next->vtable->base_type != enum_class_NameSpace) {
+                        next = pmc_new(interpreter, enum_class_NameSpace);
+                        VTABLE_set_pmc_keyed_str(INTERP, ns, part, next);
+                    }
+                }
+                else {
+                    VTABLE_set_pmc_keyed_str(INTERP, ns, part, value);
                     break;
-            default:
-                assert("not yet" == NULL);
+                }
+                ns = next;
+            }
+            return;
+        }
+        n = VTABLE_elements(INTERP, key);
+        if (!n)
+            real_exception(INTERP, NULL, E_NameError,
+                    "Empty namespace array");
+        for (i = 0; ; ++i) {
+            part = VTABLE_get_string_keyed_int(INTERP, key, i);
+            next = VTABLE_get_pmc_keyed_str(INTERP, ns, part);
+            if (i < n - 1) {
+                if (!next || next->vtable->base_type != enum_class_NameSpace) {
+                    next = pmc_new(interpreter, enum_class_NameSpace);
+                    VTABLE_set_pmc_keyed_str(INTERP, ns, part, next);
+                }
+            }
+            else {
+                VTABLE_set_pmc_keyed_str(INTERP, ns, part, value);
+                break;
+            }
+            ns = next;
         }
     }
 

Reply via email to