@@ -12,6 +12,7 @@
1212#define MT_PUBLIC MRB_METHOD_PUBLIC_FL
1313#define MT_PRIVATE MRB_METHOD_PRIVATE_FL
1414#define MT_PROTECTED MRB_METHOD_PROTECTED_FL
15+#define MT_NOPRIV (MT_PRIVATE|MT_PROTECTED)
15161617static mrb_value
1718mrb_f_nil(mrb_state *mrb, mrb_value cv)
@@ -128,43 +129,38 @@ mrb_local_variables(mrb_state *mrb, mrb_value self)
128129return mrb_proc_local_variables(mrb, mrb->c->ci[-1].proc);
129130}
130131131-KHASH_DECLARE(st, mrb_sym, char, FALSE)
132-KHASH_DEFINE(st, mrb_sym, char, FALSE, kh_int_hash_func, kh_int_hash_equal)
132+KHASH_DECLARE(st, mrb_sym, char, TRUE)
133+KHASH_DEFINE(st, mrb_sym, char, TRUE, kh_int_hash_func, kh_int_hash_equal)
133134134135struct mt_set {
136+unsigned int visibility;
135137khash_t(st) *set;
136-khash_t(st) *undef;
137138};
138139140+#define vicheck(flags, visi) (((visi)==MT_NOPRIV) ? (((flags)&0x3)!=MT_PRIVATE) : (((flags)&0x3)==(visi)))
141+139142static int
140143method_entry_i(mrb_state *mrb, mrb_sym mid, mrb_method_t m, void *p)
141144{
142145struct mt_set *s = (struct mt_set*)p;
143146144-if (MRB_METHOD_UNDEF_P(m)) {
145-if (s->undef) {
146-kh_put(st, mrb, s->undef, mid);
147- }
148- }
149-else if (s->undef == NULL ||
150-kh_get(st, mrb, s->undef, mid) == kh_end(s->undef)) {
151-kh_put(st, mrb, s->set, mid);
147+if (vicheck(m.flags, s->visibility) && kh_get(st, mrb, s->set, mid) == kh_end(s->set)) {
148+khint_t k = kh_put(st, mrb, s->set, mid);
149+kh_val(s->set, k) = !MRB_METHOD_UNDEF_P(m);
152150 }
153151return 0;
154152}
155153156154static void
157-method_entry_loop(mrb_state *mrb, struct RClass *klass, khash_t(st) *set, khash_t(st) *undef)
155+method_entry_loop(mrb_state *mrb, struct RClass *klass, khash_t(st) *set, unsigned int visibility)
158156{
159-struct mt_set s;
157+struct mt_set s = {visibility, set};
160158161-s.set = set;
162-s.undef = undef;
163159mrb_mt_foreach(mrb, klass, method_entry_i, (void*)&s);
164160}
165161166162static mrb_value
167-mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass *klass)
163+mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass *klass, unsigned int flags)
168164{
169165mrb_value ary;
170166khash_t(st) *set = kh_init(st, mrb);
@@ -173,24 +169,24 @@ mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass *kl
173169if (klass->flags & MRB_FL_CLASS_IS_PREPENDED) {
174170MRB_CLASS_ORIGIN(klass);
175171 }
176-method_entry_loop(mrb, klass, set, NULL);
172+method_entry_loop(mrb, klass, set, flags);
177173 }
178174else {
179-khash_t(st) *undef = kh_init(st, mrb);
180175struct RClass *oldklass = NULL;
181176182177while (klass && (klass != oldklass)) {
183-method_entry_loop(mrb, klass, set, undef);
178+method_entry_loop(mrb, klass, set, flags);
184179oldklass = klass;
185180klass = klass->super;
186181 }
187-kh_destroy(st, mrb, undef);
188182 }
189183190184ary = mrb_ary_new_capa(mrb, kh_size(set));
191185for (khint_t i=0; i<kh_end(set); i++) {
192186if (kh_exist(set, i)) {
193-mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(set, i)));
187+if (kh_val(set, i)) {
188+mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(set, i)));
189+ }
194190 }
195191 }
196192kh_destroy(st, mrb, set);
@@ -199,18 +195,26 @@ mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass *kl
199195}
200196201197static mrb_value
202-mrb_obj_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj, int flag)
198+mrb_obj_methods(mrb_state *mrb, mrb_value obj, unsigned int flags)
203199{
204-return mrb_class_instance_method_list(mrb, recur, mrb_class(mrb, obj));
200+mrb_bool regular = TRUE;
201+mrb_get_args(mrb, "|b", ®ular);
202+203+struct RClass *c = (regular) ? mrb_class(mrb, obj) : mrb_obj_ptr(obj)->c;
204+return mrb_class_instance_method_list(mrb, regular, c, flags);
205205}
206+206207/* 15.3.1.3.31 */
207208/*
208209 * call-seq:
209- * obj.methods -> array
210+ * obj.methods(regular=true) -> array
210211 *
211- * Returns a list of the names of methods publicly accessible in
212- * <i>obj</i>. This will include all the methods accessible in
213- * <i>obj</i>'s ancestors.
212+ * Returns a list of the names of public and protected methods of
213+ * `obj`. This will include all the methods accessible in
214+ * `obj`'s ancestors.
215+ * If the optional parameter is `false`, it
216+ * returns an array of `obj`'s public and protected singleton methods,
217+ * the array will not include methods in modules included in `obj`.
214218 *
215219 * class Klass
216220 * def kMethod()
@@ -225,9 +229,7 @@ mrb_obj_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj, int flag)
225229static mrb_value
226230mrb_obj_methods_m(mrb_state *mrb, mrb_value self)
227231{
228-mrb_bool recur = TRUE;
229-mrb_get_args(mrb, "|b", &recur);
230-return mrb_obj_methods(mrb, recur, self, MT_PUBLIC); /* everything but private */
232+return mrb_obj_methods(mrb, self, MT_NOPRIV);
231233}
232234233235/* 15.3.1.3.36 */
@@ -242,9 +244,7 @@ mrb_obj_methods_m(mrb_state *mrb, mrb_value self)
242244static mrb_value
243245mrb_obj_private_methods(mrb_state *mrb, mrb_value self)
244246{
245-mrb_bool recur = TRUE;
246-mrb_get_args(mrb, "|b", &recur);
247-return mrb_obj_methods(mrb, recur, self, MT_PRIVATE); /* private attribute not define */
247+return mrb_obj_methods(mrb, self, MT_PRIVATE);
248248}
249249250250/* 15.3.1.3.37 */
@@ -259,9 +259,7 @@ mrb_obj_private_methods(mrb_state *mrb, mrb_value self)
259259static mrb_value
260260mrb_obj_protected_methods(mrb_state *mrb, mrb_value self)
261261{
262-mrb_bool recur = TRUE;
263-mrb_get_args(mrb, "|b", &recur);
264-return mrb_obj_methods(mrb, recur, self, MT_PROTECTED); /* protected attribute not define */
262+return mrb_obj_methods(mrb, self, MT_PROTECTED);
265263}
266264267265/* 15.3.1.3.38 */
@@ -276,9 +274,7 @@ mrb_obj_protected_methods(mrb_state *mrb, mrb_value self)
276274static mrb_value
277275mrb_obj_public_methods(mrb_state *mrb, mrb_value self)
278276{
279-mrb_bool recur = TRUE;
280-mrb_get_args(mrb, "|b", &recur);
281-return mrb_obj_methods(mrb, recur, self, MT_PUBLIC); /* public attribute not define */
277+return mrb_obj_methods(mrb, self, MT_PUBLIC);
282278}
283279284280static mrb_value
@@ -287,17 +283,16 @@ mrb_obj_singleton_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj)
287283mrb_value ary;
288284struct RClass *klass;
289285khash_t(st) *set = kh_init(st, mrb);
290-khash_t(st) *undef = (recur ? kh_init(st, mrb) : NULL);
291286292287klass = mrb_class(mrb, obj);
293288294289if (klass && (klass->tt == MRB_TT_SCLASS)) {
295-method_entry_loop(mrb, klass, set, undef);
290+method_entry_loop(mrb, klass, set, MT_PUBLIC);
296291klass = klass->super;
297292 }
298293if (recur) {
299294while (klass && ((klass->tt == MRB_TT_SCLASS) || (klass->tt == MRB_TT_ICLASS))) {
300-method_entry_loop(mrb, klass, set, undef);
295+method_entry_loop(mrb, klass, set, MT_PUBLIC);
301296klass = klass->super;
302297 }
303298 }
@@ -309,7 +304,6 @@ mrb_obj_singleton_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj)
309304 }
310305 }
311306kh_destroy(st, mrb, set);
312-if (undef) kh_destroy(st, mrb, undef);
313307314308return ary;
315309}
@@ -526,6 +520,15 @@ mrb_mod_included_modules(mrb_state *mrb, mrb_value self)
526520return result;
527521}
528522523+static mrb_value
524+mod_instance_methods(mrb_state *mrb, mrb_value mod, unsigned int visibility)
525+{
526+struct RClass *c = mrb_class_ptr(mod);
527+mrb_bool recur = TRUE;
528+mrb_get_args(mrb, "|b", &recur);
529+return mrb_class_instance_method_list(mrb, recur, c, visibility);
530+}
531+529532/* 15.2.2.4.33 */
530533/*
531534 * call-seq:
@@ -557,10 +560,7 @@ mrb_mod_included_modules(mrb_state *mrb, mrb_value self)
557560static mrb_value
558561mrb_mod_instance_methods(mrb_state *mrb, mrb_value mod)
559562{
560-struct RClass *c = mrb_class_ptr(mod);
561-mrb_bool recur = TRUE;
562-mrb_get_args(mrb, "|b", &recur);
563-return mrb_class_instance_method_list(mrb, recur, c);
563+return mod_instance_methods(mrb, mod, MT_NOPRIV);
564564}
565565566566static int