Skip to content

Commit 9229da1

Browse files
committed
mruby-metaprog: implement method list from a class (or an instance)
1 parent a282f8b commit 9229da1

1 file changed

Lines changed: 47 additions & 47 deletions

File tree

mrbgems/mruby-metaprog/src/metaprog.c

Lines changed: 47 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -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)
1516

1617
static mrb_value
1718
mrb_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

134135
struct 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+
139142
static int
140143
method_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

156154
static 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

166162
static 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

201197
static 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)
225229
static mrb_value
226230
mrb_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)
242244
static mrb_value
243245
mrb_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)
259259
static mrb_value
260260
mrb_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)
276274
static mrb_value
277275
mrb_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

284280
static 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)
557560
static mrb_value
558561
mrb_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

566566
static int

0 commit comments

Comments
 (0)