Ruby 2.0.0p247(2013-06-27revision41674)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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