cvsuser     03/11/04 10:33:12

  Modified:    classes  perlhash.pmc
               include/parrot hash.h
               src      hash.c
               t/pmc    iter.t perlhash.t
  Log:
  Hash store is now a pointer; PerlHash is PMC only
  
  Revision  Changes    Path
  1.57      +115 -208  parrot/classes/perlhash.pmc
  
  Index: perlhash.pmc
  ===================================================================
  RCS file: /cvs/public/parrot/classes/perlhash.pmc,v
  retrieving revision 1.56
  retrieving revision 1.57
  diff -u -w -r1.56 -r1.57
  --- perlhash.pmc      5 Oct 2003 13:49:26 -0000       1.56
  +++ perlhash.pmc      4 Nov 2003 18:33:04 -0000       1.57
  @@ -1,7 +1,7 @@
    /* perlhash.pmc
    *  Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
    *  CVS Info
  - *     $Id: perlhash.pmc,v 1.56 2003/10/05 13:49:26 leo Exp $
  + *     $Id: perlhash.pmc,v 1.57 2003/11/04 18:33:04 leo Exp $
    *  Overview:
    *     These are the vtable functions for the PerlHash base class
    *  Data Structure and Algorithms:
  @@ -43,7 +43,7 @@
               VTABLE_init(INTERP, undef);
           }
           PObj_custom_mark_SET(SELF);
  -        new_hash(INTERP, (HASH **)&PMC_ptr1v(SELF));
  +     PMC_ptr1v(SELF) = new_hash(INTERP);
       }
   
       void mark () {
  @@ -53,25 +53,23 @@
   
       INTVAL type_keyed (PMC* key) {
           PMC* valpmc;
  +     PMC* nextkey;
           STRING* keystr = make_hash_key(INTERP, key);
  -        HASH_ENTRY* entry = hash_get(INTERP, (HASH*) PMC_ptr1v(SELF), keystr);
  -        if (entry == NULL) {
  +     HASHBUCKET* b = hash_get(INTERP, (HASH*) PMC_ptr1v(SELF), keystr);
  +     if (b == NULL) {
               return enum_hash_undef;
           }
  -        if (entry->type == enum_hash_pmc) {
  -         PMC* nextkey;
            nextkey = key_next(INTERP, key);
  -            valpmc = entry->val.pmc_val;
  +     valpmc = b->value;
            if (!nextkey)
                return enum_hash_pmc;
            return VTABLE_type_keyed(INTERP, valpmc, nextkey);
  -        }
  -        return entry->type;
  +     return enum_hash_pmc;
       }
   
       void clone (PMC *ret) {
           PObj_custom_mark_SET(ret);
  -        hash_clone(INTERP, (HASH *)PMC_ptr1v(SELF), (HASH **)&PMC_ptr1v(ret));
  +     PMC_ptr1v(ret) = hash_clone(INTERP, (HASH *)PMC_ptr1v(SELF));
       }
   
       INTVAL get_integer () {
  @@ -81,69 +79,51 @@
       INTVAL get_integer_keyed (PMC* key) {
           PMC* valpmc;
           STRING* keystr = make_hash_key(INTERP, key);
  -        HASH_ENTRY* entry = hash_get(INTERP, (HASH*) PMC_ptr1v(SELF), keystr);
  -        if (entry == NULL) {
  +     HASHBUCKET *b = hash_get(INTERP, (HASH*) PMC_ptr1v(SELF), keystr);
  +     PMC* nextkey;
  +     if (b == NULL) {
               /* XXX Warning: use of uninitialized value */
               return VTABLE_get_integer(INTERP, undef);
           }
  -        if (entry->type == enum_hash_int) return entry->val.int_val;
  -        if (entry->type == enum_hash_pmc) {
  -         PMC* nextkey;
            nextkey = key_next(INTERP, key);
  -            valpmc = entry->val.pmc_val;
  +     valpmc = b->value;
            if (!nextkey)
                return VTABLE_get_integer(INTERP, valpmc);
            return VTABLE_get_integer_keyed(INTERP, valpmc, nextkey);
   
           }
  -        internal_exception(OUT_OF_BOUNDS,
  -             "Cannot fetch integer out of non-integer key!\n");
  -        return -1;
  -    }
   
       FLOATVAL get_number_keyed (PMC* key) {
           PMC* valpmc;
           STRING* keystr = make_hash_key(INTERP, key);
  -        HASH_ENTRY* entry = hash_get(INTERP, (HASH*) PMC_ptr1v(SELF), keystr);
  -        if (entry == NULL) {
  +     HASHBUCKET *b = hash_get(INTERP, (HASH*) PMC_ptr1v(SELF), keystr);
  +     PMC* nextkey;
  +     if (b == NULL) {
               /* XXX Warning: Use of uninitialized value */
               return VTABLE_get_number(INTERP, undef);
           }
  -        if (entry->type == enum_hash_num) return entry->val.num_val;
  -        if (entry->type == enum_hash_pmc) {
  -         PMC* nextkey;
            nextkey = key_next(INTERP, key);
  -            valpmc = entry->val.pmc_val;
  +     valpmc = b->value;
            if (!nextkey)
                return VTABLE_get_number(INTERP, valpmc);
            return VTABLE_get_number_keyed(INTERP, valpmc, nextkey);
           }
  -        internal_exception(OUT_OF_BOUNDS,
  -             "Cannot fetch number out of non-numeric key!\n");
  -        return 0.0;
  -    }
   
       BIGNUM* get_bignum_keyed (PMC* key) {
           PMC* valpmc;
           STRING* keystr = make_hash_key(INTERP, key);
  -        HASH_ENTRY* entry = hash_get(INTERP, (HASH*) PMC_ptr1v(SELF), keystr);
  -        if (entry == NULL) {
  +     HASHBUCKET *b = hash_get(INTERP, (HASH*) PMC_ptr1v(SELF), keystr);
  +     PMC* nextkey;
  +     if (b == NULL) {
               /* XXX Warning: Use of uninitialized value */
               return VTABLE_get_bignum(INTERP, undef);
           }
  -        if (entry->type == enum_hash_num) return (BIGNUM*)entry->val.struct_val;
  -        if (entry->type == enum_hash_pmc) {
  -         PMC* nextkey;
            nextkey = key_next(INTERP, key);
  -            valpmc = entry->val.pmc_val;
  +     valpmc = b->value;
            if (!nextkey)
                return VTABLE_get_bignum(INTERP, valpmc);
            return VTABLE_get_bignum_keyed(INTERP, valpmc, nextkey);
           }
  -        internal_exception(OUT_OF_BOUNDS,
  -             "Cannot fetch number out of non-numeric key!\n");
  -        return NULL;
  -    }
   
       STRING* get_string () {
        return Parrot_sprintf_c(INTERP, "PerlHash[0x%x]", SELF);
  @@ -152,7 +132,8 @@
       STRING* get_string_keyed (PMC* key) {
           PMC* valpmc;
           STRING* keystr;
  -        HASH_ENTRY* entry;
  +     HASHBUCKET *b;
  +     PMC* nextkey;
   
        switch (PObj_get_FLAGS(key) & KEY_type_FLAGS) {
            case KEY_integer_FLAG:
  @@ -161,24 +142,17 @@
            default:
                keystr = make_hash_key(INTERP, key);
        }
  -        entry = hash_get(INTERP, (HASH*) PMC_ptr1v(SELF), keystr);
  -        if (entry == NULL) {
  +     b = hash_get(INTERP, (HASH*) PMC_ptr1v(SELF), keystr);
  +     if (b == NULL) {
               /* XXX Warning: use of uninitialized value */
               return VTABLE_get_string(INTERP, undef);
           }
  -        if (entry->type == enum_hash_string) return entry->val.string_val;
  -        if (entry->type == enum_hash_pmc) {
  -         PMC* nextkey;
            nextkey = key_next(INTERP, key);
  -            valpmc = entry->val.pmc_val;
  +     valpmc = b->value;
            if (!nextkey)
                return VTABLE_get_string(INTERP, valpmc);
            return VTABLE_get_string_keyed(INTERP, valpmc, nextkey);
           }
  -        internal_exception(OUT_OF_BOUNDS,
  -             "Cannot fetch string out of non-string key!\n");
  -        return NULL;
  -    }
   
       INTVAL get_bool () {
           return hash_size(INTERP, PMC_ptr1v(SELF)) != 0;
  @@ -190,23 +164,16 @@
   
       PMC* get_pmc_keyed (PMC* key) {
           STRING* keystr = make_hash_key(INTERP, key);
  -        HASH_ENTRY* entry = hash_get(INTERP, (HASH*) PMC_ptr1v(SELF), keystr);
  -        if (entry == NULL) {
  +     HASHBUCKET *b = hash_get(INTERP, (HASH*) PMC_ptr1v(SELF), keystr);
  +     PMC* nextkey;
  +     if (b == NULL) {
               PMC *new_undef = pmc_new(INTERP, enum_class_PerlUndef);
               return new_undef;
           }
  -        if (entry->type == enum_hash_pmc) {
  -         PMC* nextkey;
            nextkey = key_next(INTERP, key);
            if (!nextkey)
  -             return entry->val.pmc_val;
  -         return VTABLE_get_pmc_keyed(INTERP,
  -                 entry->val.pmc_val, nextkey);
  -
  -        }
  -        internal_exception(OUT_OF_BOUNDS,
  -             "Cannot fetch PMC out of non-PMC key!\n");
  -        return NULL;
  +         return b->value;
  +     return VTABLE_get_pmc_keyed(INTERP, (PMC*)b->value, nextkey);
       }
   
       INTVAL is_same (PMC* other) {
  @@ -214,88 +181,34 @@
                        PMC_ptr1v(other) == PMC_ptr1v(SELF));
       }
   
  -    void set_integer (PMC* value) {
  -        internal_exception(INTERNAL_PANIC, "Cannot set hash to int\n");
  -    }
  -
  -    void set_integer_native (INTVAL size) {
  -        internal_exception(INTERNAL_PANIC, "Cannot set hash to int\n");
  -    }
  -
  -    void set_integer_same (PMC* value) {
  -        internal_exception(INTERNAL_PANIC, "Cannot set hash to int\n");
  -    }
  -
       void set_integer_keyed (PMC* key, INTVAL value) {
           STRING* keystr = make_hash_key(INTERP, key);
  -        HASH_ENTRY entry;
  -        entry.type = enum_hash_int;
  -        entry.val.int_val = value;
  -        hash_put(INTERP, PMC_ptr1v(SELF), keystr, &entry);
  -    }
  -
  -    void set_number (PMC* value) {
  -        internal_exception(INTERNAL_PANIC, "Cannot set hash to number\n");
  -    }
  -
  -    void set_number_native (FLOATVAL size) {
  -        internal_exception(INTERNAL_PANIC, "Cannot set hash to number\n");
  -    }
  -
  -    void set_number_same (PMC* value) {
  -        internal_exception(INTERNAL_PANIC, "Cannot set hash to number\n");
  +        PMC *val = pmc_new(interpreter, enum_class_PerlInt);
  +        VTABLE_set_integer_native(INTERP, val, value);
  +        hash_put(INTERP, PMC_ptr1v(SELF), keystr, val);
       }
   
       void set_number_keyed (PMC* key, FLOATVAL value) {
           STRING* keystr = make_hash_key(INTERP, key);
  -        HASH_ENTRY entry;
  -        entry.type = enum_hash_num;
  -        entry.val.num_val = value;
  -        hash_put(INTERP, PMC_ptr1v(SELF), keystr, &entry);
  -    }
  -
  -    void set_bignum (PMC* value) {
  -        internal_exception(INTERNAL_PANIC, "Cannot set hash to bignum\n");
  -    }
  -
  -    void set_bignum_native (BIGNUM* size) {
  -        internal_exception(INTERNAL_PANIC, "Cannot set hash to bignum\n");
  -    }
  -
  -    void set_bignum_same (PMC* value) {
  -        internal_exception(INTERNAL_PANIC, "Cannot set hash to bignum\n");
  +        PMC *val = pmc_new(interpreter, enum_class_PerlNum);
  +        VTABLE_set_number_native(INTERP, val, value);
  +        hash_put(INTERP, PMC_ptr1v(SELF), keystr, val);
       }
   
       void set_bignum_keyed (PMC* key, BIGNUM* value) {
           /* XXX */
       }
   
  -    void set_string (PMC* value) {
  -        internal_exception(INTERNAL_PANIC, "Cannot set hash to string\n");
  -    }
  -
  -    void set_string_native (STRING* value) {
  -        internal_exception(INTERNAL_PANIC, "Cannot set hash to string\n");
  -    }
  -
  -    void set_string_same (PMC* value) {
  -        internal_exception(INTERNAL_PANIC, "Cannot set hash to string\n");
  -    }
  -
       void set_string_keyed (PMC* key, STRING* value) {
           STRING* keystr = make_hash_key(INTERP, key);
  -        HASH_ENTRY entry;
  -        entry.type = enum_hash_string;
  -        entry.val.string_val = value;
  -        hash_put(INTERP, PMC_ptr1v(SELF), keystr, &entry);
  +        PMC *val = pmc_new(interpreter, enum_class_PerlString);
  +        VTABLE_set_string_native(INTERP, val, value);
  +        hash_put(INTERP, PMC_ptr1v(SELF), keystr, val);
       }
   
       void set_pmc_keyed (PMC* dest_key, PMC* value) {
           STRING* keystr = make_hash_key(INTERP, dest_key);
  -        HASH_ENTRY entry;
  -        entry.type = enum_hash_pmc;
  -        entry.val.pmc_val = value;
  -        hash_put(INTERP, PMC_ptr1v(SELF), keystr, &entry);
  +        hash_put(INTERP, PMC_ptr1v(SELF), keystr, value);
       }
   
   
  @@ -307,51 +220,45 @@
       INTVAL exists_keyed(PMC* key) {
        STRING * sx;
        HASH * h = (HASH *)PMC_ptr1v(SELF);
  -     HASH_ENTRY * he;
  +     HASHBUCKET *b;
        sx = key_string(INTERP, key);
        key = key_next(INTERP, key);
  -     he = hash_get(INTERP, h, sx);
  -     if (he == NULL)
  +     b = hash_get(INTERP, h, sx);
  +     if (b == NULL)
            return 0;           /* no such key */
        if (key == NULL)
            return 1;           /* lookup stops here */
  -     return VTABLE_exists_keyed(INTERP, he->val.pmc_val, key);
  +     return VTABLE_exists_keyed(INTERP, (PMC*)b->value, key);
       }
   
       INTVAL defined_keyed(PMC* key) {
        STRING * sx;
        HASH * h = (HASH *)PMC_ptr1v(SELF);
  -     HASH_ENTRY * he;
  +     HASHBUCKET *b;
        sx = key_string(INTERP, key);
        key = key_next(INTERP, key);
  -     he = hash_get(INTERP, h, sx);
  -     if (he == NULL)
  +     b = hash_get(INTERP, h, sx);
  +     if (b == NULL)
            return 0;           /* no such key */
  -        if (he->type == enum_hash_pmc) {
            if (key == NULL)
  -             return VTABLE_defined(INTERP,
  -                     he->val.pmc_val);
  +         return VTABLE_defined(INTERP, (PMC*)b->value);
            else
  -             return VTABLE_defined_keyed(
  -                     INTERP, he->val.pmc_val, key);
  -     }
  -     /* some other contents */
  -     return 1;
  +         return VTABLE_defined_keyed( INTERP, (PMC*)b->value, key);
       }
   
       void delete_keyed(PMC* key) {
        STRING * sx;
        HASH * h = (HASH *)PMC_ptr1v(SELF);
  -     HASH_ENTRY * he;
  +     HASHBUCKET *b;
        sx = key_string(INTERP, key);
        key = key_next(INTERP, key);
  -     he = hash_get(INTERP, h, sx);
  -     if (he == NULL)
  +     b = hash_get(INTERP, h, sx);
  +     if (b == NULL)
               return;  /* no such key */
        else if (key == NULL)
            hash_delete(INTERP, h, sx);
        else
  -         VTABLE_delete_keyed(INTERP, he->val.pmc_val, key);
  +         VTABLE_delete_keyed(INTERP, (PMC*)b->value, key);
       }
   
       PMC* nextkey_keyed (PMC* key, INTVAL what) {
  
  
  
  1.17      +14 -8     parrot/include/parrot/hash.h
  
  Index: hash.h
  ===================================================================
  RCS file: /cvs/public/parrot/include/parrot/hash.h,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -w -r1.16 -r1.17
  --- hash.h    25 Oct 2003 14:45:24 -0000      1.16
  +++ hash.h    4 Nov 2003 18:33:08 -0000       1.17
  @@ -1,7 +1,7 @@
   /* hash.h
    *  Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
    *  CVS Info
  - *     $Id: hash.h,v 1.16 2003/10/25 14:45:24 leo Exp $
  + *     $Id: hash.h,v 1.17 2003/11/04 18:33:08 leo Exp $
    *  Overview:
    *     Hashtable implementation
    *  Data Structure and Algorithms:
  @@ -28,6 +28,9 @@
       enum_hash_pmc = enum_type_PMC
   } HASH_ENTRY_TYPE;
   
  +/*
  + * hash_entry is currently unused
  + */
   typedef struct _hash_entry {
       HASH_ENTRY_TYPE type;
       UnionVal val;
  @@ -39,8 +42,8 @@
   typedef UINTVAL HashIndex;
   struct _hashbucket {
       void *key;
  -    HASH_ENTRY value;
       BucketIndex next;
  +    void *value;
   };
   
   typedef int    (*hash_comp_fn)(Parrot_Interp, void*, void*);
  @@ -53,21 +56,24 @@
       UINTVAL entries;            /* Number of values stored in hashtable */
       Buffer *bucket_pool;        /* Buffer full of buckets, used and unused */
       BucketIndex free_list;
  +    PARROT_DATA_TYPES entry_type;   /* type of value */
  +    size_t value_size;          /* currently unused, if set this size
  +                                   at value is copied as a hash_entry */
       hash_comp_fn   compare;
       hash_hash_key_fn hash_val;
       hash_mark_key_fn mark_key;
   };
   
  -void new_hash(Interp * interpreter, HASH **hash_ptr);
  -void new_hash_x(Interp * interpreter, HASH **hash_ptr,
  +HASH * new_hash(Interp * interpreter);
  +HASH * new_hash_x(Interp * interpreter,
           hash_comp_fn, hash_hash_key_fn, hash_mark_key_fn);
  -void new_cstring_hash(Interp *interpreter, HASH **hash_ptr);
  -void hash_clone(Interp * interpreter, HASH * src, HASH **dest);
  +HASH * new_cstring_hash(Interp *interpreter);
  +HASH * hash_clone(Interp * interpreter, HASH * src);
   INTVAL hash_size(Interp * interpreter, HASH *hash);
   void hash_set_size(Interp * interpreter, HASH *hash, UINTVAL size);
   void hash_destroy(Interp * interpreter, HASH *hash);
  -HASH_ENTRY *hash_get(Interp * interpreter, HASH *hash, void *key);
  -void hash_put(Interp * interpreter, HASH *hash, void *key, HASH_ENTRY * value);
  +HASHBUCKET *hash_get(Interp * interpreter, HASH *hash, void *key);
  +void hash_put(Interp * interpreter, HASH *hash, void *key, void *value);
   void hash_delete(Interp * interpreter, HASH *hash, void *key);
   void mark_hash(Interp * interpreter, HASH *hash);
   void dump_hash(Interp * interpreter, HASH *hash);
  
  
  
  1.50      +55 -57    parrot/src/hash.c
  
  Index: hash.c
  ===================================================================
  RCS file: /cvs/public/parrot/src/hash.c,v
  retrieving revision 1.49
  retrieving revision 1.50
  diff -u -w -r1.49 -r1.50
  --- hash.c    26 Oct 2003 10:27:01 -0000      1.49
  +++ hash.c    4 Nov 2003 18:33:10 -0000       1.50
  @@ -1,7 +1,7 @@
   /* hash.c
    *  Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
    *  CVS Info
  - *     $Id: hash.c,v 1.49 2003/10/26 10:27:01 leo Exp $
  + *     $Id: hash.c,v 1.50 2003/11/04 18:33:10 leo Exp $
    *  Overview:
    *  Data Structure and Algorithms:
    *     A hashtable contains an array of bucket indexes. Buckets
  @@ -22,15 +22,23 @@
    *                    hash keys are now (void *)
    *                    add new_cstring_hash() function
    *
  + *     2003.11.04 leo bucket->value is now a plain pointer, no nore
  + *                    an HASH_ENTRY
  + *                    With little changes, we can again store
  + *                    arbitrary items if needed, s. TODO in code
  + *
    *  Notes:
    *     Future optimizations:
    *       - Stop reallocating the bucket pool, and instead add chunks on.
    *         (Saves pointer fixups and copying during realloc.)
    *       - Hash contraction (dunno if it's worth it)
  + *
    *  References:
  - *     pdd08_keys.pod */
  + *     pdd08_keys.pod
  + */
   
   #include "parrot/parrot.h"
  +#include <assert.h>
   
   #define INITIAL_BUCKETS 16
   #define MAXFULL_PERCENT 80
  @@ -49,6 +57,7 @@
   {
       if (idx == NULLBucketIndex)
           return NULL;
  +    /* TODO honor hash->value_size */
       return &((HASHBUCKET *)hash->bucket_pool->bufstart)[idx];
   }
   
  @@ -135,7 +144,7 @@
           PIO_eprintf(interpreter, "  Bucket %vd: ", i);
           while (bucket) {
               Parrot_block_GC(interpreter); /* don't allow bucket to move */
  -            PIO_eprintf(interpreter, "type(%d)", bucket->value.type);
  +            PIO_eprintf(interpreter, "(%p)", bucket->value);
               Parrot_unblock_GC(interpreter);
               bucket = getBucket(hash, bucket->next);
               if (bucket)
  @@ -156,7 +165,7 @@
           pobject_lives(interpreter, (PObj *)hash->bucket_pool);
       }
   
  -    if (hash->buffer.bufstart == NULL || hash->bucket_pool->bufstart == NULL) {
  +    if (!hash->buffer.bufstart|| !hash->bucket_pool->bufstart) {
           return;
       }
   
  @@ -165,11 +174,10 @@
           while (bucket) {
               if (hash->mark_key)
                   (hash->mark_key)(interpreter, (PObj *)bucket->key);
  -            if (bucket->value.type == enum_hash_string)
  -                pobject_lives(interpreter,
  -                             (PObj *)bucket->value.val.string_val);
  -            else if (bucket->value.type == enum_hash_pmc)
  -                pobject_lives(interpreter, (PObj *)bucket->value.val.pmc_val);
  +            if (hash->entry_type == enum_hash_string)
  +                pobject_lives(interpreter, (PObj *)bucket->value);
  +            else if (hash->entry_type == enum_hash_pmc)
  +                pobject_lives(interpreter, (PObj *)bucket->value);
               bucket = getBucket(hash, bucket->next);
           }
       }
  @@ -211,6 +219,7 @@
       UINTVAL new_pool_size = new_size * MAXFULL_PERCENT / 100;
   
       Parrot_reallocate(interpreter, hash, new_size * sizeof(BucketIndex));
  +    /* TODO honor hash->value_size */
       Parrot_reallocate(interpreter, hash->bucket_pool,
                         new_pool_size * sizeof(HASHBUCKET));
   
  @@ -262,7 +271,7 @@
   }
   
   static BucketIndex
  -new_bucket(Interp *interpreter, HASH *hash, STRING *key, HASH_ENTRY *value)
  +new_bucket(Interp *interpreter, HASH *hash, STRING *key, void *value)
   {
       BucketIndex bucket_index;
   
  @@ -285,7 +294,7 @@
   
           hash->free_list = bucket->next;
           bucket->key = key;
  -        bucket->value = *value;
  +        bucket->value = value;  /* TODO copy value_size if(value_size) */
           return bucket_index;
       }
   
  @@ -314,36 +323,36 @@
       return NULL;
   }
   
  -/* FIXME: This function can go back to just returning the hash struct
  - * pointer once Buffers can define their own custom mark routines. */
  -void
  -new_hash(Interp *interpreter, HASH **hash_ptr)
  +HASH *
  +new_hash(Interp *interpreter)
   {
  -    new_hash_x(interpreter, hash_ptr,
  +    return new_hash_x(interpreter,
               STRING_compare,     /* STRING compare */
               key_hash_STRING,    /*        hash */
               pobject_lives);     /*        mark */
   }
   
  -void
  -new_cstring_hash(Interp *interpreter, HASH **hash_ptr)
  +HASH *
  +new_cstring_hash(Interp *interpreter)
   {
  -    new_hash_x(interpreter, hash_ptr,
  +    return new_hash_x(interpreter,
               cstring_compare,     /* cstring compare */
               key_hash_cstring,    /*        hash */
               (hash_mark_key_fn)0);/* no     mark */
   }
   
  -void
  -new_hash_x(Interp *interpreter, HASH **hash_ptr,
  +HASH *
  +new_hash_x(Interp *interpreter,
           hash_comp_fn compare, hash_hash_key_fn keyhash,
           hash_mark_key_fn mark)
   {
       HASH *hash = (HASH *)new_bufferlike_header(interpreter, sizeof(*hash));
  -    *hash_ptr = hash;
       hash->compare = compare;
       hash->hash_val = keyhash;
       hash->mark_key = mark;
  +    /* TODO make next 2 params configurable */
  +    hash->entry_type = enum_type_PMC;
  +    hash->value_size = 0;       /* extra size */
   
       /*      PObj_report_SET(&hash->buffer); */
   
  @@ -362,6 +371,7 @@
       /*      PObj_report_SET(hash->bucket_pool); */
       hash->free_list = NULLBucketIndex;
       expand_hash(interpreter, hash);
  +    return hash;
   }
   
   /*=for api hash hash_size
  @@ -376,14 +386,11 @@
   {
       UNUSED(interpreter);
   
  -    if (hash != NULL) {
  +    if (hash)
           return hash->entries;
  -    }
  -    else {
  -        PIO_eprintf(interpreter, "*** hash_size asked to check a NULL hash\n");
  +    internal_exception(1, "hash_size asked to check a NULL hash\n");
           return 0;
       }
  -}
   
   /*
    * called by interator
  @@ -420,8 +427,9 @@
       return b->key;
   }
   
  -PARROT_INLINE static HASHBUCKET *
  -hash_lookup(Interp *interpreter, HASH *hash, void *key)
  +
  +HASHBUCKET *
  +hash_get(Interp *interpreter, HASH *hash, void *key)
   {
       UINTVAL hashval = (hash->hash_val)(interpreter, key);
       HashIndex *table = (HashIndex *)hash->buffer.bufstart;
  @@ -429,18 +437,9 @@
       return find_bucket(interpreter, hash, chain, key);
   }
   
  -HASH_ENTRY *
  -hash_get(Interp *interpreter, HASH *hash, void *key)
  -{
  -    HASHBUCKET *bucket = hash_lookup(interpreter, hash, key);
  -    if (bucket == NULL)
  -        return NULL;            /* Not found */
  -    return &bucket->value;
  -}
  -
   /* The key is *not* copied. */
   void
  -hash_put(Interp *interpreter, HASH *hash, void *key, HASH_ENTRY *value)
  +hash_put(Interp *interpreter, HASH *hash, void *key, void *value)
   {
       BucketIndex *table;
       UINTVAL hashval;
  @@ -452,7 +451,8 @@
   
       hashval = (hash->hash_val)(interpreter, key);
       table = (BucketIndex *)hash->buffer.bufstart;
  -    chain = table ? table[hashval & hash->max_chain] : NULLBucketIndex;
  +    assert(table);
  +    chain = table[hashval & hash->max_chain];
       bucket = find_bucket(interpreter, hash, chain, key);
   
       /*      fprintf(stderr, "HASH=%p buckets=%p chain=%p bucket=%p KEY=%s\n", */
  @@ -460,7 +460,7 @@
   
       if (bucket) {
           /* Replacing old value */
  -        memcpy(&bucket->value, value, sizeof(HASH_ENTRY));
  +        bucket->value = value;  /* TODO copy value_size */
       }
       else {
           /* Create new bucket */
  @@ -513,19 +513,20 @@
       PANIC("hash_delete given nonexistent key");
   }
   
  -void
  -hash_clone(struct Parrot_Interp *interp, HASH *hash, HASH **dest)
  +HASH *
  +hash_clone(struct Parrot_Interp *interp, HASH *hash)
   {
       HashIndex i;
  +    HASH *dest;
   
  -    new_hash_x(interp, dest, hash->compare, hash->hash_val, hash->mark_key);
  +    dest = new_hash_x(interp, hash->compare, hash->hash_val, hash->mark_key);
       for (i = 0; i <= hash->max_chain; i++) {
           BucketIndex bi = lookupBucketIndex(hash, i);
           while (bi != NULLBucketIndex) {
               HASHBUCKET *b = getBucket(hash, bi);
               void *key = b->key;
  -            HASH_ENTRY valtmp;
  -            switch (b->value.type) {
  +            void *valtmp;
  +            switch (hash->entry_type) {
               case enum_hash_undef:
               case enum_hash_int:
               case enum_hash_num:
  @@ -533,24 +534,20 @@
                   break;
   
               case enum_hash_string:
  -                valtmp.type = enum_hash_string;
  -                valtmp.val.string_val
  -                    = string_copy(interp, b->value.val.string_val);
  +                valtmp = string_copy(interp, b->value);
                   break;
   
               case enum_hash_pmc:
  -                valtmp.type = enum_hash_pmc;
  -                valtmp.val.pmc_val = pmc_new_noinit(interp,
  -                    b->value.val.pmc_val->vtable->base_type);
  -                VTABLE_clone(interp,
  -                    b->value.val.pmc_val, valtmp.val.pmc_val );
  +                valtmp = pmc_new_noinit(interp,
  +                    ((PMC*)b->value)->vtable->base_type);
  +                VTABLE_clone(interp, (PMC*)b->value, valtmp);
                   break;
   
               default:
                   internal_exception(-1, "hash corruption: type = %d\n",
  -                                   b->value.type);
  +                                   hash->entry_type);
               };
  -            hash_put(interp, *dest, key, &valtmp);
  +            hash_put(interp, dest, key, valtmp);
               /*
                * hash_put may extend the hash, which can trigger GC
                * we could also check the GC count and refetch b only when needed
  @@ -559,6 +556,7 @@
               bi = b->next;
           }
       }
  +    return dest;
   }
   
   /*
  
  
  
  1.9       +1 -47     parrot/t/pmc/iter.t
  
  Index: iter.t
  ===================================================================
  RCS file: /cvs/public/parrot/t/pmc/iter.t,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -w -r1.8 -r1.9
  --- iter.t    19 Aug 2003 18:37:28 -0000      1.8
  +++ iter.t    4 Nov 2003 18:33:12 -0000       1.9
  @@ -1,6 +1,6 @@
   #! perl -w
   
  -use Parrot::Test tests => 10;
  +use Parrot::Test tests => 9;
   use Test::More qw(skip);
   output_is(<<'CODE', <<'OUTPUT', "new iter");
        new P2, .PerlArray
  @@ -185,52 +185,6 @@
   CODE
   ok 1
   ok 2
  -OUTPUT
  -
  -output_is(<<'CODE', <<'OUTPUT', "hash iter - various types");
  -    .include "datatypes.pasm"        # type constants
  -    .include "iterator.pasm"
  -    new P1, .PerlHash
  -    set P1["int"], 10
  -    set P1["num"], 2.5
  -    set P1["str"], "string"
  -    new P2, .PerlString
  -    set P2, "string"
  -    set P1["pmc"], P2
  -
  -    set I10, 0                       # count items
  -    new P0, .Iterator, P1    # setup iterator for hash P1
  -    set P0, .ITERATE_FROM_START
  -iter_loop:
  -    unless P0, iter_end              # while (entries) ...
  -      inc I10
  -      shift S2, P0           # get key for entry
  -      typeof I0, P0[S2]              # get type of entry for key S2
  -      ne I0, .DATATYPE_INTVAL, no_int
  -      set I1, P0[S2]
  -      eq I1, 10, iter_loop
  -      print "not ok int\n"
  -    no_int:
  -      ne I0, .DATATYPE_FLOATVAL, no_num
  -      set N1, P0[S2]
  -      eq N1, 2.5, iter_loop
  -      print "not ok num\n"
  -    no_num:
  -      ne I0, .DATATYPE_STRING, no_str
  -      set S1, P0[S2]
  -      eq S1, "string", iter_loop
  -      print "not ok str\n"
  -    no_str:
  -      set P4, P0[S2]
  -      eq P4, P2, iter_loop
  -      print "not ok pmc\n"
  -      branch iter_loop
  -iter_end:
  -    print I10
  -    print "\n"
  -    end
  -CODE
  -4
   OUTPUT
   
   output_is(<<'CODE', <<OUTPUT, "string iteration forward");
  
  
  
  1.36      +2 -36     parrot/t/pmc/perlhash.t
  
  Index: perlhash.t
  ===================================================================
  RCS file: /cvs/public/parrot/t/pmc/perlhash.t,v
  retrieving revision 1.35
  retrieving revision 1.36
  diff -u -w -r1.35 -r1.36
  --- perlhash.t        26 Oct 2003 12:53:44 -0000      1.35
  +++ perlhash.t        4 Nov 2003 18:33:12 -0000       1.36
  @@ -854,49 +854,15 @@
   
   output_is(<<'CODE', <<OUTPUT, "entry types - type_keyed");
   .include "datatypes.pasm"
  -    new P0, .PerlHash
  -    set P0["int"], 10
  -    set P0["num"], 2.5
  -    set P0["str"], "string"
       new P1, .PerlHash
  -    set P0["pmc"], P1
  -    set P1["str"], "string"
  -    set P1["int"], 20
  -
  -    typeof I0, P0["int"]
  -    eq I0, .DATATYPE_INTVAL, ok1
  -    print "not "
  -ok1:print "ok 1\n"
  -    typeof I0, P0["num"]
  -    eq I0, .DATATYPE_FLOATVAL, ok2
  -    print "not "
  -ok2:print "ok 2\n"
  -    typeof I0, P0["str"]
  -    eq I0, .DATATYPE_STRING, ok3
  -    print "not "
  -ok3:print "ok 3\n"
  -    typeof I0, P0["pmc"]
  +    set P1["pmc"], P1
  +    typeof I0, P1["pmc"]
       eq I0, .DATATYPE_PMC, ok4
       print "not "
   ok4:print "ok 4\n"
  -    typeof I0, P0["pmc";"str"]
  -    eq I0, .DATATYPE_STRING, ok5
  -    print I0
  -    print " not "
  -ok5:print "ok 5\n"
  -    typeof I0, P0["pmc";"int"]
  -    eq I0, .DATATYPE_INTVAL, ok6
  -    print I0
  -    print " not "
  -ok6:print "ok 6\n"
       end
   CODE
  -ok 1
  -ok 2
  -ok 3
   ok 4
  -ok 5
  -ok 6
   OUTPUT
   
   output_is(<<'CODE', <<OUTPUT, "delete and free_list");
  
  
  

Reply via email to