# New Ticket Created by  Steve Fink 
# Please include the string:  [netlabs #571]
# in the subject line of all future correspondence about this issue. 
# <URL: http://bugs6.perl.org/rt2/Ticket/Display.html?id=571 >


This patch is independent of the previous one I sent out.

Creates a new type UnionVal that is a union of all the base types
floating around, and uses this new type in place of various unions
(usually called 'cache', even when they weren't).

But the main point of this patch is to convert KEY from an array of
KEY_PAIR to a linked list of something I call KEY_ATOM. The keys pod
is updated to reflect this change, and a couple of minor bugs in the
docs are also fixed.

THIS PATCH DOES NOT WORK ALONE!

This patch requires perlhash.pmc to be switched over to the new style
of KEYs. I will be sending out two ways of doing this: first, a dummy
patch that fixes the compile errors in perlhash.pmc but doesn't make
it do anything. (It still crashes if you attempt to use it, just like
it did before any of these patches.) Second, I will be sending out a
working hashtable implementation soon that can be used instead. "Soon"
as in it is now working, and I just need to carve it out of all my
local changes. I made the dummy perlhash.pmc patch in case the hash
patch isn't accepted or takes a while, because this KEY patch is
independently useful to what people are working on right now (eg the
assembler).

I'm still figuring out the proper way to send patches to the bugs
address. It looks like it forwards the initial message to
perl6-internals, but not followups? I guess I'll send the dummy
perlhash.pmc patch as a reply and a cc to p6i.

Index: include/parrot/interpreter.h
===================================================================
RCS file: /home/perlcvs/parrot/include/parrot/interpreter.h,v
retrieving revision 1.42
diff -a -u -r1.42 interpreter.h
--- include/parrot/interpreter.h        11 May 2002 20:19:52 -0000      1.42
+++ include/parrot/interpreter.h        14 May 2002 22:05:31 -0000
@@ -40,6 +40,14 @@
 #include "parrot/op.h"
 #include "parrot/oplib.h"
 
+typedef union UnionVal {
+    INTVAL int_val;
+    FLOATVAL num_val;
+    DPOINTER* struct_val;
+    STRING* string_val;
+    PMC* pmc_val;
+} UnionVal;
+
 typedef struct warnings_t {
     Warnings_classes classes;
 } *Warnings;
Index: core.ops
===================================================================
RCS file: /home/perlcvs/parrot/core.ops,v
retrieving revision 1.135
diff -a -u -r1.135 core.ops
--- core.ops    12 May 2002 04:37:57 -0000      1.135
+++ core.ops    14 May 2002 22:05:09 -0000
@@ -3,10 +3,10 @@
 */
 
 /* This (now even more) convoluted mess avoids costly runtime creation
- * of KEY and KEY_PAIR structures, and can be used in an expression.
+ * of KEY structures, and can be used in an expression.
  */
 
-#define MAKE_KEY(k,k_p,v,c,t) (k_p.type = c, k_p.cache.t = v, k.size = 1, k.keys = 
&k_p, &k)
+#define MAKE_KEY(k,v,c,t) (k.atom.type = c, k.atom.val.t = v, k.next = NULL, &k)
 
 VERSION = PARROT_VERSION;
 
@@ -598,97 +598,85 @@
 }
 
 inline op get_keyed(out INT, in PMC, in INT) {
-  KEY_PAIR key_p;
   KEY key;
-  MAKE_KEY(key, key_p, $3, enum_key_int, int_val);
+  MAKE_KEY(key, $3, enum_key_int, int_val);
   $1 = $2->vtable->get_integer_keyed(interpreter, $2, &key);
   goto NEXT();
 }
 
 inline op get_keyed(out INT, in PMC, in NUM) {
-  KEY_PAIR key_p;
   KEY key;
-  MAKE_KEY(key, key_p, $3, enum_key_num, num_val);
+  MAKE_KEY(key, $3, enum_key_num, num_val);
   $1 = $2->vtable->get_integer_keyed(interpreter, $2, &key);
   goto NEXT();
 }
 
 inline op get_keyed(out INT, in PMC, in STR) {
-  KEY_PAIR key_p;
   KEY key;
-  MAKE_KEY(key, key_p, $3, enum_key_string, struct_val);
+  MAKE_KEY(key, $3, enum_key_string, struct_val);
   $1 = $2->vtable->get_integer_keyed(interpreter, $2, &key);
   goto NEXT();
 }
 
 inline op get_keyed(out NUM, in PMC, in INT) {
-  KEY_PAIR key_p;
   KEY key;
-  MAKE_KEY(key, key_p, $3, enum_key_int, int_val);
+  MAKE_KEY(key, $3, enum_key_int, int_val);
   $1 = $2->vtable->get_number_keyed(interpreter, $2, &key);
   goto NEXT();
 }
 
 inline op get_keyed(out NUM, in PMC, in NUM) {
-  KEY_PAIR key_p;
   KEY key;
-  MAKE_KEY(key, key_p, $3, enum_key_num, num_val);
+  MAKE_KEY(key, $3, enum_key_num, num_val);
   $1 = $2->vtable->get_number_keyed(interpreter, $2, &key);
   goto NEXT();
 }
 
 inline op get_keyed(out NUM, in PMC, in STR) {
-  KEY_PAIR key_p;
   KEY key;
-  MAKE_KEY(key, key_p, $3, enum_key_string, struct_val);
+  MAKE_KEY(key, $3, enum_key_string, struct_val);
   $1 = $2->vtable->get_number_keyed(interpreter, $2, &key);
   goto NEXT();
 }
 
 inline op get_keyed(out STR, in PMC, in INT) {
-  KEY_PAIR key_p;
   KEY key;
-  MAKE_KEY(key, key_p, $3, enum_key_int, int_val);
+  MAKE_KEY(key, $3, enum_key_int, int_val);
   $1 = $2->vtable->get_string_keyed(interpreter, $2, &key);
   goto NEXT();
 }
 
 inline op get_keyed(out STR, in PMC, in NUM) {
-  KEY_PAIR key_p;
   KEY key;
-  MAKE_KEY(key, key_p, $3, enum_key_num, num_val);
+  MAKE_KEY(key, $3, enum_key_num, num_val);
   $1 = $2->vtable->get_string_keyed(interpreter, $2, &key);
   goto NEXT();
 }
 
 inline op get_keyed(out STR, in PMC, in STR) {
-  KEY_PAIR key_p;
   KEY key;
-  MAKE_KEY(key, key_p, $3, enum_key_string, struct_val);
+  MAKE_KEY(key, $3, enum_key_string, struct_val);
   $1 = $2->vtable->get_string_keyed(interpreter, $2, &key);
   goto NEXT();
 }
 
 inline op get_keyed(out PMC, in PMC, in INT) {
-  KEY_PAIR key_p;
   KEY key;
-  MAKE_KEY(key, key_p, $3, enum_key_int, int_val);
+  MAKE_KEY(key, $3, enum_key_int, int_val);
   $1 = $2->vtable->get_pmc_keyed(interpreter, $2, &key);
   goto NEXT();
 }
 
 inline op get_keyed(out PMC, in PMC, in NUM) {
-  KEY_PAIR key_p;
   KEY key;
-  MAKE_KEY(key, key_p, $3, enum_key_num, num_val);
+  MAKE_KEY(key, $3, enum_key_num, num_val);
   $1 = $2->vtable->get_pmc_keyed(interpreter, $2, &key);
   goto NEXT();
 }
 
 inline op get_keyed(out PMC, in PMC, in STR) {
-  KEY_PAIR key_p;
   KEY key;
-  MAKE_KEY(key, key_p, $3, enum_key_string, struct_val);
+  MAKE_KEY(key, $3, enum_key_string, struct_val);
   $1 = $2->vtable->get_pmc_keyed(interpreter, $2, &key);
   goto NEXT();
 }
@@ -718,11 +706,10 @@
 =cut
 
 inline op set_keyed (out PMC, in PMC, in PMC, in PMC)  {
-    KEY_PAIR src_key_p, dest_key_p;
     KEY src_key, dest_key;
 
-    MAKE_KEY(src_key, src_key_p, $2, enum_key_pmc, pmc_val);
-    MAKE_KEY(dest_key, dest_key_p, $4, enum_key_pmc, pmc_val);
+    MAKE_KEY(src_key, $2, enum_key_pmc, pmc_val);
+    MAKE_KEY(dest_key, $4, enum_key_pmc, pmc_val);
 
     $1->vtable->set_pmc_keyed(interpreter, 
                     $1, $2 ? &src_key : NULL, $3, $4 ? &dest_key : NULL);
@@ -730,120 +717,108 @@
 }
 
 inline op set_keyed (out PMC, in INT, in INT)  {
-    KEY_PAIR key_p;
     KEY key;
 
-    MAKE_KEY(key, key_p, $2, enum_key_int, int_val);
+    MAKE_KEY(key, $2, enum_key_int, int_val);
 
     $1->vtable->set_integer_keyed(interpreter, $1, &key, $3);
     goto NEXT();
 }
 
 inline op set_keyed (out PMC, in NUM, in INT)  {
-    KEY_PAIR key_p;
     KEY key;
 
-    MAKE_KEY(key, key_p, $2, enum_key_num, num_val);
+    MAKE_KEY(key, $2, enum_key_num, num_val);
 
     $1->vtable->set_integer_keyed(interpreter, $1, &key, $3);
     goto NEXT();
 }
 
 inline op set_keyed (out PMC, in STR, in INT)  {
-    KEY_PAIR key_p;
     KEY key;
 
-    MAKE_KEY(key, key_p, $2, enum_key_string, struct_val);
+    MAKE_KEY(key, $2, enum_key_string, struct_val);
 
     $1->vtable->set_integer_keyed(interpreter, $1, &key, $3);
     goto NEXT();
 }
 
 inline op set_keyed (out PMC, in INT, in NUM)  {
-    KEY_PAIR key_p;
     KEY key;
 
-    MAKE_KEY(key, key_p, $2, enum_key_int, int_val);
+    MAKE_KEY(key, $2, enum_key_int, int_val);
 
     $1->vtable->set_number_keyed(interpreter, $1, &key, $3);
     goto NEXT();
 }
 
 inline op set_keyed (out PMC, in NUM, in NUM)  {
-    KEY_PAIR key_p;
     KEY key;
 
-    MAKE_KEY(key, key_p, $2, enum_key_num, num_val);
+    MAKE_KEY(key, $2, enum_key_num, num_val);
 
     $1->vtable->set_number_keyed(interpreter, $1, &key, $3);
     goto NEXT();
 }
 
 inline op set_keyed (out PMC, in STR, in NUM)  {
-    KEY_PAIR key_p;
     KEY key;
 
-    MAKE_KEY(key, key_p, $2, enum_key_string, struct_val);
+    MAKE_KEY(key, $2, enum_key_string, struct_val);
 
     $1->vtable->set_number_keyed(interpreter, $1, &key, $3);
     goto NEXT();
 }
 
 inline op set_keyed (out PMC, in INT, in STR)  {
-    KEY_PAIR key_p;
     KEY key;
 
-    MAKE_KEY(key, key_p, $2, enum_key_int, int_val);
+    MAKE_KEY(key, $2, enum_key_int, int_val);
 
     $1->vtable->set_string_keyed(interpreter, $1, &key, $3);
     goto NEXT();
 }
 
 inline op set_keyed (out PMC, in NUM, in STR)  {
-    KEY_PAIR key_p;
     KEY key;
 
-    MAKE_KEY(key, key_p, $2, enum_key_num, num_val);
+    MAKE_KEY(key, $2, enum_key_num, num_val);
 
     $1->vtable->set_string_keyed(interpreter, $1, &key, $3);
     goto NEXT();
 }
 
 inline op set_keyed (out PMC, in STR, in STR)  {
-    KEY_PAIR key_p;
     KEY key;
 
-    MAKE_KEY(key, key_p, $2, enum_key_string, struct_val);
+    MAKE_KEY(key, $2, enum_key_string, struct_val);
 
     $1->vtable->set_string_keyed(interpreter, $1, &key, $3);
     goto NEXT();
 }
 
 inline op set_keyed (out PMC, in INT, in PMC)  {
-    KEY_PAIR key_p;
     KEY key;
 
-    MAKE_KEY(key, key_p, $2, enum_key_int, int_val);
+    MAKE_KEY(key, $2, enum_key_int, int_val);
 
     $1->vtable->set_pmc_keyed(interpreter, $1, &key, $3, NULL);
     goto NEXT();
 }
 
 inline op set_keyed (out PMC, in NUM, in PMC)  {
-    KEY_PAIR key_p;
     KEY key;
 
-    MAKE_KEY(key, key_p, $2, enum_key_num, num_val);
+    MAKE_KEY(key, $2, enum_key_num, num_val);
 
     $1->vtable->set_pmc_keyed(interpreter, $1, &key, $3, NULL);
     goto NEXT();
 }
 
 inline op set_keyed (out PMC, in STR, in PMC)  {
-    KEY_PAIR key_p;
     KEY key;
 
-    MAKE_KEY(key, key_p, $2, enum_key_string, struct_val);
+    MAKE_KEY(key, $2, enum_key_string, struct_val);
 
     $1->vtable->set_pmc_keyed(interpreter, $1, &key, $3, NULL);
     goto NEXT();
Index: embed.c
===================================================================
RCS file: /home/perlcvs/parrot/embed.c,v
retrieving revision 1.20
diff -a -u -r1.20 embed.c
--- embed.c     2 Apr 2002 20:35:52 -0000       1.20
+++ embed.c     14 May 2002 22:05:09 -0000
@@ -167,7 +167,6 @@
     INTVAL i;
     PMC *userargv;
     KEY key;
-    KEY_PAIR key_p;
 
     if (Interp_flags_TEST(interpreter, PARROT_DEBUG_FLAG)) {
         fprintf(stderr, "*** Parrot VM: Debugging enabled. ***\n");
@@ -201,9 +203,8 @@
     /* immediately anchor pmc to root set */
     interpreter->pmc_reg.registers[0] = userargv;
 
-    key.size = 1;
-    key.keys = &key_p;
-    key_p.type = enum_key_int;
+    key.atom.type = enum_key_int;
+    key.next = NULL;
 
     for (i = 0; i < argc; i++) {
         STRING* arg = string_make(interpreter, argv[i], strlen(argv[i]),
@@ -213,7 +214,7 @@
             fprintf(stderr, "\t" INTVAL_FMT ": %s\n", i, argv[i]);
         }
 
-        key_p.cache.int_val = i;
+        key.atom.val.int_val = i;
         userargv->vtable->set_string_keyed(interpreter, userargv, &key, arg);
     }
 
Index: key.c
===================================================================
RCS file: /home/perlcvs/parrot/key.c,v
retrieving revision 1.24
diff -a -u -r1.24 key.c
--- key.c       2 Apr 2002 20:35:52 -0000       1.24
+++ key.c       14 May 2002 22:05:09 -0000
@@ -14,107 +14,6 @@
 
 #include "parrot/parrot.h"
 
-struct _bucket {
-    KEY_PAIR pair;
-    STRING *key;
-    struct _bucket *next;
-};
-
-typedef struct _bucket BUCKET;
-
-static void
-debug_key(struct Parrot_Interp *interpreter, KEY *key)
-{
-    INTVAL i;
-    fprintf(stderr, " *** key %p\n", key);
-    fprintf(stderr, " *** size " INTVAL_FMT "\n", key->size);
-    for (i = 0; i < key->size; i++) {
-        INTVAL type = key->keys[i].type;
-        if (type == enum_key_bucket) {
-            fprintf(stderr, " *** Bucket " INTVAL_FMT " type " INTVAL_FMT "\n",
-                    i, type);
-        }
-        else if (type != enum_key_undef) {
-            fprintf(stderr, " *** Other " INTVAL_FMT " type " INTVAL_FMT "\n",
-                    i, type);
-        }
-    }
-}
-
-static BUCKET *
-new_bucket(struct Parrot_Interp *interpreter, STRING *key, KEY_PAIR *pair)
-{
-    BUCKET *bucket = mem_sys_allocate(sizeof(BUCKET));
-    if (bucket != NULL) {
-        if (key != NULL) {
-            if (pair != NULL) {
-                bucket->key = string_copy(interpreter, key);
-                memcpy(&bucket->pair, pair, sizeof(KEY_PAIR));
-            }
-            else {
-                fprintf(stderr, "*** new_bucket was given a null pair\n");
-            }
-        }
-        else {
-            fprintf(stderr, "*** new_bucket was given a null key\n");
-        }
-    }
-    else {
-        fprintf(stderr, "*** new_bucket attempted to return a null bucket\n");
-    }
-    return bucket;
-}
-
-static KEY_PAIR *
-find_bucket(struct Parrot_Interp *interpreter, BUCKET *head, STRING *key)
-{
-    KEY_PAIR *pair = NULL;
-    if (head != NULL) {
-        if (key != NULL) {
-            while (head != NULL) {
-                if (string_compare(interpreter, key, head->key) == 0) {
-                    pair = &head->pair;
-                    break;
-                }
-                head = head->next;
-            }
-        }
-        else {
-            fprintf(stderr, "*** find_bucket given a null key\n");
-        }
-    }
-    else {
-        fprintf(stderr, "*** find_bucket given a null bucket\n");
-    }
-    return pair;
-}
-
-/*=for api key key_hash
-
-Return the hashed value of the string
-
-=cut
-*/
-
-static INTVAL
-key_hash(struct Parrot_Interp *interpreter, STRING *value)
-{
-    char *buffptr = value->bufstart;
-    INTVAL len = value->bufused;
-    INTVAL hash = 5893;
-
-    UNUSED(interpreter);
-
-    while (len--) {
-        hash = hash * 33 + *buffptr++;
-    }
-    if (hash < 0) {
-        hash = -hash;
-    }
-    return hash;
-}
-
-
 /*=for api key key_new
 
 Return a pointer to a new KEY structure
@@ -123,14 +22,14 @@
 */
 
 KEY *
-key_new(struct Parrot_Interp *interpreter)
+key_new(Interp *interpreter)
 {
     KEY *key = mem_sys_allocate(sizeof(KEY));
 
     UNUSED(interpreter);
 
-    key->size = 0;
-    key->keys = NULL;
+    key->atom.type = enum_key_undef;
+    key->next = NULL;
 
     return key;
 }
@@ -143,345 +42,15 @@
 */
 
 KEY *
-key_clone(struct Parrot_Interp *interpreter, KEY *key)
+key_clone(Interp *interpreter, KEY *key)
 {
     KEY *new_key = NULL;
-    if (key != NULL) {
-        new_key = key_new(interpreter);
-        memcpy(new_key, key, sizeof(KEY));
-    }
-    else {
-        fprintf(stderr, "*** key_clone attempted to clone a NULL variable\n");
-    }
+    if (key == NULL) return NULL;
+    new_key = key_new(interpreter);
+    new_key->atom = key->atom;
+    new_key->next = key_clone(interpreter, key->next);
     return new_key;
 }
-
-/*=for api key key_size
-
-return the size of KEY <key>
-
-=cut
-*/
-
-INTVAL
-key_size(struct Parrot_Interp *interpreter, KEY *key)
-{
-    UNUSED(interpreter);
-
-    if (key != NULL) {
-        return key->size;
-    }
-    else {
-        fprintf(stderr, "*** key_size asked to check a NULL key\n");
-        return 0;
-    }
-}
-
-/*=for api key key_set_size
-
-Set the size of KEY <key> to <size>.
-
-=cut
-*/
-
-void
-key_set_size(struct Parrot_Interp *interpreter, KEY *key, INTVAL size)
-{
-    UNUSED(interpreter);
-
-    if (key != NULL) {
-        if (size < 0) {
-            fprintf(stderr, "*** key_set_size asked to resize below zero\n");
-            return;
-        }
-        if (size > key->size) {
-            KEY_PAIR *pair =
-                (KEY_PAIR *)realloc(key->keys, sizeof(KEY_PAIR *) * size);
-            if (pair != NULL) {
-                INTVAL i;
-                key->keys = pair;
-                for (i = key->size; i < size; i++) {
-                    key->keys[i].type = enum_key_undef;
-                }
-            }
-            else {
-                fprintf(stderr,
-                        "*** key_set_size tried to allocate a NULL pair\n");
-            }
-        }
-        else if (size < key->size) {
-            INTVAL i;
-            for (i = size; i < key->size; i++) {
-                /* Memory leak in the making */
-            }
-            key->keys =
-                (KEY_PAIR *)realloc(key->keys, sizeof(KEY_PAIR *) * size);
-        }
-        key->size = size;
-    }
-    else {
-        fprintf(stderr, "*** key_set_size attempted to resize a NULL key\n");
-    }
-}
-
-/*=for api key key_destroy
-
-Destroy KEY <key>
-
-=cut
-*/
-
-void
-key_destroy(struct Parrot_Interp *interpreter, KEY *key)
-{
-    UNUSED(interpreter);
-
-    if (key != NULL) {
-        INTVAL i;
-        for (i = 0; i < key->size; i++) {
-            /* Memory leak in the making */
-        }
-        free(key);
-    }
-    else {
-        fprintf(stderr, "*** key_destroy freeing NULL key\n");
-    }
-}
-
-/*=for api key key_element_type
-
-return the type of element <idx> of KEY <key>
-
-=cut
-*/
-
-INTVAL
-key_element_type(struct Parrot_Interp *interpreter, KEY *key, INTVAL idx)
-{
-    UNUSED(interpreter);
-
-    if (key != NULL) {
-        if ((idx >= 0) && (idx < key->size)) {
-            KEY_PAIR *pair = (KEY_PAIR *)&key->keys[idx];
-            return pair->type;
-        }
-        else {
-            fprintf(stderr, "*** key_element_type checking out of bounds\n");
-            return -1;
-        }
-    }
-    fprintf(stderr, "*** key_element_type checking a NULL key\n");
-    return -1;
-}
-
-/*=for api key key_element_value_i
-
-return the value of index <idx> of KEY <key>
-
-=cut
-*/
-
-KEY_PAIR *
-key_element_value_i(struct Parrot_Interp *interpreter, KEY *key, INTVAL idx)
-{
-    UNUSED(interpreter);
-
-    if (key != NULL) {
-        if ((idx >= 0) && (idx < key->size)) {
-            KEY_PAIR *pair = (KEY_PAIR *)&key->keys[idx];
-            if (pair != NULL) {
-                return pair;
-            }
-            else {
-                fprintf(stderr,
-                        "*** key_element_value_i pair returning a null key\n");
-            }
-        }
-        else {
-            fprintf(stderr,
-                    "*** key_element_value_i checking out of bounds\n");
-        }
-    }
-    fprintf(stderr, "*** key_element_value_i checking a NULL key\n");
-    return NULL;
-}
-
-KEY_PAIR *
-key_element_value_s(struct Parrot_Interp *interpreter, KEY *key, STRING *idx)
-{
-    KEY_PAIR *pair = NULL;
-    if (key != NULL) {
-        if (idx != NULL) {
-            INTVAL hash = key_hash(interpreter, idx);
-            hash = hash % NUM_BUCKETS;
-            pair =
-                find_bucket(interpreter,
-                            (BUCKET *)key->keys[hash].cache.struct_val, idx);
-            if (pair == NULL) {
-                internal_exception(KEY_NOT_FOUND,
-                                   "*** key_element_value_s pair returning a null 
key\n");
-            }
-        }
-        else {
-            internal_exception(KEY_NOT_FOUND,
-                               "*** key_element_value_s given a NULL index\n");
-        }
-    }
-    else {
-        internal_exception(KEY_NOT_FOUND,
-                           "*** key_element_value_s given a NULL key\n");
-    }
-    return pair;
-}
-
-/*=for api key key_set_element_value_i
-
-Set the value of index <idx> of key <key> to integer <value>
-
-=cut
-*/
-
-void
-key_set_element_value_i(struct Parrot_Interp *interpreter, KEY *key,
-                        INTVAL idx, KEY_PAIR *value)
-{
-    UNUSED(interpreter);
-
-    if (key != NULL) {
-        if ((idx >= 0) && (idx < key->size)) {
-            memcpy(&key->keys[idx], value, sizeof(KEY_PAIR));
-        }
-        else {
-            internal_exception(KEY_NOT_FOUND,
-                               "*** key_set_element_value_i setting value out of 
bounds\n");
-        }
-    }
-    else {
-        internal_exception(KEY_NOT_FOUND,
-                           "*** key_set_element_value_i assigning to a NULL key\n");
-    }
-}
-
-/*=for api key key_set_element_value_s
-
-Set the value of index <idx> of key <key> to string <value>
-
-=cut
-*/
-
-void
-key_set_element_value_s(struct Parrot_Interp *interpreter, KEY *key,
-                        STRING *idx, KEY_PAIR *value)
-{
-    if (key != NULL) {
-        if (idx != NULL) {
-            if (value != NULL) {
-                INTVAL hash = key_hash(interpreter, idx);
-                BUCKET *bucket = new_bucket(interpreter, idx, value);
-                if (bucket != NULL) {
-                    hash = hash % NUM_BUCKETS;
-                    /* Resize the hash here rather than set an initial size. */
-                    if (hash >= key->size) {
-                        key_set_size(interpreter, key, hash + 1);
-                    }
-                    if (key->keys[hash].type != enum_key_undef) {
-                        STRING *tmp = key->keys[hash].cache.struct_val;
-                        bucket->next = (BUCKET *)tmp;
-                    }
-                    else {
-                    }
-                    key->keys[hash].cache.struct_val = (STRING *)bucket;
-                    key->keys[hash].type = enum_key_bucket;
-                }
-                else {
-                    fprintf(stderr,
-                            "*** key_set_element_value_s given a NULL bucket\n");
-                }
-            }
-            else {
-                fprintf(stderr,
-                        "*** key_set_element_value_s given a NULL value\n");
-            }
-        }
-        else {
-            fprintf(stderr,
-                    "*** key_set_element_value_s given a NULL index\n");
-        }
-    }
-    else {
-        fprintf(stderr, "*** key_set_element_value_s given a NULL key\n");
-    }
-}
-
-/*=for api key key_chop
-
-Remove the last element of key <key>
-
-=cut
-*/
-
-void
-key_chop(struct Parrot_Interp *interpreter, KEY *key)
-{
-    UNUSED(interpreter);
-
-    if (key != NULL) {
-        if (key->size > 0) {
-            /* Memory leak in the making */
-            key->size--;
-            key->keys =
-                (KEY_PAIR *)realloc(key->keys,
-                                     sizeof(KEY_PAIR *) * key->size);
-        }
-        else if (key->size == 0) {
-            fprintf(stderr,
-                    "*** key_chop chopping a zero-length key! SHOULD NOT HAPPEN\n");
-        }
-        else {
-            fprintf(stderr,
-                    "*** key_chop chopping before start! SHOULD NOT HAPPEN\n");
-        }
-    }
-    else {
-        fprintf(stderr, "*** key_chop chopping a NULL key\n");
-    }
-}
-
-/*=for api key key_inc
-
-Increment the type of index <idx> of key <key>
-
-=cut
-*/
-
-void
-key_inc(struct Parrot_Interp *interpreter, KEY *key, INTVAL idx)
-{
-    UNUSED(interpreter);
-
-    if (key != NULL) {
-        if ((idx >= 0) && (idx < key->size)) {
-            KEY_PAIR *pair = (KEY_PAIR *)&key->keys[idx];
-            pair->type++;
-        }
-        else {
-            fprintf(stderr,
-                    "*** key_inc attempting to increment an out-of-range index\n");
-        }
-    }
-    else {
-        fprintf(stderr, "*** key_inc working on a NULL key\n");
-    }
-}
-
-/* PMC-KEY
-
-Keyed bits for PMC access. Separate from the hash key stuff but
-sharing a file for the moment, until the hash key bits get moved
-elsewhere.
-
-*/
-
 
 /*
  * Local variables:
Index: rx.ops
===================================================================
RCS file: /home/perlcvs/parrot/rx.ops,v
retrieving revision 1.18
diff -a -u -r1.18 rx.ops
--- rx.ops      19 Apr 2002 01:32:40 -0000      1.18
+++ rx.ops      14 May 2002 22:05:16 -0000
@@ -372,11 +372,10 @@
 =cut
 
 op rx_info_getgroup(in pmc, out int, out int, in int) {
-        KEY_PAIR key_p;
         KEY key;
        RX_dUNPACK($1);
 
-        MAKE_KEY(key, key_p, $4, enum_key_int, int_val);
+        MAKE_KEY(key, $4, enum_key_int, int_val);
        $2=rx->groupstart->vtable->get_integer_keyed(interpreter, rx->groupstart, 
&key);
        $3=rx->groupend->vtable->get_integer_keyed(interpreter, rx->groupend, &key);
        
@@ -636,11 +635,10 @@
 =cut
 
 op rx_startgroup(in pmc, in int) {
-        KEY_PAIR key_p;
         KEY key;
        RX_dUNPACK($1);
        
-        MAKE_KEY(key, key_p, $2, enum_key_int, int_val);
+        MAKE_KEY(key, $2, enum_key_int, int_val);
        rx->groupstart->vtable->set_integer_keyed(interpreter, rx->groupstart, &key, 
rx->index);
        
        goto NEXT();
@@ -656,11 +654,10 @@
 =cut
 
 op rx_endgroup(in pmc, in int) {
-    KEY_PAIR key_p;
     KEY key;
     RX_dUNPACK($1);
        
-    MAKE_KEY(key, key_p, $2, enum_key_int, int_val);        
+    MAKE_KEY(key, $2, enum_key_int, int_val);        
     rx->groupend->vtable->set_integer_keyed(interpreter, rx->groupend, &key, 
rx->index);
        
     goto NEXT();
Index: classes/array.pmc
===================================================================
RCS file: /home/perlcvs/parrot/classes/array.pmc,v
retrieving revision 1.21
diff -a -u -r1.21 array.pmc
--- classes/array.pmc   15 Apr 2002 21:11:00 -0000      1.21
+++ classes/array.pmc   14 May 2002 22:05:20 -0000
@@ -12,17 +12,19 @@
 
 #include "parrot/parrot.h"
 
-static INTVAL kp2int(struct Parrot_Interp *interpreter, KEY_PAIR kp) {
-    switch ((int)kp.type) {
+static INTVAL atom2int(Interp *interpreter, KEY_ATOM* atom) {
+    switch ((int)atom->type) {
         case enum_key_undef:
         default:
             return 0;
         case enum_key_int:
-            return kp.cache.int_val;
+            return atom->val.int_val;
         case enum_key_num:
-            return (INTVAL)kp.cache.num_val;
+            return (INTVAL)atom->val.num_val;
         case enum_key_pmc:
-            return kp.cache.pmc_val->vtable->get_integer(interpreter, 
kp.cache.pmc_val);
+            return atom->val.pmc_val->vtable->get_integer(interpreter, 
+atom->val.pmc_val);
+        case enum_key_string:
+            return string_to_int(atom->val.struct_val);
     }
 }
 
@@ -88,7 +90,7 @@
     }
 
     INTVAL get_integer_keyed (KEY * key) {
-        KEY_PAIR* kp;
+        KEY_ATOM* kp;
         INTVAL ix;
         PMC* value;
 
@@ -96,8 +98,8 @@
             return 0;
         }
 
-        kp = &key->keys[0];
-        ix = kp2int(INTERP, *kp);
+        kp = &key->atom;
+        ix = atom2int(INTERP, kp);
 
         if (ix > SELF->cache.int_val || ix < 0) {
             internal_exception(OUT_OF_BOUNDS, "Array element out of bounds!\n");
@@ -112,7 +114,7 @@
     }
 
     FLOATVAL get_number_keyed (KEY * key) {
-        KEY_PAIR* kp;
+        KEY_ATOM* kp;
         INTVAL ix;
         PMC* value;
 
@@ -120,8 +122,8 @@
             return 0;
         }
 
-        kp = &key->keys[0];
-        ix = kp2int(INTERP, *kp);
+        kp = &key->atom;
+        ix = atom2int(INTERP, kp);
 
         if (ix > SELF->cache.int_val || ix < 0) {
             internal_exception(OUT_OF_BOUNDS, "Array element out of bounds!\n");
@@ -136,7 +138,7 @@
     }
 
     STRING* get_string_keyed (KEY * key) {
-        KEY_PAIR* kp;
+        KEY_ATOM* kp;
         INTVAL ix;
         PMC* value;
 
@@ -144,8 +146,8 @@
             return 0;
         }
 
-        kp = &key->keys[0];
-        ix = kp2int(INTERP, *kp);
+        kp = &key->atom;
+        ix = atom2int(INTERP, kp);
 
         if (ix > SELF->cache.int_val || ix < 0) {
             internal_exception(OUT_OF_BOUNDS, "Array element out of bounds!\n");
@@ -186,7 +188,7 @@
     }
 
     void set_integer_keyed (KEY * key, INTVAL value) {
-        KEY_PAIR* kp;
+        KEY_ATOM* kp;
         INTVAL ix;
         PMC* mypmc;
 
@@ -194,8 +196,8 @@
             return;
         }
 
-        kp = &key->keys[0];
-        ix = kp2int(INTERP, *kp);
+        kp = &key->atom;
+        ix = atom2int(INTERP, kp);
 
         if (ix >= SELF->cache.int_val || ix < 0) {
             internal_exception(OUT_OF_BOUNDS, "Array element out of bounds!\n");
@@ -220,7 +222,7 @@
     }
 
     void set_number_keyed (KEY * key, FLOATVAL value) {
-        KEY_PAIR* kp;
+        KEY_ATOM* kp;
         INTVAL ix;
         PMC* mypmc;
 
@@ -228,8 +230,8 @@
             return;
         }
 
-        kp = &key->keys[0];
-        ix = kp2int(INTERP, *kp);
+        kp = &key->atom;
+        ix = atom2int(INTERP, kp);
 
         if (ix >= SELF->cache.int_val || ix < 0) {
             internal_exception(OUT_OF_BOUNDS, "Array element out of bounds!\n");
@@ -240,7 +242,7 @@
     }
 
     void set_string_keyed (KEY * key, STRING * value) {
-        KEY_PAIR* kp;
+        KEY_ATOM* kp;
         INTVAL ix;
         PMC* mypmc;
 
@@ -248,8 +250,8 @@
             return;
         }
 
-        kp = &key->keys[0];
-        ix = kp2int(INTERP, *kp);
+        kp = &key->atom;
+        ix = atom2int(INTERP, kp);
 
         if (ix >= SELF->cache.int_val || ix < 0) {
             internal_exception(OUT_OF_BOUNDS, "Array element out of bounds!\n");
@@ -264,7 +266,7 @@
             src = src->vtable->get_pmc_keyed(INTERP, src, src_key);
         }
         if (dest_key) {
-            INTVAL ix = kp2int(INTERP, dest_key->keys[0]);
+            INTVAL ix = atom2int(INTERP, &dest_key->atom);
             PMC* dest = ((PMC**)(((Buffer *)SELF->data)->bufstart))[ix];
             dest->vtable->set_pmc(INTERP, dest, src);
         } 
Index: classes/perlarray.pmc
===================================================================
RCS file: /home/perlcvs/parrot/classes/perlarray.pmc,v
retrieving revision 1.28
diff -a -u -r1.28 perlarray.pmc
--- classes/perlarray.pmc       23 Apr 2002 17:19:21 -0000      1.28
+++ classes/perlarray.pmc       14 May 2002 22:05:28 -0000
@@ -39,19 +39,19 @@
     self->cache.int_val = size;
 }
 
-static INTVAL kp2int(Interp *interpreter, KEY_PAIR* kp) {
-    switch ((int)kp->type) {
+static INTVAL atom2int(Interp *interpreter, KEY_ATOM* atom) {
+    switch ((int)atom->type) {
         case enum_key_undef:
         default:
             return 0;
         case enum_key_int:
-            return kp->cache.int_val;
+            return atom->val.int_val;
         case enum_key_num:
-            return (INTVAL)kp->cache.num_val;
+            return (INTVAL)atom->val.num_val;
         case enum_key_pmc:
-            return kp->cache.pmc_val->vtable->get_integer(interpreter, 
kp->cache.pmc_val);
+            return atom->val.pmc_val->vtable->get_integer(interpreter, 
+atom->val.pmc_val);
         case enum_key_string:
-            return string_to_int(kp->cache.struct_val);
+            return string_to_int(atom->val.struct_val);
     }
 }
 
@@ -87,7 +87,7 @@
     }
 
     void destroy () {
-       key_destroy(INTERP,SELF->data); /* XXX Huh? */
+       /* key_destroy(INTERP,SELF->data); XXX Huh? */
     }
 
     INTVAL get_integer () {
@@ -103,7 +103,7 @@
             return 0;
         }
 
-        ix = kp2int(interpreter, &key->keys[0]);
+        ix = atom2int(interpreter, &key->atom);
 
         if (ix >= SELF->cache.int_val) {
            resize_array(interpreter, SELF, ix+1);
@@ -131,7 +131,7 @@
             return 0;
         }
 
-        ix = kp2int(interpreter, &key->keys[0]);
+        ix = atom2int(interpreter, &key->atom);
 
         if (ix >= SELF->cache.int_val) {
            resize_array(interpreter, SELF, ix+1);
@@ -159,7 +159,7 @@
             return 0;
         }
 
-        ix = kp2int(interpreter, &key->keys[0]);
+        ix = atom2int(interpreter, &key->atom);
 
         if (ix >= SELF->cache.int_val) {
            resize_array(interpreter, SELF, ix+1);
@@ -183,7 +183,7 @@
             return 0;
         }
 
-        ix = kp2int(interpreter, &key->keys[0]);
+        ix = atom2int(interpreter, &key->atom);
 
         if (ix >= SELF->cache.int_val) {
            resize_array(interpreter, SELF, ix+1);
@@ -234,14 +234,14 @@
 
     void set_integer_keyed (KEY * key, INTVAL value) {
         INTVAL ix;
-        PMC* pmc2;
+        PMC* element;
         PMC** array;
 
         if (!key) {
             return;
         }
 
-       ix = kp2int(interpreter, &key->keys[0]);
+       ix = atom2int(interpreter, &key->atom);
 
         if (ix >= SELF->cache.int_val) {
            resize_array(interpreter, SELF, ix+1);
@@ -251,11 +251,14 @@
         }
 
         array = ((Buffer *) SELF->data)->bufstart;
-        pmc2 = array[ix];
-        if (pmc2 == NULL)
-            array[ix] = pmc2 = pmc_new(INTERP, enum_class_PerlInt);
+        element = array[ix];
+        if (element == NULL) {
+            element = pmc_new(INTERP, enum_class_PerlInt);
+            array = ((Buffer *) SELF->data)->bufstart; /* May have moved */
+            array[ix] = element;
+        }
 
-        pmc2->vtable->set_integer_native(INTERP, pmc2, value);
+        element->vtable->set_integer_native(INTERP, element, value);
     }
 
     void set_number (PMC * value) {
@@ -277,14 +280,14 @@
 
     void set_number_keyed (KEY * key, FLOATVAL value) {
         INTVAL ix;
-        PMC* pmc2;
+        PMC* element;
         PMC** array;
 
         if (!key) {
             return;
         }
 
-       ix = kp2int(interpreter, &key->keys[0]);
+       ix = atom2int(interpreter, &key->atom);
 
         if (ix >= SELF->cache.int_val) {
            resize_array(interpreter, SELF, ix+1);
@@ -294,11 +297,14 @@
         }
 
         array = ((Buffer *) SELF->data)->bufstart;
-        pmc2 = array[ix];
-        if (pmc2 == NULL)
-            array[ix] = pmc2 = pmc_new(INTERP, enum_class_PerlNum);
+        element = array[ix];
+        if (element == NULL) {
+            element = pmc_new(INTERP, enum_class_PerlNum);
+            array = ((Buffer *) SELF->data)->bufstart; /* May have moved */
+            array[ix] = element;
+        }
 
-        pmc2->vtable->set_number_native(INTERP, pmc2, value);
+        element->vtable->set_number_native(INTERP, element, value);
     }
 
     void set_string (PMC * value) {
@@ -318,14 +324,14 @@
 
     void set_string_keyed (KEY * key, STRING * value) {
         INTVAL ix;
-        PMC* pmc2;
         PMC** array;
+        PMC* element;
 
         if (!key) {
             return;
         }
 
-       ix = kp2int(interpreter, &key->keys[0]);
+       ix = atom2int(interpreter, &key->atom);
 
         if (ix >= SELF->cache.int_val) {
            resize_array(interpreter, SELF, ix+1);
@@ -335,14 +341,17 @@
         }
 
         array = ((Buffer *) SELF->data)->bufstart;
-        pmc2 = array[ix];
-        if (pmc2 == NULL)
-           array[ix] = pmc2 = pmc_new(INTERP, enum_class_PerlString);
+        element = array[ix];
+        if (element == NULL) {
+            element = pmc_new(INTERP, enum_class_PerlString);
+            array = ((Buffer *) SELF->data)->bufstart; /* May have moved */
+            array[ix] = element;
+        }
 
-        pmc2->vtable->set_string_native(INTERP, pmc2, value);
+        element->vtable->set_string_native(INTERP, element, value);
     }
 
-   void set_pmc_keyed (KEY* dest_key, PMC* src, KEY* src_key) {
+    void set_pmc_keyed (KEY* dest_key, PMC* src, KEY* src_key) {
         INTVAL ix;
         PMC* pmc2;
         PMC** array;
@@ -351,7 +360,7 @@
             return;
         }
 
-       ix = kp2int(interpreter, &dest_key->keys[0]);
+       ix = atom2int(interpreter, &dest_key->atom);
 
         if (ix >= SELF->cache.int_val) {
            resize_array(interpreter, SELF, ix+1);
@@ -367,7 +376,7 @@
          * With "set P0[0], P1[1]", I am ignoring P0[0]'s old value and just
          * overwriting it with P1[1]. */
         array[ix] = src;
-   }
+    }
 
     void set_value (void* value) {
     }
Index: docs/pdds/pdd08_keys.pod
===================================================================
RCS file: /home/perlcvs/parrot/docs/pdds/pdd08_keys.pod,v
retrieving revision 1.1
diff -a -u -r1.1 pdd08_keys.pod
--- docs/pdds/pdd08_keys.pod    8 Mar 2002 18:51:45 -0000       1.1
+++ docs/pdds/pdd08_keys.pod    14 May 2002 22:05:30 -0000
@@ -5,22 +5,32 @@
 
 =head1 VERSION
 
-1
-
 =head2 CURRENT
 
    Maintainer: Simon Cozens <[EMAIL PROTECTED]>
    Class: Internals
-   PDD Number: TBD 
-   Version: 1
+   PDD Number: 8
+   Version: 1.2
    Status: Developing
-   Last Modified: 17 February, 2001
+   Last Modified: 25 April, 2002
    PDD Format: 1
    Language: English
 
 =head2 HISTORY
 
-First edition.
+=over 4
+
+=item Thu Apr 25 18:30:36 UTC 2002 : Version 1.2
+
+Renamed C<KEY_PAIR> to C<KEY_ATOM>, updated to reflect changeover to
+linked list. - [EMAIL PROTECTED]
+
+=item Fri Mar  8 18:47:34 GMT 2002 : Version 1.1
+
+updated to reflect Dan's comments that non-aggregates also support
+C<_keyed> variant vtable methods.
+
+=back
 
 =head1 ABSTRACT
 
@@ -41,7 +51,7 @@
 the referent. These aren't aggregates because they don't directly store
 or reference sub-elements.
 
-Indexing operations take one or more aggregate-B<key> pairs. At runtime,
+Indexing operations take one or more aggregate-B<key> atoms. At runtime,
 these operations will index the key into the aggregate returning a
 B<value>. Here is a well-known indexing operation in Perl 6:
 
@@ -64,50 +74,34 @@
 
 Hence, the following structure was produced. First, the individual keys
 as we think of them from a language level are stored in a structure
-called a C<KEY_PAIR>. 
-
-=over 3
-
-=item Todo 
-
-This is a singularly bad name, and needs to change. Probably C<KEY_PART>
-is better. It's a shame C<KEY_ELEMENT> is so confusing, since it's accurate.
-
-=back
+called a C<KEY_ATOM>. 
 
 So, for instance, indexing the multidimensional array
-C<@foo[$a;12;"hi"]> produces three C<KEY_PAIRS>, one with a PMC type,
-one with an integer type and one with a string type. Since C<KEY_PAIRS>
+C<@foo[$a;12;"hi"]> produces three C<KEY_ATOMS>, one with a PMC type,
+one with an integer type and one with a string type. Since C<KEY_ATOMS>
 need to store the type as well as the value, they end up looking like
 this:
 
-    struct _key_pair {
-      KEY_TYPE type;
-      union {
-        INTVAL int_val;
-        FLOATVAL num_val;
-        STRING* struct_val;
-        PMC* pmc_val;
-      } cache;
+    typedef struct _key_atom KEY_ATOM;
+
+    struct _key_atom {
+        KEY_TYPE type;
+        UnionVal val;
     };
 
 The next issue is to combine these things into a single key. Hence,
 the developer-facing C<KEY> structure looks like this:
 
+    typedef struct _key KEY;
+
     struct _key {
-      INTVAL size;
-      KEY_PAIR** keys;
+        KEY_ATOM atom;
+        KEY* next;
     };
 
-=over 3
-
-=item Todo
-
-This needs to turn into a linked list, so that it can support nested
-data structures. When this is done, update this with the explanation
-of why we made this choice.
-
-=back
+So a KEY is a linked list of KEY_ATOMs. A linked list is used so that
+partial keys can be easily generated as a multidimensional data
+structure is traversed.
 
 These structures can be found in F<include/parrot/key.h>
 
@@ -150,18 +144,18 @@
 Secondly, a three-argument C<assign> as suggested by the code above
 would be ambiguous - the code above uses 3 PMCs in different ways. 
 
-Also, operations which take an aggregate-key pair for one of its
-arguments should take aggregate-key pairs for B<all> of its arguments.
+Also, operations which take an aggregate key for one of their
+arguments should take aggregate keys for B<all> of their arguments.
 This is to avoid the following:
 
-    void foo_keyed_i(PMC x, KEY y, INT a)
-    void foo_keyed_n(PMC x, KEY y, NUM a)
-    void foo_keyed_p(PMC x, KEY y, PMC a)
-    void foo_keyed_p_keyed(PMC x, KEY y, PMC a, KEY b)
+    void foo_keyed_i(PMC* x, KEY* y, INT a)
+    void foo_keyed_n(PMC* x, KEY* y, NUM a)
+    void foo_keyed_p(PMC* x, KEY* y, PMC a)
+    void foo_keyed_p_keyed(PMC* x, KEY* y, PMC* a, KEY* b)
 
 These are all replaced with the single entry
 
-    void foo_keyed(PMC x, KEY y, PMC a, KEY b)
+    void foo_keyed(PMC* x, KEY* y, PMC* a, KEY* b)
 
 (Think how much worse it gets when there are three or more PMCs in an
 entry...)
@@ -169,14 +163,18 @@
 Yes. This means that you may need to turn some things into C<PMC>s that
 you didn't want to. Since the alternative is mega pollution and
 duplication in the vtable table, and since the majority of things that
-you'll deal with in a real world situation are expected to be PMCs
+you'll deal with in a real world situation are expected to be C<PMC>s
 anyway, this shouldn't be too much of a problem.
 
 So, if you have a PMC in a C<_keyed> method which you don't want to
 index, pass in C<NULL> instead of a real key. Code implementing these
-methods should understand C<PMC* foo, KEY* NULL> as meaning the entirety
-of C<foo> in some sense; this is trivial to understand if C<foo> is
-non-aggregate, and implementation-defined if C<foo> is aggregate.
+methods should understand C<PMC* foo, KEY* NULL> as meaning the
+entirety of C<foo> in some sense; this is trivial to understand if
+C<foo> is non-aggregate, and implementation-defined if C<foo> is
+aggregate. If you remember that a C<KEY*> is really a linked list,
+you'll notice that after traversing down through the list, you'll
+reach a C<NULL> which again means the entirety of whatever object you
+traversed to.
 
 Similarly, non-C<_keyed> methods on aggregates are implementation
 defined; for instance, a C<set_integer> on a C<PerlArray> may be
@@ -189,8 +187,8 @@
 
 =head2 Input to the assembler
 
-There are several different valid specifications of an aggregate-key
-pair to the assembler. These are:
+There are several different valid specifications of an aggregate key
+to the assembler. These are:
 
     op arg, P1[1234]  # Constant integer key
     op arg, P1[12.34] # Constant number key
@@ -206,12 +204,13 @@
 
 =head2 What the assembler did next
 
-When the assembler sees an aggregate-key pair, it "detaches" the key to
+When the assembler sees an aggregate key, it "detaches" the key to
 form a separate argument. It then decides whether or not it is a
 constant key or a register key. If it is a constant key, the data is
 temporarily munged in the same way as string constants. The constant
 itself is added to the constant integer/number/string list, much like
-any other constant, and an entry is added to the list of constant keys.
+any other constant, and an entry is added to the list of constant
+keys.
 
 Next it selects the appropriate op. Register keys have the signature
 C<r> and constant keys have the signature C<kc>. For example:
@@ -234,7 +233,7 @@
 
 =back
 
-Keys with multiple key-pairs may need to be classed as constant keys.
+Keys with multiple key-atoms may need to be classed as constant keys.
 
 =head2 Bytecode representation
 
@@ -243,8 +242,8 @@
 section of the packfile's constant table. 
 
 Each key in that constant table consists of one byte specifying its
-length in terms of number of key-pairs. For instance, C<["hi"]> has
-length 1; C<["hi";P1;S1;123]> has length 4. Next, each key-pair is
+length in terms of number of key atoms. For instance, C<["hi"]> has
+length 1; C<["hi";P1;S1;123]> has length 4. Next, each key atom is
 specified using two bytes. The first byte is a type specifier:
 
     0 - Integer
@@ -278,9 +277,3 @@
 =head2 The interpreter's interpretation
 
 Delayed until we have bytecode that produces what we want.
-
-=head1 CHANGES
-
-Fri Mar  8 18:47:34 GMT 2002 - updated to reflect Dan's comments that
-non-aggregates also support C<_keyed> variant vtable methods.
-
Index: include/parrot/key.h
===================================================================
RCS file: /home/perlcvs/parrot/include/parrot/key.h,v
retrieving revision 1.10
diff -a -u -r1.10 key.h
--- include/parrot/key.h        2 Apr 2002 20:32:48 -0000       1.10
+++ include/parrot/key.h        14 May 2002 22:05:31 -0000
@@ -13,55 +13,31 @@
 #if !defined(PARROT_KEY_H_GUARD)
 #define PARROT_KEY_H_GUARD
 
-#define NUM_BUCKETS 128
-
 typedef enum {
     enum_key_undef,
     enum_key_int,
     enum_key_num,
     enum_key_string,
     enum_key_pmc,
-    enum_key_bucket,
     enum_key_max
 } KEY_TYPE;
 
-struct _key_pair {
+typedef struct _key_atom KEY_ATOM;
+
+struct _key_atom {
     KEY_TYPE type;
-    union {
-        INTVAL int_val;
-        FLOATVAL num_val;
-        STRING *struct_val;
-        PMC *pmc_val;
-    } cache;
+    UnionVal val;
 };
 
-typedef struct _key_pair KEY_PAIR;
+typedef struct _key KEY;
 
 struct _key {
-    INTVAL size;
-    KEY_PAIR *keys;
+    KEY_ATOM atom;
+    KEY* next;
 };
 
-typedef struct _key KEY;
-
-/* Prototypes */
-KEY *key_new(struct Parrot_Interp *interpreter);
-KEY *key_clone(struct Parrot_Interp *interpreter, KEY *key);
-INTVAL key_size(struct Parrot_Interp *interpreter, KEY *key);
-void key_set_size(struct Parrot_Interp *interpreter, KEY *key, INTVAL size);
-void key_destroy(struct Parrot_Interp *interpreter, KEY *key);
-INTVAL key_element_type(struct Parrot_Interp *interpreter, KEY *key,
-                        INTVAL idx);
-KEY_PAIR *key_element_value_i(struct Parrot_Interp *interpreter, KEY *key,
-                              INTVAL idx);
-KEY_PAIR *key_element_value_s(struct Parrot_Interp *interpreter, KEY *key,
-                              STRING *idx);
-void key_set_element_value_i(struct Parrot_Interp *interpreter, KEY *key,
-                             INTVAL idx, KEY_PAIR *value);
-void key_set_element_value_s(struct Parrot_Interp *interpreter, KEY *key,
-                             STRING *idx, KEY_PAIR *value);
-void key_chop(struct Parrot_Interp *interpreter, KEY *key);
-void key_inc(struct Parrot_Interp *interpreter, KEY *key, INTVAL idx);
+KEY * key_new(Interp *interpreter);
+KEY * key_clone(Interp *interpreter, KEY *key);
 
 #endif
 
Index: include/parrot/pmc.h
===================================================================
RCS file: /home/perlcvs/parrot/include/parrot/pmc.h,v
retrieving revision 1.28
diff -a -u -r1.28 pmc.h
--- include/parrot/pmc.h        9 Apr 2002 03:49:50 -0000       1.28
+++ include/parrot/pmc.h        14 May 2002 22:05:32 -0000
@@ -32,11 +32,13 @@
     VTABLE *vtable;
     INTVAL flags;
     DPOINTER *data;
-    union {                   /* cache.* is intended to just be *shortcuts* to*/
-        INTVAL int_val;       /* commonly-accessed data, *not* pointers to */
-        FLOATVAL num_val;     /* completely different data.  That's why it's */
-        DPOINTER *struct_val; /* referred to as a "cache". */
-    } cache;
+
+    /* cache.* is intended to just be *shortcuts* to*/
+    /* commonly-accessed data, *not* pointers to */
+    /* completely different data.  That's why it's */
+    /* referred to as a "cache". */
+    UnionVal cache;
+    
     SYNC *synchronize;
     /* This flag determines the next PMC in the 'used' list during 
        dead object detection in the GC. It is a linked list, which is 

Reply via email to