[svn:parrot] r39706 - branches/tt761_keys_revamp/src/pmc
bacek at svn.parrot.org
bacek at svn.parrot.org
Mon Jun 22 11:20:20 UTC 2009
Author: bacek
Date: Mon Jun 22 11:20:18 2009
New Revision: 39706
URL: https://trac.parrot.org/parrot/changeset/39706
Log:
[pmc] Partially inplement ad-hoc polymorphism for Hash keys and values.
Modified:
branches/tt761_keys_revamp/src/pmc/hash.pmc
Modified: branches/tt761_keys_revamp/src/pmc/hash.pmc
==============================================================================
--- branches/tt761_keys_revamp/src/pmc/hash.pmc Mon Jun 22 07:22:25 2009 (r39705)
+++ branches/tt761_keys_revamp/src/pmc/hash.pmc Mon Jun 22 11:20:18 2009 (r39706)
@@ -135,6 +135,250 @@
return keystr;
}
+/*
+
+Poor-man polymorphic functions to convert something to hash key-type.
+
+*/
+
+PARROT_PURE_FUNCTION
+static void*
+hash_key_from_int(PARROT_INTERP, const Hash * const hash, INTVAL 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:
+ Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED,
+ "Hash: unsupported key_type");
+ }
+ return ret;
+}
+
+PARROT_PURE_FUNCTION
+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 *)Parrot_str_new_COW(interp, key);
+ break;
+ default:
+ Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED,
+ "Hash: unsupported key_type");
+ }
+ return ret;
+}
+
+PARROT_PURE_FUNCTION
+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:
+ ret = (void *)Parrot_str_new_COW(interp, VTABLE_get_string(interp, key));
+ 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 = pmc_new(interp, enum_class_Integer);
+ 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;
+}
+
+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 = pmc_new(interp, enum_class_String);
+ 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;
+}
+
+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;
+}
+
+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 = pmc_new(interp, enum_class_Float);
+ 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;
+}
+
+static STRING*
+hash_value_to_string(PARROT_INTERP, const Hash * const hash, void *value)
+{
+ 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;
+}
+
+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 = pmc_new(interp, enum_class_Integer);
+ VTABLE_set_integer_native(interp, ret, (INTVAL)value);
+ break;
+ case enum_type_STRING:
+ ret = pmc_new(interp, enum_class_String);
+ 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;
+}
+
+static void*
+hash_value_to_number(PARROT_INTERP, const Hash * const hash, FLOATVAL value)
+{
+ Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED,
+ "Hash: unimplemented");
+}
+
+
/* Needs ext struct for the next_for_GC pointer
* We would get recursive marking of a deeply nested HoHoH...
*/
@@ -241,7 +485,12 @@
if (type == Hash_key_type_STRING)
new_hash = parrot_new_hash(INTERP);
else if (type == Hash_key_type_int)
- new_hash = parrot_new_intval_hash(INTERP);
+ /* 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
@@ -299,28 +548,25 @@
*/
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 *)SELF.get_pointer(), key);
+ parrot_hash_get_bucket(INTERP, hash, hash_key_from_string(INTERP, hash, key));
if (!b)
return 0;
- return VTABLE_get_integer(INTERP, (PMC*) b->value);
+ return hash_value_to_int(INTERP, hash, b->value);
}
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);
+ 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 (INTVAL)b->value;
+ return hash_value_to_int(INTERP, hash, b->value);
}
/*
@@ -502,18 +748,25 @@
*/
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 *)SELF.get_pointer(), key);
+ 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 VTABLE_get_string(INTERP, (PMC*) b->value);
+ return hash_value_to_string(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);
+ 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 hash_value_to_string(INTERP, hash, b->value);
}
/*
@@ -607,28 +860,6 @@
return SELF.get_pmc_keyed_str(s);
}
-/*
-
-=item C<PMC *get_iter()>
-
-Return a new iterator for the slice PMC C<key>
-
-=item C<PMC *get_pmc_keyed(PMC *key)>
-
-Returns the PMC value for the element at C<*key>.
-
-=cut
-
-*/
-
- VTABLE PMC *get_iter() {
- return pmc_new_init(INTERP, enum_class_HashIterator, SELF);
- }
-
- VTABLE PMC *slice(PMC *key) {
- return PMCNULL;
- }
-
VTABLE PMC *get_pmc_keyed(PMC *key) {
const Hash * const hash = (Hash *)SELF.get_pointer();
STRING *keystr;
@@ -656,6 +887,28 @@
/*
+=item C<PMC *get_iter()>
+
+Return a new iterator for the slice PMC C<key>
+
+=item C<PMC *get_pmc_keyed(PMC *key)>
+
+Returns the PMC value for the element at C<*key>.
+
+=cut
+
+*/
+
+ VTABLE PMC *get_iter() {
+ return pmc_new_init(INTERP, enum_class_HashIterator, SELF);
+ }
+
+ VTABLE PMC *slice(PMC *key) {
+ return PMCNULL;
+ }
+
+/*
+
=item C<INTVAL is_same(const PMC *other)>
Returns whether the hash is the same as C<*other>.
@@ -707,14 +960,7 @@
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);
- }
- else {
- SUPER(key, value);
- }
+ parrot_hash_put(INTERP, hash, hash_key_from_int(INTERP, hash, key), (void *)value);
}
/*
@@ -793,6 +1039,7 @@
*/
VTABLE void set_string_keyed(PMC *key, STRING *value) {
+ Hash *hash = (Hash *)SELF.get_pointer();
STRING *keystr;
PMC *nextkey;
PMC *box;
@@ -804,9 +1051,9 @@
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);
+ parrot_hash_put(INTERP, hash,
+ hash_key_from_pmc(INTERP, hash, key),
+ hash_value_from_string(INTERP, hash, value));
return;
}
@@ -828,10 +1075,17 @@
*/
VTABLE void set_string_keyed_str(STRING *key, STRING *value) {
- PMC * const val = get_string_pmc(INTERP, SELF->vtable->base_type);
+ 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));
+ }
- VTABLE_set_string_native(INTERP, val, 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));
}
/*
More information about the parrot-commits
mailing list