summaryrefslogtreecommitdiffhomepage
path: root/src/kernel.c
diff options
context:
space:
mode:
authorh2so5 <[email protected]>2013-10-27 03:18:22 +0900
committerh2so5 <[email protected]>2013-10-27 04:04:06 +0900
commit88758e36308492c860808ed9f7fb66e74f89e589 (patch)
tree90fbe608749027aacabea16491cb0ea7a99b86f9 /src/kernel.c
parent3a668241bead302d3fa3db8a6b1915ec192ea274 (diff)
downloadmruby-88758e36308492c860808ed9f7fb66e74f89e589.tar.gz
mruby-88758e36308492c860808ed9f7fb66e74f89e589.zip
Uniquify the results of Object#methods
Diffstat (limited to 'src/kernel.c')
-rw-r--r--src/kernel.c36
1 files changed, 29 insertions, 7 deletions
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;i<kh_end(h);i++) {
if (kh_exist(h, i)) {
- mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(h,i)));
+ kh_put(st, set, kh_key(h,i));
}
}
}
@@ -738,13 +741,14 @@ method_entry_loop(mrb_state *mrb, struct RClass* klass, mrb_value ary)
mrb_value
class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* klass, int obj)
{
+ khint_t i;
mrb_value ary;
struct RClass* oldklass;
+ khash_t(st)* set = kh_init(st, mrb);
- ary = mrb_ary_new(mrb);
oldklass = 0;
while (klass && (klass != oldklass)) {
- method_entry_loop(mrb, klass, ary);
+ method_entry_loop(mrb, klass, set);
if ((klass->tt == 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;i<kh_end(set);i++) {
+ if (kh_exist(set, i)) {
+ mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(set,i)));
+ }
+ }
+ kh_destroy(st, set);
+
return ary;
}
mrb_value
mrb_obj_singleton_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj)
{
+ khint_t i;
mrb_value ary;
struct RClass* klass;
+ khash_t(st)* set = kh_init(st, mrb);
klass = mrb_class(mrb, obj);
- ary = mrb_ary_new(mrb);
+
if (klass && (klass->tt == 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<kh_end(set);i++) {
+ if (kh_exist(set, i)) {
+ mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(set,i)));
+ }
+ }
+ kh_destroy(st, set);
+
return ary;
}