The Ruby Cross Reference

Implementation: mri jruby rubinius
Version: 1.8.7-p374 1.9.1-p431 1.9.2-p381 1.9.3-p547 2.0.0-p481 2.1.0-p0 2.1.1 2.1.2 HEAD
001 /*
002  * This file is included by vm.c
003  */
004 
005 #define CACHE_SIZE 0x800
006 #define CACHE_MASK 0x7ff
007 #define EXPR1(c,m) ((((c)>>3)^(m))&CACHE_MASK)
008 
009 #define NOEX_NOREDEF 0
010 #ifndef NOEX_NOREDEF
011 #define NOEX_NOREDEF NOEX_RESPONDS
012 #endif
013 
014 static void rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me, VALUE klass);
015 
016 #define object_id           idObject_id
017 #define added               idMethod_added
018 #define singleton_added     idSingleton_method_added
019 #define removed             idMethod_removed
020 #define singleton_removed   idSingleton_method_removed
021 #define undefined           idMethod_undefined
022 #define singleton_undefined idSingleton_method_undefined
023 #define attached            id__attached__
024 
025 struct cache_entry {            /* method hash table. */
026     VALUE filled_version;        /* filled state version */
027     ID mid;                     /* method's id */
028     VALUE klass;                /* receiver's class */
029     rb_method_entry_t *me;
030     VALUE defined_class;
031 };
032 
033 static struct cache_entry cache[CACHE_SIZE];
034 #define ruby_running (GET_VM()->running)
035 /* int ruby_running = 0; */
036 
037 static void
038 vm_clear_global_method_cache(void)
039 {
040     struct cache_entry *ent, *end;
041 
042     ent = cache;
043     end = ent + CACHE_SIZE;
044     while (ent < end) {
045         ent->filled_version = 0;
046         ent++;
047     }
048 }
049 
050 void
051 rb_clear_cache(void)
052 {
053     rb_vm_change_state();
054 }
055 
056 static void
057 rb_clear_cache_for_undef(VALUE klass, ID id)
058 {
059     rb_vm_change_state();
060 }
061 
062 static void
063 rb_clear_cache_by_id(ID id)
064 {
065     rb_vm_change_state();
066 }
067 
068 void
069 rb_clear_cache_by_class(VALUE klass)
070 {
071     rb_vm_change_state();
072 }
073 
074 VALUE
075 rb_f_notimplement(int argc, VALUE *argv, VALUE obj)
076 {
077     rb_notimplement();
078 
079     UNREACHABLE;
080 }
081 
082 static void
083 rb_define_notimplement_method_id(VALUE mod, ID id, rb_method_flag_t noex)
084 {
085     rb_add_method(mod, id, VM_METHOD_TYPE_NOTIMPLEMENTED, 0, noex);
086 }
087 
088 void
089 rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_flag_t noex)
090 {
091     if (argc < -2 || 15 < argc) rb_raise(rb_eArgError, "arity out of range: %d for -2..15", argc);
092     if (func != rb_f_notimplement) {
093         rb_method_cfunc_t opt;
094         opt.func = func;
095         opt.argc = argc;
096         rb_add_method(klass, mid, VM_METHOD_TYPE_CFUNC, &opt, noex);
097     }
098     else {
099         rb_define_notimplement_method_id(klass, mid, noex);
100     }
101 }
102 
103 void
104 rb_unlink_method_entry(rb_method_entry_t *me)
105 {
106     struct unlinked_method_entry_list_entry *ume = ALLOC(struct unlinked_method_entry_list_entry);
107     ume->me = me;
108     ume->next = GET_VM()->unlinked_method_entry_list;
109     GET_VM()->unlinked_method_entry_list = ume;
110 }
111 
112 void
113 rb_gc_mark_unlinked_live_method_entries(void *pvm)
114 {
115     rb_vm_t *vm = pvm;
116     struct unlinked_method_entry_list_entry *ume = vm->unlinked_method_entry_list;
117 
118     while (ume) {
119         if (ume->me->mark) {
120             rb_mark_method_entry(ume->me);
121         }
122         ume = ume->next;
123     }
124 }
125 
126 void
127 rb_sweep_method_entry(void *pvm)
128 {
129     rb_vm_t *vm = pvm;
130     struct unlinked_method_entry_list_entry **prev_ume = &vm->unlinked_method_entry_list, *ume = *prev_ume, *curr_ume;
131 
132     while (ume) {
133         if (ume->me->mark) {
134             ume->me->mark = 0;
135             prev_ume = &ume->next;
136             ume = *prev_ume;
137         }
138         else {
139             rb_free_method_entry(ume->me);
140 
141             curr_ume = ume;
142             ume = ume->next;
143             *prev_ume = ume;
144             xfree(curr_ume);
145         }
146     }
147 }
148 
149 static void
150 release_method_definition(rb_method_definition_t *def)
151 {
152     if (def == 0)
153         return;
154     if (def->alias_count == 0) {
155         if (def->type == VM_METHOD_TYPE_REFINED &&
156             def->body.orig_me) {
157             release_method_definition(def->body.orig_me->def);
158             xfree(def->body.orig_me);
159         }
160         xfree(def);
161     }
162     else if (def->alias_count > 0) {
163         def->alias_count--;
164     }
165 }
166 
167 void
168 rb_free_method_entry(rb_method_entry_t *me)
169 {
170     release_method_definition(me->def);
171     xfree(me);
172 }
173 
174 static int rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2);
175 
176 static inline rb_method_entry_t *
177 lookup_method_table(VALUE klass, ID id)
178 {
179     st_data_t body;
180     st_table *m_tbl = RCLASS_M_TBL(klass);
181     if (st_lookup(m_tbl, id, &body)) {
182         return (rb_method_entry_t *) body;
183     }
184     else {
185         return 0;
186     }
187 }
188 
189 static void
190 make_method_entry_refined(rb_method_entry_t *me)
191 {
192     rb_method_definition_t *new_def;
193 
194     if (me->def && me->def->type == VM_METHOD_TYPE_REFINED)
195         return;
196 
197     new_def = ALLOC(rb_method_definition_t);
198     new_def->type = VM_METHOD_TYPE_REFINED;
199     new_def->original_id = me->called_id;
200     new_def->alias_count = 0;
201     new_def->body.orig_me = ALLOC(rb_method_entry_t);
202     *new_def->body.orig_me = *me;
203     rb_vm_check_redefinition_opt_method(me, me->klass);
204     if (me->def) me->def->alias_count++;
205     me->def = new_def;
206 }
207 
208 void
209 rb_add_refined_method_entry(VALUE refined_class, ID mid)
210 {
211     rb_method_entry_t *me = lookup_method_table(refined_class, mid);
212 
213     if (me) {
214         make_method_entry_refined(me);
215     }
216     else {
217         rb_add_method(refined_class, mid, VM_METHOD_TYPE_REFINED, 0,
218                       NOEX_PUBLIC);
219     }
220 }
221 
222 static rb_method_entry_t *
223 rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type,
224                      rb_method_definition_t *def, rb_method_flag_t noex)
225 {
226     rb_method_entry_t *me;
227 #if NOEX_NOREDEF
228     VALUE rklass;
229 #endif
230     st_table *mtbl;
231     st_data_t data;
232     int make_refined = 0;
233 
234     if (NIL_P(klass)) {
235         klass = rb_cObject;
236     }
237     if (!FL_TEST(klass, FL_SINGLETON) &&
238         type != VM_METHOD_TYPE_NOTIMPLEMENTED &&
239         type != VM_METHOD_TYPE_ZSUPER &&
240         (mid == idInitialize || mid == idInitialize_copy ||
241          mid == idInitialize_clone || mid == idInitialize_dup ||
242          mid == idRespond_to_missing)) {
243         noex = NOEX_PRIVATE | noex;
244     }
245 
246     rb_check_frozen(klass);
247 #if NOEX_NOREDEF
248     rklass = klass;
249 #endif
250     if (FL_TEST(klass, RMODULE_IS_REFINEMENT)) {
251         VALUE refined_class =
252             rb_refinement_module_get_refined_class(klass);
253 
254         rb_add_refined_method_entry(refined_class, mid);
255     }
256     if (type == VM_METHOD_TYPE_REFINED) {
257         rb_method_entry_t *old_me =
258             lookup_method_table(RCLASS_ORIGIN(klass), mid);
259         if (old_me) rb_vm_check_redefinition_opt_method(old_me, klass);
260     }
261     else {
262         klass = RCLASS_ORIGIN(klass);
263     }
264     mtbl = RCLASS_M_TBL(klass);
265 
266     /* check re-definition */
267     if (st_lookup(mtbl, mid, &data)) {
268         rb_method_entry_t *old_me = (rb_method_entry_t *)data;
269         rb_method_definition_t *old_def = old_me->def;
270 
271         if (rb_method_definition_eq(old_def, def)) return old_me;
272 #if NOEX_NOREDEF
273         if (old_me->flag & NOEX_NOREDEF) {
274             rb_raise(rb_eTypeError, "cannot redefine %"PRIsVALUE"#%"PRIsVALUE,
275                      rb_class_name(rklass), rb_id2str(mid));
276         }
277 #endif
278         rb_vm_check_redefinition_opt_method(old_me, klass);
279         if (old_def->type == VM_METHOD_TYPE_REFINED)
280             make_refined = 1;
281 
282         if (RTEST(ruby_verbose) &&
283             type != VM_METHOD_TYPE_UNDEF &&
284             old_def->alias_count == 0 &&
285             old_def->type != VM_METHOD_TYPE_UNDEF &&
286             old_def->type != VM_METHOD_TYPE_ZSUPER) {
287             rb_iseq_t *iseq = 0;
288 
289             rb_warning("method redefined; discarding old %s", rb_id2name(mid));
290             switch (old_def->type) {
291               case VM_METHOD_TYPE_ISEQ:
292                 iseq = old_def->body.iseq;
293                 break;
294               case VM_METHOD_TYPE_BMETHOD:
295                 iseq = rb_proc_get_iseq(old_def->body.proc, 0);
296                 break;
297               default:
298                 break;
299             }
300             if (iseq && !NIL_P(iseq->location.path)) {
301                 int line = iseq->line_info_table ? rb_iseq_first_lineno(iseq) : 0;
302                 rb_compile_warning(RSTRING_PTR(iseq->location.path), line,
303                                    "previous definition of %s was here",
304                                    rb_id2name(old_def->original_id));
305             }
306         }
307 
308         rb_unlink_method_entry(old_me);
309     }
310 
311     me = ALLOC(rb_method_entry_t);
312 
313     rb_clear_cache_by_id(mid);
314 
315     me->flag = NOEX_WITH_SAFE(noex);
316     me->mark = 0;
317     me->called_id = mid;
318     me->klass = klass;
319     me->def = def;
320 
321     if (def) {
322         def->alias_count++;
323 
324         switch(def->type) {
325           case VM_METHOD_TYPE_ISEQ:
326             OBJ_WRITTEN(klass, Qundef, def->body.iseq);
327             break;
328           case VM_METHOD_TYPE_IVAR:
329             OBJ_WRITTEN(klass, Qundef, def->body.attr.location);
330             break;
331           case VM_METHOD_TYPE_BMETHOD:
332             OBJ_WRITTEN(klass, Qundef, def->body.proc);
333             break;
334           default:;
335             /* ignore */
336         }
337     }
338 
339     /* check mid */
340     if (klass == rb_cObject && mid == idInitialize) {
341         rb_warn("redefining Object#initialize may cause infinite loop");
342     }
343     /* check mid */
344     if (mid == object_id || mid == id__send__) {
345         if (type == VM_METHOD_TYPE_ISEQ) {
346             rb_warn("redefining `%s' may cause serious problems", rb_id2name(mid));
347         }
348     }
349 
350     if (make_refined) {
351         make_method_entry_refined(me);
352     }
353 
354     st_insert(mtbl, mid, (st_data_t) me);
355 
356     return me;
357 }
358 
359 #define CALL_METHOD_HOOK(klass, hook, mid) do {         \
360         const VALUE arg = ID2SYM(mid);                  \
361         VALUE recv_class = (klass);                     \
362         ID hook_id = (hook);                            \
363         if (FL_TEST((klass), FL_SINGLETON)) {           \
364             recv_class = rb_ivar_get((klass), attached);        \
365             hook_id = singleton_##hook;                 \
366         }                                               \
367         rb_funcall2(recv_class, hook_id, 1, &arg);      \
368     } while (0)
369 
370 static void
371 method_added(VALUE klass, ID mid)
372 {
373     if (ruby_running) {
374         CALL_METHOD_HOOK(klass, added, mid);
375     }
376 }
377 
378 static VALUE
379 (*call_cfunc_invoker_func(int argc))(VALUE (*func)(ANYARGS), VALUE recv, int argc, const VALUE *)
380 {
381     switch (argc) {
382       case -2: return &call_cfunc_m2;
383       case -1: return &call_cfunc_m1;
384       case 0: return &call_cfunc_0;
385       case 1: return &call_cfunc_1;
386       case 2: return &call_cfunc_2;
387       case 3: return &call_cfunc_3;
388       case 4: return &call_cfunc_4;
389       case 5: return &call_cfunc_5;
390       case 6: return &call_cfunc_6;
391       case 7: return &call_cfunc_7;
392       case 8: return &call_cfunc_8;
393       case 9: return &call_cfunc_9;
394       case 10: return &call_cfunc_10;
395       case 11: return &call_cfunc_11;
396       case 12: return &call_cfunc_12;
397       case 13: return &call_cfunc_13;
398       case 14: return &call_cfunc_14;
399       case 15: return &call_cfunc_15;
400       default:
401         rb_bug("call_cfunc_func: unsupported length: %d", argc);
402     }
403 }
404 
405 static void
406 setup_method_cfunc_struct(rb_method_cfunc_t *cfunc, VALUE (*func)(), int argc)
407 {
408     cfunc->func = func;
409     cfunc->argc = argc;
410     cfunc->invoker = call_cfunc_invoker_func(argc);
411 }
412 
413 rb_method_entry_t *
414 rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_flag_t noex)
415 {
416     rb_thread_t *th;
417     rb_control_frame_t *cfp;
418     int line;
419     rb_method_entry_t *me = rb_method_entry_make(klass, mid, type, 0, noex);
420     rb_method_definition_t *def = ALLOC(rb_method_definition_t);
421     if (me->def && me->def->type == VM_METHOD_TYPE_REFINED) {
422         me->def->body.orig_me->def = def;
423     }
424     else {
425         me->def = def;
426     }
427     def->type = type;
428     def->original_id = mid;
429     def->alias_count = 0;
430     switch (type) {
431       case VM_METHOD_TYPE_ISEQ: {
432           rb_iseq_t *iseq = (rb_iseq_t *)opts;
433           *(rb_iseq_t **)&def->body.iseq = iseq;
434           OBJ_WRITTEN(klass, Qundef, iseq->self);
435           break;
436       }
437       case VM_METHOD_TYPE_CFUNC:
438         {
439             rb_method_cfunc_t *cfunc = (rb_method_cfunc_t *)opts;
440             setup_method_cfunc_struct(&def->body.cfunc, cfunc->func, cfunc->argc);
441         }
442         break;
443       case VM_METHOD_TYPE_ATTRSET:
444       case VM_METHOD_TYPE_IVAR:
445         def->body.attr.id = (ID)opts;
446         OBJ_WRITE(klass, &def->body.attr.location, Qfalse);
447         th = GET_THREAD();
448         cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
449         if (cfp && (line = rb_vm_get_sourceline(cfp))) {
450             VALUE location = rb_ary_new3(2, cfp->iseq->location.path, INT2FIX(line));
451             OBJ_WRITE(klass, &def->body.attr.location, rb_ary_freeze(location));
452         }
453         break;
454       case VM_METHOD_TYPE_BMETHOD:
455         OBJ_WRITE(klass, &def->body.proc, (VALUE)opts);
456         break;
457       case VM_METHOD_TYPE_NOTIMPLEMENTED:
458         setup_method_cfunc_struct(&def->body.cfunc, rb_f_notimplement, -1);
459         break;
460       case VM_METHOD_TYPE_OPTIMIZED:
461         def->body.optimize_type = (enum method_optimized_type)opts;
462         break;
463       case VM_METHOD_TYPE_ZSUPER:
464       case VM_METHOD_TYPE_UNDEF:
465         break;
466       case VM_METHOD_TYPE_REFINED:
467         def->body.orig_me = (rb_method_entry_t *) opts;
468         break;
469       default:
470         rb_bug("rb_add_method: unsupported method type (%d)\n", type);
471     }
472     if (type != VM_METHOD_TYPE_UNDEF && type != VM_METHOD_TYPE_REFINED) {
473         method_added(klass, mid);
474     }
475     return me;
476 }
477 
478 rb_method_entry_t *
479 rb_method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me, rb_method_flag_t noex)
480 {
481     rb_method_type_t type = me->def ? me->def->type : VM_METHOD_TYPE_UNDEF;
482     rb_method_entry_t *newme = rb_method_entry_make(klass, mid, type, me->def, noex);
483     method_added(klass, mid);
484     return newme;
485 }
486 
487 #define UNDEF_ALLOC_FUNC ((rb_alloc_func_t)-1)
488 
489 void
490 rb_define_alloc_func(VALUE klass, VALUE (*func)(VALUE))
491 {
492     Check_Type(klass, T_CLASS);
493     RCLASS_EXT(klass)->allocator = func;
494 }
495 
496 void
497 rb_undef_alloc_func(VALUE klass)
498 {
499     rb_define_alloc_func(klass, UNDEF_ALLOC_FUNC);
500 }
501 
502 rb_alloc_func_t
503 rb_get_alloc_func(VALUE klass)
504 {
505     Check_Type(klass, T_CLASS);
506 
507     for (; klass; klass = RCLASS_SUPER(klass)) {
508         rb_alloc_func_t allocator = RCLASS_EXT(klass)->allocator;
509         if (allocator == UNDEF_ALLOC_FUNC) break;
510         if (allocator) return allocator;
511     }
512     return 0;
513 }
514 
515 static inline rb_method_entry_t*
516 search_method(VALUE klass, ID id, VALUE *defined_class_ptr)
517 {
518     rb_method_entry_t *me;
519 
520     for (me = 0; klass; klass = RCLASS_SUPER(klass)) {
521         if ((me = lookup_method_table(klass, id)) != 0) break;
522     }
523 
524     if (defined_class_ptr)
525         *defined_class_ptr = klass;
526     return me;
527 }
528 
529 rb_method_entry_t *
530 rb_method_entry_at(VALUE klass, ID id)
531 {
532     return lookup_method_table(klass, id);
533 }
534 
535 /*
536  * search method entry without the method cache.
537  *
538  * if you need method entry with method cache (normal case), use
539  * rb_method_entry() simply.
540  */
541 rb_method_entry_t *
542 rb_method_entry_get_without_cache(VALUE klass, ID id,
543                                   VALUE *defined_class_ptr)
544 {
545     VALUE defined_class;
546     rb_method_entry_t *me = search_method(klass, id, &defined_class);
547 
548     if (ruby_running) {
549         struct cache_entry *ent;
550         ent = cache + EXPR1(klass, id);
551         ent->filled_version = GET_VM_STATE_VERSION();
552         ent->klass = klass;
553         ent->defined_class = defined_class;
554 
555         if (UNDEFINED_METHOD_ENTRY_P(me)) {
556             ent->mid = id;
557             ent->me = 0;
558             me = 0;
559         }
560         else {
561             ent->mid = id;
562             ent->me = me;
563         }
564     }
565 
566     if (defined_class_ptr)
567         *defined_class_ptr = defined_class;
568     return me;
569 }
570 
571 rb_method_entry_t *
572 rb_method_entry(VALUE klass, ID id, VALUE *defined_class_ptr)
573 {
574 #if OPT_GLOBAL_METHOD_CACHE
575     struct cache_entry *ent;
576 
577     ent = cache + EXPR1(klass, id);
578     if (ent->filled_version == GET_VM_STATE_VERSION() &&
579         ent->mid == id && ent->klass == klass) {
580         if (defined_class_ptr)
581             *defined_class_ptr = ent->defined_class;
582         return ent->me;
583     }
584 #endif
585 
586     return rb_method_entry_get_without_cache(klass, id, defined_class_ptr);
587 }
588 
589 static rb_method_entry_t *
590 get_original_method_entry(VALUE refinements,
591                           rb_method_entry_t *me,
592                           VALUE *defined_class_ptr)
593 {
594     if (me->def->body.orig_me) {
595         return me->def->body.orig_me;
596     }
597     else {
598         rb_method_entry_t *tmp_me;
599         tmp_me = rb_method_entry(RCLASS_SUPER(me->klass), me->called_id,
600                                  defined_class_ptr);
601         return rb_resolve_refined_method(refinements, tmp_me,
602                                          defined_class_ptr);
603     }
604 }
605 
606 rb_method_entry_t *
607 rb_resolve_refined_method(VALUE refinements, rb_method_entry_t *me,
608                           VALUE *defined_class_ptr)
609 {
610     if (me && me->def->type == VM_METHOD_TYPE_REFINED) {
611         VALUE refinement;
612         rb_method_entry_t *tmp_me;
613 
614         refinement = find_refinement(refinements, me->klass);
615         if (NIL_P(refinement)) {
616             return get_original_method_entry(refinements, me,
617                                              defined_class_ptr);
618         }
619         tmp_me = rb_method_entry(refinement, me->called_id,
620                                  defined_class_ptr);
621         if (tmp_me && tmp_me->def->type != VM_METHOD_TYPE_REFINED) {
622             return tmp_me;
623         }
624         else {
625             return get_original_method_entry(refinements, me,
626                                              defined_class_ptr);
627         }
628     }
629     else {
630         return me;
631     }
632 }
633 
634 rb_method_entry_t *
635 rb_method_entry_with_refinements(VALUE klass, ID id,
636                                  VALUE *defined_class_ptr)
637 {
638     VALUE defined_class;
639     rb_method_entry_t *me = rb_method_entry(klass, id, &defined_class);
640 
641     if (me && me->def->type == VM_METHOD_TYPE_REFINED) {
642         NODE *cref = rb_vm_cref();
643         VALUE refinements = cref ? cref->nd_refinements : Qnil;
644 
645         me = rb_resolve_refined_method(refinements, me, &defined_class);
646     }
647     if (defined_class_ptr)
648         *defined_class_ptr = defined_class;
649     return me;
650 }
651 
652 rb_method_entry_t *
653 rb_method_entry_without_refinements(VALUE klass, ID id,
654                                     VALUE *defined_class_ptr)
655 {
656     VALUE defined_class;
657     rb_method_entry_t *me = rb_method_entry(klass, id, &defined_class);
658 
659     if (me && me->def->type == VM_METHOD_TYPE_REFINED) {
660         me = rb_resolve_refined_method(Qnil, me, &defined_class);
661     }
662     if (defined_class_ptr)
663         *defined_class_ptr = defined_class;
664     return me;
665 }
666 
667 static void
668 remove_method(VALUE klass, ID mid)
669 {
670     st_data_t key, data;
671     rb_method_entry_t *me = 0;
672     VALUE self = klass;
673 
674     klass = RCLASS_ORIGIN(klass);
675     if (klass == rb_cObject) {
676     }
677     rb_check_frozen(klass);
678     if (mid == object_id || mid == id__send__ || mid == idInitialize) {
679         rb_warn("removing `%s' may cause serious problems", rb_id2name(mid));
680     }
681 
682     if (!st_lookup(RCLASS_M_TBL(klass), mid, &data) ||
683         !(me = (rb_method_entry_t *)data) ||
684         (!me->def || me->def->type == VM_METHOD_TYPE_UNDEF)) {
685         rb_name_error(mid, "method `%s' not defined in %s",
686                       rb_id2name(mid), rb_class2name(klass));
687     }
688     key = (st_data_t)mid;
689     st_delete(RCLASS_M_TBL(klass), &key, &data);
690 
691     rb_vm_check_redefinition_opt_method(me, klass);
692     rb_clear_cache_for_undef(klass, mid);
693     rb_unlink_method_entry(me);
694 
695     CALL_METHOD_HOOK(self, removed, mid);
696 }
697 
698 void
699 rb_remove_method_id(VALUE klass, ID mid)
700 {
701     remove_method(klass, mid);
702 }
703 
704 void
705 rb_remove_method(VALUE klass, const char *name)
706 {
707     remove_method(klass, rb_intern(name));
708 }
709 
710 /*
711  *  call-seq:
712  *     remove_method(symbol)   -> self
713  *     remove_method(string)   -> self
714  *
715  *  Removes the method identified by _symbol_ from the current
716  *  class. For an example, see <code>Module.undef_method</code>.
717  *  String arguments are converted to symbols.
718  */
719 
720 static VALUE
721 rb_mod_remove_method(int argc, VALUE *argv, VALUE mod)
722 {
723     int i;
724 
725     for (i = 0; i < argc; i++) {
726         VALUE v = argv[i];
727         ID id = rb_check_id(&v);
728         if (!id) {
729             rb_name_error_str(v, "method `%s' not defined in %s",
730                               RSTRING_PTR(v), rb_class2name(mod));
731         }
732         remove_method(mod, id);
733     }
734     return mod;
735 }
736 
737 #undef rb_disable_super
738 #undef rb_enable_super
739 
740 void
741 rb_disable_super(VALUE klass, const char *name)
742 {
743     /* obsolete - no use */
744 }
745 
746 void
747 rb_enable_super(VALUE klass, const char *name)
748 {
749     rb_warning("rb_enable_super() is obsolete");
750 }
751 
752 static void
753 rb_export_method(VALUE klass, ID name, rb_method_flag_t noex)
754 {
755     rb_method_entry_t *me;
756     VALUE defined_class;
757 
758     if (klass == rb_cObject) {
759     }
760 
761     me = search_method(klass, name, &defined_class);
762     if (!me && RB_TYPE_P(klass, T_MODULE)) {
763         me = search_method(rb_cObject, name, &defined_class);
764     }
765 
766     if (UNDEFINED_METHOD_ENTRY_P(me)) {
767         rb_print_undef(klass, name, 0);
768     }
769 
770     if (me->flag != noex) {
771         rb_vm_check_redefinition_opt_method(me, klass);
772 
773         if (klass == defined_class ||
774             RCLASS_ORIGIN(klass) == defined_class) {
775             me->flag = noex;
776             if (me->def->type == VM_METHOD_TYPE_REFINED) {
777                 me->def->body.orig_me->flag = noex;
778             }
779         }
780         else {
781             rb_add_method(klass, name, VM_METHOD_TYPE_ZSUPER, 0, noex);
782         }
783     }
784 }
785 
786 int
787 rb_method_boundp(VALUE klass, ID id, int ex)
788 {
789     rb_method_entry_t *me =
790         rb_method_entry_without_refinements(klass, id, 0);
791 
792     if (me != 0) {
793         if ((ex & ~NOEX_RESPONDS) &&
794             ((me->flag & NOEX_PRIVATE) ||
795              ((ex & NOEX_RESPONDS) && (me->flag & NOEX_PROTECTED)))) {
796             return 0;
797         }
798         if (!me->def) return 0;
799         if (me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) {
800             if (ex & NOEX_RESPONDS) return 2;
801             return 0;
802         }
803         return 1;
804     }
805     return 0;
806 }
807 
808 void
809 rb_attr(VALUE klass, ID id, int read, int write, int ex)
810 {
811     const char *name;
812     ID attriv;
813     VALUE aname;
814     rb_method_flag_t noex;
815 
816     if (!ex) {
817         noex = NOEX_PUBLIC;
818     }
819     else {
820         if (SCOPE_TEST(NOEX_PRIVATE)) {
821             noex = NOEX_PRIVATE;
822             rb_warning((SCOPE_CHECK(NOEX_MODFUNC)) ?
823                        "attribute accessor as module_function" :
824                        "private attribute?");
825         }
826         else if (SCOPE_TEST(NOEX_PROTECTED)) {
827             noex = NOEX_PROTECTED;
828         }
829         else {
830             noex = NOEX_PUBLIC;
831         }
832     }
833 
834     if (!rb_is_local_id(id) && !rb_is_const_id(id)) {
835         rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id));
836     }
837     name = rb_id2name(id);
838     if (!name) {
839         rb_raise(rb_eArgError, "argument needs to be symbol or string");
840     }
841     aname = rb_sprintf("@%s", name);
842     rb_enc_copy(aname, rb_id2str(id));
843     attriv = rb_intern_str(aname);
844     if (read) {
845         rb_add_method(klass, id, VM_METHOD_TYPE_IVAR, (void *)attriv, noex);
846     }
847     if (write) {
848         rb_add_method(klass, rb_id_attrset(id), VM_METHOD_TYPE_ATTRSET, (void *)attriv, noex);
849     }
850 }
851 
852 void
853 rb_undef(VALUE klass, ID id)
854 {
855     rb_method_entry_t *me;
856 
857     if (NIL_P(klass)) {
858         rb_raise(rb_eTypeError, "no class to undef method");
859     }
860     if (rb_vm_cbase() == rb_cObject && klass == rb_cObject) {
861     }
862     rb_frozen_class_p(klass);
863     if (id == object_id || id == id__send__ || id == idInitialize) {
864         rb_warn("undefining `%s' may cause serious problems", rb_id2name(id));
865     }
866 
867     me = search_method(klass, id, 0);
868 
869     if (UNDEFINED_METHOD_ENTRY_P(me)) {
870         const char *s0 = " class";
871         VALUE c = klass;
872 
873         if (FL_TEST(c, FL_SINGLETON)) {
874             VALUE obj = rb_ivar_get(klass, attached);
875 
876             if (RB_TYPE_P(obj, T_MODULE) || RB_TYPE_P(obj, T_CLASS)) {
877                 c = obj;
878                 s0 = "";
879             }
880         }
881         else if (RB_TYPE_P(c, T_MODULE)) {
882             s0 = " module";
883         }
884         rb_name_error(id, "undefined method `%"PRIsVALUE"' for%s `%"PRIsVALUE"'",
885                       QUOTE_ID(id), s0, rb_class_name(c));
886     }
887 
888     rb_add_method(klass, id, VM_METHOD_TYPE_UNDEF, 0, NOEX_PUBLIC);
889 
890     CALL_METHOD_HOOK(klass, undefined, id);
891 }
892 
893 /*
894  *  call-seq:
895  *     undef_method(symbol)    -> self
896  *     undef_method(string)    -> self
897  *
898  *  Prevents the current class from responding to calls to the named
899  *  method. Contrast this with <code>remove_method</code>, which deletes
900  *  the method from the particular class; Ruby will still search
901  *  superclasses and mixed-in modules for a possible receiver.
902  *  String arguments are converted to symbols.
903  *
904  *     class Parent
905  *       def hello
906  *         puts "In parent"
907  *       end
908  *     end
909  *     class Child < Parent
910  *       def hello
911  *         puts "In child"
912  *       end
913  *     end
914  *
915  *
916  *     c = Child.new
917  *     c.hello
918  *
919  *
920  *     class Child
921  *       remove_method :hello  # remove from child, still in parent
922  *     end
923  *     c.hello
924  *
925  *
926  *     class Child
927  *       undef_method :hello   # prevent any calls to 'hello'
928  *     end
929  *     c.hello
930  *
931  *  <em>produces:</em>
932  *
933  *     In child
934  *     In parent
935  *     prog.rb:23: undefined method `hello' for #<Child:0x401b3bb4> (NoMethodError)
936  */
937 
938 static VALUE
939 rb_mod_undef_method(int argc, VALUE *argv, VALUE mod)
940 {
941     int i;
942     for (i = 0; i < argc; i++) {
943         VALUE v = argv[i];
944         ID id = rb_check_id(&v);
945         if (!id) {
946             rb_method_name_error(mod, v);
947         }
948         rb_undef(mod, id);
949     }
950     return mod;
951 }
952 
953 /*
954  *  call-seq:
955  *     mod.method_defined?(symbol)    -> true or false
956  *     mod.method_defined?(string)    -> true or false
957  *
958  *  Returns +true+ if the named method is defined by
959  *  _mod_ (or its included modules and, if _mod_ is a class,
960  *  its ancestors). Public and protected methods are matched.
961  *  String arguments are converted to symbols.
962  *
963  *     module A
964  *       def method1()  end
965  *     end
966  *     class B
967  *       def method2()  end
968  *     end
969  *     class C < B
970  *       include A
971  *       def method3()  end
972  *     end
973  *
974  *     A.method_defined? :method1    #=> true
975  *     C.method_defined? "method1"   #=> true
976  *     C.method_defined? "method2"   #=> true
977  *     C.method_defined? "method3"   #=> true
978  *     C.method_defined? "method4"   #=> false
979  */
980 
981 static VALUE
982 rb_mod_method_defined(VALUE mod, VALUE mid)
983 {
984     ID id = rb_check_id(&mid);
985     if (!id || !rb_method_boundp(mod, id, 1)) {
986         return Qfalse;
987     }
988     return Qtrue;
989 
990 }
991 
992 #define VISI_CHECK(x,f) (((x)&NOEX_MASK) == (f))
993 
994 static VALUE
995 check_definition(VALUE mod, VALUE mid, rb_method_flag_t noex)
996 {
997     const rb_method_entry_t *me;
998     ID id = rb_check_id(&mid);
999     if (!id) return Qfalse;
1000     me = rb_method_entry(mod, id, 0);
1001     if (me) {
1002         if (VISI_CHECK(me->flag, noex))
1003             return Qtrue;
1004     }
1005     return Qfalse;
1006 }
1007 
1008 /*
1009  *  call-seq:
1010  *     mod.public_method_defined?(symbol)   -> true or false
1011  *     mod.public_method_defined?(string)   -> true or false
1012  *
1013  *  Returns +true+ if the named public method is defined by
1014  *  _mod_ (or its included modules and, if _mod_ is a class,
1015  *  its ancestors).
1016  *  String arguments are converted to symbols.
1017  *
1018  *     module A
1019  *       def method1()  end
1020  *     end
1021  *     class B
1022  *       protected
1023  *       def method2()  end
1024  *     end
1025  *     class C < B
1026  *       include A
1027  *       def method3()  end
1028  *     end
1029  *
1030  *     A.method_defined? :method1           #=> true
1031  *     C.public_method_defined? "method1"   #=> true
1032  *     C.public_method_defined? "method2"   #=> false
1033  *     C.method_defined? "method2"          #=> true
1034  */
1035 
1036 static VALUE
1037 rb_mod_public_method_defined(VALUE mod, VALUE mid)
1038 {
1039     return check_definition(mod, mid, NOEX_PUBLIC);
1040 }
1041 
1042 /*
1043  *  call-seq:
1044  *     mod.private_method_defined?(symbol)    -> true or false
1045  *     mod.private_method_defined?(string)    -> true or false
1046  *
1047  *  Returns +true+ if the named private method is defined by
1048  *  _ mod_ (or its included modules and, if _mod_ is a class,
1049  *  its ancestors).
1050  *  String arguments are converted to symbols.
1051  *
1052  *     module A
1053  *       def method1()  end
1054  *     end
1055  *     class B
1056  *       private
1057  *       def method2()  end
1058  *     end
1059  *     class C < B
1060  *       include A
1061  *       def method3()  end
1062  *     end
1063  *
1064  *     A.method_defined? :method1            #=> true
1065  *     C.private_method_defined? "method1"   #=> false
1066  *     C.private_method_defined? "method2"   #=> true
1067  *     C.method_defined? "method2"           #=> false
1068  */
1069 
1070 static VALUE
1071 rb_mod_private_method_defined(VALUE mod, VALUE mid)
1072 {
1073     return check_definition(mod, mid, NOEX_PRIVATE);
1074 }
1075 
1076 /*
1077  *  call-seq:
1078  *     mod.protected_method_defined?(symbol)   -> true or false
1079  *     mod.protected_method_defined?(string)   -> true or false
1080  *
1081  *  Returns +true+ if the named protected method is defined
1082  *  by _mod_ (or its included modules and, if _mod_ is a
1083  *  class, its ancestors).
1084  *  String arguments are converted to symbols.
1085  *
1086  *     module A
1087  *       def method1()  end
1088  *     end
1089  *     class B
1090  *       protected
1091  *       def method2()  end
1092  *     end
1093  *     class C < B
1094  *       include A
1095  *       def method3()  end
1096  *     end
1097  *
1098  *     A.method_defined? :method1              #=> true
1099  *     C.protected_method_defined? "method1"   #=> false
1100  *     C.protected_method_defined? "method2"   #=> true
1101  *     C.method_defined? "method2"             #=> true
1102  */
1103 
1104 static VALUE
1105 rb_mod_protected_method_defined(VALUE mod, VALUE mid)
1106 {
1107     return check_definition(mod, mid, NOEX_PROTECTED);
1108 }
1109 
1110 int
1111 rb_method_entry_eq(const rb_method_entry_t *m1, const rb_method_entry_t *m2)
1112 {
1113     return rb_method_definition_eq(m1->def, m2->def);
1114 }
1115 
1116 static int
1117 rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2)
1118 {
1119     if (d1 && d1->type == VM_METHOD_TYPE_REFINED)
1120         d1 = d1->body.orig_me->def;
1121     if (d2 && d2->type == VM_METHOD_TYPE_REFINED)
1122         d2 = d2->body.orig_me->def;
1123     if (d1 == d2) return 1;
1124     if (!d1 || !d2) return 0;
1125     if (d1->type != d2->type) {
1126         return 0;
1127     }
1128     switch (d1->type) {
1129       case VM_METHOD_TYPE_ISEQ:
1130         return d1->body.iseq == d2->body.iseq;
1131       case VM_METHOD_TYPE_CFUNC:
1132         return
1133           d1->body.cfunc.func == d2->body.cfunc.func &&
1134           d1->body.cfunc.argc == d2->body.cfunc.argc;
1135       case VM_METHOD_TYPE_ATTRSET:
1136       case VM_METHOD_TYPE_IVAR:
1137         return d1->body.attr.id == d2->body.attr.id;
1138       case VM_METHOD_TYPE_BMETHOD:
1139         return RTEST(rb_equal(d1->body.proc, d2->body.proc));
1140       case VM_METHOD_TYPE_MISSING:
1141         return d1->original_id == d2->original_id;
1142       case VM_METHOD_TYPE_ZSUPER:
1143       case VM_METHOD_TYPE_NOTIMPLEMENTED:
1144       case VM_METHOD_TYPE_UNDEF:
1145         return 1;
1146       case VM_METHOD_TYPE_OPTIMIZED:
1147         return d1->body.optimize_type == d2->body.optimize_type;
1148       default:
1149         rb_bug("rb_method_entry_eq: unsupported method type (%d)\n", d1->type);
1150         return 0;
1151     }
1152 }
1153 
1154 static st_index_t
1155 rb_hash_method_definition(st_index_t hash, const rb_method_definition_t *def)
1156 {
1157   again:
1158     hash = rb_hash_uint(hash, def->type);
1159     switch (def->type) {
1160       case VM_METHOD_TYPE_ISEQ:
1161         return rb_hash_uint(hash, (st_index_t)def->body.iseq);
1162       case VM_METHOD_TYPE_CFUNC:
1163         hash = rb_hash_uint(hash, (st_index_t)def->body.cfunc.func);
1164         return rb_hash_uint(hash, def->body.cfunc.argc);
1165       case VM_METHOD_TYPE_ATTRSET:
1166       case VM_METHOD_TYPE_IVAR:
1167         return rb_hash_uint(hash, def->body.attr.id);
1168       case VM_METHOD_TYPE_BMETHOD:
1169         return rb_hash_proc(hash, def->body.proc);
1170       case VM_METHOD_TYPE_MISSING:
1171         return rb_hash_uint(hash, def->original_id);
1172       case VM_METHOD_TYPE_ZSUPER:
1173       case VM_METHOD_TYPE_NOTIMPLEMENTED:
1174       case VM_METHOD_TYPE_UNDEF:
1175         return hash;
1176       case VM_METHOD_TYPE_OPTIMIZED:
1177         return rb_hash_uint(hash, def->body.optimize_type);
1178       case VM_METHOD_TYPE_REFINED:
1179         if (def->body.orig_me) {
1180             def = def->body.orig_me->def;
1181             goto again;
1182         }
1183         else {
1184             return hash;
1185         }
1186       default:
1187         rb_bug("rb_hash_method_definition: unsupported method type (%d)\n", def->type);
1188     }
1189     return hash;
1190 }
1191 
1192 st_index_t
1193 rb_hash_method_entry(st_index_t hash, const rb_method_entry_t *me)
1194 {
1195     return rb_hash_method_definition(hash, me->def);
1196 }
1197 
1198 void
1199 rb_alias(VALUE klass, ID name, ID def)
1200 {
1201     VALUE target_klass = klass;
1202     rb_method_entry_t *orig_me;
1203     rb_method_flag_t flag = NOEX_UNDEF;
1204 
1205     if (NIL_P(klass)) {
1206         rb_raise(rb_eTypeError, "no class to make alias");
1207     }
1208 
1209     rb_frozen_class_p(klass);
1210     if (klass == rb_cObject) {
1211     }
1212 
1213   again:
1214     orig_me = search_method(klass, def, 0);
1215 
1216     if (UNDEFINED_METHOD_ENTRY_P(orig_me)) {
1217         if ((!RB_TYPE_P(klass, T_MODULE)) ||
1218             (orig_me = search_method(rb_cObject, def, 0),
1219              UNDEFINED_METHOD_ENTRY_P(orig_me))) {
1220             rb_print_undef(klass, def, 0);
1221         }
1222     }
1223     if (orig_me->def->type == VM_METHOD_TYPE_ZSUPER) {
1224         klass = RCLASS_SUPER(klass);
1225         def = orig_me->def->original_id;
1226         flag = orig_me->flag;
1227         goto again;
1228     }
1229 
1230     if (flag == NOEX_UNDEF) flag = orig_me->flag;
1231     rb_method_entry_set(target_klass, name, orig_me, flag);
1232 }
1233 
1234 /*
1235  *  call-seq:
1236  *     alias_method(new_name, old_name)   -> self
1237  *
1238  *  Makes <i>new_name</i> a new copy of the method <i>old_name</i>. This can
1239  *  be used to retain access to methods that are overridden.
1240  *
1241  *     module Mod
1242  *       alias_method :orig_exit, :exit
1243  *       def exit(code=0)
1244  *         puts "Exiting with code #{code}"
1245  *         orig_exit(code)
1246  *       end
1247  *     end
1248  *     include Mod
1249  *     exit(99)
1250  *
1251  *  <em>produces:</em>
1252  *
1253  *     Exiting with code 99
1254  */
1255 
1256 static VALUE
1257 rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname)
1258 {
1259     ID oldid = rb_check_id(&oldname);
1260     if (!oldid) {
1261         rb_print_undef_str(mod, oldname);
1262     }
1263     rb_alias(mod, rb_to_id(newname), oldid);
1264     return mod;
1265 }
1266 
1267 static void
1268 set_method_visibility(VALUE self, int argc, VALUE *argv, rb_method_flag_t ex)
1269 {
1270     int i;
1271 
1272     if (argc == 0) {
1273         rb_warning("%"PRIsVALUE" with no argument is just ignored",
1274                    QUOTE_ID(rb_frame_callee()));
1275         return;
1276     }
1277 
1278     for (i = 0; i < argc; i++) {
1279         VALUE v = argv[i];
1280         ID id = rb_check_id(&v);
1281         if (!id) {
1282             rb_print_undef_str(self, v);
1283         }
1284         rb_export_method(self, id, ex);
1285     }
1286     rb_clear_cache_by_class(self);
1287 }
1288 
1289 static VALUE
1290 set_visibility(int argc, VALUE *argv, VALUE module, rb_method_flag_t ex)
1291 {
1292     if (argc == 0) {
1293         SCOPE_SET(ex);
1294     }
1295     else {
1296         set_method_visibility(module, argc, argv, ex);
1297     }
1298     return module;
1299 }
1300 
1301 /*
1302  *  call-seq:
1303  *     public                 -> self
1304  *     public(symbol, ...)    -> self
1305  *     public(string, ...)    -> self
1306  *
1307  *  With no arguments, sets the default visibility for subsequently
1308  *  defined methods to public. With arguments, sets the named methods to
1309  *  have public visibility.
1310  *  String arguments are converted to symbols.
1311  */
1312 
1313 static VALUE
1314 rb_mod_public(int argc, VALUE *argv, VALUE module)
1315 {
1316     return set_visibility(argc, argv, module, NOEX_PUBLIC);
1317 }
1318 
1319 /*
1320  *  call-seq:
1321  *     protected                -> self
1322  *     protected(symbol, ...)   -> self
1323  *     protected(string, ...)   -> self
1324  *
1325  *  With no arguments, sets the default visibility for subsequently
1326  *  defined methods to protected. With arguments, sets the named methods
1327  *  to have protected visibility.
1328  *  String arguments are converted to symbols.
1329  */
1330 
1331 static VALUE
1332 rb_mod_protected(int argc, VALUE *argv, VALUE module)
1333 {
1334     return set_visibility(argc, argv, module, NOEX_PROTECTED);
1335 }
1336 
1337 /*
1338  *  call-seq:
1339  *     private                 -> self
1340  *     private(symbol, ...)    -> self
1341  *     private(string, ...)    -> self
1342  *
1343  *  With no arguments, sets the default visibility for subsequently
1344  *  defined methods to private. With arguments, sets the named methods
1345  *  to have private visibility.
1346  *  String arguments are converted to symbols.
1347  *
1348  *     module Mod
1349  *       def a()  end
1350  *       def b()  end
1351  *       private
1352  *       def c()  end
1353  *       private :a
1354  *     end
1355  *     Mod.private_instance_methods   #=> [:a, :c]
1356  */
1357 
1358 static VALUE
1359 rb_mod_private(int argc, VALUE *argv, VALUE module)
1360 {
1361     return set_visibility(argc, argv, module, NOEX_PRIVATE);
1362 }
1363 
1364 /*
1365  *  call-seq:
1366  *     mod.public_class_method(symbol, ...)    -> mod
1367  *     mod.public_class_method(string, ...)    -> mod
1368  *
1369  *  Makes a list of existing class methods public.
1370  *
1371  *  String arguments are converted to symbols.
1372  */
1373 
1374 static VALUE
1375 rb_mod_public_method(int argc, VALUE *argv, VALUE obj)
1376 {
1377     set_method_visibility(rb_singleton_class(obj), argc, argv, NOEX_PUBLIC);
1378     return obj;
1379 }
1380 
1381 /*
1382  *  call-seq:
1383  *     mod.private_class_method(symbol, ...)   -> mod
1384  *     mod.private_class_method(string, ...)   -> mod
1385  *
1386  *  Makes existing class methods private. Often used to hide the default
1387  *  constructor <code>new</code>.
1388  *
1389  *  String arguments are converted to symbols.
1390  *
1391  *     class SimpleSingleton  # Not thread safe
1392  *       private_class_method :new
1393  *       def SimpleSingleton.create(*args, &block)
1394  *         @me = new(*args, &block) if ! @me
1395  *         @me
1396  *       end
1397  *     end
1398  */
1399 
1400 static VALUE
1401 rb_mod_private_method(int argc, VALUE *argv, VALUE obj)
1402 {
1403     set_method_visibility(rb_singleton_class(obj), argc, argv, NOEX_PRIVATE);
1404     return obj;
1405 }
1406 
1407 /*
1408  *  call-seq:
1409  *     public
1410  *     public(symbol, ...)
1411  *     public(string, ...)
1412  *
1413  *  With no arguments, sets the default visibility for subsequently
1414  *  defined methods to public. With arguments, sets the named methods to
1415  *  have public visibility.
1416  *
1417  *  String arguments are converted to symbols.
1418  */
1419 
1420 static VALUE
1421 top_public(int argc, VALUE *argv)
1422 {
1423     return rb_mod_public(argc, argv, rb_cObject);
1424 }
1425 
1426 /*
1427  *  call-seq:
1428  *     private
1429  *     private(symbol, ...)
1430  *     private(string, ...)
1431  *
1432  *  With no arguments, sets the default visibility for subsequently
1433  *  defined methods to private. With arguments, sets the named methods to
1434  *  have private visibility.
1435  *
1436  *  String arguments are converted to symbols.
1437  */
1438 static VALUE
1439 top_private(int argc, VALUE *argv)
1440 {
1441     return rb_mod_private(argc, argv, rb_cObject);
1442 }
1443 
1444 /*
1445  *  call-seq:
1446  *     module_function(symbol, ...)    -> self
1447  *     module_function(string, ...)    -> self
1448  *
1449  *  Creates module functions for the named methods. These functions may
1450  *  be called with the module as a receiver, and also become available
1451  *  as instance methods to classes that mix in the module. Module
1452  *  functions are copies of the original, and so may be changed
1453  *  independently. The instance-method versions are made private. If
1454  *  used with no arguments, subsequently defined methods become module
1455  *  functions.
1456  *  String arguments are converted to symbols.
1457  *
1458  *     module Mod
1459  *       def one
1460  *         "This is one"
1461  *       end
1462  *       module_function :one
1463  *     end
1464  *     class Cls
1465  *       include Mod
1466  *       def call_one
1467  *         one
1468  *       end
1469  *     end
1470  *     Mod.one     #=> "This is one"
1471  *     c = Cls.new
1472  *     c.call_one  #=> "This is one"
1473  *     module Mod
1474  *       def one
1475  *         "This is the new one"
1476  *       end
1477  *     end
1478  *     Mod.one     #=> "This is one"
1479  *     c.call_one  #=> "This is the new one"
1480  */
1481 
1482 static VALUE
1483 rb_mod_modfunc(int argc, VALUE *argv, VALUE module)
1484 {
1485     int i;
1486     ID id;
1487     const rb_method_entry_t *me;
1488 
1489     if (!RB_TYPE_P(module, T_MODULE)) {
1490         rb_raise(rb_eTypeError, "module_function must be called for modules");
1491     }
1492 
1493     if (argc == 0) {
1494         SCOPE_SET(NOEX_MODFUNC);
1495         return module;
1496     }
1497 
1498     set_method_visibility(module, argc, argv, NOEX_PRIVATE);
1499 
1500     for (i = 0; i < argc; i++) {
1501         VALUE m = module;
1502 
1503         id = rb_to_id(argv[i]);
1504         for (;;) {
1505             me = search_method(m, id, 0);
1506             if (me == 0) {
1507                 me = search_method(rb_cObject, id, 0);
1508             }
1509             if (UNDEFINED_METHOD_ENTRY_P(me)) {
1510                 rb_print_undef(module, id, 0);
1511             }
1512             if (me->def->type != VM_METHOD_TYPE_ZSUPER) {
1513                 break; /* normal case: need not to follow 'super' link */
1514             }
1515             m = RCLASS_SUPER(m);
1516             if (!m)
1517                 break;
1518         }
1519         rb_method_entry_set(rb_singleton_class(module), id, me, NOEX_PUBLIC);
1520     }
1521     return module;
1522 }
1523 
1524 int
1525 rb_method_basic_definition_p(VALUE klass, ID id)
1526 {
1527     const rb_method_entry_t *me = rb_method_entry(klass, id, 0);
1528     if (me && (me->flag & NOEX_BASIC))
1529         return 1;
1530     return 0;
1531 }
1532 
1533 static inline int
1534 basic_obj_respond_to(VALUE obj, ID id, int pub)
1535 {
1536     VALUE klass = CLASS_OF(obj);
1537     VALUE args[2];
1538 
1539     switch (rb_method_boundp(klass, id, pub|NOEX_RESPONDS)) {
1540       case 2:
1541         return FALSE;
1542       case 0:
1543         args[0] = ID2SYM(id);
1544         args[1] = pub ? Qfalse : Qtrue;
1545         return RTEST(rb_funcall2(obj, idRespond_to_missing, 2, args));
1546       default:
1547         return TRUE;
1548     }
1549 }
1550 
1551 int
1552 rb_obj_respond_to(VALUE obj, ID id, int priv)
1553 {
1554     VALUE klass = CLASS_OF(obj);
1555 
1556     if (rb_method_basic_definition_p(klass, idRespond_to)) {
1557         return basic_obj_respond_to(obj, id, !RTEST(priv));
1558     }
1559     else {
1560         int argc = 1;
1561         VALUE args[2];
1562         args[0] = ID2SYM(id);
1563         args[1] = Qtrue;
1564         if (priv) {
1565             if (rb_obj_method_arity(obj, idRespond_to) != 1) {
1566                 argc = 2;
1567             }
1568             else if (!NIL_P(ruby_verbose)) {
1569                 VALUE klass = CLASS_OF(obj);
1570                 VALUE location = rb_mod_method_location(klass, idRespond_to);
1571                 rb_warn("%"PRIsVALUE"%c""respond_to?(:%"PRIsVALUE") is"
1572                         " old fashion which takes only one parameter",
1573                         (FL_TEST(klass, FL_SINGLETON) ? obj : klass),
1574                         (FL_TEST(klass, FL_SINGLETON) ? '.' : '#'),
1575                         QUOTE_ID(id));
1576                 if (!NIL_P(location)) {
1577                     VALUE path = RARRAY_AREF(location, 0);
1578                     VALUE line = RARRAY_AREF(location, 1);
1579                     if (!NIL_P(path)) {
1580                         rb_compile_warn(RSTRING_PTR(path), NUM2INT(line),
1581                                         "respond_to? is defined here");
1582                     }
1583                 }
1584             }
1585         }
1586         return RTEST(rb_funcall2(obj, idRespond_to, argc,  args));
1587     }
1588 }
1589 
1590 int
1591 rb_respond_to(VALUE obj, ID id)
1592 {
1593     return rb_obj_respond_to(obj, id, FALSE);
1594 }
1595 
1596 
1597 /*
1598  *  call-seq:
1599  *     obj.respond_to?(symbol, include_all=false) -> true or false
1600  *     obj.respond_to?(string, include_all=false) -> true or false
1601  *
1602  *  Returns +true+ if _obj_ responds to the given method.  Private and
1603  *  protected methods are included in the search only if the optional
1604  *  second parameter evaluates to +true+.
1605  *
1606  *  If the method is not implemented,
1607  *  as Process.fork on Windows, File.lchmod on GNU/Linux, etc.,
1608  *  false is returned.
1609  *
1610  *  If the method is not defined, <code>respond_to_missing?</code>
1611  *  method is called and the result is returned.
1612  *
1613  *  When the method name parameter is given as a string, the string is
1614  *  converted to a symbol.
1615  */
1616 
1617 static VALUE
1618 obj_respond_to(int argc, VALUE *argv, VALUE obj)
1619 {
1620     VALUE mid, priv;
1621     ID id;
1622 
1623     rb_scan_args(argc, argv, "11", &mid, &priv);
1624     if (!(id = rb_check_id(&mid))) {
1625         if (!rb_method_basic_definition_p(CLASS_OF(obj), idRespond_to_missing)) {
1626             VALUE args[2];
1627             args[0] = ID2SYM(rb_to_id(mid));
1628             args[1] = priv;
1629             return rb_funcall2(obj, idRespond_to_missing, 2, args);
1630         }
1631         return Qfalse;
1632     }
1633     if (basic_obj_respond_to(obj, id, !RTEST(priv)))
1634         return Qtrue;
1635     return Qfalse;
1636 }
1637 
1638 /*
1639  *  call-seq:
1640  *     obj.respond_to_missing?(symbol, include_all) -> true or false
1641  *     obj.respond_to_missing?(string, include_all) -> true or false
1642  *
1643  *  DO NOT USE THIS DIRECTLY.
1644  *
1645  *  Hook method to return whether the _obj_ can respond to _id_ method
1646  *  or not.
1647  *
1648  *  When the method name parameter is given as a string, the string is
1649  *  converted to a symbol.
1650  *
1651  *  See #respond_to?.
1652  */
1653 static VALUE
1654 obj_respond_to_missing(VALUE obj, VALUE mid, VALUE priv)
1655 {
1656     return Qfalse;
1657 }
1658 
1659 void
1660 Init_eval_method(void)
1661 {
1662 #undef rb_intern
1663 #define rb_intern(str) rb_intern_const(str)
1664 
1665     rb_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1);
1666     rb_define_method(rb_mKernel, "respond_to_missing?", obj_respond_to_missing, 2);
1667 
1668     rb_define_private_method(rb_cModule, "remove_method", rb_mod_remove_method, -1);
1669     rb_define_private_method(rb_cModule, "undef_method", rb_mod_undef_method, -1);
1670     rb_define_private_method(rb_cModule, "alias_method", rb_mod_alias_method, 2);
1671     rb_define_private_method(rb_cModule, "public", rb_mod_public, -1);
1672     rb_define_private_method(rb_cModule, "protected", rb_mod_protected, -1);
1673     rb_define_private_method(rb_cModule, "private", rb_mod_private, -1);
1674     rb_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1);
1675 
1676     rb_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, 1);
1677     rb_define_method(rb_cModule, "public_method_defined?", rb_mod_public_method_defined, 1);
1678     rb_define_method(rb_cModule, "private_method_defined?", rb_mod_private_method_defined, 1);
1679     rb_define_method(rb_cModule, "protected_method_defined?", rb_mod_protected_method_defined, 1);
1680     rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1);
1681     rb_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1);
1682 
1683     rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
1684                              "public", top_public, -1);
1685     rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
1686                              "private", top_private, -1);
1687 
1688     {
1689 #define REPLICATE_METHOD(klass, id, noex) \
1690         rb_method_entry_set((klass), (id), \
1691                             rb_method_entry((klass), (id), 0), \
1692                             (rb_method_flag_t)(noex | NOEX_BASIC | NOEX_NOREDEF))
1693         REPLICATE_METHOD(rb_eException, idMethodMissing, NOEX_PRIVATE);
1694         REPLICATE_METHOD(rb_eException, idRespond_to, NOEX_PUBLIC);
1695         REPLICATE_METHOD(rb_eException, idRespond_to_missing, NOEX_PUBLIC);
1696     }
1697 }