[svn:parrot] r40100 - in trunk: config/gen include/parrot lib/Parrot/Pmc2c src src/dynpmc src/pmc t/compilers/pct t/native_pbc t/op t/pmc t/pmc/testlib

bacek at svn.parrot.org bacek at svn.parrot.org
Wed Jul 15 13:15:28 UTC 2009


Author: bacek
Date: Wed Jul 15 13:15:25 2009
New Revision: 40100
URL: https://trac.parrot.org/parrot/changeset/40100

Log:
Merge branch tt761_keys_revamp into trunk.

Added:
   trunk/src/pmc/arrayiterator.pmc
   trunk/src/pmc/hashiterator.pmc
   trunk/src/pmc/hashiteratorkey.pmc
   trunk/src/pmc/orderedhashiterator.pmc
   trunk/src/pmc/stringiterator.pmc
   trunk/t/pmc/hashiterator.t
Modified:
   trunk/config/gen/parrot_include.pm
   trunk/include/parrot/hash.h
   trunk/include/parrot/pmc.h
   trunk/lib/Parrot/Pmc2c/Method.pm
   trunk/lib/Parrot/Pmc2c/PMCEmitter.pm
   trunk/src/dynpmc/rational.pmc
   trunk/src/hash.c
   trunk/src/packfile.c
   trunk/src/pmc.c
   trunk/src/pmc/array.pmc
   trunk/src/pmc/env.pmc
   trunk/src/pmc/fixedbooleanarray.pmc
   trunk/src/pmc/fixedfloatarray.pmc
   trunk/src/pmc/fixedintegerarray.pmc
   trunk/src/pmc/fixedpmcarray.pmc
   trunk/src/pmc/fixedstringarray.pmc
   trunk/src/pmc/hash.pmc
   trunk/src/pmc/iterator.pmc
   trunk/src/pmc/namespace.pmc
   trunk/src/pmc/orderedhash.pmc
   trunk/src/pmc/string.pmc
   trunk/t/compilers/pct/past.t
   trunk/t/compilers/pct/post.t
   trunk/t/native_pbc/annotations.pbc
   trunk/t/native_pbc/integer_1.pbc
   trunk/t/native_pbc/number_1.pbc
   trunk/t/native_pbc/string_1.pbc
   trunk/t/op/gc.t
   trunk/t/pmc/hash.t
   trunk/t/pmc/iterator.t
   trunk/t/pmc/namespace.t
   trunk/t/pmc/orderedhash.t
   trunk/t/pmc/packfileannotations.t
   trunk/t/pmc/packfilerawsegment.t
   trunk/t/pmc/pmc.t
   trunk/t/pmc/testlib/packfile_common.pir

Modified: trunk/config/gen/parrot_include.pm
==============================================================================
--- trunk/config/gen/parrot_include.pm	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/config/gen/parrot_include.pm	Wed Jul 15 13:15:25 2009	(r40100)
@@ -33,6 +33,7 @@
         include/parrot/events.h
         include/parrot/scheduler.h
         include/parrot/exceptions.h
+        include/parrot/hash.h
         include/parrot/interpreter.h
         include/parrot/io.h
         include/parrot/longopt.h

Modified: trunk/include/parrot/hash.h
==============================================================================
--- trunk/include/parrot/hash.h	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/include/parrot/hash.h	Wed Jul 15 13:15:25 2009	(r40100)
@@ -46,6 +46,7 @@
 typedef void (*hash_mark_key_fn)(PARROT_INTERP, PObj *);
 typedef size_t (*hash_hash_key_fn)(PARROT_INTERP, ARGIN(const void *), size_t seed);
 
+/* &gen_from_enum(hash_key_type.pasm) */
 typedef enum {
     Hash_key_type_int,
     Hash_key_type_cstring,
@@ -53,6 +54,7 @@
     Hash_key_type_PMC,
     Hash_key_type_ptr
 } Hash_key_type;
+/* &end_gen */
 
 typedef struct _hashbucket {
     struct _hashbucket *next;
@@ -128,10 +130,9 @@
 PARROT_CAN_RETURN_NULL
 HashBucket * parrot_hash_get_bucket(PARROT_INTERP,
     ARGIN(const Hash *hash),
-    ARGIN(const void *key))
+    ARGIN_NULLOK(const void *key))
         __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        __attribute__nonnull__(3);
+        __attribute__nonnull__(2);
 
 PARROT_EXPORT
 PARROT_WARN_UNUSED_RESULT
@@ -149,11 +150,10 @@
 PARROT_CANNOT_RETURN_NULL
 HashBucket* parrot_hash_put(PARROT_INTERP,
     ARGMOD(Hash *hash),
-    ARGIN(void *key),
+    ARGIN_NULLOK(void *key),
     ARGIN_NULLOK(void *value))
         __attribute__nonnull__(1)
         __attribute__nonnull__(2)
-        __attribute__nonnull__(3)
         FUNC_MODIFIES(*hash);
 
 PARROT_EXPORT
@@ -212,8 +212,9 @@
 
 PARROT_WARN_UNUSED_RESULT
 PARROT_PURE_FUNCTION
-size_t key_hash_int(SHIM_INTERP, ARGIN(const void *value), size_t seed)
-        __attribute__nonnull__(2);
+size_t key_hash_int(SHIM_INTERP,
+    ARGIN_NULLOK(const void *value),
+    size_t seed);
 
 void parrot_chash_destroy(PARROT_INTERP, ARGMOD(Hash *hash))
         __attribute__nonnull__(1)
@@ -261,16 +262,14 @@
     || PARROT_ASSERT_ARG(key)
 #define ASSERT_ARGS_parrot_hash_get_bucket __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(hash) \
-    || PARROT_ASSERT_ARG(key)
+    || PARROT_ASSERT_ARG(hash)
 #define ASSERT_ARGS_parrot_hash_get_idx __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp) \
     || PARROT_ASSERT_ARG(hash) \
     || PARROT_ASSERT_ARG(key)
 #define ASSERT_ARGS_parrot_hash_put __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(hash) \
-    || PARROT_ASSERT_ARG(key)
+    || PARROT_ASSERT_ARG(hash)
 #define ASSERT_ARGS_parrot_hash_size __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(hash)
 #define ASSERT_ARGS_parrot_hash_visit __attribute__unused__ int _ASSERT_ARGS_CHECK = \
@@ -292,8 +291,7 @@
 #define ASSERT_ARGS_parrot_new_pointer_hash __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp)
 #define ASSERT_ARGS_int_compare __attribute__unused__ int _ASSERT_ARGS_CHECK = 0
-#define ASSERT_ARGS_key_hash_int __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(value)
+#define ASSERT_ARGS_key_hash_int __attribute__unused__ int _ASSERT_ARGS_CHECK = 0
 #define ASSERT_ARGS_parrot_chash_destroy __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp) \
     || PARROT_ASSERT_ARG(hash)

Modified: trunk/include/parrot/pmc.h
==============================================================================
--- trunk/include/parrot/pmc.h	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/include/parrot/pmc.h	Wed Jul 15 13:15:25 2009	(r40100)
@@ -85,7 +85,7 @@
 PMC * pmc_reuse(PARROT_INTERP,
     ARGIN(PMC *pmc),
     INTVAL new_type,
-    NULLOK(UINTVAL flags))
+    UINTVAL flags)
         __attribute__nonnull__(1)
         __attribute__nonnull__(2);
 
@@ -102,6 +102,18 @@
         FUNC_MODIFIES(*pmc);
 
 PARROT_EXPORT
+PARROT_CANNOT_RETURN_NULL
+PARROT_IGNORABLE_RESULT
+PMC * pmc_reuse_init(PARROT_INTERP,
+    ARGIN(PMC *pmc),
+    INTVAL new_type,
+    ARGIN(PMC *init),
+    UINTVAL flags)
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
+        __attribute__nonnull__(4);
+
+PARROT_EXPORT
 PARROT_WARN_UNUSED_RESULT
 INTVAL pmc_type(PARROT_INTERP, ARGIN_NULLOK(STRING *name))
         __attribute__nonnull__(1);
@@ -155,6 +167,10 @@
        PARROT_ASSERT_ARG(interp) \
     || PARROT_ASSERT_ARG(pmc) \
     || PARROT_ASSERT_ARG(class_)
+#define ASSERT_ARGS_pmc_reuse_init __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp) \
+    || PARROT_ASSERT_ARG(pmc) \
+    || PARROT_ASSERT_ARG(init)
 #define ASSERT_ARGS_pmc_type __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp)
 #define ASSERT_ARGS_pmc_type_p __attribute__unused__ int _ASSERT_ARGS_CHECK = \

Modified: trunk/lib/Parrot/Pmc2c/Method.pm
==============================================================================
--- trunk/lib/Parrot/Pmc2c/Method.pm	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/lib/Parrot/Pmc2c/Method.pm	Wed Jul 15 13:15:25 2009	(r40100)
@@ -104,8 +104,8 @@
 
     return $1  if $char =~ /([ISP])/;
     return 'N' if $char eq 'F';
-    return 'v' if $type eq 'void';
     return 'V' if $type =~ /void\s*\*/;
+    return 'v' if $type =~ /void\s*$/;
     return 'P' if $type =~ /opcode_t\*/;
     return 'I' if $type =~ /int(val)?/i;
     return '?';

Modified: trunk/lib/Parrot/Pmc2c/PMCEmitter.pm
==============================================================================
--- trunk/lib/Parrot/Pmc2c/PMCEmitter.pm	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/lib/Parrot/Pmc2c/PMCEmitter.pm	Wed Jul 15 13:15:25 2009	(r40100)
@@ -1002,12 +1002,15 @@
 
         my $multis = $multi_methods{$vt_method_name};
 
+        # Get parameters.      strip type from param
+        my @parameters = map { s/(\s*\S+\s*\*?\s*)//; $_ } split (/,/, $method->parameters);
+
         # Gather "case :"
-        my @cases = map { $self->generate_single_case($vt_method_name, $_) } @$multis;
+        my @cases = map { $self->generate_single_case($vt_method_name, $_, @parameters) } @$multis;
         my $cases = join "\n", @cases;
 
         my $body = <<"BODY";
-    INTVAL type = VTABLE_type(INTERP, value);
+    INTVAL type = VTABLE_type(INTERP, $parameters[0]);
     /* For dynpmc fallback to MMD */
     if ((type >= enum_class_core_max) || (SELF.type() >= enum_class_core_max))
         type = enum_class_core_max;
@@ -1027,13 +1030,12 @@
 
 # Generate single case for switch VTABLE
 sub generate_single_case {
-    my ($self, $vt_method_name, $multi) = @_;
+    my ($self, $vt_method_name, $multi, @parameters) = @_;
 
     my ($type, $ssig, $fsig, $ns, $func, $impl) = @$multi;
     my $case;
 
     # Gather parameters names
-    my @parameters = map { s/\s*PMC\s*\*\s*//; $_ } split (/,/, $impl->parameters);
     my $parameters = join ', ', @parameters;
     # ISO C forbids return with expression from void functions.
     my $return = $impl->return_type =~ /^void\s*$/
@@ -1082,12 +1084,20 @@
             'return retval;',
         );
     }
+    elsif ($letter eq 'S') {
+        return (
+            "PP->" . $letter,
+            "STRING *retval;",
+            ', &retval',
+            'return retval;',
+        );
+    }
     elsif ($letter eq 'P') {
         return (
             'PPP->P',
-            '',
-            ", &$parameters[1]",
-            "return $parameters[1];",
+            'PMC *retval;',
+            ", &retval",
+            "return retval;",
         );
     }
     elsif ($letter eq 'v') {

Modified: trunk/src/dynpmc/rational.pmc
==============================================================================
--- trunk/src/dynpmc/rational.pmc	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/src/dynpmc/rational.pmc	Wed Jul 15 13:15:25 2009	(r40100)
@@ -66,28 +66,19 @@
 
 /*
 
-=item * static void rat_add_integer(PARROT_INTERP, PMC *self, int value, PMC *dest)
+=item * static void rat_add_integer(PARROT_INTERP, PMC *self, int value)
 
-Adds an integer "value" to a Rational-PMC and stores the result in (another) Rational-PMC.
+Adds an integer "value" to a Rational-PMC inplace.
 
 =cut
 
 */
-static void rat_add_integer(PARROT_INTERP, PMC *self, int value, PMC *dest) {
+static void rat_add_integer(PARROT_INTERP, PMC *self, int value) {
   #ifdef PARROT_HAS_GMP
     mpq_t t;
-
-    if (dest) {
-        if (self != dest)
-            pmc_reuse(interp, dest, self->vtable->base_type, 0);
-    }
-    else {
-        dest = pmc_new(interp, self->vtable->base_type);
-    }
-
     mpq_init(t);
     mpq_set_si(t, (int) value, 1);
-    mpq_add(RT(dest), RT(self), t);
+    mpq_add(RT(self), RT(self), t);
     mpq_clear(t);
   #else
     RAISE_EXCEPTION
@@ -96,26 +87,21 @@
 
 /*
 
-=item * static void rat_add_float(PARROT_INTERP, PMC *self, double value, PMC *dest)
+=item * static void rat_add_float(PARROT_INTERP, PMC *self, double value)
 
-Adds a float "value" to a Rational-PMC and stores the result in (another) Rational-PMC. "value" is
-first conveted to a rational using GMPs mpq_set_d-function. This is meant to be exact.
+Adds a float "value" to a Rational-PMC in-place. "value" is first conveted to a
+rational using GMPs mpq_set_d-function. This is meant to be exact.
 
 =cut
 
 */
-static void rat_add_float(PARROT_INTERP, PMC *self, double value, PMC *dest) {
+static void rat_add_float(PARROT_INTERP, PMC *self, double value) {
   #ifdef PARROT_HAS_GMP
     mpq_t t;
 
-    if (dest)
-        pmc_reuse(interp, dest, self->vtable->base_type, 0);
-    else
-        dest = pmc_new(interp, self->vtable->base_type);
-
     mpq_init(t);
     mpq_set_d(t, (double) value);
-    mpq_add(RT(dest), RT(self), t);
+    mpq_add(RT(self), RT(self), t);
     mpq_clear(t);
   #else
     RAISE_EXCEPTION
@@ -124,22 +110,16 @@
 
 /*
 
-=item * static void rat_multiply_integer(PARROT_INTERP, PMC *self, int value, PMC *dest)
+=item * static void rat_multiply_integer(PARROT_INTERP, PMC *self, int value)
 
-Multiplys a Rational-PMC with an integer "value" and stores the result in (another) Rational-PMC.
+Multiplys a Rational-PMC with an integer "value" in-place.
 
 =cut
 
 */
-static void rat_multiply_integer(PARROT_INTERP, PMC *self, int value, PMC *dest) {
+static void rat_multiply_integer(PARROT_INTERP, PMC *self, int value) {
   #ifdef PARROT_HAS_GMP
-    if (dest)
-        pmc_reuse(interp, dest, self->vtable->base_type, 0);
-    else
-        dest = pmc_new(interp, self->vtable->base_type);
-
-    mpz_mul_ui(mpq_numref(RT(dest)), mpq_numref(RT(self)), (unsigned int) value);
-    mpq_set_den(RT(dest), mpq_denref(RT(self)));
+    mpz_mul_ui(mpq_numref(RT(self)), mpq_numref(RT(self)), (unsigned int) value);
   #else
     RAISE_EXCEPTION
   #endif
@@ -147,25 +127,20 @@
 
 /*
 
-=item * static void rat_multiply_float(PARROT_INTERP, PMC *self, double value, PMC *dest)
+=item * static void rat_multiply_float(PARROT_INTERP, PMC *self, double value)
 
-Multiplies a Rational-PMC with a float "value" and stores the result in (another) Rational-PMC.
+Multiplies a Rational-PMC with a float "value" in-place.
 
 =cut
 
 */
-static void rat_multiply_float(PARROT_INTERP, PMC *self, double value, PMC *dest) {
+static void rat_multiply_float(PARROT_INTERP, PMC *self, double value) {
   #ifdef PARROT_HAS_GMP
     mpq_t t;
 
-    if (dest)
-        pmc_reuse(interp, dest, self->vtable->base_type, 0);
-    else
-        dest = pmc_new(interp, self->vtable->base_type);
-
     mpq_init(t);
     mpq_set_d(t, (double) value);
-    mpq_mul(RT(dest), RT(self), t);
+    mpq_mul(RT(self), RT(self), t);
     mpq_clear(t);
   #else
     RAISE_EXCEPTION
@@ -174,25 +149,20 @@
 
 /*
 
-=item * static void rat_divide_integer(PARROT_INTERP, PMC *self, int value, PMC *dest)
+=item * static void rat_divide_integer(PARROT_INTERP, PMC *self, int value)
 
-Divides a Rational-PMC through an integer "value" and stores the result in (another) Rational-PMC.
+Divides a Rational-PMC through an integer "value" in-place.
 
 =cut
 
 */
-static void rat_divide_integer(PARROT_INTERP, PMC *self, int value, PMC *dest) {
+static void rat_divide_integer(PARROT_INTERP, PMC *self, int value) {
   #ifdef PARROT_HAS_GMP
     mpq_t t;
 
-    if (dest)
-        pmc_reuse(interp, dest, self->vtable->base_type, 0);
-    else
-        dest = pmc_new(interp, self->vtable->base_type);
-
     mpq_init(t);
     mpq_set_si(t, (int) value, 1);
-    mpq_div(RT(dest), RT(self), t);
+    mpq_div(RT(self), RT(self), t);
     mpq_clear(t);
   #else
     RAISE_EXCEPTION
@@ -201,25 +171,20 @@
 
 /*
 
-=item * static void rat_divide_float(PARROT_INTERP, PMC *self, double value, PMC *dest)
+=item * static void rat_divide_float(PARROT_INTERP, PMC *self, double value)
 
-Divides a Rational-PMC through a float "value" and stores the result in (another) Rational-PMC.
+Divides a Rational-PMC through a float "value" in-place.
 
 =cut
 
 */
-static void rat_divide_float(PARROT_INTERP, PMC *self, double value, PMC *dest) {
+static void rat_divide_float(PARROT_INTERP, PMC *self, double value) {
   #ifdef PARROT_HAS_GMP
     mpq_t t;
 
-    if (dest)
-        pmc_reuse(interp, dest, self->vtable->base_type, 0);
-    else
-        dest = pmc_new(interp, self->vtable->base_type);
-
     mpq_init(t);
     mpq_set_d(t, (double) value);
-    mpq_div(RT(dest), RT(self), t);
+    mpq_div(RT(self), RT(self), t);
     mpq_clear(t);
   #else
     RAISE_EXCEPTION
@@ -228,32 +193,27 @@
 
 /*
 
-=item * static void rat_power_int(PARROT_INTERP, PMC *self, int value, PMC *dest)
+=item * static void rat_power_int(PARROT_INTERP, PMC *self, int value)
 
-Calculates the power of a Rational-PMC to an exponent value and stores the result in (another)
-Rational-PMC.
+Calculates the power of a Rational-PMC to an exponent value in-place.
 
 =cut
 
 */
-static void rat_power_int(PARROT_INTERP, PMC *self, int value, PMC *dest) {
+static void rat_power_int(PARROT_INTERP, PMC *self, int value) {
   #ifdef PARROT_HAS_GMP
-    mpz_t t;
+    mpz_t num, den;
+
+    mpq_get_num(num, RT(self));
+    mpq_get_den(den, RT(self));
 
-    if (dest)
-        pmc_reuse(interp, dest, self->vtable->base_type, 0);
-    else
-        dest = pmc_new(interp, self->vtable->base_type);
-
-    mpq_get_num(t, RT(self));
-    mpz_pow_ui(t, t, (unsigned int) value);
-    mpq_set_num(RT(dest), t);
-    mpz_clear(t);
-
-    mpq_get_den(t, RT(self));
-    mpz_pow_ui(t, t, (unsigned int) value);
-    mpq_set_den(RT(dest), t);
-    mpz_clear(t);
+    mpz_pow_ui(num, num, (unsigned int) value);
+    mpq_set_num(RT(self), num);
+    mpz_clear(num);
+
+    mpz_pow_ui(den, den, (unsigned int) value);
+    mpq_set_den(RT(self), den);
+    mpz_clear(den);
   #else
     RAISE_EXCEPTION
   #endif
@@ -322,14 +282,8 @@
 */
     VTABLE PMC *clone() {
       #ifdef PARROT_HAS_GMP
-        mpz_t num, den;
         PMC * const ret = pmc_new(INTERP, SELF->vtable->base_type);
-        mpq_get_num(num, RT(SELF));
-        mpq_get_den(den, RT(SELF));
-        mpq_set_num(RT(ret), num);
-        mpq_set_den(RT(ret), den);
-        mpz_clear(num);
-        mpz_clear(den);
+        mpq_set(RT(ret), RT(SELF));
         return ret;
       #else
         RAISE_EXCEPTION
@@ -554,21 +508,20 @@
 
 */
     MULTI PMC *add(Integer value, PMC* dest) {
-        rat_add_integer(INTERP, SELF, VTABLE_get_integer(INTERP, value), dest);
+        dest = STATICSELF.clone();
+        rat_add_integer(INTERP, dest, VTABLE_get_integer(INTERP, value));
         return dest;
     }
 
     MULTI PMC *add(Float value, PMC* dest) {
-        rat_add_float(INTERP, SELF, VTABLE_get_number(INTERP, value), dest);
+        dest = STATICSELF.clone();
+        rat_add_float(INTERP, dest, VTABLE_get_number(INTERP, value));
         return dest;
     }
 
     MULTI PMC *add(Rational value, PMC* dest) {
       #ifdef PARROT_HAS_GMP
-        if (dest)
-            pmc_reuse(interp, dest, SELF->vtable->base_type, 0);
-        else
-            dest = pmc_new(INTERP, SELF->vtable->base_type);
+        dest = pmc_new(INTERP, SELF->vtable->base_type);
 
         mpq_add(RT(dest), RT(SELF), RT(value));
         return dest;
@@ -590,11 +543,11 @@
 
 */
     MULTI void i_add(Integer value) {
-        rat_add_integer(INTERP, SELF, (int) VTABLE_get_integer(INTERP, value), SELF);
+        rat_add_integer(INTERP, SELF, (int) VTABLE_get_integer(INTERP, value));
     }
 
     MULTI void i_add(Float value) {
-        rat_add_float(INTERP, SELF, (double) VTABLE_get_number(INTERP, value), SELF);
+        rat_add_float(INTERP, SELF, (double) VTABLE_get_number(INTERP, value));
     }
 
     MULTI void i_add(Rational value) {
@@ -618,7 +571,8 @@
 
 */
     VTABLE PMC *add_int(INTVAL value, PMC* dest) {
-        rat_add_integer(INTERP, SELF, (int) value, dest);
+        dest = STATICSELF.clone();;
+        rat_add_integer(INTERP, dest, (int) value);
         return dest;
     }
 
@@ -630,7 +584,7 @@
 
 */
     VTABLE void i_add_int(INTVAL value) {
-        rat_add_integer(INTERP, SELF, (int) value, SELF);
+        rat_add_integer(INTERP, SELF, (int) value);
     }
 
 /*
@@ -641,7 +595,8 @@
 
 */
     VTABLE PMC *add_float(FLOATVAL value, PMC* dest) {
-        rat_add_float(INTERP, SELF, (double) value, dest);
+        dest = STATICSELF.clone();
+        rat_add_float(INTERP, dest, (double) value);
         return dest;
     }
 
@@ -653,7 +608,7 @@
 
 */
     VTABLE void i_add_float(FLOATVAL value) {
-        rat_add_float(INTERP, SELF, (double) value, SELF);
+        rat_add_float(INTERP, SELF, (double) value);
     }
 
 /*
@@ -664,22 +619,20 @@
 
 */
     MULTI PMC *subtract(Integer value, PMC* dest) {
-        rat_add_integer(INTERP, SELF, -((int) VTABLE_get_integer(INTERP, value)), dest);
+        dest = STATICSELF.clone();
+        rat_add_integer(INTERP, dest, -((int) VTABLE_get_integer(INTERP, value)));
         return dest;
     }
 
     MULTI PMC *subtract(Float value, PMC* dest) {
-        rat_add_float(INTERP, SELF, - ((double) VTABLE_get_number(INTERP, value)), dest);
+        dest = STATICSELF.clone();
+        rat_add_float(INTERP, dest, - ((double) VTABLE_get_number(INTERP, value)));
         return dest;
     }
 
     MULTI PMC *subtract(Rational value, PMC* dest) {
       #ifdef PARROT_HAS_GMP
-        if (dest)
-            pmc_reuse(interp, dest, SELF->vtable->base_type, 0);
-        else
-            dest = pmc_new(INTERP, SELF->vtable->base_type);
-
+        dest = pmc_new(INTERP, SELF->vtable->base_type);
         mpq_sub(RT(dest), RT(SELF), RT(value));
         return dest;
       #else
@@ -700,11 +653,11 @@
 
 */
     MULTI void i_subtract(Integer value) {
-        rat_add_integer(INTERP, SELF, -((int) VTABLE_get_integer(INTERP, value)), SELF);
+        rat_add_integer(INTERP, SELF, -((int) VTABLE_get_integer(INTERP, value)));
     }
 
     MULTI void i_subtract(Float value) {
-        rat_add_float(INTERP, SELF, - ((double) VTABLE_get_number(INTERP, value)), SELF);
+        rat_add_float(INTERP, SELF, - ((double) VTABLE_get_number(INTERP, value)));
     }
 
     MULTI void i_subtract(Rational value) {
@@ -728,7 +681,8 @@
 
 */
     VTABLE PMC *subtract_int(INTVAL value, PMC* dest) {
-        rat_add_integer(INTERP, SELF, -((int) value), dest);
+        dest = STATICSELF.clone();
+        rat_add_integer(INTERP, dest, -((int) value));
         return dest;
     }
 
@@ -740,7 +694,7 @@
 
 */
     VTABLE void i_subtract_int(INTVAL value) {
-        rat_add_integer(INTERP, SELF, -((int) value), SELF);
+        rat_add_integer(INTERP, SELF, -((int) value));
     }
 
 /*
@@ -751,7 +705,8 @@
 
 */
     VTABLE PMC *subtract_float(FLOATVAL value, PMC* dest) {
-        rat_add_float(INTERP, SELF, -((double) value), dest);
+        dest = STATICSELF.clone();
+        rat_add_float(INTERP, dest, -((double) value));
         return dest;
     }
 
@@ -763,7 +718,7 @@
 
 */
     VTABLE void i_subtract_float(FLOATVAL value) {
-        rat_add_float(INTERP, SELF, -((double) value), SELF);
+        rat_add_float(INTERP, SELF, -((double) value));
     }
 
 /*
@@ -774,22 +729,20 @@
 
 */
     MULTI PMC *multiply(Integer value, PMC* dest) {
-        rat_multiply_integer(INTERP, SELF, (int) VTABLE_get_integer(INTERP, value), dest);
+        dest = STATICSELF.clone();
+        rat_multiply_integer(INTERP, dest, (int) VTABLE_get_integer(INTERP, value));
         return dest;
     }
 
     MULTI PMC *multiply(Float value, PMC* dest) {
-        rat_multiply_float(INTERP, SELF, (double) VTABLE_get_number(INTERP, value), dest);
+        dest = STATICSELF.clone();
+        rat_multiply_float(INTERP, dest, (double) VTABLE_get_number(INTERP, value));
         return dest;
     }
 
     MULTI PMC *multiply(Rational value, PMC* dest) {
       #ifdef PARROT_HAS_GMP
-        if (dest)
-            pmc_reuse(interp, dest, SELF->vtable->base_type, 0);
-        else
-            dest = pmc_new(INTERP, SELF->vtable->base_type);
-
+        dest = pmc_new(INTERP, SELF->vtable->base_type);
         mpq_mul(RT(dest), RT(SELF), RT(value));
         return dest;
       #else
@@ -810,11 +763,11 @@
 
 */
     MULTI void i_multiply(Integer value) {
-        rat_multiply_integer(INTERP, SELF, (int) VTABLE_get_integer(INTERP, value), SELF);
+        rat_multiply_integer(INTERP, SELF, (int) VTABLE_get_integer(INTERP, value));
     }
 
     MULTI void i_multiply(Float value) {
-        rat_multiply_float(INTERP, SELF, (double) VTABLE_get_number(INTERP, value), SELF);
+        rat_multiply_float(INTERP, SELF, (double) VTABLE_get_number(INTERP, value));
     }
 
     MULTI void i_multiply(Rational value) {
@@ -838,7 +791,8 @@
 
 */
     VTABLE PMC *multiply_int(INTVAL value, PMC* dest) {
-        rat_multiply_integer(INTERP, SELF, (int) value, dest);
+        dest = STATICSELF.clone();
+        rat_multiply_integer(INTERP, dest, (int) value);
         return dest;
     }
 
@@ -850,7 +804,7 @@
 
 */
     VTABLE void i_multiply_int(INTVAL value) {
-        rat_multiply_integer(INTERP, SELF, (int) value, SELF);
+        rat_multiply_integer(INTERP, SELF, (int) value);
     }
 
 /*
@@ -861,7 +815,8 @@
 
 */
     VTABLE PMC *multiply_float(FLOATVAL value, PMC* dest) {
-        rat_multiply_float(INTERP, SELF, (double) value, dest);
+        dest = STATICSELF.clone();
+        rat_multiply_float(INTERP, dest, (double) value);
         return dest;
     }
 
@@ -873,7 +828,7 @@
 
 */
     VTABLE void i_multiply_float(FLOATVAL value) {
-        rat_multiply_float(INTERP, SELF, (double) value, SELF);
+        rat_multiply_float(INTERP, SELF, (double) value);
     }
 
 /*
@@ -884,22 +839,20 @@
 
 */
     MULTI PMC *divide(Integer value, PMC* dest) {
-        rat_divide_integer(INTERP, SELF, (int) VTABLE_get_integer(INTERP, value), dest);
+        dest = STATICSELF.clone();
+        rat_divide_integer(INTERP, dest, (int) VTABLE_get_integer(INTERP, value));
         return dest;
     }
 
     MULTI PMC *divide(Float value, PMC* dest) {
-        rat_divide_float(INTERP, SELF, (double) VTABLE_get_number(INTERP, value), dest);
+        dest = STATICSELF.clone();
+        rat_divide_float(INTERP, dest, (double) VTABLE_get_number(INTERP, value));
         return dest;
     }
 
     MULTI PMC *divide(Rational value, PMC* dest) {
       #ifdef PARROT_HAS_GMP
-        if (dest)
-            pmc_reuse(interp, dest, SELF->vtable->base_type, 0);
-        else
-            dest = pmc_new(INTERP, SELF->vtable->base_type);
-
+        dest = pmc_new(INTERP, SELF->vtable->base_type);
         mpq_div(RT(dest), RT(SELF), RT(value));
         return dest;
       #else
@@ -920,11 +873,11 @@
 
 */
     MULTI void i_divide(Integer value) {
-        rat_divide_integer(INTERP, SELF, (int) VTABLE_get_integer(INTERP, value), SELF);
+        rat_divide_integer(INTERP, SELF, (int) VTABLE_get_integer(INTERP, value));
     }
 
     MULTI void i_divide(Float value) {
-        rat_divide_float(INTERP, SELF, (double) VTABLE_get_number(INTERP, value), SELF);
+        rat_divide_float(INTERP, SELF, (double) VTABLE_get_number(INTERP, value));
     }
 
     MULTI void i_divide(Rational value) {
@@ -948,7 +901,8 @@
 
 */
     VTABLE PMC *divide_int(INTVAL value, PMC* dest) {
-        rat_divide_integer(INTERP, SELF, (int) value, dest);
+        dest = STATICSELF.clone();
+        rat_divide_integer(INTERP, dest, (int) value);
         return dest;
     }
 
@@ -960,7 +914,7 @@
 
 */
     VTABLE void i_divide_int(INTVAL value) {
-        rat_divide_integer(INTERP, SELF, (int) value, SELF);
+        rat_divide_integer(INTERP, SELF, (int) value);
     }
 
 /*
@@ -971,7 +925,8 @@
 
 */
     VTABLE PMC *divide_float(FLOATVAL value, PMC* dest) {
-        rat_divide_float(INTERP, SELF, (double) value, dest);
+        dest = STATICSELF.clone();
+        rat_divide_float(INTERP, dest, (double) value);
         return dest;
     }
 
@@ -983,7 +938,7 @@
 
 */
     VTABLE void i_divide_float(FLOATVAL value) {
-        rat_divide_float(INTERP, SELF, (double) value, SELF);
+        rat_divide_float(INTERP, SELF, (double) value);
     }
 
 /*
@@ -995,10 +950,7 @@
 */
     VTABLE PMC *neg(PMC* dest) {
       #ifdef PARROT_HAS_GMP
-        if (dest)
-            pmc_reuse(interp, dest, SELF->vtable->base_type, 0);
-        else
-            dest = pmc_new(INTERP, SELF->vtable->base_type);
+        dest = pmc_new(INTERP, SELF->vtable->base_type);
 
         mpq_neg(RT(dest), RT(SELF));
         return dest;
@@ -1031,10 +983,7 @@
 */
     VTABLE PMC *absolute(PMC* dest) {
       #ifdef PARROT_HAS_GMP
-        if (dest)
-            pmc_reuse(interp, dest, SELF->vtable->base_type, 0);
-        else
-            dest = pmc_new(INTERP, SELF->vtable->base_type);
+        dest = pmc_new(INTERP, SELF->vtable->base_type);
 
         mpq_abs(RT(dest), RT(SELF));
         return dest;

Modified: trunk/src/hash.c
==============================================================================
--- trunk/src/hash.c	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/src/hash.c	Wed Jul 15 13:15:25 2009	(r40100)
@@ -322,13 +322,12 @@
 PARROT_WARN_UNUSED_RESULT
 PARROT_PURE_FUNCTION
 size_t
-key_hash_int(SHIM_INTERP, ARGIN(const void *value), size_t seed)
+key_hash_int(SHIM_INTERP, ARGIN_NULLOK(const void *value), size_t seed)
 {
     ASSERT_ARGS(key_hash_int)
     return (size_t)value ^ seed;
 }
 
-
 /*
 
 =item C<int int_compare(PARROT_INTERP, const void *a, const void *b)>
@@ -350,7 +349,6 @@
     return a != b;
 }
 
-
 /*
 
 =item C<void parrot_dump_hash(PARROT_INTERP, const Hash *hash)>
@@ -823,7 +821,7 @@
 
 =item C<Hash* parrot_new_hash(PARROT_INTERP)>
 
-Creates a new Parrot STRING hash in C<hptr>.
+Creates a new Parrot STRING hash.
 
 =cut
 
@@ -1198,7 +1196,7 @@
 PARROT_WARN_UNUSED_RESULT
 PARROT_CAN_RETURN_NULL
 HashBucket *
-parrot_hash_get_bucket(PARROT_INTERP, ARGIN(const Hash *hash), ARGIN(const void *key))
+parrot_hash_get_bucket(PARROT_INTERP, ARGIN(const Hash *hash), ARGIN_NULLOK(const void *key))
 {
     ASSERT_ARGS(parrot_hash_get_bucket)
 
@@ -1214,7 +1212,7 @@
             HashBucket *bucket = hash->bs + i;
 
             /* the hash->compare cost is too high for this fast path */
-            if (bucket->key && bucket->key == key)
+            if (bucket->key == key)
                 return bucket;
         }
     }
@@ -1297,7 +1295,8 @@
 PARROT_IGNORABLE_RESULT
 PARROT_CANNOT_RETURN_NULL
 HashBucket*
-parrot_hash_put(PARROT_INTERP, ARGMOD(Hash *hash), ARGIN(void *key), ARGIN_NULLOK(void *value))
+parrot_hash_put(PARROT_INTERP, ARGMOD(Hash *hash),
+        ARGIN_NULLOK(void *key), ARGIN_NULLOK(void *value))
 {
     ASSERT_ARGS(parrot_hash_put)
     const UINTVAL hashval = (hash->hash_val)(interp, key, hash->seed);

Modified: trunk/src/packfile.c
==============================================================================
--- trunk/src/packfile.c	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/src/packfile.c	Wed Jul 15 13:15:25 2009	(r40100)
@@ -2251,6 +2251,26 @@
             }
         }
     }
+
+    /* XXX
+     * Temporary? hack to put ConstantTable in front of other segments.
+     * This is useful for Annotations because we ensure that constants used
+     * for keys already available during unpack.
+     */
+    seg = dir->segments[2];
+
+    if (seg->type != PF_CONST_SEG) {
+        size_t i;
+
+        for (i = 3; i < num_segs; i++) {
+            PackFile_Segment * const s2 = dir->segments[i];
+            if (s2->type == PF_CONST_SEG) {
+                dir->segments[2] = s2;
+                dir->segments[i] = seg;
+                break;
+            }
+        }
+    }
 }
 
 

Modified: trunk/src/pmc.c
==============================================================================
--- trunk/src/pmc.c	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/src/pmc.c	Wed Jul 15 13:15:25 2009	(r40100)
@@ -50,6 +50,14 @@
         __attribute__nonnull__(2)
         FUNC_MODIFIES(* pmc);
 
+PARROT_CANNOT_RETURN_NULL
+static PMC* pmc_reuse_no_init(PARROT_INTERP,
+    ARGIN(PMC *pmc),
+    INTVAL new_type,
+    SHIM(UINTVAL flags))
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2);
+
 #define ASSERT_ARGS_check_pmc_reuse_flags __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp)
 #define ASSERT_ARGS_create_class_pmc __attribute__unused__ int _ASSERT_ARGS_CHECK = \
@@ -59,6 +67,9 @@
 #define ASSERT_ARGS_pmc_reuse_check_pmc_ext __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp) \
     || PARROT_ASSERT_ARG(pmc)
+#define ASSERT_ARGS_pmc_reuse_no_init __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp) \
+    || PARROT_ASSERT_ARG(pmc)
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 /* HEADERIZER END: static */
 
@@ -145,9 +156,68 @@
 PARROT_IGNORABLE_RESULT
 PMC *
 pmc_reuse(PARROT_INTERP, ARGIN(PMC *pmc), INTVAL new_type,
-          SHIM(UINTVAL flags))
+          UINTVAL flags)
 {
     ASSERT_ARGS(pmc_reuse)
+    pmc = pmc_reuse_no_init(interp, pmc, new_type, flags);
+
+    /* Call the base init for the redone pmc. Warning, this should not
+       be called on Object PMCs. */
+    VTABLE_init(interp, pmc);
+
+    return pmc;
+}
+
+/*
+
+=item C<PMC * pmc_reuse_init(PARROT_INTERP, PMC *pmc, INTVAL new_type, PMC
+*init, UINTVAL flags)>
+
+Reuse an existing PMC, turning it into an PMC of the new type. Any
+required internal structure will be put in place (such as the extension area)
+and the PMC will be inited.
+
+Cannot currently handle converting a non-Object PMC into an Object. Use
+C<pmc_reuse_by_class> for that.
+
+
+=cut
+
+*/
+
+PARROT_EXPORT
+PARROT_CANNOT_RETURN_NULL
+PARROT_IGNORABLE_RESULT
+PMC *
+pmc_reuse_init(PARROT_INTERP, ARGIN(PMC *pmc), INTVAL new_type, ARGIN(PMC *init),
+          UINTVAL flags)
+{
+    ASSERT_ARGS(pmc_reuse_init)
+    pmc = pmc_reuse_no_init(interp, pmc, new_type, flags);
+
+    /* Call the base init for the redone pmc. Warning, this should not
+       be called on Object PMCs. */
+    VTABLE_init_pmc(interp, pmc, init);
+
+    return pmc;
+}
+
+/*
+
+=item C<static PMC* pmc_reuse_no_init(PARROT_INTERP, PMC *pmc, INTVAL new_type,
+UINTVAL flags)>
+
+Prepare pmc for reuse. Do all scuffolding except initing.
+
+=cut
+
+*/
+PARROT_CANNOT_RETURN_NULL
+static PMC*
+pmc_reuse_no_init(PARROT_INTERP, ARGIN(PMC *pmc), INTVAL new_type,
+    SHIM(UINTVAL flags)) {
+
+    ASSERT_ARGS(pmc_reuse_no_init)
     VTABLE *new_vtable;
     INTVAL  has_ext, new_flags = 0;
 
@@ -171,10 +241,6 @@
     /* Set the right vtable */
     pmc->vtable = new_vtable;
 
-    /* Call the base init for the redone pmc. Warning, this should not
-       be called on Object PMCs. */
-    VTABLE_init(interp, pmc);
-
     return pmc;
 }
 

Modified: trunk/src/pmc/array.pmc
==============================================================================
--- trunk/src/pmc/array.pmc	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/src/pmc/array.pmc	Wed Jul 15 13:15:25 2009	(r40100)
@@ -1184,19 +1184,7 @@
     }
 
     VTABLE PMC *get_iter() {
-        STRING * const name = CONST_STRING(interp, "set_key");
-        PMC * const iter = pmc_new_init(INTERP, enum_class_Iterator, SELF);
-        PMC * const key  = pmc_new(INTERP, enum_class_Key);
-        Parrot_PCCINVOKE(interp, iter, name, "P->", key);
-
-        PObj_get_FLAGS(key) |= KEY_integer_FLAG;
-
-        if (!((List *)PMC_data(SELF))->length)
-            VTABLE_set_integer_native(INTERP, key, -1);
-        else
-            VTABLE_set_integer_native(INTERP, key, 0);
-
-        return iter;
+        return pmc_new_init(INTERP, enum_class_ArrayIterator, SELF);
     }
 
 /*

Added: trunk/src/pmc/arrayiterator.pmc
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/src/pmc/arrayiterator.pmc	Wed Jul 15 13:15:25 2009	(r40100)
@@ -0,0 +1,590 @@
+/*
+Copyright (C) 2001-2009, Parrot Foundation.
+$Id$
+
+=head1 NAME
+
+src/pmc/arrayiterator.pmc - Implementation of Iterator for Arrays.
+
+=head1 DESCRIPTION
+
+Generic iterator for traversing arrays.
+
+=head1 SYNOPSIS
+
+=head2 default usage
+
+    .local pmc iterator, array, entry
+    iterator = iter array
+  iter_loop:
+    unless iterator, iter_end  # while (more values)
+    entry = shift iterator     # get an entry
+    ...
+    goto iter_loop
+  iter_end:
+
+
+=head2 iterate from the end, for arrays
+
+    .local pmc iterator, array, entry
+    iterator = iter array
+    iterator = .ITERATE_FROM_END
+  iter_loop:
+    unless iterator, iter_end  # while (more values)
+    entry = pop iterator     # get an entry
+    ...
+    goto iter_loop
+  iter_end:
+
+=head2 Warning!
+
+NB: for different direction you have to use different ops!
+
+TODO: Discuss idea of having separate get_iter/get_reverse_iter VTABLE methods
+to avoid this caveat.
+
+=head1 Methods
+
+=over 4
+
+=cut
+
+*/
+
+pmclass ArrayIterator no_ro {
+    ATTR PMC    *array;     /* the array which this Iterator iterates */
+    ATTR INTVAL  pos;       /* Current position of iterator for forward iterator */
+                            /* Previous position of iterator for reverse iterator */
+    ATTR INTVAL  length;    /* Length of C<array> */
+    ATTR INTVAL  reverse;   /* Direction of iteration. 1 - for reverse iteration */
+
+/*
+
+=item C<void init()>
+
+Raises an exception. Use C<init_pmc()>.
+
+=cut
+
+*/
+
+    VTABLE void init() {
+        Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
+                "ArrayIterator init without aggregate");
+    }
+
+/*
+
+=item C<void init_pmc(PMC *initializer)>
+
+Initializes the iterator with an aggregate PMC.
+Defaults iteration mode to iterate from start.
+
+=cut
+
+*/
+
+    VTABLE void init_pmc(PMC *array) {
+        Parrot_ArrayIterator_attributes *attrs =
+            mem_allocate_zeroed_typed(Parrot_ArrayIterator_attributes);
+
+        attrs->array     = array;
+        PMC_data(SELF)   = attrs;
+
+        PObj_custom_mark_destroy_SETALL(SELF);
+
+        /* by default, iterate from start */
+        SELF.set_integer_native(ITERATE_FROM_START);
+    }
+
+/*
+
+=item C<void destroy()>
+
+destroys this PMC
+
+=cut
+
+*/
+
+    VTABLE void destroy() {
+        mem_sys_free(PMC_data(SELF));
+    }
+
+/*
+
+=item C<void mark()>
+
+Marks the current idx/key and the aggregate as live.
+
+=cut
+
+*/
+
+    VTABLE void mark() {
+        PMC *array;
+        GET_ATTR_array(INTERP, SELF, array);
+        if (array)
+             Parrot_gc_mark_PObj_alive(INTERP, (PObj *)array);
+    }
+
+/*
+
+=item C<PMC *clone()>
+
+=cut
+
+*/
+    VTABLE PMC* clone() {
+        Parrot_ArrayIterator_attributes *attrs =
+                PARROT_ARRAYITERATOR(SELF);
+        PMC                             *clone =
+                pmc_new_init(INTERP, enum_class_ArrayIterator, attrs->array);
+        Parrot_ArrayIterator_attributes *clone_attrs =
+                PARROT_ARRAYITERATOR(clone);
+
+        clone_attrs->pos     = attrs->pos;
+        clone_attrs->reverse = attrs->reverse;
+        return clone;
+    }
+
+/*
+
+=item C<INTVAL get_bool()>
+
+Returns true if there is more elements to iterate over.
+
+=cut
+
+*/
+
+    VTABLE INTVAL get_bool() {
+        return SELF.elements() > 0;
+    }
+
+/*
+
+=item C<INTVAL elements()>
+
+Returns the number of remaining elements in the array.
+
+=cut
+
+*/
+
+    VTABLE INTVAL elements() {
+        Parrot_ArrayIterator_attributes *attrs =
+                PARROT_ARRAYITERATOR(SELF);
+        if (attrs->reverse)
+            return attrs->pos;
+        else
+            return attrs->length - attrs->pos;
+    }
+
+    VTABLE INTVAL get_integer() {
+        return SELF.elements();
+    }
+
+/*
+
+=item C<void set_integer_native(INTVAL value)>
+
+Reset the Iterator. C<value> must be one of
+
+ ITERATE_FROM_START        ... Iterate from start
+ ITERATE_FROM_END          ... Iterate from end
+
+=cut
+
+*/
+
+    VTABLE void set_integer_native(INTVAL value) {
+        Parrot_ArrayIterator_attributes *attrs =
+                PARROT_ARRAYITERATOR(SELF);
+        if (value == ITERATE_FROM_START) {
+            attrs->reverse   = 0;
+            attrs->pos       = 0;
+            attrs->length    = VTABLE_elements(INTERP, attrs->array);
+        }
+        else if (value == ITERATE_FROM_END) {
+            attrs->reverse   = 1;
+            attrs->pos       = attrs->length
+                             = VTABLE_elements(INTERP, attrs->array);
+        }
+        else
+            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
+                    "Wrong direction for ArrayIterator");
+    }
+
+/*
+
+=item C<PMC *get_pmc()>
+
+Returns this Iterator's array.
+
+=cut
+
+*/
+
+    VTABLE PMC *get_pmc() {
+        PMC *array;
+        GET_ATTR_array(INTERP, SELF, array);
+        return array ? array : PMCNULL;
+    }
+
+/*
+
+=item C<INTVAL shift_integer()>
+
+Returns the element for the current idx and sets the idx to
+the next one.
+
+=cut
+
+*/
+
+    VTABLE INTVAL shift_integer() {
+        Parrot_ArrayIterator_attributes *attrs =
+                PARROT_ARRAYITERATOR(SELF);
+
+        if (attrs->pos >= attrs->length)
+            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
+                "StopIteration");
+
+        return VTABLE_get_integer_keyed_int(INTERP, attrs->array, attrs->pos++);
+    }
+
+/*
+
+=item C<FLOATVAL shift_float()>
+
+=cut
+
+*/
+
+    VTABLE FLOATVAL shift_float() {
+        Parrot_ArrayIterator_attributes *attrs =
+                PARROT_ARRAYITERATOR(SELF);
+
+        if (!STATICSELF.get_bool())
+            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
+                "StopIteration");
+
+        return VTABLE_get_number_keyed_int(INTERP, attrs->array, attrs->pos++);
+    }
+
+
+/*
+
+=item C<STRING *shift_string()>
+
+=cut
+
+*/
+
+    VTABLE STRING *shift_string() {
+        Parrot_ArrayIterator_attributes *attrs =
+                PARROT_ARRAYITERATOR(SELF);
+
+        if (!STATICSELF.get_bool())
+            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
+                "StopIteration");
+
+        return VTABLE_get_string_keyed_int(INTERP, attrs->array, attrs->pos++);
+    }
+
+/*
+
+=item C<PMC *shift_pmc()>
+
+Returns the element for the current idx/key and sets the idx/key to
+the next one.
+
+=cut
+
+*/
+
+    VTABLE PMC *shift_pmc() {
+        Parrot_ArrayIterator_attributes *attrs =
+                PARROT_ARRAYITERATOR(SELF);
+
+        if (!STATICSELF.get_bool())
+            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
+                "StopIteration");
+
+        return VTABLE_get_pmc_keyed_int(INTERP, attrs->array, attrs->pos++);
+    }
+
+
+/*
+
+=item C<INTVAL pop_integer()>
+
+Returns the element for the current idx and sets the idx to
+the next one.
+
+=cut
+
+*/
+
+    VTABLE INTVAL pop_integer() {
+        Parrot_ArrayIterator_attributes *attrs =
+                PARROT_ARRAYITERATOR(SELF);
+
+        if (!STATICSELF.get_bool())
+            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
+                "StopIteration");
+
+        return VTABLE_get_integer_keyed_int(INTERP, attrs->array, --attrs->pos);
+    }
+
+/*
+
+=item C<FLOATVAL pop_float()>
+
+=cut
+
+*/
+
+    VTABLE FLOATVAL pop_float() {
+        Parrot_ArrayIterator_attributes *attrs =
+                PARROT_ARRAYITERATOR(SELF);
+
+        if (!STATICSELF.get_bool())
+            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
+                "StopIteration");
+
+        return VTABLE_get_number_keyed_int(INTERP, attrs->array, --attrs->pos);
+    }
+
+
+/*
+
+=item C<STRING *pop_string()>
+
+=cut
+
+*/
+
+    VTABLE STRING *pop_string() {
+        Parrot_ArrayIterator_attributes *attrs =
+                PARROT_ARRAYITERATOR(SELF);
+
+        if (!STATICSELF.get_bool())
+            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
+                "StopIteration");
+
+        return VTABLE_get_string_keyed_int(INTERP, attrs->array, --attrs->pos);
+    }
+
+/*
+
+=item C<PMC *pop_pmc()>
+
+Returns the element for the current idx/key and sets the idx/key to
+the next one.
+
+=cut
+
+*/
+
+    VTABLE PMC *pop_pmc() {
+        Parrot_ArrayIterator_attributes *attrs =
+                PARROT_ARRAYITERATOR(SELF);
+
+        if (!STATICSELF.get_bool())
+            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
+                "StopIteration");
+
+        return VTABLE_get_pmc_keyed_int(INTERP, attrs->array, --attrs->pos);
+    }
+
+/*
+=item C<PMC *get_pmc_keyed(PMC *key)>
+
+Returns the element for C<*key>.
+
+=cut
+
+*/
+
+    VTABLE PMC *get_pmc_keyed(PMC *key) {
+        return STATICSELF.get_pmc_keyed_int(VTABLE_get_integer(INTERP, key));
+    }
+
+/*
+
+=item C<PMC *get_pmc_keyed_int(INTVAL key)>
+
+Returns the element for C<key>.
+
+=cut
+
+*/
+
+    VTABLE PMC *get_pmc_keyed_int(INTVAL idx) {
+        return VTABLE_get_pmc_keyed_int(INTERP, STATICSELF.get_pmc(),
+                PARROT_ARRAYITERATOR(SELF)->pos + idx);
+    }
+/*
+
+=item C<INTVAL get_integer_keyed(PMC *key)>
+
+=cut
+
+*/
+
+    VTABLE INTVAL get_integer_keyed(PMC *key) {
+        return STATICSELF.get_integer_keyed_int(VTABLE_get_integer(INTERP, key));
+    }
+
+/*
+
+=item C<INTVAL get_integer_keyed_int(INTVAL idx)>
+
+Get integer value of current position plus idx.
+
+=cut
+
+*/
+
+    VTABLE INTVAL get_integer_keyed_int(INTVAL idx) {
+        return VTABLE_get_integer_keyed_int(INTERP, STATICSELF.get_pmc(),
+                PARROT_ARRAYITERATOR(SELF)->pos + idx);
+    }
+
+/*
+
+=item C<FLOATVAL get_number_keyed(PMC *key)>
+
+=cut
+
+*/
+
+    VTABLE FLOATVAL get_number_keyed(PMC *key) {
+        return STATICSELF.get_number_keyed_int(VTABLE_get_integer(INTERP, key));
+    }
+
+/*
+
+=item C<FLOATVAL get_number_keyed_int(INTVAL idx)>
+
+Get number value of current position plus idx.
+
+=cut
+
+*/
+
+    VTABLE FLOATVAL get_number_keyed_int(INTVAL idx) {
+        return VTABLE_get_number_keyed_int(INTERP, STATICSELF.get_pmc(),
+                PARROT_ARRAYITERATOR(SELF)->pos + idx);
+    }
+
+
+
+/*
+
+=item C<STRING *get_string_keyed(PMC *key)>
+
+=cut
+
+*/
+
+    VTABLE STRING *get_string_keyed(PMC *key) {
+        return STATICSELF.get_string_keyed_int(VTABLE_get_integer(INTERP, key));
+    }
+
+/*
+
+=item C<STRING *get_string_keyed_int(INTVAL idx)>
+
+Get string value of current position plus idx.
+
+=cut
+
+*/
+
+    VTABLE STRING *get_string_keyed_int(INTVAL idx) {
+        return VTABLE_get_string_keyed_int(INTERP, STATICSELF.get_pmc(),
+                PARROT_ARRAYITERATOR(SELF)->pos + idx);
+    }
+
+/*
+
+=item C<INTVAL exists_keyed(PMC *key)>
+
+Returns whether an element for C<*key> exists in the array.
+
+=cut
+
+*/
+
+    VTABLE INTVAL exists_keyed(PMC *key) {
+        return STATICSELF.exists_keyed_int(VTABLE_get_integer(INTERP, key));
+    }
+
+/*
+
+=item C<INTVAL exists_keyed_int(INTVAL idx)>
+
+Returns whether an element for C<idx> exists in the aggregate.
+
+=cut
+
+*/
+
+    VTABLE INTVAL exists_keyed_int(INTVAL idx) {
+        Parrot_ArrayIterator_attributes *attrs =
+                PARROT_ARRAYITERATOR(SELF);
+        /* Cheat! */
+        INTVAL final_pos = attrs->pos + idx - attrs->reverse;
+
+        return VTABLE_exists_keyed_int(INTERP, attrs->array, final_pos);
+    }
+
+/*
+
+=item C<INTVAL defined_keyed(PMC *key)>
+
+=cut
+
+*/
+
+    VTABLE INTVAL defined_keyed(PMC *key) {
+        return STATICSELF.defined_keyed_int(VTABLE_get_integer(INTERP, key));
+    }
+
+/*
+
+=item C<INTVAL defined_keyed_int(INTVAL key)>
+
+Returns the result of calling C<defined_keyed(key)> on the aggregate.
+
+=cut
+
+*/
+
+    VTABLE INTVAL defined_keyed_int(INTVAL idx) {
+        Parrot_ArrayIterator_attributes *attrs =
+                PARROT_ARRAYITERATOR(SELF);
+        /* Cheat! */
+        INTVAL final_pos = attrs->pos + idx - attrs->reverse;
+
+        return VTABLE_defined_keyed_int(INTERP, attrs->array, final_pos);
+    }
+}
+
+/*
+
+=back
+
+=cut
+
+*/
+
+/*
+ * Local variables:
+ *   c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */

Modified: trunk/src/pmc/env.pmc
==============================================================================
--- trunk/src/pmc/env.pmc	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/src/pmc/env.pmc	Wed Jul 15 13:15:25 2009	(r40100)
@@ -10,6 +10,9 @@
 
 C<Env> is a singleton class which provides access to the system environment.
 
+XXX Think about returning Pair back. Currently there is no way to iterate over
+environment I<keys>.
+
 =head2 Methods
 
 =over 4
@@ -71,19 +74,7 @@
 */
 
     VTABLE PMC *get_iter() {
-        STRING *name         = CONST_STRING(interp, "set_key");
-        PMC    *iter         = pmc_new_init(interp, enum_class_Iterator, SELF);
-        PMC    *key          = pmc_new(interp, enum_class_Key);
-
-        Parrot_PCCINVOKE(interp, iter, name, "P->", key);
-        PObj_get_FLAGS(key) |= KEY_integer_FLAG;
-
-        if (!environ[0])
-            VTABLE_set_integer_native(INTERP, key, -1);
-        else
-            VTABLE_set_integer_native(INTERP, key, 0);
-
-        return iter;
+        return pmc_new_init(INTERP, enum_class_ArrayIterator, SELF);
     }
 
 /*
@@ -143,40 +134,53 @@
 
 */
 
-    VTABLE STRING *get_string_keyed(PMC *key) {
-        if ((PObj_get_FLAGS(key) & KEY_type_FLAGS) == KEY_integer_FLAG) {
-            INTVAL const keynum = VTABLE_get_integer(INTERP, key);
-            if (keynum < 0 || keynum >= SELF.elements()) {
-                return string_from_literal(interp, "");
-            }
-            else {
-                const char * const envp = environ[keynum];
-                const char * const p    = strchr(envp, '=');
-                return Parrot_str_new(interp, envp, (UINTVAL)(p - envp));
+    VTABLE STRING *get_string_keyed_str(STRING *key) {
+        char * const keyname = Parrot_str_to_cstring(interp, key);
+
+        if (keyname) {
+            int free_it = 0;
+            char * const val = Parrot_getenv(keyname, &free_it);
+            Parrot_str_free_cstring(keyname);
+
+            if (val) {
+                STRING * const retval = Parrot_str_new(interp, val, 0);
+
+                if (free_it)
+                    mem_sys_free(val);
+
+                return retval;
+
             }
         }
-        else {
-            char * const keyname = Parrot_str_to_cstring(interp,
-                VTABLE_get_string(interp, key));
 
-            if (keyname) {
-                int free_it = 0;
-                char * const val = Parrot_getenv(keyname, &free_it);
-                Parrot_str_free_cstring(keyname);
+        return string_from_literal(interp, "");
+    }
 
-                if (val) {
-                    STRING * const retval = Parrot_str_new(interp, val, 0);
+    VTABLE STRING *get_string_keyed(PMC *key) {
+        return SELF.get_string_keyed_str(VTABLE_get_string(INTERP, key));
+    }
 
-                    if (free_it)
-                        mem_sys_free(val);
+/*
 
-                    return retval;
+=item C<STRING *get_string_keyed_int(PMC *key)>
 
-                }
-            }
+Returns the Parrot string value for the environment variable at position C<pos>.
 
+Used during iteration.
+
+=cut
+
+*/
+
+    VTABLE STRING *get_string_keyed_int(INTVAL pos) {
+        if (pos < 0 || pos >= SELF.elements()) {
             return string_from_literal(interp, "");
         }
+        else {
+            const char * const envp = environ[pos];
+            const char * const p    = strchr(envp, '=');
+            return Parrot_str_new(interp, envp, (UINTVAL)(p - envp));
+        }
     }
 
 /*

Modified: trunk/src/pmc/fixedbooleanarray.pmc
==============================================================================
--- trunk/src/pmc/fixedbooleanarray.pmc	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/src/pmc/fixedbooleanarray.pmc	Wed Jul 15 13:15:25 2009	(r40100)
@@ -504,19 +504,7 @@
 */
 
     VTABLE PMC *get_iter() {
-        STRING     *name     = CONST_STRING(interp, "set_key");
-        PMC * const iter     = pmc_new_init(INTERP, enum_class_Iterator, SELF);
-        PMC * const key      = pmc_new(INTERP, enum_class_Key);
-
-        Parrot_PCCINVOKE(interp, iter, name, "P->", key);
-        PObj_get_FLAGS(key) |= KEY_integer_FLAG;
-
-        if (SELF.get_integer() == 0)
-            VTABLE_set_integer_native(INTERP, key, -1);
-        else
-            VTABLE_set_integer_native(INTERP, key, 0);
-
-        return iter;
+        return pmc_new_init(INTERP, enum_class_ArrayIterator, SELF);
     }
 
 

Modified: trunk/src/pmc/fixedfloatarray.pmc
==============================================================================
--- trunk/src/pmc/fixedfloatarray.pmc	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/src/pmc/fixedfloatarray.pmc	Wed Jul 15 13:15:25 2009	(r40100)
@@ -107,19 +107,7 @@
 */
 
     VTABLE PMC *get_iter() {
-        STRING     *name     = CONST_STRING(interp, "set_key");
-        PMC * const iter     = pmc_new_init(INTERP, enum_class_Iterator, SELF);
-        PMC * const key      = pmc_new(INTERP, enum_class_Key);
-
-        Parrot_PCCINVOKE(interp, iter, name, "P->", key);
-        PObj_get_FLAGS(key) |= KEY_integer_FLAG;
-
-        if (SELF.get_integer() == 0)
-            VTABLE_set_integer_native(INTERP, key, -1);
-        else
-            VTABLE_set_integer_native(INTERP, key, 0);
-
-        return iter;
+        return pmc_new_init(INTERP, enum_class_ArrayIterator, SELF);
     }
 
 /*

Modified: trunk/src/pmc/fixedintegerarray.pmc
==============================================================================
--- trunk/src/pmc/fixedintegerarray.pmc	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/src/pmc/fixedintegerarray.pmc	Wed Jul 15 13:15:25 2009	(r40100)
@@ -597,22 +597,7 @@
 */
 
     VTABLE PMC *get_iter() {
-        STRING     *name = CONST_STRING(interp, "set_key");
-        PMC * const iter = pmc_new_init(INTERP, enum_class_Iterator, SELF);
-        PMC * const key  = pmc_new(INTERP, enum_class_Key);
-        INTVAL      size;
-
-        Parrot_PCCINVOKE(interp, iter, name, "P->", key);
-        PObj_get_FLAGS(key) |= KEY_integer_FLAG;
-
-        GET_ATTR_size(INTERP, SELF, size);
-
-        if (size)
-            VTABLE_set_integer_native(INTERP, key, 0);
-        else
-            VTABLE_set_integer_native(INTERP, key, -1);
-
-        return iter;
+        return pmc_new_init(INTERP, enum_class_ArrayIterator, SELF);
     }
 
 /*

Modified: trunk/src/pmc/fixedpmcarray.pmc
==============================================================================
--- trunk/src/pmc/fixedpmcarray.pmc	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/src/pmc/fixedpmcarray.pmc	Wed Jul 15 13:15:25 2009	(r40100)
@@ -646,19 +646,7 @@
     }
 
     VTABLE PMC *get_iter() {
-        STRING     *name     = CONST_STRING(interp, "set_key");
-        PMC * const iter     = pmc_new_init(INTERP, enum_class_Iterator, SELF);
-        PMC * const key      = pmc_new(INTERP, enum_class_Key);
-
-        Parrot_PCCINVOKE(interp, iter, name, "P->", key);
-        PObj_get_FLAGS(key) |= KEY_integer_FLAG;
-
-        if (PMC_size(SELF) == 0)
-            VTABLE_set_integer_native(INTERP, key, -1);
-        else
-            VTABLE_set_integer_native(INTERP, key, 0);
-
-        return iter;
+        return pmc_new_init(INTERP, enum_class_ArrayIterator, SELF);
     }
 
 /*

Modified: trunk/src/pmc/fixedstringarray.pmc
==============================================================================
--- trunk/src/pmc/fixedstringarray.pmc	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/src/pmc/fixedstringarray.pmc	Wed Jul 15 13:15:25 2009	(r40100)
@@ -159,16 +159,7 @@
 
 */
     VTABLE PMC *get_iter() {
-        STRING     *name = CONST_STRING(interp, "set_key");
-        PMC * const iter = pmc_new_init(INTERP, enum_class_Iterator, SELF);
-        PMC * const key  = pmc_new(INTERP, enum_class_Key);
-
-        Parrot_PCCINVOKE(interp, iter, name, "P->", key);
-        PObj_get_FLAGS(key) |= KEY_integer_FLAG;
-        VTABLE_set_integer_native(INTERP, key,
-                VTABLE_get_bool(INTERP, SELF) ? 0 : -1);
-
-        return iter;
+        return pmc_new_init(INTERP, enum_class_ArrayIterator, SELF);
     }
 
 /*

Modified: trunk/src/pmc/hash.pmc
==============================================================================
--- trunk/src/pmc/hash.pmc	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/src/pmc/hash.pmc	Wed Jul 15 13:15:25 2009	(r40100)
@@ -8,6 +8,28 @@
 
 =head1 DESCRIPTION
 
+Hash PMC wraps Parrot's _hash to provide high-level API:
+
+=over 4
+
+=item *
+
+Convert between various types to use as hash keys.
+
+=item *
+
+Convert between various types to use as hash values.
+
+=item *
+
+Handle compound Keys for nested Hash/Array lookups.
+
+=item *
+
+Provide C<HashIterator> to iterate over C<Hash>.
+
+=back
+
 These are the vtable functions for the Hash PMC.
 
 =head2 Functions
@@ -20,6 +42,7 @@
 
 #include "pmc_iterator.h"
 #include "pmc_key.h"
+#include "pmc_hashiteratorkey.h"
 
 /*
 
@@ -31,8 +54,7 @@
 
 */
 
-static PMC *get_integer_pmc(PARROT_INTERP, INTVAL base_type) {
-    UNUSED(base_type)
+static PMC *get_integer_pmc(PARROT_INTERP) {
     return pmc_new(interp, Parrot_get_ctx_HLL_type(interp, enum_class_Integer));
 }
 
@@ -47,8 +69,7 @@
 
 */
 
-static PMC *get_number_pmc(PARROT_INTERP, INTVAL base_type) {
-    UNUSED(base_type)
+static PMC *get_number_pmc(PARROT_INTERP) {
     return pmc_new(interp, Parrot_get_ctx_HLL_type(interp, enum_class_Float));
 }
 
@@ -62,78 +83,283 @@
 
 */
 
-static PMC *get_string_pmc(PARROT_INTERP, INTVAL base_type) {
-    UNUSED(base_type)
+static PMC *get_string_pmc(PARROT_INTERP) {
     return pmc_new(interp, Parrot_get_ctx_HLL_type(interp, enum_class_String));
 }
 
 
 /*
 
-=item C<static STRING *make_ro_hash_key(PARROT_INTERP, PMC *key)>
-
-Returns a Parrot STRING for C<*key>.
+Poor-man polymorphic functions to convert something to something.
 
-You I<must not> modify this STRING, nor pass it to anything which may store it.
-It's only safe to use for looking up elements of a hash or deleting them --
-I<never> storing them.  (If you have to ask why, don't use this function.  It's
-for optimization purposes only.)
+There is bunch of functions to convert from passed value to stored keys type and to/from
+stored values type.
 
-=cut
+void *hash_key_from_TYPE convert to keys type.
+void *hash_value_from_TYPE convert to values type.
+TYPE hash_value_to_TYPE convert from values type.
 
 */
 
-static STRING
-*make_ro_hash_key(PARROT_INTERP, NOTNULL(PMC *key))
+static void*
+hash_key_from_int(PARROT_INTERP, const Hash * const hash, INTVAL key)
 {
-    STRING *s;
-
-    switch (PObj_get_FLAGS(key) & KEY_type_FLAGS) {
-        case KEY_string_FLAG:
-            GETATTR_Key_str_key(interp, key, s);
-            break;
-        case KEY_string_FLAG | KEY_register_FLAG:
-        {
-            INTVAL  int_key;
-            GETATTR_Key_int_key(interp, key, int_key);
-            s = REG_STR(interp, int_key);
+    void *ret;
+    switch (hash->key_type) {
+        case Hash_key_type_int:
+            ret = (void *)key;
+            break;
+        /* Currently PMCs are stringified */
+        case Hash_key_type_PMC:
+        case Hash_key_type_STRING:
+            ret = (void *)Parrot_str_from_int(interp, key);
             break;
-        }
         default:
-            s = key_string(interp, key);
+            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED,
+                    "Hash: unsupported key_type");
     }
+    return ret;
+}
 
-    if (STRING_IS_NULL(s))
-        Parrot_ex_throw_from_c_args(interp, NULL,
-            EXCEPTION_UNEXPECTED_NULL, "Hash: Cannot use NULL STRING key");
+static void*
+hash_key_from_string(PARROT_INTERP, const Hash * const hash, ARGIN(STRING *key))
+{
+    void *ret;
+    switch (hash->key_type) {
+        case Hash_key_type_int:
+            ret = (void *)Parrot_str_to_int(interp, key);
+            break;
+        /* Currently PMCs are stringified */
+        case Hash_key_type_PMC:
+        case Hash_key_type_STRING:
+            ret = (void *)key;
+            break;
+        default:
+            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED,
+                    "Hash: unsupported key_type");
+    }
+    return ret;
+}
 
-    return s;
+static void*
+hash_key_from_pmc(PARROT_INTERP, const Hash * const hash, ARGIN(PMC *key))
+{
+    void *ret;
+    switch (hash->key_type) {
+        case Hash_key_type_int:
+            ret = (void *)VTABLE_get_integer(interp, key);
+            break;
+        /* Currently PMCs are stringified */
+        case Hash_key_type_PMC:
+        case Hash_key_type_STRING:
+            {
+                STRING *tmp = VTABLE_get_string(interp, key);
+                if (!tmp)
+                    Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNEXPECTED_NULL,
+                            "hash: can't use null as key");
+                ret = (void *)tmp;
+            }
+            break;
+        default:
+            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED,
+                    "Hash: unsupported key_type");
+    }
+    return ret;
 }
 
 
-/*
+/* Second part - convert from stored void* to real type */
+/* TODO: FLOATVALs converted into Float PMC for now */
+static void*
+hash_value_from_int(PARROT_INTERP, const Hash * const hash, INTVAL value)
+{
+    void *ret;
+    switch (hash->entry_type) {
+        case enum_type_INTVAL:
+            ret = (void*)value;
+            break;
+        case enum_type_PMC:
+            {
+                PMC *tmp = get_integer_pmc(interp);
+                VTABLE_set_integer_native(interp, tmp, value);
+                ret = (void *)tmp;
+            }
+            break;
+        case enum_type_STRING:
+            ret = (void *)Parrot_str_from_int(interp, value);
+            break;
+        default:
+            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED,
+                    "Hash: unsupported entry_type");
+    }
+    return ret;
+}
 
-=item C<static STRING *make_hash_key(PARROT_INTERP, PMC *key)>
+static void*
+hash_value_from_string(PARROT_INTERP, const Hash * const hash, STRING *value)
+{
+    void *ret;
+    switch (hash->entry_type) {
+        case enum_type_INTVAL:
+            ret = (void*)Parrot_str_to_int(interp, value);
+            break;
+        case enum_type_STRING:
+            ret = (void *)value;
+            break;
+        case enum_type_PMC:
+            {
+                PMC *s = get_string_pmc(interp);
+                VTABLE_set_string_native(interp, s, value);
+                ret = (void *)s;
+            }
+            break;
+        default:
+            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED,
+                    "Hash: unsupported entry_type");
+    }
+    return ret;
+}
 
-Returns a Parrot STRING for C<*key>.  This STRING is safe to modify or store.
+static void*
+hash_value_from_pmc(PARROT_INTERP, const Hash * const hash, PMC *value)
+{
+    void *ret;
+    switch (hash->entry_type) {
+        case enum_type_INTVAL:
+            ret = (void*)VTABLE_get_integer(interp, value);
+            break;
+        case enum_type_STRING:
+            ret = (void *)VTABLE_get_string(interp, value);
+            break;
+        case enum_type_PMC:
+            ret = (void *)value;
+            break;
+        default:
+            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED,
+                    "Hash: unsupported entry_type");
+    }
+    return ret;
+}
 
-=cut
+static void*
+hash_value_from_number(PARROT_INTERP, const Hash * const hash, FLOATVAL value)
+{
+    void *ret;
+    switch (hash->entry_type) {
+        case enum_type_INTVAL:
+            {
+                INTVAL tmp = value;
+                ret = (void*)tmp;
+            }
+            break;
+        case enum_type_STRING:
+            ret = (void *)Parrot_str_from_num(interp, value);
+            break;
+        case enum_type_PMC:
+            {
+                PMC *tmp = get_number_pmc(interp);
+                VTABLE_set_number_native(interp, tmp, value);
+                ret = (void *)tmp;
+            }
+            break;
+        default:
+            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED,
+                    "Hash: unsupported entry_type");
+    }
+    return ret;
+}
 
-*/
+static INTVAL
+hash_value_to_int(PARROT_INTERP, const Hash * const hash, void *value)
+{
+    INTVAL ret;
+    switch (hash->entry_type) {
+        case enum_type_INTVAL:
+            ret = (INTVAL)value;
+            break;
+        case enum_type_STRING:
+            ret = Parrot_str_to_int(interp, (STRING*)value);
+            break;
+        case enum_type_PMC:
+            ret = VTABLE_get_integer(interp, (PMC*)value);
+            break;
+        default:
+            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED,
+                    "Hash: unsupported entry_type");
+    }
+    return ret;
+}
 
-PARROT_CANNOT_RETURN_NULL
-static STRING
-*make_hash_key(PARROT_INTERP, NOTNULL(PMC *key))
+static STRING*
+hash_value_to_string(PARROT_INTERP, const Hash * const hash, void *value)
 {
-    STRING * const keystr = key_string(interp, key);
+    STRING *ret;
+    switch (hash->entry_type) {
+        case enum_type_INTVAL:
+            ret = Parrot_str_from_int(interp, (INTVAL)value);
+            break;
+        case enum_type_STRING:
+            ret = (STRING *)value;
+            break;
+        case enum_type_PMC:
+            ret = VTABLE_get_string(interp, (PMC *)value);
+            break;
+        default:
+            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED,
+                    "Hash: unsupported entry_type");
+    }
+    return ret;
+}
 
-    if (STRING_IS_NULL(keystr))
-        Parrot_ex_throw_from_c_args(interp, NULL,
-            EXCEPTION_UNEXPECTED_NULL, "Hash: Cannot use NULL STRING key");
+static PMC*
+hash_value_to_pmc(PARROT_INTERP, const Hash * const hash, void *value)
+{
+    PMC *ret;
+    switch (hash->entry_type) {
+        case enum_type_INTVAL:
+            ret = get_integer_pmc(interp);
+            VTABLE_set_integer_native(interp, ret, (INTVAL)value);
+            break;
+        case enum_type_STRING:
+            ret = get_string_pmc(interp);
+            VTABLE_set_string_native(interp, ret, (STRING *)value);
+            break;
+        case enum_type_PMC:
+            ret = (PMC *)value;
+            break;
+        default:
+            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED,
+                    "Hash: unsupported entry_type");
+    }
+    return ret;
+}
 
-    return keystr;
+static FLOATVAL
+hash_value_to_number(PARROT_INTERP, const Hash * const hash, void *value)
+{
+    FLOATVAL ret;
+    switch (hash->entry_type) {
+        case enum_type_INTVAL:
+            {
+                /* Pacify compiler about casting */
+                INTVAL tmp = (INTVAL)value;
+                ret = tmp;
+            }
+            break;
+        case enum_type_STRING:
+            ret = Parrot_str_to_num(interp, (STRING*)value);
+            break;
+        case enum_type_PMC:
+            ret = VTABLE_get_number(interp, (PMC*)value);
+            break;
+        default:
+            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED,
+                    "Hash: unsupported entry_type");
+    }
+    return ret;
 }
 
+
 /* Needs ext struct for the next_for_GC pointer
  * We would get recursive marking of a deeply nested HoHoH...
  */
@@ -228,182 +454,133 @@
     }
 
 /*
+=item C<void set_integer(INTVAL type)>
 
-=item C<void *get_pointer()>
+Reset Hash to use differen keys. See enum C<Hash_key_type> for possible values.
 
-Get a pointer to this PMC's Hash*.
+NB: this method will destroy all old data!
 
 =cut
-
 */
-    VTABLE void *get_pointer() {
-        return PARROT_HASH(SELF)->hash;
-    }
-
-/*
-
-=item C<INTVAL get_integer()>
+    VTABLE void set_integer_native(INTVAL type) {
+        Hash *old_hash = (Hash *)SELF.get_pointer();
+        Hash *new_hash = 0;
 
-Returns the size of the hash.
+        if (type == Hash_key_type_STRING)
+            new_hash = parrot_new_hash(INTERP);
+        else if (type == Hash_key_type_int)
+            /* new_int_hash set BOTH keys and values to INTVAL */
+            new_hash = parrot_create_hash(interp,
+                    old_hash ? old_hash->entry_type : enum_type_PMC,
+                    Hash_key_type_int,
+                    int_compare,
+                    key_hash_int);
+        else
+            /*
+                We probably will not implement other types of keys. They are way
+                too dangerous to use from PIR
+            */
+            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_UNIMPLEMENTED,
+                "Hash: Unknown key type");
 
-=cut
 
-*/
+        PARROT_HASH(SELF)->hash = new_hash;
+        new_hash->container     = SELF;
 
-    VTABLE INTVAL get_integer() {
-        return parrot_hash_size(INTERP, (Hash *)SELF.get_pointer());
+        if (old_hash)
+            parrot_hash_destroy(INTERP, old_hash);
     }
 
-/*
-
-=item C<INTVAL get_integer_keyed_str(STRING *key)>
-
-=item C<INTVAL get_integer_keyed_int(INTVAL key)>
-
-=cut
-
-*/
-
-    VTABLE INTVAL get_integer_keyed_str(STRING *key) {
-        HashBucket * const b =
-            parrot_hash_get_bucket(INTERP, (Hash *)SELF.get_pointer(), key);
-
-        if (!b)
-            return 0;
-
-        return VTABLE_get_integer(INTERP, (PMC*) b->value);
+    METHOD set_key_type(INTVAL type) {
+        SELF.set_integer_native(type);
     }
 
-    VTABLE INTVAL get_integer_keyed_int(INTVAL key) {
-        const Hash * const hash = (Hash *)SELF.get_pointer();
-        HashBucket *b;
-
-        if (hash->key_type == Hash_key_type_STRING)
-            return SELF.get_integer_keyed_str(Parrot_str_from_int(INTERP, key));
-
-        b = parrot_hash_get_bucket(INTERP, hash, (void *)key);
-
-        if (!b)
-            return 0;
-
-        return (INTVAL)b->value;
+    METHOD get_key_type() {
+        INTVAL ret = ((Hash *)SELF.get_pointer())->key_type;
+        RETURN(INTVAL ret);
     }
+
 /*
 
-=item C<INTVAL get_integer_keyed(PMC *key)>
+=item C<METHOD set_value_type(INTVAL type)>
 
-Returns the integer value for the element at C<*key>.
+Reset Hash to use different value-type for stored items. If there is no
+previous _hash was set defaults to STRING* keys.
 
-=cut
+NB: this method will destroy all old data!
 
+=cut
 */
+    METHOD set_value_type(INTVAL type) {
+        Hash *old_hash = (Hash *)SELF.get_pointer();
+        Hash *new_hash = 0;
 
-    VTABLE INTVAL get_integer_keyed(PMC *key) {
-        PMC        *valpmc;
-        STRING     *keystr;
-        HashBucket *b;
-        PMC        *nextkey;
-        const Hash * const hash = (Hash *)SELF.get_pointer();
-
-        /* called from iterator with an integer idx in key */
-        if ((PObj_get_FLAGS(key) & KEY_type_FLAGS) == KEY_hash_iterator_FLAGS) {
-
-            /* check if we really have Hash_key_type_int */
-            if (hash->key_type == Hash_key_type_int) {
-                void *idx = parrot_hash_get_idx(INTERP, hash, key);
-                return (INTVAL)idx;
-            }
-            else {
-                const STRING * const s =
-                    (STRING *)parrot_hash_get_idx(INTERP, hash, key);
-                return Parrot_str_to_int(INTERP, s);
-            }
+        /*
+        If someone called Hash.set_pointer with NULL pointer...
+        It will create STRING* keys hash. Because we can't use STRING_compare
+        directly - it declared static in F<src/hash.c>
+        */
+        if (!old_hash)
+            old_hash = parrot_new_hash(INTERP);
+
+        switch (type) {
+            case enum_type_INTVAL:
+            case enum_type_STRING:
+            case enum_type_PMC:
+                new_hash = parrot_create_hash(interp,
+                        type,
+                        old_hash->key_type,
+                        old_hash->compare,
+                        old_hash->hash_val);
+                break;
+            default:
+                Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED,
+                        "Hash: unsupported entry_type");
         }
 
-        keystr  = make_ro_hash_key(INTERP, key);
-        b       = parrot_hash_get_bucket(INTERP, hash, keystr);
-
-        if (!b)
-            return 0;
-
-        nextkey = key_next(INTERP, key);
-        valpmc  = (PMC *)b->value;
-
-        if (!nextkey)
-            return VTABLE_get_integer(INTERP, valpmc);
+        PARROT_HASH(SELF)->hash = new_hash;
+        new_hash->container     = SELF;
 
-        return VTABLE_get_integer_keyed(INTERP, valpmc, nextkey);
+        parrot_hash_destroy(INTERP, old_hash);
     }
 
-/*
-
-=item C<FLOATVAL get_number()>
-
-Returns the size of the hash.
-
-=cut
-
-*/
-
-    VTABLE FLOATVAL get_number() {
-        /* doing this in two steps avoids dodgy cast warnings with -O */
-        const INTVAL size = parrot_hash_size(INTERP, (Hash *)SELF.get_pointer());
-        return (FLOATVAL)size;
+    METHOD get_value_type() {
+        INTVAL ret = ((Hash *)SELF.get_pointer())->entry_type;
+        RETURN(INTVAL ret);
     }
 
 /*
 
-=item C<FLOATVAL get_number_keyed_str(STRING *key)>
+=item C<void *get_pointer()>
 
-=item C<FLOATVAL get_number_keyed_int(INTVAL key)>
+Get a pointer to this PMC's Hash*.
 
 =cut
 
 */
-
-    VTABLE FLOATVAL get_number_keyed_str(STRING *key) {
-        HashBucket * const b =
-            parrot_hash_get_bucket(INTERP, (Hash *)SELF.get_pointer(), key);
-
-        if (!b)
-            return 0.0;
-
-        return VTABLE_get_number(INTERP, (PMC *)b->value);
+    VTABLE void *get_pointer() {
+        return PARROT_HASH(SELF)->hash;
     }
 
-    VTABLE FLOATVAL get_number_keyed_int(INTVAL key) {
-        STRING * const s = Parrot_str_from_int(INTERP, key);
-        return SELF.get_number_keyed_str(s);
-    }
 /*
 
-=item C<FLOATVAL get_number_keyed(PMC *key)>
+=item C<INTVAL get_integer()>
 
-Returns the floating-point value for the element at C<*key>.
+=item C<FLOATVAL get_number()>
+
+Returns the size of the hash.
 
 =cut
 
 */
 
-    VTABLE FLOATVAL get_number_keyed(PMC *key) {
-        PMC               *nextkey;
-        PMC               *valpmc;
-        STRING     * const keystr = make_ro_hash_key(INTERP, key);
-        HashBucket * const b      = parrot_hash_get_bucket(INTERP,
-                                           (Hash *)SELF.get_pointer(), keystr);
-
-        if (!b)
-            return 0.0;
-
-        nextkey = key_next(INTERP, key);
-        valpmc  = (PMC *)b->value;
-
-        if (!nextkey)
-            return VTABLE_get_number(INTERP, valpmc);
-
-        return VTABLE_get_number_keyed(INTERP, valpmc, nextkey);
+    VTABLE INTVAL get_integer() {
+        return parrot_hash_size(INTERP, (Hash *)SELF.get_pointer());
     }
 
+    VTABLE FLOATVAL get_number() {
+        return SELF.get_integer();
+    }
 
 /*
 
@@ -468,374 +645,412 @@
 
 /*
 
-=item C<STRING *get_string_keyed_str(STRING *key)>
+=item C<INTVAL get_integer_keyed_str(STRING *key)>
 
-=item C<STRING *get_string_keyed_int(INTVAL key)>
+=item C<INTVAL get_integer_keyed_int(INTVAL key)>
 
 =cut
 
 */
 
-    VTABLE STRING *get_string_keyed_str(STRING *key) {
-        HashBucket * const b =
-            parrot_hash_get_bucket(INTERP, (Hash *)SELF.get_pointer(), key);
+    VTABLE INTVAL get_integer_keyed_str(STRING *key) {
+        const Hash * const hash = (Hash*)SELF.get_pointer();
+        HashBucket * const b = parrot_hash_get_bucket(INTERP, hash,
+                hash_key_from_string(INTERP, hash, key));
 
         if (!b)
-            return Parrot_str_new_noinit(INTERP, enum_stringrep_one, 0);
+            return 0;
 
-        return VTABLE_get_string(INTERP, (PMC*) b->value);
+        return hash_value_to_int(INTERP, hash, b->value);
     }
 
-    VTABLE STRING *get_string_keyed_int(INTVAL key) {
-        STRING * const s = Parrot_str_from_int(INTERP, key);
-        return SELF.get_string_keyed_str(s);
-    }
+    VTABLE INTVAL get_integer_keyed_int(INTVAL key) {
+        const Hash * const hash = (Hash*)SELF.get_pointer();
+        HashBucket * const b = parrot_hash_get_bucket(INTERP, hash,
+                hash_key_from_int(INTERP, hash, key));
 
+        if (!b)
+            return 0;
+
+        return hash_value_to_int(INTERP, hash, b->value);
+    }
 /*
 
-=item C<STRING *get_string_keyed(PMC *key)>
+=item C<INTVAL get_integer_keyed(PMC *key)>
 
-Returns the string value for the element at C<*key>.
+Returns the integer value for the element at C<*key>.
 
 =cut
 
 */
 
-    VTABLE STRING *get_string_keyed(PMC *key) {
-        PMC         *valpmc;
-        STRING      *keystr;
-        HashBucket  *b;
-        PMC         *nextkey;
-        Hash * const hash = (Hash *)SELF.get_pointer();
-
-        if ((PObj_get_FLAGS(key) & KEY_type_FLAGS) == KEY_hash_iterator_FLAGS) {
-            /* called from iterator with an integer idx in key */
-            if (hash->key_type == Hash_key_type_int) {
-                void  *idx = parrot_hash_get_idx(INTERP, hash, key);
-                return Parrot_str_from_int(INTERP, (INTVAL)idx);
-            }
-
-            return (STRING *)parrot_hash_get_idx(INTERP, hash, key);
-        }
-
-        keystr = make_ro_hash_key(INTERP, key);
-        b      = parrot_hash_get_bucket(INTERP, hash, keystr);
+    /* Handling Keys */
+    VTABLE INTVAL get_integer_keyed(PMC *key) {
+        const Hash * const hash = (Hash *)SELF.get_pointer();
+        HashBucket *b = parrot_hash_get_bucket(INTERP, hash,
+                hash_key_from_pmc(INTERP, hash, key));
+        PMC        *valpmc;
+        PMC        *nextkey;
 
         if (!b)
-            return Parrot_str_new_noinit(INTERP, enum_stringrep_one, 0);
+            return 0;
 
         nextkey = key_next(INTERP, key);
-        valpmc  = (PMC *)b->value;
+        valpmc  = hash_value_to_pmc(INTERP, hash, b->value);
 
+        /* Stop recursion. This is last step */
         if (!nextkey)
-            return VTABLE_get_string(INTERP, valpmc);
+            return VTABLE_get_integer(INTERP, valpmc);
 
-        return VTABLE_get_string_keyed(INTERP, valpmc, nextkey);
+        /* Recusively call to enclosed aggregate */
+        return VTABLE_get_integer_keyed(INTERP, valpmc, nextkey);
     }
 
 /*
 
-=item C<INTVAL get_bool()>
-
-Returns true if the hash size is not zero.
+=item C<void set_integer_keyed(PMC *key, INTVAL value)>
 
 =cut
 
 */
 
-    VTABLE INTVAL get_bool() {
-        return parrot_hash_size(INTERP, (Hash *)SELF.get_pointer()) != 0;
+    VTABLE void set_integer_keyed(PMC *key, INTVAL value) {
+        Hash   *hash    = (Hash *)SELF.get_pointer();
+        void   *keystr  = hash_key_from_pmc(INTERP, hash, key);
+        PMC    *nextkey = key_next(INTERP, key);
+        PMC    *box     = NULL;
+        HashBucket *b;
+
+        if (!nextkey) {
+            parrot_hash_put(INTERP, hash, keystr,
+                    hash_value_from_int(INTERP, hash, value));
+            return;
+        }
+
+        b = parrot_hash_get_bucket(INTERP, hash, keystr);
+        if (b)
+            box = hash_value_to_pmc(INTERP, hash, b->value);
+        else {
+            /* autovivify an Hash */
+            box = pmc_new(INTERP, SELF.type());
+            parrot_hash_put(INTERP, hash, keystr,
+                    hash_value_from_pmc(INTERP, hash, box));
+        }
+
+        VTABLE_set_integer_keyed(INTERP, box, nextkey, value);
     }
 
-/*
+    VTABLE void set_integer_keyed_int(INTVAL key, INTVAL value) {
+        Hash * const hash = (Hash *)SELF.get_pointer();
+        parrot_hash_put(INTERP, hash, hash_key_from_int(INTERP, hash, key),
+                hash_value_from_int(INTERP, hash, value));
+    }
 
-=item C<INTVAL elements()>
+/*
 
-Returns the number of elements in the hash.
+=item C<void set_integer_keyed_str(STRING *key, INTVAL value)>
 
 =cut
 
 */
 
-    VTABLE INTVAL elements() {
-        return parrot_hash_size(INTERP, (Hash *)SELF.get_pointer());
+    VTABLE void set_integer_keyed_str(STRING *key, INTVAL value) {
+        Hash * const hash = (Hash *)SELF.get_pointer();
+        parrot_hash_put(INTERP, hash, hash_key_from_string(INTERP, hash, key),
+                hash_value_from_int(INTERP, hash, value));
     }
 
+
 /*
 
-=item C<PMC *get_pmc_keyed_str(STRING *key)>
+=item C<FLOATVAL get_number_keyed_str(STRING *key)>
 
-=item C<PMC *get_pmc_keyed_int(INTVAL key)>
+=item C<FLOATVAL get_number_keyed_int(INTVAL key)>
 
 =cut
 
 */
 
-    VTABLE PMC *get_pmc_keyed_str(STRING *key) {
-        HashBucket * const b =
-            parrot_hash_get_bucket(INTERP, (Hash *)SELF.get_pointer(), key);
+    VTABLE FLOATVAL get_number_keyed_str(STRING *key) {
+        const Hash * const hash = (Hash *)SELF.get_pointer();
+        HashBucket * const b = parrot_hash_get_bucket(INTERP, hash,
+                hash_key_from_string(INTERP, hash, key));
 
         if (!b)
-            return PMCNULL;
-
-        return (PMC *)b->value;
-    }
+            return 0.0;
 
-    VTABLE PMC *get_pmc_keyed_int(INTVAL key) {
-        STRING * const s = Parrot_str_from_int(INTERP, key);
-        return SELF.get_pmc_keyed_str(s);
+        return hash_value_to_number(INTERP, hash, b->value);
     }
 
-/*
+    VTABLE FLOATVAL get_number_keyed_int(INTVAL key) {
+        const Hash * const hash = (Hash *)SELF.get_pointer();
+        HashBucket * const b = parrot_hash_get_bucket(INTERP, hash,
+                hash_key_from_int(INTERP, hash, key));
 
-=item C<PMC *get_iter()>
+        if (!b)
+            return 0.0;
 
-Return a new iterator for the slice PMC C<key>
+        return hash_value_to_number(INTERP, hash, b->value);
+    }
+/*
 
-=item C<PMC *get_pmc_keyed(PMC *key)>
+=item C<FLOATVAL get_number_keyed(PMC *key)>
 
-Returns the PMC value for the element at C<*key>.
+Returns the floating-point value for the element at C<*key>.
 
 =cut
 
 */
 
-    VTABLE PMC *get_iter() {
-        PMC * const iter     = pmc_new_init(INTERP, enum_class_Iterator, SELF);
-        PMC * const key      = pmc_new(INTERP, enum_class_Key);
+    /* I can't migrate this function right now. Some problem with JITting */
+    VTABLE FLOATVAL get_number_keyed(PMC *key) {
+        PMC               *nextkey;
+        PMC               *valpmc;
+        const Hash * const hash   = (Hash *)VTABLE_get_pointer(interp, pmc);
+        void              *keystr = hash_key_from_pmc(INTERP, hash, key);
+        HashBucket * const b      = parrot_hash_get_bucket(INTERP, hash, keystr);
 
-        SETATTR_Iterator_key(INTERP, iter, key);
-        PObj_get_FLAGS(key) |= KEY_hash_iterator_FLAGS;
-        SETATTR_Key_next_key(INTERP, key, (PMC *)INITBucketIndex);
+        if (!b)
+            return 0.0;
 
-        /* -1 for an empty hash, 0 for a non-empty hash.  */
-        SETATTR_Key_int_key(INTERP, key,
-            parrot_hash_size(INTERP, (Hash *)SELF.get_pointer()) ? 0 : -1);
+        nextkey = key_next(INTERP, key);
+        valpmc  = hash_value_to_pmc(INTERP, hash, b->value);
 
-        return iter;
-    }
+        if (!nextkey)
+            return VTABLE_get_number(INTERP, valpmc);
 
-    VTABLE PMC *slice(PMC *key) {
-        return PMCNULL;
+        return VTABLE_get_number_keyed(INTERP, valpmc, nextkey);
     }
 
-    VTABLE PMC *get_pmc_keyed(PMC *key) {
-        const Hash * const hash = (Hash *)SELF.get_pointer();
-        STRING        *keystr;
-        HashBucket    *b;
-        PMC           *nextkey;
-
-        /* called from iterator with an integer idx in key */
-        if ((PObj_get_FLAGS(key) & KEY_type_FLAGS) == KEY_hash_iterator_FLAGS) {
-            PMC *result;
-
-            /* check if we really have Hash_key_type_int */
-            if (hash->key_type == Hash_key_type_int) {
-                void *idx           = parrot_hash_get_idx(INTERP, hash, key);
-                const INTVAL i      = (INTVAL)idx;
-                result              = pmc_new(INTERP, enum_class_Integer);
-                VTABLE_set_integer_native(INTERP, result, i);
-            }
-            else {
-                STRING *s = (STRING *)parrot_hash_get_idx(INTERP, hash, key);
-                result    = pmc_new(INTERP, enum_class_String);
-                VTABLE_set_string_native(INTERP, result, s);
-            }
 
-            return result;
-        }
+/*
 
-        keystr = make_ro_hash_key(INTERP, key);
-        b      = parrot_hash_get_bucket(INTERP, hash, keystr);
+=item C<STRING *get_string_keyed_str(STRING *key)>
+
+=item C<STRING *get_string_keyed_int(INTVAL key)>
+
+=cut
+
+*/
+
+    VTABLE STRING *get_string_keyed_str(STRING *key) {
+        const Hash * const hash = (Hash*)SELF.get_pointer();
+        HashBucket * const b =
+            parrot_hash_get_bucket(INTERP, hash, hash_key_from_string(INTERP, hash, key));
 
         if (!b)
-            return PMCNULL;
+            return Parrot_str_new_noinit(INTERP, enum_stringrep_one, 0);
 
-        nextkey = key_next(INTERP, key);
+        return hash_value_to_string(INTERP, hash, b->value);
+    }
 
-        if (!nextkey)
-            return (PMC *)b->value;
+    VTABLE STRING *get_string_keyed_int(INTVAL key) {
+        const Hash * const hash = (Hash*)SELF.get_pointer();
+        HashBucket * const b =
+            parrot_hash_get_bucket(INTERP, hash, hash_key_from_int(INTERP, hash, key));
+
+        if (!b)
+            return Parrot_str_new_noinit(INTERP, enum_stringrep_one, 0);
 
-        return VTABLE_get_pmc_keyed(INTERP, (PMC*)b->value, nextkey);
+        return hash_value_to_string(INTERP, hash, b->value);
     }
 
 /*
 
-=item C<INTVAL is_same(const PMC *other)>
+=item C<STRING *get_string_keyed(PMC *key)>
 
-Returns whether the hash is the same as C<*other>.
+Returns the string value for the element at C<*key>.
 
 =cut
 
 */
 
-    VTABLE INTVAL is_same(PMC *other) {
-        return (INTVAL)(other->vtable == SELF->vtable &&
-            VTABLE_get_pointer(INTERP, other) == SELF.get_pointer());
+    VTABLE STRING *get_string_keyed(PMC *key) {
+        const Hash * const hash = (Hash *)SELF.get_pointer();
+        HashBucket *b = parrot_hash_get_bucket(INTERP, hash,
+                hash_key_from_pmc(INTERP, hash, key));
+        PMC        *valpmc;
+        PMC        *nextkey;
+
+        if (!b)
+            return Parrot_str_new_noinit(INTERP, enum_stringrep_one, 0);
+
+        nextkey = key_next(INTERP, key);
+        valpmc  = hash_value_to_pmc(INTERP, hash, b->value);
+
+        /* Stop recursion. This is last step */
+        if (!nextkey)
+            return VTABLE_get_string(INTERP, valpmc);
+
+        /* Recusively call to enclosed aggregate */
+        return VTABLE_get_string_keyed(INTERP, valpmc, nextkey);
     }
 
 /*
 
-=item C<void set_integer_keyed(PMC *key, INTVAL value)>
+=item C<void set_string_keyed(PMC *key, STRING *value)>
 
 =cut
 
 */
 
-    VTABLE void set_integer_keyed(PMC *key, INTVAL value) {
-        STRING *keystr;
+    VTABLE void set_string_keyed(PMC *key, STRING *value) {
+        Hash   *hash    = (Hash *)SELF.get_pointer();
+        void   *keystr  = hash_key_from_pmc(INTERP, hash, key);
         PMC    *nextkey;
-        PMC    *box;
-
-        if (!key)
-            return;
+        PMC    *box     = NULL;
+        HashBucket *b;
 
-        keystr  = make_hash_key(INTERP, key);
         nextkey = key_next(INTERP, key);
-
         if (!nextkey) {
-            PMC *val = get_integer_pmc(INTERP, SELF->vtable->base_type);
-
-            VTABLE_set_integer_native(INTERP, val, value);
-            parrot_hash_put(INTERP, (Hash *)SELF.get_pointer(), keystr, val);
+            parrot_hash_put(INTERP, hash, keystr,
+                    hash_value_from_string(INTERP, hash, value));
             return;
         }
 
-        box = SELF.get_pmc_keyed_str(keystr);
-
-        /* autovivify an Hash */
-        if (!box)
-            box = pmc_new(INTERP, SELF.type());
-
-        VTABLE_set_integer_keyed(INTERP, box, nextkey, value);
-    }
-
-    VTABLE void set_integer_keyed_int(INTVAL key, INTVAL value) {
-        Hash * const hash = (Hash *)SELF.get_pointer();
-
-        /* check if we really have Hash_key_type_int */
-        if (hash->key_type == Hash_key_type_int) {
-            parrot_hash_put(INTERP, hash, (void *)key, (void *)value);
-        }
+        b = parrot_hash_get_bucket(INTERP, hash, keystr);
+        if (b)
+            box = hash_value_to_pmc(INTERP, hash, b->value);
         else {
-            SUPER(key, value);
+            /* autovivify an Hash */
+            box = pmc_new(INTERP, SELF.type());
+            parrot_hash_put(INTERP, hash, keystr,
+                    hash_value_from_pmc(INTERP, hash, box));
         }
+
+        VTABLE_set_string_keyed(INTERP, box, nextkey, value);
     }
 
 /*
 
-=item C<void set_integer_keyed_str(STRING *key, INTVAL value)>
+=item C<void set_string_keyed_str(STRING *key, STRING *value)>
 
 =cut
 
 */
 
-    VTABLE void set_integer_keyed_str(STRING *key, INTVAL value) {
-        PMC * const val  = get_integer_pmc(INTERP, SELF->vtable->base_type);
-        VTABLE_set_integer_native(INTERP, val, value);
+    VTABLE void set_string_keyed_str(STRING *key, STRING *value) {
+        Hash *hash = (Hash *)SELF.get_pointer();
+        parrot_hash_put(INTERP, hash,
+                hash_key_from_string(INTERP, hash, key),
+                hash_value_from_string(INTERP, hash, value));
+    }
 
-        parrot_hash_put(INTERP, (Hash *)SELF.get_pointer(), key, val);
+    VTABLE void set_string_keyed_int(INTVAL key, STRING *value) {
+        Hash *hash = (Hash *)SELF.get_pointer();
+        parrot_hash_put(INTERP, hash,
+                hash_key_from_int(INTERP, hash, key),
+                hash_value_from_string(INTERP, hash, value));
     }
 
 /*
 
-=item C<void set_number_keyed(PMC *key, FLOATVAL value)>
-
-=cut
+=item C<PMC *get_pmc_keyed(PMC *key)>
 
-*/
+=item C<PMC *get_pmc_keyed_str(STRING *key)>
 
-    VTABLE void set_number_keyed(PMC *key, FLOATVAL value) {
-        STRING *keystr;
-        PMC    *nextkey;
-        PMC    *box;
+=item C<PMC *get_pmc_keyed_int(INTVAL key)>
 
-        if (!key)
-            return;
+Returns the PMC value for the element at C<*key>.
 
-        keystr  = make_hash_key(INTERP, key);
-        nextkey = key_next(INTERP, key);
+=cut
 
-        if (!nextkey) {
-            PMC *val         = get_number_pmc(INTERP, SELF->vtable->base_type);
-            VTABLE_set_number_native(INTERP, val, value);
-            parrot_hash_put(INTERP, (Hash *)SELF.get_pointer(), keystr, val);
-            return;
-        }
+*/
 
-        box = SELF.get_pmc_keyed_str(keystr);
+    VTABLE PMC *get_pmc_keyed_str(STRING *key) {
+        const Hash * const hash = (Hash *)SELF.get_pointer();
+        HashBucket * const b    = parrot_hash_get_bucket(INTERP, hash,
+                hash_key_from_string(INTERP, hash, key));
 
-        /* autovivify an Hash */
-        if (!box)
-            box = pmc_new(INTERP, SELF.type());
+        if (!b)
+            return PMCNULL;
 
-        VTABLE_set_number_keyed(INTERP, box, nextkey, value);
+        return hash_value_to_pmc(INTERP, hash, b->value);
     }
 
-/*
+    VTABLE PMC *get_pmc_keyed_int(INTVAL key) {
+        const Hash * const hash = (Hash *)SELF.get_pointer();
+        HashBucket * const b    = parrot_hash_get_bucket(INTERP, hash,
+                hash_key_from_int(INTERP, hash, key));
 
-=item C<void set_number_keyed_str(STRING *key, FLOATVAL value)>
+        if (!b)
+            return PMCNULL;
 
-Sets C<value> as the value for C<*key>.
+        return hash_value_to_pmc(INTERP, hash, b->value);
+    }
 
-=cut
+    /* Compound Key */
+    VTABLE PMC *get_pmc_keyed(PMC *key) {
+        const Hash * const hash = (Hash *)SELF.get_pointer();
+        HashBucket *b = parrot_hash_get_bucket(INTERP, hash,
+                hash_key_from_pmc(INTERP, hash, key));
+        PMC        *valpmc;
+        PMC        *nextkey;
 
-*/
+        if (!b)
+            return PMCNULL;
 
-    VTABLE void set_number_keyed_str(STRING *key, FLOATVAL value) {
-        PMC * const val  = get_number_pmc(INTERP, SELF->vtable->base_type);
-        VTABLE_set_number_native(INTERP, val, value);
+        nextkey = key_next(INTERP, key);
+        valpmc  = hash_value_to_pmc(INTERP, hash, b->value);
 
-        parrot_hash_put(INTERP, (Hash *)SELF.get_pointer(), key, val);
+        /* Stop recursion. This is last step */
+        if (!nextkey)
+            return valpmc;
+
+        /* Recusively call to enclosed aggregate */
+        return VTABLE_get_pmc_keyed(INTERP, valpmc, nextkey);
     }
 
 /*
 
-=item C<void set_string_keyed(PMC *key, STRING *value)>
+=item C<void set_number_keyed(PMC *key, FLOATVAL value)>
 
 =cut
 
 */
 
-    VTABLE void set_string_keyed(PMC *key, STRING *value) {
-        STRING *keystr;
+    VTABLE void set_number_keyed(PMC *key, FLOATVAL value) {
+        Hash   *hash = (Hash *)SELF.get_pointer();
+        void   *keystr;
         PMC    *nextkey;
         PMC    *box;
+        HashBucket *b;
 
-        if (!key)
-            return;
-
-        keystr  = make_hash_key(INTERP, key);
+        keystr  = hash_key_from_pmc(INTERP, hash, key);
         nextkey = key_next(INTERP, key);
 
         if (!nextkey) {
-            PMC * const val = get_string_pmc(INTERP, SELF->vtable->base_type);
-            VTABLE_set_string_native(INTERP, val, value);
-            parrot_hash_put(INTERP, (Hash *)SELF.get_pointer(), keystr, val);
+            PMC *val = get_number_pmc(INTERP);
+            VTABLE_set_number_native(INTERP, val, value);
+            parrot_hash_put(INTERP, hash, keystr, hash_value_from_pmc(INTERP, hash, val));
             return;
         }
 
-        box = SELF.get_pmc_keyed_str(keystr);
+        b = parrot_hash_get_bucket(INTERP, (Hash *)SELF.get_pointer(), keystr);
+        if (b)
+            box = hash_value_to_pmc(INTERP, hash, b->value);
 
         /* autovivify an Hash */
         if (!box)
             box = pmc_new(INTERP, SELF.type());
 
-        VTABLE_set_string_keyed(INTERP, box, nextkey, value);
+        VTABLE_set_number_keyed(INTERP, box, nextkey, value);
     }
 
 /*
 
-=item C<void set_string_keyed_str(STRING *key, STRING *value)>
+=item C<void set_number_keyed_str(STRING *key, FLOATVAL value)>
+
+Sets C<value> as the value for C<*key>.
 
 =cut
 
 */
 
-    VTABLE void set_string_keyed_str(STRING *key, STRING *value) {
-        PMC * const val = get_string_pmc(INTERP, SELF->vtable->base_type);
+    VTABLE void set_number_keyed_str(STRING *key, FLOATVAL value) {
+        PMC * const val  = get_number_pmc(INTERP);
+        VTABLE_set_number_native(INTERP, val, value);
 
-        VTABLE_set_string_native(INTERP, val, value);
         parrot_hash_put(INTERP, (Hash *)SELF.get_pointer(), key, val);
     }
 
@@ -848,26 +1063,30 @@
 */
 
     VTABLE void set_pmc_keyed(PMC *key, PMC *value) {
-        STRING *keystr;
+        Hash   *hash = (Hash *)SELF.get_pointer();
+        void   *keystr;
         PMC    *nextkey;
         PMC    *box;
+        HashBucket *b;
 
-        if (!key)
-            return;
-
-        keystr  = make_hash_key(INTERP, key);
+        keystr  = hash_key_from_pmc(INTERP, hash, key);
         nextkey = key_next(INTERP, key);
 
         if (!nextkey) {
-            parrot_hash_put(INTERP, (Hash *)SELF.get_pointer(), keystr, value);
+            parrot_hash_put(INTERP, hash, keystr, value);
             return;
         }
 
-        box = SELF.get_pmc_keyed_str(keystr);
-
-        /* autovivify an Hash */
-        if (!box)
+        b = parrot_hash_get_bucket(INTERP, hash, keystr);
+        if (b)
+            box = hash_value_to_pmc(INTERP, hash, b->value);
+        else {
+            /* autovivify an Hash */
             box = pmc_new(INTERP, SELF.type());
+            parrot_hash_put(INTERP, hash, keystr,
+                    hash_value_from_pmc(INTERP, hash, box));
+        }
+
 
         VTABLE_set_pmc_keyed(INTERP, box, nextkey, value);
     }
@@ -883,54 +1102,9 @@
 */
 
     VTABLE void set_pmc_keyed_str(STRING *key, PMC *value) {
-        parrot_hash_put(INTERP, (Hash *)SELF.get_pointer(), key, value);
-    }
-
-/*
-
-=item C<INTVAL is_equal(PMC *value)>
-
-The C<==> operation.
-
-Check if two hashes hold the same keys and values.
-
-=cut
-
-*/
-
-    VTABLE INTVAL is_equal(PMC *value) {
-        PMC * const iter = VTABLE_get_iter(INTERP, SELF);
-        INTVAL      j, n;
-
-        if (value->vtable->base_type != SELF->vtable->base_type)
-            return 0;
-
-        n = SELF.elements();
-
-        if (VTABLE_elements(INTERP, value) != n)
-            return 0;
-
-        for (j = 0; j < n; ++j) {
-            STRING * const key = VTABLE_shift_string(INTERP, iter);
-            PMC           *item1, *item2;
-            INTVAL         result;
-
-            if (!VTABLE_exists_keyed_str(INTERP, value, key))
-                return 0;
-
-            item1 = SELF.get_pmc_keyed_str(key);
-            item2 = VTABLE_get_pmc_keyed_str(INTERP, value, key);
-
-            if (item1 == item2)
-                continue;
-
-            Parrot_mmd_multi_dispatch_from_c_args(INTERP, "is_equal",
-                "PP->I", item1, item2, &result);
-            if (!result)
-                return 0;
-        }
-
-        return 1;
+        Hash *hash = (Hash *)SELF.get_pointer();
+        parrot_hash_put(INTERP, hash, hash_key_from_string(INTERP, hash, key),
+                hash_value_from_pmc(INTERP, hash, value));
     }
 
 /*
@@ -942,8 +1116,9 @@
 */
 
     VTABLE INTVAL exists_keyed_str(STRING *key) {
-        HashBucket * const b =
-            parrot_hash_get_bucket(INTERP, (Hash *)SELF.get_pointer(), key);
+        Hash *hash = (Hash *)SELF.get_pointer();
+        HashBucket * const b = parrot_hash_get_bucket(INTERP, hash,
+                hash_key_from_string(INTERP, hash, key));
         return b != NULL;
     }
 
@@ -959,7 +1134,7 @@
 
     VTABLE INTVAL exists_keyed(PMC *key) {
         Hash   * const h  = (Hash *)SELF.get_pointer();
-        STRING * const sx = make_ro_hash_key(INTERP, key);
+        void          *sx = hash_key_from_pmc(INTERP, h, key);
         HashBucket    *b  = parrot_hash_get_bucket(INTERP, h, sx);
 
         /* no such key */
@@ -972,7 +1147,7 @@
         if (!key)
             return 1;
 
-        return VTABLE_exists_keyed(INTERP, (PMC *)b->value, key);
+        return VTABLE_exists_keyed(INTERP, hash_value_to_pmc(INTERP, h, b->value), key);
     }
 
 /*
@@ -984,14 +1159,15 @@
 */
 
     VTABLE INTVAL defined_keyed_str(STRING *key) {
-        HashBucket * const b =
-            parrot_hash_get_bucket(INTERP, (Hash *)SELF.get_pointer(), key);
+        const Hash * const hash = (Hash *)SELF.get_pointer();
+        HashBucket * const b = parrot_hash_get_bucket(INTERP, hash,
+                hash_key_from_string(INTERP, hash, key));
 
         /* no such key */
         if (!b)
             return 0;
 
-        return VTABLE_defined(INTERP, (PMC*)b->value);
+        return VTABLE_defined(INTERP, hash_value_to_pmc(INTERP, hash, b->value));
     }
 
 /*
@@ -1006,7 +1182,7 @@
 
     VTABLE INTVAL defined_keyed(PMC *key) {
         Hash   * const h  = (Hash *)SELF.get_pointer();
-        STRING * const sx = make_ro_hash_key(INTERP, key);
+        void          *sx = hash_key_from_pmc(INTERP, h, key);
         HashBucket    *b  = parrot_hash_get_bucket(INTERP, h, sx);
 
         /* no such key */
@@ -1016,9 +1192,10 @@
         key = key_next(INTERP, key);
 
         if (!key)
-            return VTABLE_defined(INTERP, (PMC *)b->value);
+            return VTABLE_defined(INTERP, hash_value_to_pmc(INTERP, h, b->value));
         else
-            return VTABLE_defined_keyed(INTERP, (PMC *)b->value, key);
+            return VTABLE_defined_keyed(INTERP,
+                    hash_value_to_pmc(INTERP, h, b->value), key);
     }
 
 /*
@@ -1030,7 +1207,8 @@
 */
 
     VTABLE void delete_keyed_str(STRING *key) {
-        parrot_hash_delete(INTERP, (Hash *)SELF.get_pointer(), key);
+        Hash *hash = (Hash *)SELF.get_pointer();
+        parrot_hash_delete(INTERP, hash, hash_key_from_string(INTERP, hash, key));
     }
 
 /*
@@ -1045,7 +1223,7 @@
 
     VTABLE void delete_keyed(PMC *key) {
         Hash   * const h  = (Hash *)SELF.get_pointer();
-        STRING * const sx = make_ro_hash_key(INTERP, key);
+        void          *sx = hash_key_from_pmc(INTERP, h, key);
         HashBucket    *b  = parrot_hash_get_bucket(INTERP, h, sx);
 
         /* no such key */
@@ -1062,6 +1240,110 @@
 
 /*
 
+=item C<INTVAL get_bool()>
+
+Returns true if the hash size is not zero.
+
+=cut
+
+*/
+
+    VTABLE INTVAL get_bool() {
+        return parrot_hash_size(INTERP, (Hash *)SELF.get_pointer()) != 0;
+    }
+
+/*
+
+=item C<INTVAL elements()>
+
+Returns the number of elements in the hash.
+
+=cut
+
+*/
+
+    VTABLE INTVAL elements() {
+        return parrot_hash_size(INTERP, (Hash *)SELF.get_pointer());
+    }
+
+/*
+
+=item C<PMC *get_iter()>
+
+Return a new iterator for the slice PMC C<key>
+
+=cut
+
+*/
+
+    VTABLE PMC *get_iter() {
+        return pmc_new_init(INTERP, enum_class_HashIterator, SELF);
+    }
+
+/*
+
+=item C<INTVAL is_same(const PMC *other)>
+
+Returns whether the hash is the same as C<*other>.
+
+=cut
+
+*/
+
+    VTABLE INTVAL is_same(PMC *other) {
+        return (INTVAL)(other->vtable == SELF->vtable &&
+            VTABLE_get_pointer(INTERP, other) == SELF.get_pointer());
+    }
+
+/*
+
+=item C<INTVAL is_equal(PMC *value)>
+
+The C<==> operation.
+
+Check if two hashes hold the same keys and values.
+
+=cut
+
+*/
+
+    VTABLE INTVAL is_equal(PMC *value) {
+        PMC * const iter = VTABLE_get_iter(INTERP, SELF);
+        INTVAL      j, n;
+
+        if (value->vtable->base_type != SELF->vtable->base_type)
+            return 0;
+
+        n = SELF.elements();
+
+        if (VTABLE_elements(INTERP, value) != n)
+            return 0;
+
+        for (j = 0; j < n; ++j) {
+            STRING * const key = VTABLE_shift_string(INTERP, iter);
+            PMC           *item1, *item2;
+            INTVAL         result;
+
+            if (!VTABLE_exists_keyed_str(INTERP, value, key))
+                return 0;
+
+            item1 = SELF.get_pmc_keyed_str(key);
+            item2 = VTABLE_get_pmc_keyed_str(INTERP, value, key);
+
+            if (item1 == item2)
+                continue;
+
+            Parrot_mmd_multi_dispatch_from_c_args(INTERP, "is_equal",
+                "PP->I", item1, item2, &result);
+            if (!result)
+                return 0;
+        }
+
+        return 1;
+    }
+
+/*
+
 =item C<PMC *slice(PMC *key)>
 
 Return a new iterator for the slice PMC C<key>
@@ -1072,9 +1354,7 @@
 
     VTABLE PMC *slice(PMC *key, INTVAL f) {
         if (f == 0) {
-            PMC * const iter = pmc_new_init(INTERP, enum_class_Iterator, SELF);
-            PARROT_ITERATOR(iter)->key = key;
-            return iter;
+            return SELF.get_iter();
         }
 
         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,

Added: trunk/src/pmc/hashiterator.pmc
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/src/pmc/hashiterator.pmc	Wed Jul 15 13:15:25 2009	(r40100)
@@ -0,0 +1,283 @@
+/*
+Copyright (C) 2001-2009, Parrot Foundation.
+$Id$
+
+=head1 NAME
+
+src/pmc/hashiterator.pmc - Implementation of Iterator for Hashes.
+
+=head1 DESCRIPTION
+
+Generic iterator for traversing Hash.
+
+=head1 SYNOPSIS
+
+=head2 default usage
+
+    .local pmc iterator, hash, key, entry
+    iterator = iter hash
+  iter_loop:
+    unless iterator, iter_end  # while (more values)
+    key   = shift iterator     # get the key. Some key
+    entry = hash[key]
+    ...
+    goto iter_loop
+  iter_end:
+
+=head2 C++-style usage
+
+    .local pmc iterator, hash, iter_key, key, entry
+    iterator = iter hash
+  iter_loop:
+    unless iterator, iter_end  # while (more values)
+    iter_key = shift iterator     # get the key
+    key = iter_key.'key'()        # get an original key used to put value
+    key = iter_key.'value'()      # get an entry
+    ...
+    goto iter_loop
+  iter_end:
+
+
+=head1 Methods
+
+=over 4
+
+=cut
+
+*/
+
+#include "pmc_hash.h"
+#include "pmc_hashiteratorkey.h"
+
+/*
+
+Advance to next position. Return found (if any) HashBucket.
+
+*/
+static HashBucket*
+advance_to_next(PARROT_INTERP, PMC *self) {
+    Parrot_HashIterator_attributes *attrs  = PARROT_HASHITERATOR(self);
+    HashBucket                     *bucket = attrs->bucket;
+
+    /* Try to advance current bucket */
+    if (bucket)
+        bucket = bucket->next;
+
+    while (!bucket) {
+        /* If there is no more buckets */
+        if (attrs->pos == attrs->total_buckets)
+            break;
+
+        bucket = attrs->parrot_hash->bi[attrs->pos++];
+    }
+    attrs->bucket = bucket;
+    attrs->elements--;
+    return bucket;
+}
+
+pmclass HashIterator extends Iterator no_ro {
+    ATTR PMC        *pmc_hash;      /* the Hash which this Iterator iterates */
+    ATTR Hash       *parrot_hash;   /* Underlying implementation of hash */
+    ATTR HashBucket *bucket;        /* Current bucket */
+    ATTR INTVAL      total_buckets; /* Total buckets in index */
+    ATTR INTVAL      pos;           /* Current position in index */
+    ATTR INTVAL      elements;      /* How many elements left to iterate over */
+
+/*
+
+=item C<void init_pmc(PMC *initializer)>
+
+Initializes the iterator with an aggregate PMC.
+Defaults iteration mode to iterate from start.
+
+=cut
+
+*/
+
+    VTABLE void init_pmc(PMC *hash) {
+        Parrot_HashIterator_attributes *attrs =
+            mem_allocate_zeroed_typed(Parrot_HashIterator_attributes);
+
+        attrs->pmc_hash         = hash;
+        attrs->parrot_hash      = (Hash*)VTABLE_get_pointer(INTERP, hash);
+        attrs->total_buckets    = attrs->parrot_hash->mask + 1;
+        attrs->bucket           = 0;
+        attrs->pos              = 0;
+        /* Will be decreased on initial advance_to_next */
+        /* XXX Do we really need to support this use-case ? */
+        attrs->elements         = attrs->parrot_hash->entries + 1;
+        PMC_data(SELF)          = attrs;
+
+        PObj_custom_mark_destroy_SETALL(SELF);
+
+        /* Initial state of iterator is "before start" */
+        /* So, advance to first element */
+        advance_to_next(INTERP, SELF);
+    }
+
+/*
+
+=item C<void destroy()>
+
+destroys this PMC
+
+=cut
+
+*/
+
+    VTABLE void destroy() {
+        mem_sys_free(PMC_data(SELF));
+    }
+
+/*
+
+=item C<void mark()>
+
+Marks the hash as live.
+
+=cut
+
+*/
+
+    VTABLE void mark() {
+        PMC *hash = PARROT_HASHITERATOR(SELF)->pmc_hash;
+        if (hash)
+             Parrot_gc_mark_PObj_alive(INTERP, (PObj *)hash);
+        /* We don't mark underlying parrot_hash. Hash PMC will mark it */
+    }
+
+/*
+
+=item C<PMC *clone()>
+
+=cut
+
+*/
+    VTABLE PMC* clone() {
+        return PMCNULL;
+    }
+
+/*
+
+=item C<void set_integer_native()>
+
+=cut
+
+*/
+    VTABLE void set_integer_native(INTVAL value) {
+        Parrot_HashIterator_attributes *attrs =
+                PARROT_HASHITERATOR(SELF);
+
+        if (value == 0) {
+            /* Restart iterator */
+            attrs->bucket           = 0;
+            attrs->pos              = 0;
+            advance_to_next(INTERP, SELF);
+            return;
+        }
+
+        Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
+                "HashIterator: unknown iterator type");
+    };
+
+/*
+
+=item C<PMC *get_pmc()>
+
+Returns this Iterator's Hash.
+
+=cut
+*/
+    VTABLE PMC* get_pmc() {
+        return PARROT_HASHITERATOR(SELF)->pmc_hash;
+    }
+
+/*
+
+=item C<INTVAL get_bool()>
+
+Returns true if there is more elements to iterate over.
+
+=cut
+
+*/
+
+    VTABLE INTVAL get_bool() {
+        return PARROT_HASHITERATOR(SELF)->bucket != 0;
+    }
+
+/*
+
+=item C<INTVAL elements()>
+
+Returns the number of remaining elements in the Hash.
+
+=cut
+
+*/
+
+    VTABLE INTVAL elements() {
+        return PARROT_HASHITERATOR(SELF)->elements;
+    }
+
+    VTABLE INTVAL get_integer() {
+        return SELF.elements();
+    }
+
+/*
+
+=item C<PMC *shift_pmc()>
+
+Returns the HashIteratorKey for the current position and advance
+the next one.
+
+=cut
+
+*/
+
+    VTABLE PMC *shift_pmc() {
+        Parrot_HashIterator_attributes *attrs =
+                PARROT_HASHITERATOR(SELF);
+
+        PMC        *ret;
+
+        if (!attrs->bucket)
+            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
+                "StopIteration");
+
+        ret = pmc_new(INTERP, enum_class_HashIteratorKey);
+        /* Poke directly into HIK. We don't want to create any kind of public API for this */
+        PARROT_HASHITERATORKEY(ret)->parrot_hash = attrs->parrot_hash;
+        PARROT_HASHITERATORKEY(ret)->bucket      = attrs->bucket;
+
+        /* Move to next bucket */
+        advance_to_next(INTERP, SELF);
+
+        return ret;
+    }
+
+/*
+
+*/
+
+    VTABLE STRING* shift_string() {
+        PMC *key = SELF.shift_pmc();
+        return VTABLE_get_string(INTERP, key);
+    }
+
+}
+
+/*
+
+=back
+
+=cut
+
+*/
+
+/*
+ * Local variables:
+ *   c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */

Added: trunk/src/pmc/hashiteratorkey.pmc
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/src/pmc/hashiteratorkey.pmc	Wed Jul 15 13:15:25 2009	(r40100)
@@ -0,0 +1,118 @@
+/*
+Copyright (C) 2001-2009, Parrot Foundation.
+$Id$
+
+=head1 NAME
+
+src/pmc/hashiteratorkey.pmc - accessor for single value during hash iteration.
+
+=head1 DESCRIPTION
+
+Single (key,value) pair.
+
+
+=head1 Methods
+
+=over 4
+
+=cut
+
+*/
+
+pmclass HashIteratorKey no_ro {
+    ATTR Hash        *parrot_hash; /* Underlying parrot's hash */
+    ATTR HashBucket  *bucket;      /* Current bucket from HashItertor */
+
+/*
+
+=item C<void init()>
+
+Initializes the PMC.
+
+Not really part of public API.
+
+=cut
+
+*/
+
+    VTABLE void init() {
+        Parrot_HashIteratorKey_attributes *attrs =
+            mem_allocate_zeroed_typed(Parrot_HashIteratorKey_attributes);
+
+        PMC_data(SELF) = attrs;
+
+        PObj_active_destroy_SET(SELF);
+    }
+
+/*
+
+=item C<void destroy()>
+
+Destroys this PMC
+
+=cut
+
+*/
+
+    VTABLE void destroy() {
+        mem_sys_free(PMC_data(SELF));
+    }
+
+/*
+
+=item C<get_pmc()>
+
+Get "key".
+
+=cut
+
+*/
+    VTABLE PMC* get_pmc() {
+        return PMCNULL;
+    }
+
+    VTABLE INTVAL get_integer() {
+        return -1;
+    }
+
+    VTABLE STRING* get_string() {
+        Parrot_HashIteratorKey_attributes *attrs =
+                PARROT_HASHITERATORKEY(SELF);
+
+        switch (attrs->parrot_hash->key_type) {
+            case Hash_key_type_int:
+                return Parrot_str_from_int(INTERP, (INTVAL)attrs->bucket->key);
+
+            case Hash_key_type_STRING:
+                return (STRING*)attrs->bucket->key;
+
+            case Hash_key_type_PMC:
+                return VTABLE_get_string(INTERP, (PMC *)attrs->bucket->key);
+
+            default:
+                /* Horribly die? */
+                break;
+        }
+
+        return NULL;
+    }
+
+
+
+}
+
+/*
+
+=back
+
+=cut
+
+*/
+
+/*
+ * Local variables:
+ *   c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */
+

Modified: trunk/src/pmc/iterator.pmc
==============================================================================
--- trunk/src/pmc/iterator.pmc	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/src/pmc/iterator.pmc	Wed Jul 15 13:15:25 2009	(r40100)
@@ -17,7 +17,7 @@
 =head2 default usage
 
     .local pmc iterator, array, entry
-    iterator = new 'Iterator', array
+    iterator = iter array
   iter_loop:
     unless iterator, iter_end  # while (more values)
     entry = shift iterator     # get an entry
@@ -25,14 +25,10 @@
     goto iter_loop
   iter_end:
 
-The C<new> can alternatively be written as:
-
-  iterator = iter array
-
 =head2 iterate from the end, for arrays
 
     .local pmc iterator, array, entry
-    iterator = new 'Iterator', array
+    iterator = iter array
     iterator = .ITERATE_FROM_END
   iter_loop:
     unless iterator, iter_end  # while (more values)
@@ -44,7 +40,7 @@
 =head2 iterate over a hash
 
     .local pmc iterator, hash, key, entry
-    iterator = new 'Iterator', hash
+    iterator = iter hash
   iter_loop:
     unless iterator, iter_end  # while (more values)
     key   = shift iterator     # get the key..
@@ -62,17 +58,6 @@
 */
 
 pmclass Iterator no_ro {
-    ATTR PMC *aggregate; /* the aggregate which this Iterator iterates */
-    ATTR PMC *key;       /* the Key used by this Iterator */
-
-    void class_init() {
-        if (pass) {
-            /* Make the shift_pmc vtable function available as
-             * a method named "next" */
-            register_nci_method(INTERP, enum_class_Iterator,
-                    F2DPTR(Parrot_Iterator_shift_pmc), "next", "PJO");
-        }
-    }
 
 /*
 
@@ -101,107 +86,20 @@
 */
 
     VTABLE void init_pmc(PMC *aggregate) {
-        Parrot_Iterator_attributes *attrs =
-            mem_allocate_zeroed_typed(Parrot_Iterator_attributes);
-
-        attrs->aggregate = aggregate;
-        attrs->key       = PMCNULL;
-        PMC_data(SELF)   = attrs;
-
-        PObj_custom_mark_destroy_SETALL(SELF);
-
-        /* by default, iterate from start */
-        SELF.set_integer_native(ITERATE_FROM_START);
-    }
-
-/*
-
-=item C<void destroy()>
-
-destroys this PMC
-
-=cut
-
-*/
-
-    VTABLE void destroy() {
-        mem_sys_free(PMC_data(SELF));
-    }
-
-/*
-
-=item C<void mark()>
-
-Marks the current idx/key and the aggregate as live.
-
-=cut
-
-*/
-
-    VTABLE void mark() {
-        /* the Key */
-        PMC *key;
-        GET_ATTR_key(INTERP, SELF, key);
-        if (key)
-             Parrot_gc_mark_PObj_alive(INTERP, (PObj *)key);
-
-        /* the aggregate */
-        if (SELF.get_pmc() != PMCNULL)
-             Parrot_gc_mark_PObj_alive(INTERP, (PObj *)SELF.get_pmc());
-    }
-
-/*
-
-=item C<PMC *clone()>
-
-Make a clone of the iterator.
-
-=cut
-
-*/
-
-    VTABLE PMC *clone() {
-        PMC           *key;
-        STRING * const name = CONST_STRING(interp, "set_key");
-        PMC    * const res  = pmc_new_init(INTERP, SELF->vtable->base_type,
-                                           SELF.get_pmc());
-
-        GET_ATTR_key(INTERP, SELF, key);
-
-        Parrot_PCCINVOKE(interp, res, name, "P->", VTABLE_clone(interp, key));
-        return res;
-    }
-
-/*
-
-=item C<INTVAL get_integer()>
-
-Get number of remaining elements. Does not work for hashes yet.
-TODO: keep track of current position and direction
-
-=cut
-
-*/
-
-    VTABLE INTVAL get_integer() {
-        return SELF.elements();
+        if (VTABLE_does(INTERP, aggregate, CONST_STRING(INTERP, "array"))
+            || VTABLE_does(INTERP, aggregate, CONST_STRING(INTERP, "hash"))
+            || VTABLE_does(INTERP, aggregate, CONST_STRING(INTERP, "string"))) {
+            /* It's ugly hack... But I cant figure out proper way to do it. */
+            PMC *real_iter = VTABLE_get_iter(INTERP, aggregate);
+            SELF = pmc_reuse_init(INTERP, SELF, VTABLE_type(INTERP, real_iter), aggregate, 0);
+            return;
+        }
+        else {
+            /* Die horribly */
+            PARROT_ASSERT(!"Unsupported Aggregate for Iterator");
+        }
     }
 
-/*
-
-=item C<STRING *get_string()>
-
-Returns a textual representation of the iterator.
-
-=cut
-
-*/
-
-    VTABLE STRING *get_string() {
-        PMC *key;
-        GET_ATTR_key(INTERP, SELF, key);
-        return Parrot_str_from_int(INTERP, VTABLE_get_integer(INTERP, key));
-    }
 
 /*
 
@@ -217,25 +115,6 @@
 
 /*
 
-=item C<INTVAL get_integer_keyed_int(INTVAL idx)>
-
-Get integer value of current position plus idx.
-
-=cut
-
-*/
-
-    VTABLE INTVAL get_integer_keyed_int(INTVAL idx) {
-        PMC * const agg = SELF.get_pmc();
-        PMC        *key;
-
-        GET_ATTR_key(INTERP, SELF, key);
-        return VTABLE_get_integer_keyed_int(INTERP, agg,
-                VTABLE_get_integer(INTERP, key) +idx);
-    }
-
-/*
-
 =item C<FLOATVAL get_number_keyed(PMC *key)>
 
 =cut
@@ -246,26 +125,6 @@
         return VTABLE_get_number_keyed(INTERP, SELF.get_pmc(), key);
     }
 
-/*
-
-=item C<FLOATVAL get_number_keyed_int(INTVAL idx)>
-
-Get number value of current position plus idx.
-
-=cut
-
-*/
-
-    VTABLE FLOATVAL get_number_keyed_int(INTVAL idx) {
-        PMC * const agg = SELF.get_pmc();
-        PMC        *key;
-
-        GET_ATTR_key(INTERP, SELF, key);
-        return VTABLE_get_number_keyed_int(INTERP, agg,
-                VTABLE_get_integer(INTERP, key) + idx);
-    }
-
-
 
 /*
 
@@ -280,72 +139,6 @@
     }
 
 /*
-
-=item C<STRING *get_string_keyed_int(INTVAL idx)>
-
-Get string value of current position plus idx.
-
-=cut
-
-*/
-
-    VTABLE STRING *get_string_keyed_int(INTVAL idx) {
-        PMC * const agg = SELF.get_pmc();
-        PMC        *key;
-
-        GET_ATTR_key(INTERP, SELF, key);
-        return VTABLE_get_string_keyed_int(INTERP, agg,
-                VTABLE_get_integer(INTERP, key) + idx);
-    }
-
-/*
-
-=item C<INTVAL get_bool()>
-
-Returns true if the idx/key is not C<-1>.
-
-=cut
-
-*/
-
-    VTABLE INTVAL get_bool() {
-        PMC *key;
-        GET_ATTR_key(INTERP, SELF, key);
-        return !PMC_is_null(INTERP, key) &&
-                VTABLE_get_integer(INTERP, key) != -1;
-    }
-
-/*
-
-=item C<INTVAL elements()>
-
-Returns the number of remaining elements in the aggregate. TODO.
-
-=cut
-
-*/
-
-    VTABLE INTVAL elements() {
-        return VTABLE_elements(INTERP, SELF.get_pmc());
-    }
-
-/*
-
-=item C<PMC *get_pmc()>
-
-Returns this Iterator's aggregate.
-
-=cut
-
-*/
-
-    VTABLE PMC *get_pmc() {
-        PMC *agg;
-        GET_ATTR_aggregate(INTERP, SELF, agg);
-        return agg ? agg : PMCNULL;
-    }
-
-/*
 =item C<PMC *get_pmc_keyed(PMC *key)>
 
 Returns the element for C<*key>.
@@ -360,292 +153,6 @@
 
 /*
 
-=item C<PMC *get_pmc_keyed_int(INTVAL key)>
-
-Returns the element for C<key>.
-
-=cut
-
-*/
-
-    VTABLE PMC *get_pmc_keyed_int(INTVAL idx) {
-        PMC * const agg = SELF.get_pmc();
-        PMC        *key;
-
-        GET_ATTR_key(INTERP, SELF, key);
-        return VTABLE_get_pmc_keyed_int(INTERP, agg,
-                VTABLE_get_integer(INTERP, key) + idx);
-    }
-
-/*
-
-=item C<void set_integer_native(INTVAL value)>
-
-Reset the Iterator. C<value> must be one of
-
- ITERATE_FROM_START        ... Iterate from start
- ITERATE_FROM_START_KEYS   ... OrderedHash by keys
- ITERATE_FROM_END          ... Arrays only
-
-=cut
-
-*/
-
-    VTABLE void set_integer_native(INTVAL value) {
-        PMC *agg;
-        PMC *key;
-        if (value < ITERATE_FROM_START || value > ITERATE_FROM_END)
-            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
-                    "Illegal set_integer on iterator");
-
-        /* reset iterator on aggregate */
-        agg = SELF.get_pmc();
-
-        GET_ATTR_key(INTERP, SELF, key);
-        if (PMC_is_null(INTERP, key))
-            key = key_new(INTERP);
-
-        SET_ATTR_key(INTERP, SELF,
-                VTABLE_nextkey_keyed(INTERP, key, agg, value));
-    }
-
-/*
-
-=item C<INTVAL pop_integer()>
-
-=cut
-
-*/
-
-    VTABLE INTVAL pop_integer() {
-        PMC * const  agg   = SELF.get_pmc();
-        PMC         *key;
-        INTVAL       ret;
-
-        GET_ATTR_key(INTERP, SELF, key);
-        ret  = VTABLE_get_integer_keyed(INTERP, agg, key);
-        SET_ATTR_key(INTERP, SELF,
-            VTABLE_nextkey_keyed(INTERP, key, agg, ITERATE_GET_PREV));
-
-        return ret;
-    }
-
-/*
-
-=item C<FLOATVAL pop_float()>
-
-=cut
-
-*/
-
-    VTABLE FLOATVAL pop_float() {
-        PMC * const    agg = SELF.get_pmc();
-        PMC           *key;
-        FLOATVAL       ret;
-
-        GET_ATTR_key(INTERP, SELF, key);
-        ret = VTABLE_get_number_keyed(INTERP, agg, key);
-        SET_ATTR_key(INTERP, SELF,
-            VTABLE_nextkey_keyed(INTERP, key, agg, ITERATE_GET_PREV));
-
-        return ret;
-    }
-
-/*
-
-=item C<STRING *pop_string()>
-
-=cut
-
-*/
-
-    VTABLE STRING *pop_string() {
-        STRING     *ret;
-        PMC        *key;
-        PMC * const agg = SELF.get_pmc();
-
-        GET_ATTR_key(INTERP, SELF, key);
-        ret = VTABLE_get_string_keyed(INTERP, agg, key);
-        SET_ATTR_key(INTERP, SELF,
-            VTABLE_nextkey_keyed(INTERP, key, agg, ITERATE_GET_PREV));
-
-        return ret;
-    }
-
-/*
-
-=item C<PMC *pop_pmc()>
-
-Returns the element for the current idx/key and sets the idx/key to
-the previous one.
-
-=cut
-
-*/
-
-    VTABLE PMC *pop_pmc() {
-        PMC * const agg = SELF.get_pmc();
-        PMC        *key;
-        PMC        *ret;
-
-        GET_ATTR_key(INTERP, SELF, key);
-        ret = VTABLE_get_pmc_keyed(INTERP, agg, key);
-        SET_ATTR_key(INTERP, SELF,
-            VTABLE_nextkey_keyed(INTERP, key, agg, ITERATE_GET_PREV));
-
-        return ret;
-    }
-
-/*
-
-=item C<INTVAL shift_integer()>
-
-Returns the element for the current idx/key and sets the idx/key to
-the next one.
-
-=cut
-
-*/
-
-    VTABLE INTVAL shift_integer() {
-        INTVAL       ret;
-        PMC         *key;
-        PMC * const  agg = SELF.get_pmc();
-
-        GET_ATTR_key(INTERP, SELF, key);
-        ret = VTABLE_get_integer_keyed(INTERP, agg, key);
-        SET_ATTR_key(INTERP, SELF,
-            VTABLE_nextkey_keyed(INTERP, key, agg, ITERATE_GET_NEXT));
-
-        return ret;
-    }
-
-/*
-
-=item C<opcode_t *invoke(void *next)>
-
-Return the next element of the aggregate. The return type may depend on
-the aggregate. If there are no more items in the aggregate, I1 .. I4 are
-zero.
-
-See F<docs/pdds/pdd03_calling_conventions.pod>.
-
-=cut
-
-*/
-    VTABLE opcode_t *invoke(void *next) {
-        PMC *agg;
-
-        /* iterator constructor */
-        if (REG_INT(interp, 3) == 1) {
-            PMC * const arg = REG_PMC(interp, 5);
-            PMC *iter;
-
-            if (PObj_is_object_TEST(arg)) {
-                REG_PMC(interp, 5) = VTABLE_get_iter(INTERP, arg);
-                return (opcode_t *)next;
-            }
-
-            REG_PMC(interp, 5) = iter = pmc_new_init(INTERP,
-                    enum_class_Iterator, arg);
-            VTABLE_set_integer_native(INTERP, iter, 0);
-            return (opcode_t *)next;
-        }
-        /* TODO function + sentinel */
-        else if (REG_INT(interp, 3) == 2)
-            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
-                    "Iterator: invoke 2 args");
-
-        REG_INT(interp, 1) =
-            REG_INT(interp, 2) =
-            REG_INT(interp, 3) =
-            REG_INT(interp, 4) = 0;
-
-        agg = SELF.get_pmc();
-
-        {
-            PMC * const res    = SELF.shift_pmc();
-            REG_INT(interp, 3) = 1;
-            REG_PMC(interp, 5) = res;
-            return (opcode_t *)next;
-        }
-    }
-
-/*
-
-=item C<FLOATVAL shift_float()>
-
-=cut
-
-*/
-
-    VTABLE FLOATVAL shift_float() {
-        PMC        *key;
-        PMC * const agg = SELF.get_pmc();
-        FLOATVAL    ret;
-
-        GET_ATTR_key(INTERP, SELF, key);
-        ret = VTABLE_get_number_keyed(INTERP, agg, key);
-        SET_ATTR_key(INTERP, SELF,
-            VTABLE_nextkey_keyed(INTERP, key, agg, ITERATE_GET_NEXT));
-
-        return ret;
-    }
-
-
-/*
-
-=item C<STRING *shift_string()>
-
-=cut
-
-*/
-
-    VTABLE STRING *shift_string() {
-        PMC        *key;
-        PMC * const agg = SELF.get_pmc();
-        STRING     *ret;
-
-        GET_ATTR_key(INTERP, SELF, key);
-        ret = VTABLE_get_string_keyed(INTERP, agg, key);
-        SET_ATTR_key(INTERP, SELF,
-            VTABLE_nextkey_keyed(INTERP, key, agg, ITERATE_GET_NEXT));
-
-        return ret;
-    }
-
-/*
-
-=item C<PMC *shift_pmc()>
-
-Returns the element for the current idx/key and sets the idx/key to
-the next one.
-
-=cut
-
-*/
-
-    VTABLE PMC *shift_pmc() {
-        PMC * const agg = SELF.get_pmc();
-        PMC        *ret;
-        PMC        *key;
-
-        GET_ATTR_key(INTERP, SELF, key);
-
-        if (VTABLE_get_integer(INTERP, key) == -1)
-            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
-                "StopIteration");
-
-        ret = VTABLE_get_pmc_keyed(INTERP, agg, key);
-
-        SET_ATTR_key(INTERP, SELF,
-            VTABLE_nextkey_keyed(INTERP, key, agg, ITERATE_GET_NEXT));
-
-        return ret;
-    }
-
-/*
-
 =item C<INTVAL exists_keyed(PMC *key)>
 
 Returns whether an element for C<*key> exists in the aggregate.
@@ -660,24 +167,6 @@
 
 /*
 
-=item C<INTVAL exists_keyed_int(INTVAL idx)>
-
-Returns whether an element for C<idx> exists in the aggregate.
-
-=cut
-
-*/
-
-    VTABLE INTVAL exists_keyed_int(INTVAL idx) {
-        PMC * const agg = SELF.get_pmc();
-        PMC        *key;
-        GET_ATTR_key(INTERP, SELF, key);
-        return VTABLE_exists_keyed_int(INTERP, agg,
-                VTABLE_get_integer(INTERP, key) + idx);
-    }
-
-/*
-
 =item C<INTVAL defined()>
 
 Returns whether the iterator contains an aggregate.
@@ -702,39 +191,34 @@
         return VTABLE_defined_keyed(INTERP, SELF.get_pmc(), key);
     }
 
-/*
 
-=item C<INTVAL defined_keyed_int(INTVAL key)>
+    VTABLE PMC *get_iter() {
+        return SELF;
+    }
 
-Returns the result of calling C<defined_keyed(key)> on the aggregate.
+    /* Make the shift_pmc vtable function available as
+     * a method named "next" */
+     METHOD next() {
+        PMC *next = VTABLE_shift_pmc(INTERP, SELF);
+        RETURN(PMC* next);
+     }
 
-=cut
-
-*/
+/*
 
-    VTABLE INTVAL defined_keyed_int(INTVAL idx) {
-        PMC * const agg = SELF.get_pmc();
-        PMC        *key;
+=item C<void set_integer_native(INTVAL value)>
 
-        GET_ATTR_key(INTERP, SELF, key);
-        return VTABLE_defined_keyed_int(INTERP, agg,
-                VTABLE_get_integer(INTERP, key) + idx);
-    }
+Restart iterator
 
-    VTABLE PMC *get_iter() {
-        return SELF;
-    }
+=cut
 
-    METHOD set_key(PMC *key) {
-        SET_ATTR_key(INTERP, SELF, key);
-    }
+*/
+    VTABLE void set_integer_native(INTVAL value) {
+        PMC *self = SELF;
+        PARROT_ASSERT(!"Iterator: implementation have to override this method");
 
-    METHOD get_key() {
-        PMC *key;
-        GET_ATTR_key(INTERP, SELF, key);
-        RETURN(PMC *key);
+        Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_UNIMPLEMENTED,
+                "Iterator: unimplemented method");
     }
-
 }
 
 /*

Modified: trunk/src/pmc/namespace.pmc
==============================================================================
--- trunk/src/pmc/namespace.pmc	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/src/pmc/namespace.pmc	Wed Jul 15 13:15:25 2009	(r40100)
@@ -396,7 +396,8 @@
     }
 
     VTABLE PMC *get_pmc_keyed(PMC *key) {
-        PMC    *ns = SUPER(key);
+        /* PMC    *ns = SUPER(key); */
+        PMC    *ns = INTERP->vtables[enum_class_Hash]->get_pmc_keyed(INTERP, SELF, key);
 
         if (!PMC_IS_NULL(ns))
             return ns;

Modified: trunk/src/pmc/orderedhash.pmc
==============================================================================
--- trunk/src/pmc/orderedhash.pmc	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/src/pmc/orderedhash.pmc	Wed Jul 15 13:15:25 2009	(r40100)
@@ -77,6 +77,20 @@
 
 /*
 
+=item C<PMC *get_iter()>
+
+Return a new iterator
+
+=cut
+
+*/
+
+    VTABLE PMC *get_iter() {
+        return pmc_new_init(INTERP, enum_class_OrderedHashIterator, SELF);
+    }
+
+/*
+
 =item C<PMC *get_pmc_keyed(PMC *key)>
 
 =item C<PMC *get_pmc_keyed_int(INTVAL key)>
@@ -119,7 +133,7 @@
             return VTABLE_get_pmc_keyed(INTERP, item, next);
         }
 
-        return SUPER(key);
+        return INTERP->vtables[enum_class_Hash]->get_pmc_keyed(INTERP, SELF, key);
     }
 
 /*
@@ -167,7 +181,7 @@
             return VTABLE_get_string_keyed(INTERP, item, next);
         }
 
-        return SUPER(key);
+        return INTERP->vtables[enum_class_Hash]->get_string_keyed(INTERP, SELF, key);
     }
 /*
 
@@ -216,7 +230,7 @@
             return VTABLE_get_integer_keyed(INTERP, item, next);
         }
 
-        return SUPER(key);
+        return INTERP->vtables[enum_class_Hash]->get_integer_keyed(INTERP, SELF, key);
     }
 
 /*

Added: trunk/src/pmc/orderedhashiterator.pmc
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/src/pmc/orderedhashiterator.pmc	Wed Jul 15 13:15:25 2009	(r40100)
@@ -0,0 +1,265 @@
+/*
+Copyright (C) 2001-2009, Parrot Foundation.
+$Id$
+
+=head1 NAME
+
+src/pmc/orderedhashiterator.pmc - Implementation of Iterator for OrderedHash.
+
+=head1 DESCRIPTION
+
+=head1 SYNOPSIS
+
+=head1 Methods
+
+=over 4
+
+=cut
+
+*/
+
+#include "pmc_hash.h"
+#include "pmc_hashiteratorkey.h"
+
+pmclass OrderedHashIterator extends Iterator no_ro {
+    ATTR PMC        *pmc_hash;      /* the Hash which this Iterator iterates */
+    ATTR Hash       *parrot_hash;   /* Underlying implementation of hash */
+    ATTR INTVAL      pos;           /* */
+    ATTR INTVAL      elements;      /* How many elements left to iterate over */
+    ATTR INTVAL      reverse;       /* Direction of iteration. 1 - for reverse iteration */
+
+/*
+
+=item C<void init_pmc(PMC *initializer)>
+
+Initializes the iterator with an aggregate PMC.
+Defaults iteration mode to iterate from start.
+
+=cut
+
+*/
+
+    VTABLE void init_pmc(PMC *hash) {
+        Parrot_OrderedHashIterator_attributes *attrs =
+            mem_allocate_zeroed_typed(Parrot_OrderedHashIterator_attributes);
+
+        attrs->pmc_hash         = hash;
+        attrs->parrot_hash      = (Hash*)VTABLE_get_pointer(INTERP, hash);
+        attrs->pos              = 0;
+        /* Will be decreased on initial advance_to_next */
+        /* XXX Do we really need to support this use-case ? */
+        attrs->elements         = attrs->parrot_hash->entries;
+        PMC_data(SELF)          = attrs;
+
+        PObj_custom_mark_destroy_SETALL(SELF);
+    }
+
+/*
+
+=item C<void destroy()>
+
+destroys this PMC
+
+=cut
+
+*/
+
+    VTABLE void destroy() {
+        mem_sys_free(PMC_data(SELF));
+    }
+
+/*
+
+=item C<void mark()>
+
+Marks the hash as live.
+
+=cut
+
+*/
+
+    VTABLE void mark() {
+        PMC *hash = PARROT_ORDEREDHASHITERATOR(SELF)->pmc_hash;
+        if (hash)
+             Parrot_gc_mark_PObj_alive(INTERP, (PObj *)hash);
+    }
+
+/*
+
+=item C<PMC *clone()>
+
+=cut
+
+*/
+    VTABLE PMC* clone() {
+        return PMCNULL;
+    }
+
+/*
+
+=item C<void set_integer_native()>
+
+=cut
+
+*/
+    VTABLE void set_integer_native(INTVAL value) {
+        Parrot_OrderedHashIterator_attributes *attrs =
+                PARROT_ORDEREDHASHITERATOR(SELF);
+
+        /* Restart iterator */
+        attrs->elements         = attrs->parrot_hash->entries;
+        if (value == ITERATE_FROM_START || value == ITERATE_FROM_START_KEYS) {
+            attrs->pos      = 0;
+            attrs->reverse  = 0;
+            return;
+        }
+        else if (value == ITERATE_FROM_END) {
+            attrs->pos      = attrs->elements;
+            attrs->reverse  = 1;
+            return;
+        }
+
+        Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
+                "HashIterator: unknown iterator type");
+    };
+
+/*
+
+=item C<PMC *get_pmc()>
+
+Returns this Iterator's Hash.
+
+=cut
+*/
+    VTABLE PMC* get_pmc() {
+        return PARROT_ORDEREDHASHITERATOR(SELF)->pmc_hash;
+    }
+
+/*
+
+=item C<INTVAL get_bool()>
+
+Returns true if there is more elements to iterate over.
+
+=cut
+
+*/
+
+    VTABLE INTVAL get_bool() {
+        return STATICSELF.elements() > 0;
+    }
+
+/*
+
+=item C<INTVAL elements()>
+
+Returns the number of remaining elements in the Hash.
+
+=cut
+
+*/
+
+    VTABLE INTVAL elements() {
+        return PARROT_ORDEREDHASHITERATOR(SELF)->elements;
+    }
+
+    VTABLE INTVAL get_integer() {
+        return SELF.elements();
+    }
+
+/*
+
+=item C<PMC *shift_pmc()>
+
+Returns the HashIteratorKey for the current position and advance
+the next one.
+
+=cut
+
+*/
+
+    VTABLE PMC *shift_pmc() {
+        Parrot_OrderedHashIterator_attributes *attrs =
+                PARROT_ORDEREDHASHITERATOR(SELF);
+
+        PMC        *ret;
+        HashBucket *bucket;
+
+        if (!attrs->elements)
+            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
+                "StopIteration");
+
+        /* Get bucket and move to next bucket */
+        do {
+            bucket = attrs->parrot_hash->bs + attrs->pos++;
+            attrs->elements--;
+        } while(attrs->elements && !bucket->key);
+
+        /* Reuse HashIteratorKey */
+        ret = pmc_new(INTERP, enum_class_HashIteratorKey);
+        /* Poke directly into HIK. We don't want to create any kind of public API for this */
+        PARROT_HASHITERATORKEY(ret)->parrot_hash = attrs->parrot_hash;
+        PARROT_HASHITERATORKEY(ret)->bucket      = bucket;
+
+        return ret;
+    }
+
+/*
+
+=item C<PMC *pop_pmc()>
+
+Returns the HashIteratorKey for the current position and advance
+the next one for reverse iterator.
+
+=cut
+
+*/
+
+    VTABLE PMC *pop_pmc() {
+        Parrot_OrderedHashIterator_attributes *attrs =
+                PARROT_ORDEREDHASHITERATOR(SELF);
+
+        PMC        *ret;
+        HashBucket *bucket;
+
+        if (!attrs->elements)
+            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
+                "StopIteration");
+
+        /* Get bucket and move to next bucket */
+        bucket = attrs->parrot_hash->bs + --attrs->pos;
+        attrs->elements--;
+
+        /* Reuse HashIteratorKey */
+        ret = pmc_new(INTERP, enum_class_HashIteratorKey);
+        /* Poke directly into HIK. We don't want to create any kind of public API for this */
+        PARROT_HASHITERATORKEY(ret)->parrot_hash = attrs->parrot_hash;
+        PARROT_HASHITERATORKEY(ret)->bucket      = bucket;
+
+        return ret;
+    }
+
+/*
+
+*/
+
+    VTABLE STRING* shift_string() {
+        PMC *key = SELF.shift_pmc();
+        return VTABLE_get_string(INTERP, key);
+    }
+}
+
+/*
+
+=back
+
+=cut
+
+*/
+
+/*
+ * Local variables:
+ *   c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */

Modified: trunk/src/pmc/string.pmc
==============================================================================
--- trunk/src/pmc/string.pmc	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/src/pmc/string.pmc	Wed Jul 15 13:15:25 2009	(r40100)
@@ -647,27 +647,42 @@
 */
 
     VTABLE STRING *get_string_keyed(PMC *key) {
+        return SELF.get_string_keyed_int(VTABLE_get_integer(INTERP, key));
+    }
+
+    VTABLE STRING *get_string_keyed_int(INTVAL pos) {
         STRING * const s = SELF.get_string();
-        const INTVAL   k = VTABLE_get_integer(INTERP, key);
-        return Parrot_str_substr(INTERP, s, k, 1, NULL, 0);
+        return Parrot_str_substr(INTERP, s, pos, 1, NULL, 0);
     }
 
     VTABLE INTVAL get_integer_keyed(PMC *key) {
+        return SELF.get_integer_keyed_int(VTABLE_get_integer(INTERP, key));
+    }
+
+    VTABLE INTVAL get_integer_keyed_int(INTVAL pos) {
         STRING * const s = SELF.get_string();
-        return string_ord(INTERP, s, VTABLE_get_integer(INTERP, key));
+        return string_ord(INTERP, s, pos);
     }
 
     VTABLE void set_string_keyed(PMC *key, STRING * const value) {
+        SELF.set_string_keyed_int(VTABLE_get_integer(INTERP, key), value);
+    }
+
+    VTABLE void set_string_keyed_int(INTVAL pos, STRING * const value) {
         STRING * const s   = SELF.get_string();
         const INTVAL   len = Parrot_str_byte_length(INTERP, value);
-        Parrot_str_replace(INTERP, s, VTABLE_get_integer(INTERP, key), len, value, NULL);
+        Parrot_str_replace(INTERP, s, pos, len, value, NULL);
         VTABLE_set_string_native(INTERP, SELF, s);
     }
 
     VTABLE void set_integer_keyed(PMC *key, INTVAL value) {
+        SELF.set_integer_keyed_int(VTABLE_get_integer(INTERP, key), value);
+    }
+
+    VTABLE void set_integer_keyed_int(INTVAL pos, INTVAL value) {
         STRING * const s = SELF.get_string();
         STRING * const c = string_chr(INTERP, (UINTVAL) value);
-        Parrot_str_replace(INTERP, s, VTABLE_get_integer(INTERP, key), 1, c, NULL);
+        Parrot_str_replace(INTERP, s, pos, 1, c, NULL);
         VTABLE_set_string_native(INTERP, SELF, s);
     }
 /*
@@ -796,19 +811,7 @@
     }
 
     VTABLE PMC *get_iter() {
-        STRING     *name     = CONST_STRING(interp, "set_key");
-        PMC * const iter     = pmc_new_init(INTERP, enum_class_Iterator, SELF);
-        PMC * const key      = pmc_new(INTERP, enum_class_Key);
-
-        Parrot_PCCINVOKE(interp, iter, name, "P->", key);
-        PObj_get_FLAGS(key) |= KEY_integer_FLAG;
-
-        if (!Parrot_str_byte_length(INTERP, VTABLE_get_string(INTERP, SELF)))
-            VTABLE_set_integer_native(INTERP, key, -1);
-        else
-            VTABLE_set_integer_native(INTERP, key, 0);
-
-        return iter;
+        return pmc_new_init(INTERP, enum_class_StringIterator, SELF);
     }
 
 /*

Added: trunk/src/pmc/stringiterator.pmc
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/src/pmc/stringiterator.pmc	Wed Jul 15 13:15:25 2009	(r40100)
@@ -0,0 +1,314 @@
+/*
+Copyright (C) 2001-2009, Parrot Foundation.
+$Id$
+
+=head1 NAME
+
+src/pmc/stringiterator.pmc - StringIterator PMC
+
+=head1 DESCRIPTION
+
+Implementation of Iterator for String PMC.
+
+=head1 SYNOPSIS
+
+
+=head1 Methods
+
+=over 4
+
+=cut
+
+*/
+
+
+pmclass StringIterator extends Iterator {
+    ATTR PMC    *string;    /* String to iterate over */
+    ATTR INTVAL  pos;       /* Current position of iterator for forward iterator */
+                            /* Previous position of iterator for reverse iterator */
+    ATTR INTVAL  length;    /* Length of C<string> */
+    ATTR INTVAL  reverse;   /* Direction of iteration. 1 - for reverse iteration */
+
+/*
+
+=item C<void init_pmc()>
+
+Initialize StringIterator.
+
+=cut
+
+*/
+    VTABLE void init_pmc(PMC *string) {
+        Parrot_StringIterator_attributes *attrs =
+            mem_allocate_zeroed_typed(Parrot_StringIterator_attributes);
+
+        attrs->string    = string;
+        PMC_data(SELF)   = attrs;
+
+        PObj_custom_mark_destroy_SETALL(SELF);
+
+        /* by default, iterate from start */
+        SELF.set_integer_native(ITERATE_FROM_START);
+    }
+
+/*
+
+=item C<void destroy()>
+
+destroys this PMC
+
+=cut
+
+*/
+
+    VTABLE void destroy() {
+        mem_sys_free(PMC_data(SELF));
+    }
+
+/*
+
+=item C<void mark()>
+
+Marks the current idx/key and the aggregate as live.
+
+=cut
+
+*/
+
+    VTABLE void mark() {
+        PMC *string;
+        GET_ATTR_string(INTERP, SELF, string);
+        if (string)
+             Parrot_gc_mark_PObj_alive(INTERP, (PObj *)string);
+    }
+
+/*
+
+=item C<PMC *clone()>
+
+=cut
+
+*/
+    VTABLE PMC* clone() {
+        Parrot_StringIterator_attributes *attrs =
+                PARROT_STRINGITERATOR(SELF);
+        PMC                              *clone =
+                pmc_new_init(INTERP, enum_class_StringIterator, attrs->string);
+        Parrot_StringIterator_attributes *clone_attrs =
+                PARROT_STRINGITERATOR(clone);
+
+        clone_attrs->pos     = attrs->pos;
+        clone_attrs->reverse = attrs->reverse;
+        return clone;
+    }
+
+/*
+
+=item C<INTVAL get_bool()>
+
+Returns true if there is more elements to iterate over.
+
+=cut
+
+*/
+
+    VTABLE INTVAL get_bool() {
+        return SELF.elements() > 0;
+    }
+
+/*
+
+=item C<INTVAL elements()>
+
+Returns the number of remaining elements in the C<string>.
+
+=cut
+
+*/
+
+    VTABLE INTVAL elements() {
+        Parrot_StringIterator_attributes *attrs =
+                PARROT_STRINGITERATOR(SELF);
+        if (attrs->reverse)
+            return attrs->pos;
+        else
+            return attrs->length - attrs->pos;
+    }
+
+    VTABLE INTVAL get_integer() {
+        return SELF.elements();
+    }
+
+/*
+
+=item C<void set_integer_native(INTVAL value)>
+
+Reset the Iterator. C<value> must be one of
+
+ ITERATE_FROM_START        ... Iterate from start
+ ITERATE_FROM_END          ... Iterate from end
+
+=cut
+
+*/
+
+    VTABLE void set_integer_native(INTVAL value) {
+        Parrot_StringIterator_attributes *attrs =
+                PARROT_STRINGITERATOR(SELF);
+        if (value == ITERATE_FROM_START) {
+            attrs->reverse   = 0;
+            attrs->pos       = 0;
+            attrs->length    = VTABLE_elements(INTERP, attrs->string);
+        }
+        else if (value == ITERATE_FROM_END) {
+            attrs->reverse   = 1;
+            attrs->pos       = attrs->length
+                             = VTABLE_elements(INTERP, attrs->string);
+        }
+        else
+            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
+                    "Wrong direction for StringIterator");
+    }
+
+/*
+
+=item C<PMC *get_pmc()>
+
+Returns this Iterator's string.
+
+=cut
+
+*/
+
+    VTABLE PMC *get_pmc() {
+        PMC *string;
+        GET_ATTR_string(INTERP, SELF, string);
+        return string ? string : PMCNULL;
+    }
+
+/*
+
+=item C<STRING *shift_string()>
+
+Shift next character from C<string>.
+
+=cut
+
+*/
+    VTABLE STRING *shift_string() {
+        Parrot_StringIterator_attributes *attrs =
+                PARROT_STRINGITERATOR(SELF);
+
+        if (attrs->pos >= attrs->length)
+            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
+                "StopIteration");
+
+        return VTABLE_get_string_keyed_int(INTERP, attrs->string, attrs->pos++);
+    }
+
+/*
+
+=item C<INTVAL shift_integer()>
+
+Shift next character code from C<string>.
+
+=cut
+
+*/
+    VTABLE INTVAL shift_integer() {
+        Parrot_StringIterator_attributes *attrs =
+                PARROT_STRINGITERATOR(SELF);
+
+        if (attrs->pos >= attrs->length)
+            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
+                "StopIteration");
+
+        return VTABLE_get_integer_keyed_int(INTERP, attrs->string, attrs->pos++);
+    }
+
+/*
+
+=item C<STRING *pop_string()>
+
+Shift "next" character from C<string> for reverse iterator.
+
+=cut
+
+*/
+    VTABLE STRING *pop_string() {
+        Parrot_StringIterator_attributes *attrs =
+                PARROT_STRINGITERATOR(SELF);
+
+        if (!STATICSELF.get_bool())
+            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
+                "StopIteration");
+
+        return VTABLE_get_string_keyed_int(INTERP, attrs->string, --attrs->pos);
+    }
+
+/*
+
+=item C<INTVAL pop_integer()>
+
+Shift "next" character code from C<string> for reverse iterator.
+
+=cut
+
+*/
+    VTABLE INTVAL pop_integer() {
+        Parrot_StringIterator_attributes *attrs =
+                PARROT_STRINGITERATOR(SELF);
+
+        if (!STATICSELF.get_bool())
+            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
+                "StopIteration");
+
+        return VTABLE_get_integer_keyed_int(INTERP, attrs->string, --attrs->pos);
+    }
+
+/*
+
+=item C<INTVAL get_integer_keyed_int(INTVAL idx)>
+
+Get integer value of current position plus idx.
+
+=cut
+
+*/
+
+    VTABLE INTVAL get_integer_keyed_int(INTVAL idx) {
+        return VTABLE_get_integer_keyed_int(INTERP, STATICSELF.get_pmc(),
+                PARROT_STRINGITERATOR(SELF)->pos + idx);
+    }
+
+/*
+
+=item C<STRING *get_string_keyed_int(INTVAL idx)>
+
+Get string value of current position plus idx.
+
+=cut
+
+*/
+
+    VTABLE STRING *get_string_keyed_int(INTVAL idx) {
+        return VTABLE_get_string_keyed_int(INTERP, STATICSELF.get_pmc(),
+                PARROT_STRINGITERATOR(SELF)->pos + idx);
+    }
+}
+
+
+/*
+
+=back
+
+=cut
+
+*/
+
+/*
+ * Local variables:
+ *   c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */

Modified: trunk/t/compilers/pct/past.t
==============================================================================
--- trunk/t/compilers/pct/past.t	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/t/compilers/pct/past.t	Wed Jul 15 13:15:25 2009	(r40100)
@@ -48,6 +48,11 @@
 
 }
 
+# Next tests marked as "skip" instead of "todo" to prevent false-positives in case
+# when Hash keys order occationally can be same as in test.
+SKIP: {
+skip('Hash keys order dependency', 4);
+
 pir_output_is( <<'CODE', <<'OUT', 'dump PAST::Val node in visual format' );
 .sub _main :main
     load_bytecode 'PCT.pbc'
@@ -133,6 +138,8 @@
 }
 OUT
 
+}
+
 # Local Variables:
 #   mode: cperl
 #   cperl-indent-level: 4

Modified: trunk/t/compilers/pct/post.t
==============================================================================
--- trunk/t/compilers/pct/post.t	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/t/compilers/pct/post.t	Wed Jul 15 13:15:25 2009	(r40100)
@@ -47,6 +47,11 @@
 
 }
 
+SKIP: {
+    skip('Hash keys order dependency', 1);
+
+# Next tests marked as "skip" instead of "todo" to prevent false-positives in case
+# when Hash keys order occationally can be same as in test.
 pir_output_is( <<'CODE', <<'OUT', 'dump POST::Op node in visual format' );
 .sub _main
     load_bytecode 'PCT.pbc'
@@ -67,6 +72,8 @@
 }
 OUT
 
+}
+
 pir_output_is( <<'CODE', <<'OUT', 'dump POST::Label node in visual format' );
 .sub _main
     load_bytecode 'PCT.pbc'

Modified: trunk/t/native_pbc/annotations.pbc
==============================================================================
Binary file (source and/or target). No diff available.

Modified: trunk/t/native_pbc/integer_1.pbc
==============================================================================
Binary file (source and/or target). No diff available.

Modified: trunk/t/native_pbc/number_1.pbc
==============================================================================
Binary file (source and/or target). No diff available.

Modified: trunk/t/native_pbc/string_1.pbc
==============================================================================
Binary file (source and/or target). No diff available.

Modified: trunk/t/op/gc.t
==============================================================================
--- trunk/t/op/gc.t	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/t/op/gc.t	Wed Jul 15 13:15:25 2009	(r40100)
@@ -533,17 +533,20 @@
     reg[b] = nil
     reg[c] = nil
 
+    $P1 = new ['ResizablePMCArray']
     it = iter reg
 loop:
     unless it goto done
     $P0 = shift it
-    print $P0
+    $S0 = $P0
+    push $P1, $S0
     goto loop
 done:
+    $P1.'sort'()
+    $S1 = join '', $P1
+    print $S1
     print "\n"
 .end
-# the current hash implementation returns entries in order
-# for a few keys, and if there were no deletes
 CODE
 k1k2k3
 OUTPUT

Modified: trunk/t/pmc/hash.t
==============================================================================
--- trunk/t/pmc/hash.t	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/t/pmc/hash.t	Wed Jul 15 13:15:25 2009	(r40100)
@@ -21,8 +21,9 @@
 .sub main :main
     .include 'test_more.pir'
     .include 'except_types.pasm'
+    .include 'datatypes.pasm'
 
-    plan(146)
+    plan(155)
 
     initial_hash_tests()
     more_than_one_hash()
@@ -67,6 +68,8 @@
     unicode_keys_register_rt_39249()
     unicode_keys_literal_rt_39249()
 
+    integer_keys()
+    value_types_convertion()
 .end
 
 .sub initial_hash_tests
@@ -1204,22 +1207,27 @@
   iter = new ['Iterator'], thash
   iter = .ITERATE_FROM_START
 
-  .local string key
+  .local pmc keys, key
+  keys = new ['ResizablePMCArray']
 
   # go through the hash, print out all the keys: should be a c and e
 preit_loop:
   unless iter goto preit_end
 
   key = shift iter
-  result .= key
+  $S0 = key
+  push keys, $S0
 
   branch preit_loop
 preit_end:
 
+  keys.'sort'()
+  result = join '', keys
   is( result, 'ace', 'iterated through keys successfully' )
 
   # get rid of the c element?
   delete thash["c"]
+  keys = new ['ResizablePMCArray']
 
   # what do we have after deletion?
   result = ""
@@ -1233,11 +1241,15 @@
   unless iter goto postit_end
 
   key = shift iter
-  result .= key
+  $S0 = key
+  push keys, $S0
+
 
   branch postit_loop
 postit_end:
 
+  keys.'sort'()
+  result = join '', keys
   is( result, 'ae', 'the c key was no longer iterated over' )
 .end
 
@@ -1262,6 +1274,70 @@
   is( $S1, 'ok', 'literal unicode key lookup via var' )
 .end
 
+# Switch to use integer keys instead of strings.
+.sub integer_keys
+    .include "hash_key_type.pasm"
+    .local pmc hash
+    hash = new ['Hash']
+    hash = .Hash_key_type_int
+
+    hash[0]   = 'foo'
+    hash[42]  = 'bar'
+    $S0       = 'foo'
+    hash[$S0] = 'BAZ'
+
+    $S0       = '42 parrots'
+    hash[$S0] = 'Wins!'
+
+    # 'foo' numifies to '0'. So check it
+    $S0 = hash[0]
+    is($S0, 'BAZ', 'Key was numified')
+
+    # '42 parrots' numifies to '42'. So check it
+    $S0 = hash[42]
+    is($S0, 'Wins!', 'Key was numified again')
+.end
+
+# Check that we can set various value types and they properly converted
+.sub value_types_convertion
+    .local pmc hash
+    hash = new ['Hash']
+
+    # PMC is first value type
+    hash.'set_value_type'(.DATATYPE_PMC)
+    $P0 = new 'Env' # arbitary choice. Just to prevent possible casting.
+    hash['env'] = $P0
+    hash['foo'] = 42
+    hash['bar'] = 21285.06
+    hash['baz'] = 'forty two'
+
+    # Check that original value preserved
+    $P1 = hash['env']
+    $I0 = isa $P1, 'Env'
+    ok($I0, 'Env PMC preserved')
+    $I0 = hash['foo']
+    is($I0, 42, 'Intval preserved')
+    $N0 = hash['bar']
+    is($N0, 21285.06, 'Number preserved')
+    $S0 = hash['baz']
+    is($S0, 'forty two', 'String preserved')
+
+    # Clear the Hash and set INTVAL as stored values.
+    hash.'set_value_type'(.DATATYPE_INTVAL)
+    hash['foo'] = 42            # Use as-is
+    hash['bar'] = 21285.06      # Truncate to int
+    hash['baz'] = 'forty two'   # Cast to int
+
+    $I0 = hash['foo']
+    is($I0, 42, 'Intval preserved with datatype int')
+    $I0 = hash['bar']
+    is($I0, 21285, 'Floatval trunkated to int')
+    $I0 = hash['baz']
+    is($I0, 0, 'String casted to int')
+
+    # TODO Add tests for String.
+.end
+
 # Local Variables:
 #   mode: pir
 #   fill-column: 100

Added: trunk/t/pmc/hashiterator.t
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/t/pmc/hashiterator.t	Wed Jul 15 13:15:25 2009	(r40100)
@@ -0,0 +1,74 @@
+#! parrot
+# Copyright (C) 2001-2008, Parrot Foundation.
+# $Id$
+
+=head1 NAME
+
+t/pmc/hash.t - Test the Hash PMC
+
+=head1 SYNOPSIS
+
+    % prove t/pmc/hash.t
+
+=head1 DESCRIPTION
+
+Tests the C<Hash> PMC. Checks key access with various types of
+normal and potentially hazardous keys. Does a bit of stress testing as
+well.
+
+=cut
+
+.sub main :main
+    .include 'test_more.pir'
+    .include 'except_types.pasm'
+
+    plan(6)
+
+    iter_over_empty_hash()
+    iter_over_single_element()
+    iter_over_single_element_with_checks()
+
+.end
+
+.sub 'iter_over_empty_hash'
+    .local pmc hash, it
+    hash = new 'Hash'
+    it   = new 'HashIterator', hash
+    $I0  = isfalse it
+    ok($I0, "Iterator for empty Hash is empty")
+.end
+
+.sub 'iter_over_single_element'
+    .local pmc hash, it
+    hash = new 'Hash'
+    hash["foo"] = "bar"
+    it   = new 'HashIterator', hash
+    $I0  = istrue it
+    ok($I0, "Iterator for non empty Hash is not empty")
+    $P0  = shift it
+    $I0  = isfalse it
+    ok($I0, "And contains one element")
+.end
+
+.sub 'iter_over_single_element_with_checks'
+    .local pmc hash, it
+    hash = new 'Hash'
+    hash["foo"] = "bar"
+
+    it   = new 'HashIterator', hash
+    $P0  = shift it
+    $I0  = isa $P0, 'HashIteratorKey'
+    ok($I0, "HashIteratorKey fetched successfully")
+
+    $S0  = $P0 # Get key
+    is($S0, "foo", "Key fetched successfully")
+    $S1  = hash[$P0]
+    is($S1, "bar", "Value fetched successfully")
+
+.end
+
+# Local Variables:
+#   mode: pir
+#   fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:

Modified: trunk/t/pmc/iterator.t
==============================================================================
--- trunk/t/pmc/iterator.t	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/t/pmc/iterator.t	Wed Jul 15 13:15:25 2009	(r40100)
@@ -507,7 +507,7 @@
 
     print 'Iterator shift_float: '
     .local num felem_2
-    shift felem_2, iter_2
+    pop felem_2, iter_2
     print felem_2
     print "\n"
 

Modified: trunk/t/pmc/namespace.t
==============================================================================
--- trunk/t/pmc/namespace.t	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/t/pmc/namespace.t	Wed Jul 15 13:15:25 2009	(r40100)
@@ -1699,21 +1699,24 @@
      $P1 = 0
      set_root_global [ "DUMMY"; "X"; "Y" ], "T0", $P0
 
-     .local pmc dummy_x_y_ns, iter
+     .local pmc dummy_x_y_ns, iter, res
      dummy_x_y_ns = get_root_namespace [ "DUMMY"; "X"; "Y" ]
      iter = new ['Iterator'], dummy_x_y_ns
+     res  = new ['ResizablePMCArray']
 loop:
      unless iter goto loop_end
      $S0 = shift iter
-     print $S0
-     print "\n"
+     push res, $S0
      goto loop
 loop_end:
 
+     res.'sort'()
+     $S0 = join ' ', res
+     say $S0
+
 .end
 CODE
-Explosion
-T0
+Explosion T0
 OUT
 
 pir_error_output_like( <<'CODE', <<OUT, "NameSpace with no class, RT #55620" );
@@ -1730,6 +1733,9 @@
 .namespace [ 'bar' ]
 
 .sub 'main' :main
+    .local pmc res
+    res = new ['ResizablePMCArray']
+
     $P0 = get_namespace
     say $P0
     $I0 = elements $P0
@@ -1738,9 +1744,13 @@
   L1:
     unless $P1 goto L2
     $P2 = shift $P1
-    say $P2
+    $S0 = $P2
+    push res, $S0
     goto L1
   L2:
+    res.'sort'()
+    $S0 = join "\n", res
+    say $S0
     say 'OK'
 .end
 
@@ -1750,8 +1760,8 @@
 CODE
 bar
 2
-main
 foo
+main
 OK
 OUT
 

Modified: trunk/t/pmc/orderedhash.t
==============================================================================
--- trunk/t/pmc/orderedhash.t	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/t/pmc/orderedhash.t	Wed Jul 15 13:15:25 2009	(r40100)
@@ -94,7 +94,8 @@
 iter_loop:
     unless P2, end_iter
     shift P3, P2
-    print P3
+    set P4, P0[P3]
+    print P4
     branch iter_loop
 end_iter:
 
@@ -102,7 +103,8 @@
 iter_loop2:
     unless P2, end_iter2
     pop P3, P2
-    print P3
+    set P4, P0[P3]
+    print P4
     branch iter_loop2
 end_iter2:
     end

Modified: trunk/t/pmc/packfileannotations.t
==============================================================================
--- trunk/t/pmc/packfileannotations.t	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/t/pmc/packfileannotations.t	Wed Jul 15 13:15:25 2009	(r40100)
@@ -148,3 +148,10 @@
     # BAIL_OUT
     skip(9, "PackfileAnnotations tests failed")
 .end
+
+# Local Variables:
+#   mode: cperl
+#   cperl-indent-level: 4
+#   fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4:

Modified: trunk/t/pmc/packfilerawsegment.t
==============================================================================
--- trunk/t/pmc/packfilerawsegment.t	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/t/pmc/packfilerawsegment.t	Wed Jul 15 13:15:25 2009	(r40100)
@@ -34,9 +34,7 @@
     .local pmc pf, pfdir, pfseg
     pf    = _pbc()
     pfdir = pf.'get_directory'()
-    $P0   = iter pfdir
-    $S0   = shift $P0
-    pfseg = pfdir[$S0]
+    pfseg = '_find_segment_by_prefix'(pf, 'BYTECODE')
     $I0   = elements pfseg
     ok($I0, 'PackfileRawSegment contains some data')
 .end
@@ -46,9 +44,7 @@
     .local pmc pf, pfdir, pfseg
     pf    = _pbc()
     pfdir = pf.'get_directory'()
-    $P0   = iter pfdir
-    $S0   = shift $P0
-    pfseg = pfdir[$S0]
+    pfseg = '_find_segment_by_prefix'(pf, 'BYTECODE')
 
     $I0   = 0
     $I1   = pfseg[0]

Modified: trunk/t/pmc/pmc.t
==============================================================================
--- trunk/t/pmc/pmc.t	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/t/pmc/pmc.t	Wed Jul 15 13:15:25 2009	(r40100)
@@ -49,7 +49,7 @@
 my $checkTypes;
 my %types_we_cant_test
     = map { $_ => 1; } (    # These require initializers.
-    qw(default Null Iterator Enumerate ParrotObject ParrotThread BigInt LexInfo LexPad Object Handle),
+    qw(default Null Iterator ArrayIterator HashIterator StringIterator OrderedHashIterator Enumerate ParrotObject ParrotThread BigInt LexInfo LexPad Object Handle),
 
     # Instances of these appear to have other types.
     qw(PMCProxy Class) );

Modified: trunk/t/pmc/testlib/packfile_common.pir
==============================================================================
--- trunk/t/pmc/testlib/packfile_common.pir	Wed Jul 15 12:18:34 2009	(r40099)
+++ trunk/t/pmc/testlib/packfile_common.pir	Wed Jul 15 13:15:25 2009	(r40100)
@@ -45,6 +45,24 @@
     .return ()
 .end
 
+.sub '_find_segment_by_prefix'
+    .param pmc pf
+    .param string prefix
+    .local pmc pfdir, it
+
+    pfdir = pf.'get_directory'()
+    it = iter pfdir
+  loop:
+    unless it goto done
+    $S0 = shift it
+    $I0 = index $S0, prefix
+    if $I0 != 0 goto loop
+    $P0 = pfdir[$S0]
+    .return ($P0)
+  done:
+    .return ()
+.end
+
 .sub '_get_fixup_table'
     .param pmc pf
 


More information about the parrot-commits mailing list