The implementation of the methods key_* in keys.c imposed to the PMCs to be of type Key. I don't' see the interest for atomic keys that could be mere PMCs.
This concretely means that one can write the following and save a intermediate register: P3 = PO[P1] instead of: P3 = new P2, .Key P2 = P1 P3 = PO[P1] or instead of: S0 = P1 P3 = P0[S0] # if the key is used as a string Patch includes code and test. Affects src/key.c and t/pmc/key.t. -- stef --- src/key.c.old 2004-01-27 01:01:16.000000000 +0100 +++ src/key.c 2004-02-09 18:11:47.000000000 +0100 @@ -283,21 +283,27 @@ key_integer(struct Parrot_Interp *interpreter, PMC *key) { PMC *reg; + int flags = PObj_get_FLAGS(key); + int key_flags = flags & KEY_type_FLAGS; - switch (PObj_get_FLAGS(key) & KEY_type_FLAGS) { - case KEY_integer_FLAG: - return key->cache.int_val; - case KEY_integer_FLAG | KEY_register_FLAG: - return interpreter->int_reg.registers[key->cache.int_val]; - case KEY_pmc_FLAG: - return VTABLE_get_integer(interpreter, - key->cache.pmc_val); - case KEY_pmc_FLAG | KEY_register_FLAG: - reg = interpreter->pmc_reg.registers[key->cache.int_val]; - return VTABLE_get_integer(interpreter, reg); - default: - internal_exception(INVALID_OPERATION, "Key not an integer!\n"); - return 0; + if(key_flags) { + switch (key_flags) { + case KEY_integer_FLAG: + return key->cache.int_val; + case KEY_integer_FLAG | KEY_register_FLAG: + return interpreter->int_reg.registers[key->cache.int_val]; + case KEY_pmc_FLAG: + return VTABLE_get_integer(interpreter, + key->cache.pmc_val); + case KEY_pmc_FLAG | KEY_register_FLAG: + reg = interpreter->pmc_reg.registers[key->cache.int_val]; + return VTABLE_get_integer(interpreter, reg); + default: + internal_exception(INVALID_OPERATION, "Key not an integer!\n"); + return 0; + } + } else { + return VTABLE_get_integer(interpreter, key); } } @@ -313,22 +319,29 @@ FLOATVAL key_number(struct Parrot_Interp *interpreter, PMC *key) { + PMC *reg; + int flags = PObj_get_FLAGS(key); + int key_flags = flags & KEY_type_FLAGS; - switch (PObj_get_FLAGS(key) & KEY_type_FLAGS) { - case KEY_number_FLAG: - return key->cache.num_val; - case KEY_number_FLAG | KEY_register_FLAG: - return interpreter->num_reg.registers[key->cache.int_val]; - case KEY_pmc_FLAG: - return VTABLE_get_number(interpreter, - key->cache.pmc_val); - case KEY_pmc_FLAG | KEY_register_FLAG: - reg = interpreter->pmc_reg.registers[key->cache.int_val]; - return VTABLE_get_number(interpreter, reg); - default: - internal_exception(INVALID_OPERATION, "Key not a number!\n"); - return 0; + if (key_flags) { + switch (key_flags) { + case KEY_number_FLAG: + return key->cache.num_val; + case KEY_number_FLAG | KEY_register_FLAG: + return interpreter->num_reg.registers[key->cache.int_val]; + case KEY_pmc_FLAG: + return VTABLE_get_number(interpreter, + key->cache.pmc_val); + case KEY_pmc_FLAG | KEY_register_FLAG: + reg = interpreter->pmc_reg.registers[key->cache.int_val]; + return VTABLE_get_number(interpreter, reg); + default: + internal_exception(INVALID_OPERATION, "Key not a number!\n"); + return 0; + } + } else { + return VTABLE_get_number(interpreter, key); } } @@ -345,21 +358,29 @@ key_string(struct Parrot_Interp *interpreter, PMC *key) { PMC *reg; + int flags = PObj_get_FLAGS(key); + int key_flags = flags & KEY_type_FLAGS; - switch (PObj_get_FLAGS(key) & KEY_type_FLAGS) { - case KEY_string_FLAG: - return key->cache.string_val; - case KEY_string_FLAG | KEY_register_FLAG: - return interpreter->string_reg.registers[key->cache.int_val]; - case KEY_pmc_FLAG: - return VTABLE_get_string(interpreter, - key->cache.pmc_val); - case KEY_pmc_FLAG | KEY_register_FLAG: - reg = interpreter->pmc_reg.registers[key->cache.int_val]; - return VTABLE_get_string(interpreter, reg); - default: - internal_exception(INVALID_OPERATION, "Key not a string!\n"); - return 0; + if (key_flags) { + switch (PObj_get_FLAGS(key) & KEY_type_FLAGS) { + case KEY_integer_FLAG: + string_from_int(interpreter, key->cache.int_val); + case KEY_string_FLAG: + return key->cache.string_val; + case KEY_string_FLAG | KEY_register_FLAG: + return interpreter->string_reg.registers[key->cache.int_val]; + case KEY_pmc_FLAG: + return VTABLE_get_string(interpreter, + key->cache.pmc_val); + case KEY_pmc_FLAG | KEY_register_FLAG: + reg = interpreter->pmc_reg.registers[key->cache.int_val]; + return VTABLE_get_string(interpreter, reg); + default: + internal_exception(INVALID_OPERATION, "Key not a string!\n"); + return 0; + } + } else { + return VTABLE_get_string(interpreter, key); } } @@ -403,7 +424,10 @@ PMC * key_next(struct Parrot_Interp *interpreter, PMC *key) { - return PMC_data(key); + if (PObj_get_FLAGS(key) & KEY_type_FLAGS) + return PMC_data(key); + return (PMC*) NULL; + } /* --- t/pmc/key.t.old 2004-02-09 19:41:22.000000000 +0100 +++ t/pmc/key.t 2004-02-09 20:06:41.000000000 +0100 @@ -1,6 +1,6 @@ #! perl -w -use Parrot::Test tests => 2; +use Parrot::Test tests => 3; use Test::More; output_is(<<'CODE', <<'OUT', 'traverse key chain'); @@ -64,3 +64,58 @@ ok 1 123 OUT + +my $qr = "0\n0.00*\n\n\n" x 3; +$qr = qr|$qr|; + +output_like(<<'CODE', $qr, 'mere PMCs used as keys'); + new P0, .Array + set P0, 1 + + new P1, .PerlInt + set P1, 0 + set I2, P0[P1] + print I2 + print "\n" + set N2, P0[P1] + print N2 + print "\n" + set S2, P0[P1] + print S2 + print "\n" + set P2, P0[P1] + print P2 + print "\n" + + new P1, .PerlString + set P1, "0" + set I2, P0[P1] + print I2 + print "\n" + set N2, P0[P1] + print N2 + print "\n" + set S2, P0[P1] + print S2 + print "\n" + set P2, P0[P1] + print P2 + print "\n" + + new P1, .PerlNum + set P1, 0.0 + set I2, P0[P1] + print I2 + print "\n" + set N2, P0[P1] + print N2 + print "\n" + set S2, P0[P1] + print S2 + print "\n" + set P2, P0[P1] + print P2 + print "\n" + end +CODE +