Author: leo
Date: Fri Mar 10 06:24:22 2006
New Revision: 11853

Modified:
   trunk/src/pmc/fixedpmcarray.pmc
   trunk/src/pmc/namespace.pmc

Log:
Namespaces 13 - implement half-typed namespace storage

* to be compliant with current behavior, a namespace slot can hold 
  another namespace, a var_or_sub, or both (but not a var and a sub)
* expanding this scheme to a fully typed namespace should be simple  


Modified: trunk/src/pmc/fixedpmcarray.pmc
==============================================================================
--- trunk/src/pmc/fixedpmcarray.pmc     (original)
+++ trunk/src/pmc/fixedpmcarray.pmc     Fri Mar 10 06:24:22 2006
@@ -11,6 +11,11 @@
 This class, FixedPMCArray, implements an array of fixed size, which stores 
PMCs,
 it puts things into Integer, Float, or String PMCs as appropriate
 
+=head2 Note
+
+The flag C<PObj_private0_FLAG> is used in the C<NameSpace> PMC and should 
+never be set for user arrays.
+
 =head2 Functions
 
 =over 4

Modified: trunk/src/pmc/namespace.pmc
==============================================================================
--- trunk/src/pmc/namespace.pmc (original)
+++ trunk/src/pmc/namespace.pmc Fri Mar 10 06:24:22 2006
@@ -12,8 +12,9 @@
 
 =head2 Data
 
-  PMC_struct_val       ... the hash, bucket->value is an array
-                           of 3 PMCs (namespace, sub, var) slot ???
+  PMC_struct_val       ... the hash, bucket->value is either a
+                           var/sub or a namespace, of a FixedPMCarray
+                           of 2 PMCs (namespace, sub/var) slots
   PMC_pmc_val          ... parent namespace
   PMC_data             ... name STRING of this namespace part 
 
@@ -28,6 +29,25 @@
 #include "parrot/parrot.h"
 #include <assert.h>
 
+/*
+ * Typically a named slot either contains another namespace or a
+ * var/sub (not both). 
+ * In case that the bucket->value is occupied, a FixedPMCArray is
+ * created, and the items are moved over to that extra storage.
+ * The array is flagged with FPA_is_ns_ext to distinguish it from a
+ * plain array variable.
+ *
+ * This could easily expanded to a full-fledged typed namespace if needed. 
+ */
+
+enum {
+    NS_slot_ns,
+    NS_slot_var_sub,         /* unspecified ~half-raw slot */
+    NS_max_slots
+} NS_slot_enum;
+
+#define FPA_is_ns_ext PObj_private0_FLAG
+
 pmclass NameSpace extends Hash need_ext {
 
 /*
@@ -83,15 +103,67 @@
 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)> 
+
+Return the given namespace item or PMCNULL. If the named item is either
+a NameSpace or a var, the NameSpace is returned.
+
 =cut
 
 */
 
     void set_pmc_keyed_str(STRING *key, PMC *value) {
-        SUPER(key, value);
-        if (value->vtable->base_type == enum_class_NameSpace) {
+        PMC *tuple = NULL;
+        HashBucket *b = hash_get_bucket(INTERP, 
+                (Hash*) PMC_struct_val(SELF), key);
+        int val_is_NS = value->vtable->base_type == enum_class_NameSpace;
+        if (PMC_IS_NULL(value))
+            real_exception(INTERP, NULL, E_NameError,
+                    "Attempt to set NULL namespace (part)");
+        if (!b)
+            SUPER(key, value);
+        else {
+            PMC *old = b->value;
+            if (old->vtable->base_type == enum_class_NameSpace &&
+                    val_is_NS) {
+                SUPER(key, value);      /* ns changed */
+            }
+            else if (old->vtable->base_type != enum_class_NameSpace &&
+                    !val_is_NS) {
+                SUPER(key, value);      /* var/sub changed */
+            }
+            else if ((PObj_get_FLAGS(old) & FPA_is_ns_ext) &&
+                    old->vtable->base_type == enum_class_FixedPMCArray) {
+                /* we have a tuple extension already */
+                VTABLE_set_pmc_keyed_int(INTERP, old, 
+                        val_is_NS ? NS_slot_ns : NS_slot_var_sub, value);
+            }
+            else {
+                /* creat new tuple */
+                tuple = pmc_new(INTERP, enum_class_FixedPMCArray);
+                /* flag it as special */
+                PObj_get_FLAGS(tuple) |= FPA_is_ns_ext;
+                /* for a fully typed namespace, we'd need 3 or 4 */
+                VTABLE_set_integer_native(INTERP, tuple, NS_max_slots);
+            }
+        }
+        if (val_is_NS) {
             PMC_pmc_val(value) = SELF;  /* set parent */
             PMC_data(value)    = key;   /* and name */
+            if (tuple) {
+                VTABLE_set_pmc_keyed_int(INTERP, tuple, NS_slot_ns, value);
+                VTABLE_set_pmc_keyed_int(INTERP, tuple, NS_slot_var_sub, 
+                        b->value);
+                b->value = tuple;
+                /* distinction from a plain FPA, which doesn't extend the
+                 * namespace storage
+                 */
+            }
+        }
+        else if (tuple) {
+            VTABLE_set_pmc_keyed_int(INTERP, tuple, NS_slot_ns, b->value);
+            VTABLE_set_pmc_keyed_int(INTERP, tuple, NS_slot_var_sub, value);
+            b->value = tuple;
         }
     }
 
@@ -106,11 +178,15 @@
         }
     }
 
-    /* XXX Hash would return Undef, which is probably wrong */
     PMC* get_pmc_keyed_str (STRING* key) {
-        HashBucket *b = hash_get_bucket(INTERP, 
+        PMC *ns = hash_get(INTERP, 
                 (Hash*) PMC_struct_val(SELF), key);
-        return b->value;
+        if (!ns)
+            return PMCNULL;
+        if ((PObj_get_FLAGS(ns) & FPA_is_ns_ext) &&
+                ns->vtable->base_type == enum_class_FixedPMCArray)
+            ns = VTABLE_get_pmc_keyed_int(INTERP, ns, NS_slot_ns);
+        return ns ? ns : PMCNULL;
     }
     
     PMC* get_pmc_keyed(PMC *key) {
@@ -122,7 +198,7 @@
             while (key) {
                 part = key_string(INTERP, key);
                 ns = VTABLE_get_pmc_keyed_str(INTERP, ns, part);
-                if (!ns)
+                if (ns == PMCNULL)
                     return PMCNULL;
                 key = key_next(INTERP, key);
             }
@@ -134,7 +210,7 @@
         for (i = 0; i < n; ++i) {
             part = VTABLE_get_string_keyed_int(INTERP, key, i);
             ns = VTABLE_get_pmc_keyed_str(INTERP, ns, part);
-            if (!ns)
+            if (ns == PMCNULL)
                 return PMCNULL;
         }
         return ns;

Reply via email to