From 6e879dbe87cf62c77c981f25ca77cec2c954c9d7 Mon Sep 17 00:00:00 2001 From: Doug Currie Date: Sat, 26 Dec 2015 22:19:05 -0500 Subject: [PATCH 1/3] Better error reporting for uninitialized global. --- extlib/benz/include/picrin/khash.h | 13 +++++++++++++ extlib/benz/include/picrin/reg.h | 1 + extlib/benz/reg.c | 13 +++++++++++++ extlib/benz/vm.c | 4 ++-- 4 files changed, 29 insertions(+), 2 deletions(-) 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; } From 17d731228abfb63a7dde03cd377843a22a52b9dc Mon Sep 17 00:00:00 2001 From: Doug Currie Date: Sun, 27 Dec 2015 10:11:47 -0500 Subject: [PATCH 2/3] Use pic_eq_p to compare pic_values; move reverse lookup out of khash.h --- extlib/benz/include/picrin/khash.h | 13 ------------- extlib/benz/reg.c | 13 ++++++++----- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/extlib/benz/include/picrin/khash.h b/extlib/benz/include/picrin/khash.h index e762ae21..3d8d2ed9 100644 --- a/extlib/benz/include/picrin/khash.h +++ b/extlib/benz/include/picrin/khash.h @@ -72,7 +72,6 @@ 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); @@ -110,17 +109,6 @@ 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; \ @@ -245,7 +233,6 @@ 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/reg.c b/extlib/benz/reg.c index 9d1282d4..a589b8ea 100644 --- a/extlib/benz/reg.c +++ b/extlib/benz/reg.c @@ -35,13 +35,16 @@ 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); + if (h->n_buckets) { + khint_t i = 0; + while ((i < h->n_buckets) && (ac_iseither(h->flags, i) || !pic_eq_p(h->vals[i], val))) { + i += 1; + } + if (i < h->n_buckets) return kh_key(h, i); } - return kh_key(h, it); + pic_errorf(pic, "key not found for an element: ~s", val); + return NULL; } void From b585d89056959152e7851a44c95131193f0030db Mon Sep 17 00:00:00 2001 From: Doug Currie Date: Sun, 27 Dec 2015 21:27:26 -0500 Subject: [PATCH 3/3] Fix for equal? bug #312 --- extlib/benz/bool.c | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/extlib/benz/bool.c b/extlib/benz/bool.c index c26b9950..ad9dbcbe 100644 --- a/extlib/benz/bool.c +++ b/extlib/benz/bool.c @@ -10,8 +10,10 @@ KHASH_DEFINE2(m, void *, int, 0, kh_ptr_hash_func, kh_ptr_hash_equal) static bool internal_equal_p(pic_state *pic, pic_value x, pic_value y, int depth, khash_t(m) *h) { - pic_value local = pic_nil_value(); - int c = 0; + pic_value localx = pic_nil_value(); + pic_value localy = pic_nil_value(); + int cx = 0; + int cy = 0; if (depth > 10) { if (depth > 200) { @@ -68,17 +70,30 @@ internal_equal_p(pic_state *pic, pic_value x, pic_value y, int depth, khash_t(m) return false; /* Floyd's cycle-finding algorithm */ - if (pic_nil_p(local)) { - local = x; + if (pic_nil_p(localx)) { + localx = x; } x = pic_cdr(pic, x); + cx++; + if (pic_nil_p(localy)) { + localy = y; + } y = pic_cdr(pic, y); - c++; - if (c == 2) { - c = 0; - local = pic_cdr(pic, local); - if (pic_eq_p(local, x)) { - return true; + cy++; + if (cx == 2) { + cx = 0; + localx = pic_cdr(pic, localx); + if (pic_eq_p(localx, x)) { + if (cy < 0 ) return true; /* both lists circular */ + cx = INT_MIN; /* found a cycle on x */ + } + } + if (cy == 2) { + cy = 0; + localy = pic_cdr(pic, localy); + if (pic_eq_p(localy, y)) { + if (cx < 0 ) return true; /* both lists circular */ + cy = INT_MIN; /* found a cycle on y */ } } goto LOOP; /* tail-call optimization */