diff --git a/extlib/benz/include/picrin/khash.h b/extlib/benz/include/picrin/khash.h index 3d8d2ed9..e762ae21 100644 --- a/extlib/benz/include/picrin/khash.h +++ b/extlib/benz/include/picrin/khash.h @@ -72,6 +72,7 @@ PIC_INLINE khint_t ac_Wang_hash(khint_t key) void kh_destroy_##name(pic_state *, kh_##name##_t *h); \ void kh_clear_##name(kh_##name##_t *h); \ khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); \ + khint_t kh_reverse_get_##name(const kh_##name##_t *h, khval_t val); \ void kh_resize_##name(pic_state *, kh_##name##_t *h, khint_t new_n_buckets); \ khint_t kh_put_##name(pic_state *, kh_##name##_t *h, khkey_t key, int *ret); \ void kh_del_##name(kh_##name##_t *h, khint_t x); @@ -109,6 +110,17 @@ PIC_INLINE khint_t ac_Wang_hash(khint_t key) return ac_iseither(h->flags, i)? h->n_buckets : i; \ } else return 0; \ } \ + khint_t kh_reverse_get_##name(const kh_##name##_t *h, khval_t val) \ + { \ + if (h->n_buckets) { \ + khint_t i = 0; \ + while (ac_iseither(h->flags, i) || (h->vals[i] != val)) { \ + i += 1; \ + if (i == h->n_buckets) return -1; \ + } \ + return i; \ + } else return -1; \ + } \ void kh_resize_##name(pic_state *pic, kh_##name##_t *h, khint_t new_n_buckets) \ { /* This function uses 0.25*n_buckets bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. */ \ int *new_flags = 0; \ @@ -233,6 +245,7 @@ PIC_INLINE khint_t ac_Wang_hash(khint_t key) #define kh_resize(name, h, s) kh_resize_##name(pic, h, s) #define kh_put(name, h, k, r) kh_put_##name(pic, h, k, r) #define kh_get(name, h, k) kh_get_##name(h, k) +#define kh_reverse_get(name, h, v) kh_reverse_get_##name(h, v) #define kh_del(name, h, k) kh_del_##name(h, k) #define kh_exist(h, x) (!ac_iseither((h)->flags, (x))) diff --git a/extlib/benz/include/picrin/reg.h b/extlib/benz/include/picrin/reg.h index c64c548f..73ebf069 100644 --- a/extlib/benz/include/picrin/reg.h +++ b/extlib/benz/include/picrin/reg.h @@ -26,6 +26,7 @@ pic_value pic_reg_ref(pic_state *, struct pic_reg *, void *); void pic_reg_set(pic_state *, struct pic_reg *, void *, pic_value); void pic_reg_del(pic_state *, struct pic_reg *, void *); bool pic_reg_has(pic_state *, struct pic_reg *, void *); +void *pic_reg_rev_ref(pic_state *, struct pic_reg *, pic_value); #if defined(__cplusplus) } diff --git a/extlib/benz/reg.c b/extlib/benz/reg.c index 655f3b08..9d1282d4 100644 --- a/extlib/benz/reg.c +++ b/extlib/benz/reg.c @@ -31,6 +31,19 @@ pic_reg_ref(pic_state *pic, struct pic_reg *reg, void *key) return kh_val(h, it); } +void * +pic_reg_rev_ref(pic_state *pic, struct pic_reg *reg, pic_value val) +{ + khash_t(reg) *h = ®->hash; + khiter_t it; + + it = kh_reverse_get(reg, h, val); + if (it == -1) { + pic_errorf(pic, "key not found for an element: ~s", val); + } + return kh_key(h, it); +} + void pic_reg_set(pic_state PIC_UNUSED(*pic), struct pic_reg *reg, void *key, pic_value val) { diff --git a/extlib/benz/vm.c b/extlib/benz/vm.c index 3e383bef..3e73578d 100644 --- a/extlib/benz/vm.c +++ b/extlib/benz/vm.c @@ -198,9 +198,9 @@ vm_gref(pic_state *pic, struct pic_box *slot, pic_sym *uid) { if (pic_invalid_p(slot->value)) { if (uid == NULL) { - uid = pic_intern(pic, "unknown"); /* FIXME */ + uid = pic_reg_rev_ref(pic, pic->globals, pic_obj_value(slot)); } - pic_errorf(pic, "uninitialized global variable: ~a", pic_obj_value(uid)); + pic_errorf(pic, "uninitialized global variable: %s", pic_symbol_name(pic, uid)); } return slot->value; }