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)
1516
1617static mrb_value
1718mrb_f_nil (mrb_state * mrb , mrb_value cv )
@@ -128,43 +129,38 @@ mrb_local_variables(mrb_state *mrb, mrb_value self)
128129 return mrb_proc_local_variables (mrb , mrb -> c -> ci [-1 ].proc );
129130}
130131
131- 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 )
133134
134135struct mt_set {
136+ unsigned int visibility ;
135137 khash_t (st ) * set ;
136- khash_t (st ) * undef ;
137138};
138139
140+ #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{
142145 struct mt_set * s = (struct mt_set * )p ;
143146
144- 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 }
153151 return 0 ;
154152}
155153
156154static 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 } ;
160158
161- s .set = set ;
162- s .undef = undef ;
163159 mrb_mt_foreach (mrb , klass , method_entry_i , (void * )& s );
164160}
165161
166162static 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{
169165 mrb_value ary ;
170166 khash_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
173169 if (klass -> flags & MRB_FL_CLASS_IS_PREPENDED ) {
174170 MRB_CLASS_ORIGIN (klass );
175171 }
176- method_entry_loop (mrb , klass , set , NULL );
172+ method_entry_loop (mrb , klass , set , flags );
177173 }
178174 else {
179- khash_t (st ) * undef = kh_init (st , mrb );
180175 struct RClass * oldklass = NULL ;
181176
182177 while (klass && (klass != oldklass )) {
183- method_entry_loop (mrb , klass , set , undef );
178+ method_entry_loop (mrb , klass , set , flags );
184179 oldklass = klass ;
185180 klass = klass -> super ;
186181 }
187- kh_destroy (st , mrb , undef );
188182 }
189183
190184 ary = mrb_ary_new_capa (mrb , kh_size (set ));
191185 for (khint_t i = 0 ; i < kh_end (set ); i ++ ) {
192186 if (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 }
196192 kh_destroy (st , mrb , set );
@@ -199,18 +195,26 @@ mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass *kl
199195}
200196
201197static 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" , & regular );
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}
232234
233235/* 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}
249249
250250/* 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}
266264
267265/* 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}
283279
284280static mrb_value
@@ -287,17 +283,16 @@ mrb_obj_singleton_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj)
287283 mrb_value ary ;
288284 struct RClass * klass ;
289285 khash_t (st ) * set = kh_init (st , mrb );
290- khash_t (st ) * undef = (recur ? kh_init (st , mrb ) : NULL );
291286
292287 klass = mrb_class (mrb , obj );
293288
294289 if (klass && (klass -> tt == MRB_TT_SCLASS )) {
295- method_entry_loop (mrb , klass , set , undef );
290+ method_entry_loop (mrb , klass , set , MT_PUBLIC );
296291 klass = klass -> super ;
297292 }
298293 if (recur ) {
299294 while (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 );
301296 klass = klass -> super ;
302297 }
303298 }
@@ -309,7 +304,6 @@ mrb_obj_singleton_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj)
309304 }
310305 }
311306 kh_destroy (st , mrb , set );
312- if (undef ) kh_destroy (st , mrb , undef );
313307
314308 return ary ;
315309}
@@ -526,6 +520,15 @@ mrb_mod_included_modules(mrb_state *mrb, mrb_value self)
526520 return result ;
527521}
528522
523+ 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}
565565
566566static int
0 commit comments