diff --git a/dict.c b/dict.c index a4a1e3d7..6f8b04d8 100644 --- a/dict.c +++ b/dict.c @@ -7,35 +7,96 @@ #include "picrin/cont.h" #include "picrin/pair.h" +static int +xh_value_hash(const void *key, void *data) +{ + union { double f; int i; } u; + pic_value val = *(pic_value *)key; + int hash; + + UNUSED(data); + + switch (pic_vtype(val)) { + default: + hash = 0; + break; + case PIC_VTYPE_SYMBOL: + hash = pic_sym(val); + break; + case PIC_VTYPE_FLOAT: + u.f = pic_float(val); + hash = u.i; + break; + case PIC_VTYPE_INT: + hash = pic_int(val); + break; + case PIC_VTYPE_HEAP: + hash = (int)pic_ptr(val); + break; + } + + return hash + pic_vtype(val); +} + +static int +xh_value_equal(const void *key1, const void *key2, void *pic) +{ + return pic_equal_p(pic, *(pic_value *)key1, *(pic_value *)key2); +} + +static void +xh_init_value(pic_state *pic, xhash *x) +{ + xh_init_(x, sizeof(pic_value), sizeof(pic_value), xh_value_hash, xh_value_equal, pic); +} + +static inline xh_entry * +xh_get_value(xhash *x, pic_value key) +{ + return xh_get_(x, &key); +} + +static inline xh_entry * +xh_put_value(xhash *x, pic_value key, void *val) +{ + return xh_put_(x, &key, val); +} + +static inline void +xh_del_value(xhash *x, pic_value key) +{ + xh_del_(x, &key); +} + struct pic_dict * pic_make_dict(pic_state *pic) { struct pic_dict *dict; dict = (struct pic_dict *)pic_obj_alloc(pic, sizeof(struct pic_dict), PIC_TT_DICT); - xh_init_int(&dict->hash, sizeof(pic_value)); + xh_init_value(pic, &dict->hash); return dict; } pic_value -pic_dict_ref(pic_state *pic, struct pic_dict *dict, pic_sym key) +pic_dict_ref(pic_state *pic, struct pic_dict *dict, pic_value key) { xh_entry *e; - e = xh_get_int(&dict->hash, key); + e = xh_get_value(&dict->hash, key); if (! e) { - pic_errorf(pic, "element not found for a key: ~s", pic_sym_value(key)); + pic_errorf(pic, "element not found for a key: ~s", key); } return xh_val(e, pic_value); } void -pic_dict_set(pic_state *pic, struct pic_dict *dict, pic_sym key, pic_value val) +pic_dict_set(pic_state *pic, struct pic_dict *dict, pic_value key, pic_value val) { UNUSED(pic); - xh_put_int(&dict->hash, key, &val); + xh_put_value(&dict->hash, key, &val); } size_t @@ -47,21 +108,21 @@ pic_dict_size(pic_state *pic, struct pic_dict *dict) } bool -pic_dict_has(pic_state *pic, struct pic_dict *dict, pic_sym key) +pic_dict_has(pic_state *pic, struct pic_dict *dict, pic_value key) { UNUSED(pic); - return xh_get_int(&dict->hash, key) != NULL; + return xh_get_value(&dict->hash, key) != NULL; } void -pic_dict_del(pic_state *pic, struct pic_dict *dict, pic_sym key) +pic_dict_del(pic_state *pic, struct pic_dict *dict, pic_value key) { - if (xh_get_int(&dict->hash, key) == NULL) { - pic_errorf(pic, "no slot named ~s found in dictionary", pic_sym_value(key)); + if (xh_get_value(&dict->hash, key) == NULL) { + pic_errorf(pic, "no slot named ~s found in dictionary", key); } - xh_del_int(&dict->hash, key); + xh_del_value(&dict->hash, key); } static pic_value @@ -88,8 +149,7 @@ pic_dict_dictionary(pic_state *pic) dict = pic_make_dict(pic); for (i = 0; i < argc; i += 2) { - pic_assert_type(pic, argv[i], sym); - pic_dict_set(pic, dict, pic_sym(argv[i]), argv[i+1]); + pic_dict_set(pic, dict, argv[i], argv[i+1]); } return pic_obj_value(dict); @@ -109,9 +169,9 @@ static pic_value pic_dict_dictionary_ref(pic_state *pic) { struct pic_dict *dict; - pic_sym key; + pic_value key; - pic_get_args(pic, "dm", &dict, &key); + pic_get_args(pic, "do", &dict, &key); if (pic_dict_has(pic, dict, key)) { return pic_values2(pic, pic_dict_ref(pic, dict, key), pic_true_value()); @@ -124,10 +184,9 @@ static pic_value pic_dict_dictionary_set(pic_state *pic) { struct pic_dict *dict; - pic_sym key; - pic_value val; + pic_value key, val; - pic_get_args(pic, "dmo", &dict, &key, &val); + pic_get_args(pic, "doo", &dict, &key, &val); pic_dict_set(pic, dict, key, val); @@ -138,9 +197,9 @@ static pic_value pic_dict_dictionary_del(pic_state *pic) { struct pic_dict *dict; - pic_sym key; + pic_value key; - pic_get_args(pic, "dm", &dict, &key); + pic_get_args(pic, "do", &dict, &key); pic_dict_del(pic, dict, key); @@ -169,7 +228,7 @@ pic_dict_dictionary_map(pic_state *pic) xh_begin(&it, &dict->hash); while (xh_next(&it)) { - item = pic_cons(pic, pic_sym_value(xh_key(it.e, pic_sym)), xh_val(it.e, pic_value)); + item = pic_cons(pic, xh_key(it.e, pic_value), xh_val(it.e, pic_value)); pic_push(pic, pic_apply1(pic, proc, item), list); } @@ -190,7 +249,7 @@ pic_dict_dictionary_for_each(pic_state *pic) while (xh_next(&it)) { int ai = pic_gc_arena_preserve(pic); - item = pic_cons(pic, pic_sym_value(xh_key(it.e, pic_sym)), xh_val(it.e, pic_value)); + item = pic_cons(pic, xh_key(it.e, pic_value), xh_val(it.e, pic_value)); pic_apply1(pic, proc, item); pic_gc_arena_restore(pic, ai); @@ -210,7 +269,7 @@ pic_dict_dictionary_to_alist(pic_state *pic) xh_begin(&it, &dict->hash); while (xh_next(&it)) { - item = pic_cons(pic, pic_sym_value(xh_key(it.e, pic_sym)), xh_val(it.e, pic_value)); + item = pic_cons(pic, xh_key(it.e, pic_value), xh_val(it.e, pic_value)); pic_push(pic, item, alist); } @@ -228,8 +287,7 @@ pic_dict_alist_to_dictionary(pic_state *pic) dict = pic_make_dict(pic); pic_for_each (e, pic_reverse(pic, alist)) { - pic_assert_type(pic, pic_car(pic, e), sym); - pic_dict_set(pic, dict, pic_sym(pic_car(pic, e)), pic_cdr(pic, e)); + pic_dict_set(pic, dict, pic_car(pic, e), pic_cdr(pic, e)); } return pic_obj_value(dict); @@ -247,7 +305,7 @@ pic_dict_dictionary_to_plist(pic_state *pic) xh_begin(&it, &dict->hash); while (xh_next(&it)) { pic_push(pic, xh_val(it.e, pic_value), plist); - pic_push(pic, pic_sym_value(xh_key(it.e, pic_sym)), plist); + pic_push(pic, xh_key(it.e, pic_value), plist); } return pic_reverse(pic, plist); @@ -264,8 +322,7 @@ pic_dict_plist_to_dictionary(pic_state *pic) dict = pic_make_dict(pic); for (e = pic_reverse(pic, plist); ! pic_nil_p(e); e = pic_cddr(pic, e)) { - pic_assert_type(pic, pic_car(pic, e), sym); - pic_dict_set(pic, dict, pic_sym(pic_car(pic, e)), pic_cadr(pic, e)); + pic_dict_set(pic, dict, pic_car(pic, e), pic_cadr(pic, e)); } return pic_obj_value(dict); diff --git a/gc.c b/gc.c index 4150be8d..9e669de4 100644 --- a/gc.c +++ b/gc.c @@ -498,6 +498,7 @@ gc_mark_object(pic_state *pic, struct pic_object *obj) xh_begin(&it, &dict->hash); while (xh_next(&it)) { + gc_mark(pic, xh_key(it.e, pic_value)); gc_mark(pic, xh_val(it.e, pic_value)); } break; diff --git a/include/picrin/dict.h b/include/picrin/dict.h index 8d6077af..36160c24 100644 --- a/include/picrin/dict.h +++ b/include/picrin/dict.h @@ -19,11 +19,11 @@ struct pic_dict { struct pic_dict *pic_make_dict(pic_state *); -pic_value pic_dict_ref(pic_state *, struct pic_dict *, pic_sym); -void pic_dict_set(pic_state *, struct pic_dict *, pic_sym, pic_value); -void pic_dict_del(pic_state *, struct pic_dict *, pic_sym); +pic_value pic_dict_ref(pic_state *, struct pic_dict *, pic_value); +void pic_dict_set(pic_state *, struct pic_dict *, pic_value, pic_value); +void pic_dict_del(pic_state *, struct pic_dict *, pic_value); size_t pic_dict_size(pic_state *, struct pic_dict *); -bool pic_dict_has(pic_state *, struct pic_dict *, pic_sym); +bool pic_dict_has(pic_state *, struct pic_dict *, pic_value); #if defined(__cplusplus) } diff --git a/proc.c b/proc.c index e68965fc..1dee4813 100644 --- a/proc.c +++ b/proc.c @@ -61,13 +61,13 @@ pic_attr(pic_state *pic, struct pic_proc *proc) pic_value pic_attr_ref(pic_state *pic, struct pic_proc *proc, const char *key) { - return pic_dict_ref(pic, pic_attr(pic, proc), pic_intern_cstr(pic, key)); + return pic_dict_ref(pic, pic_attr(pic, proc), pic_sym_value(pic_intern_cstr(pic, key))); } void pic_attr_set(pic_state *pic, struct pic_proc *proc, const char *key, pic_value v) { - pic_dict_set(pic, pic_attr(pic, proc), pic_intern_cstr(pic, key), v); + pic_dict_set(pic, pic_attr(pic, proc), pic_sym_value(pic_intern_cstr(pic, key)), v); } static pic_value diff --git a/write.c b/write.c index d552721f..2a0e7548 100644 --- a/write.c +++ b/write.c @@ -336,7 +336,9 @@ write_core(struct writer_control *p, pic_value obj) xfprintf(file, "#.(dictionary"); xh_begin(&it, &pic_dict_ptr(obj)->hash); while (xh_next(&it)) { - xfprintf(file, " '%s ", pic_symbol_name(pic, xh_key(it.e, pic_sym))); + xfprintf(file, " '"); + write_core(p, xh_key(it.e, pic_value)); + xfprintf(file, " "); write_core(p, xh_val(it.e, pic_value)); } xfprintf(file, ")");