From 88758e36308492c860808ed9f7fb66e74f89e589 Mon Sep 17 00:00:00 2001 From: h2so5 Date: Sun, 27 Oct 2013 03:18:22 +0900 Subject: Uniquify the results of Object#methods --- include/mruby/khash.h | 15 ++++++++------- src/kernel.c | 36 +++++++++++++++++++++++++++++------- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/include/mruby/khash.h b/include/mruby/khash.h index fb11586d2..cadb3d074 100644 --- a/include/mruby/khash.h +++ b/include/mruby/khash.h @@ -50,7 +50,7 @@ static const uint8_t __m_either[8] = {0x03, 0x0c, 0x30, 0xc0}; name: hash name khkey_t: key data type khval_t: value data type - kh_is_map: (not implemented / not used in RiteVM) + kh_is_map: (0: hash set / 1: hash map) */ #define KHASH_DECLARE(name, khkey_t, khval_t, kh_is_map) \ typedef struct kh_##name { \ @@ -89,7 +89,7 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len) name: hash name khkey_t: key data type khval_t: value data type - kh_is_map: (not implemented / not used in RiteVM) + kh_is_map: (0: hash set / 1: hash map) __hash_func: hash function __hash_equal: hash comparation function */ @@ -97,12 +97,13 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len) void kh_alloc_##name(kh_##name##_t *h) \ { \ khint_t sz = h->n_buckets; \ - uint8_t *p = mrb_malloc(h->mrb, sizeof(uint8_t)*sz/4+(sizeof(khkey_t)+sizeof(khval_t))*sz); \ + int len = sizeof(khkey_t) + (kh_is_map ? sizeof(khval_t) : 0); \ + uint8_t *p = mrb_malloc(h->mrb, sizeof(uint8_t)*sz/4+len*sz); \ h->size = h->n_occupied = 0; \ h->upper_bound = UPPER_BOUND(sz); \ h->keys = (khkey_t *)p; \ - h->vals = (khval_t *)(p+sizeof(khkey_t)*sz); \ - h->ed_flags = (p+sizeof(khkey_t)*sz+sizeof(khval_t)*sz); \ + h->vals = kh_is_map ? (khval_t *)(p+sizeof(khkey_t)*sz) : NULL; \ + h->ed_flags = p+len*sz; \ kh_fill_flags(h->ed_flags, 0xaa, sz/4); \ h->mask = sz-1; \ h->inc = sz/2-1; \ @@ -162,7 +163,7 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len) for (i=0 ; imrb, old_keys); \ @@ -207,7 +208,7 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len) for (k = kh_begin(h); k != kh_end(h); k++) { \ if (kh_exist(h, k)) { \ k2 = kh_put_##name(h2, kh_key(h, k)); \ - kh_value(h2, k2) = kh_value(h, k); \ + if(kh_is_map) kh_value(h2, k2) = kh_value(h, k); \ } \ } \ return h2; \ diff --git a/src/kernel.c b/src/kernel.c index bd58078fe..05ad37fa7 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -721,8 +721,11 @@ mrb_obj_is_kind_of_m(mrb_state *mrb, mrb_value self) return mrb_bool_value(kind_of_p); } +KHASH_DECLARE(st, mrb_sym, char, 0) +KHASH_DEFINE(st, mrb_sym, char, 0, kh_int_hash_func, kh_int_hash_equal) + static void -method_entry_loop(mrb_state *mrb, struct RClass* klass, mrb_value ary) +method_entry_loop(mrb_state *mrb, struct RClass* klass, khash_t(st)* set) { khint_t i; @@ -730,7 +733,7 @@ method_entry_loop(mrb_state *mrb, struct RClass* klass, mrb_value ary) if (!h) return; for (i=0;itt == MRB_TT_ICLASS) || (klass->tt == MRB_TT_SCLASS)) { } @@ -755,28 +759,46 @@ class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* klass, klass = klass->super; } + ary = mrb_ary_new(mrb); + for (i=0;itt == MRB_TT_SCLASS)) { - method_entry_loop(mrb, klass, ary); + method_entry_loop(mrb, klass, set); klass = klass->super; } if (recur) { while (klass && ((klass->tt == MRB_TT_SCLASS) || (klass->tt == MRB_TT_ICLASS))) { - method_entry_loop(mrb, klass, ary); + method_entry_loop(mrb, klass, set); klass = klass->super; } } + ary = mrb_ary_new(mrb); + for (i=0;i