00001
00002
00003
00004
00005 #ifndef GLOBAL_METHOD_CACHE_SIZE
00006 #define GLOBAL_METHOD_CACHE_SIZE 0x800
00007 #endif
00008 #ifndef GLOBAL_METHOD_CACHE_MASK
00009 #define GLOBAL_METHOD_CACHE_MASK 0x7ff
00010 #endif
00011
00012 #define GLOBAL_METHOD_CACHE_KEY(c,m) ((((c)>>3)^(m))&GLOBAL_METHOD_CACHE_MASK)
00013 #define GLOBAL_METHOD_CACHE(c,m) (global_method_cache + GLOBAL_METHOD_CACHE_KEY(c,m))
00014 #include "method.h"
00015
00016 #define NOEX_NOREDEF 0
00017 #ifndef NOEX_NOREDEF
00018 #define NOEX_NOREDEF NOEX_RESPONDS
00019 #endif
00020
00021 static void rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me, VALUE klass);
00022
00023 #define object_id idObject_id
00024 #define added idMethod_added
00025 #define singleton_added idSingleton_method_added
00026 #define removed idMethod_removed
00027 #define singleton_removed idSingleton_method_removed
00028 #define undefined idMethod_undefined
00029 #define singleton_undefined idSingleton_method_undefined
00030 #define attached id__attached__
00031
00032 struct cache_entry {
00033 rb_serial_t method_state;
00034 rb_serial_t class_serial;
00035 ID mid;
00036 rb_method_entry_t* me;
00037 VALUE defined_class;
00038 };
00039
00040 static struct cache_entry global_method_cache[GLOBAL_METHOD_CACHE_SIZE];
00041 #define ruby_running (GET_VM()->running)
00042
00043
00044 static void
00045 rb_class_clear_method_cache(VALUE klass)
00046 {
00047 RCLASS_SERIAL(klass) = rb_next_class_serial();
00048 rb_class_foreach_subclass(klass, rb_class_clear_method_cache);
00049 }
00050
00051 void
00052 rb_clear_cache(void)
00053 {
00054 rb_warning("rb_clear_cache() is deprecated.");
00055 INC_GLOBAL_METHOD_STATE();
00056 INC_GLOBAL_CONSTANT_STATE();
00057 }
00058
00059 void
00060 rb_clear_constant_cache(void)
00061 {
00062 INC_GLOBAL_CONSTANT_STATE();
00063 }
00064
00065 void
00066 rb_clear_method_cache_by_class(VALUE klass)
00067 {
00068 if (klass && klass != Qundef) {
00069 int global = klass == rb_cBasicObject || klass == rb_cObject || klass == rb_mKernel;
00070
00071 if (RUBY_DTRACE_METHOD_CACHE_CLEAR_ENABLED()) {
00072 RUBY_DTRACE_METHOD_CACHE_CLEAR(global ? "global" : rb_class2name(klass), rb_sourcefile(), rb_sourceline());
00073 }
00074
00075 if (global) {
00076 INC_GLOBAL_METHOD_STATE();
00077 }
00078 else {
00079 rb_class_clear_method_cache(klass);
00080 }
00081 }
00082 }
00083
00084 VALUE
00085 rb_f_notimplement(int argc, VALUE *argv, VALUE obj)
00086 {
00087 rb_notimplement();
00088
00089 UNREACHABLE;
00090 }
00091
00092 static void
00093 rb_define_notimplement_method_id(VALUE mod, ID id, rb_method_flag_t noex)
00094 {
00095 rb_add_method(mod, id, VM_METHOD_TYPE_NOTIMPLEMENTED, 0, noex);
00096 }
00097
00098 void
00099 rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_flag_t noex)
00100 {
00101 if (argc < -2 || 15 < argc) rb_raise(rb_eArgError, "arity out of range: %d for -2..15", argc);
00102 if (func != rb_f_notimplement) {
00103 rb_method_cfunc_t opt;
00104 opt.func = func;
00105 opt.argc = argc;
00106 rb_add_method(klass, mid, VM_METHOD_TYPE_CFUNC, &opt, noex);
00107 }
00108 else {
00109 rb_define_notimplement_method_id(klass, mid, noex);
00110 }
00111 }
00112
00113 void
00114 rb_unlink_method_entry(rb_method_entry_t *me)
00115 {
00116 struct unlinked_method_entry_list_entry *ume = ALLOC(struct unlinked_method_entry_list_entry);
00117 ume->me = me;
00118 ume->next = GET_VM()->unlinked_method_entry_list;
00119 GET_VM()->unlinked_method_entry_list = ume;
00120 }
00121
00122 void
00123 rb_gc_mark_unlinked_live_method_entries(void *pvm)
00124 {
00125 rb_vm_t *vm = pvm;
00126 struct unlinked_method_entry_list_entry *ume = vm->unlinked_method_entry_list;
00127
00128 while (ume) {
00129 if (ume->me->mark) {
00130 rb_mark_method_entry(ume->me);
00131 }
00132 ume = ume->next;
00133 }
00134 }
00135
00136 void
00137 rb_sweep_method_entry(void *pvm)
00138 {
00139 rb_vm_t *vm = pvm;
00140 struct unlinked_method_entry_list_entry **prev_ume = &vm->unlinked_method_entry_list, *ume = *prev_ume, *curr_ume;
00141
00142 while (ume) {
00143 if (ume->me->mark) {
00144 ume->me->mark = 0;
00145 prev_ume = &ume->next;
00146 ume = *prev_ume;
00147 }
00148 else {
00149 rb_free_method_entry(ume->me);
00150
00151 curr_ume = ume;
00152 ume = ume->next;
00153 *prev_ume = ume;
00154 xfree(curr_ume);
00155 }
00156 }
00157 }
00158
00159 static void
00160 release_method_definition(rb_method_definition_t *def)
00161 {
00162 if (def == 0)
00163 return;
00164 if (def->alias_count == 0) {
00165 if (def->type == VM_METHOD_TYPE_REFINED &&
00166 def->body.orig_me) {
00167 release_method_definition(def->body.orig_me->def);
00168 xfree(def->body.orig_me);
00169 }
00170 xfree(def);
00171 }
00172 else if (def->alias_count > 0) {
00173 def->alias_count--;
00174 }
00175 }
00176
00177 void
00178 rb_free_method_entry(rb_method_entry_t *me)
00179 {
00180 release_method_definition(me->def);
00181 xfree(me);
00182 }
00183
00184 static inline rb_method_entry_t *search_method(VALUE klass, ID id, VALUE *defined_class_ptr);
00185 static int rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2);
00186
00187 static inline rb_method_entry_t *
00188 lookup_method_table(VALUE klass, ID id)
00189 {
00190 st_data_t body;
00191 st_table *m_tbl = RCLASS_M_TBL(klass);
00192 if (st_lookup(m_tbl, id, &body)) {
00193 return (rb_method_entry_t *) body;
00194 }
00195 else {
00196 return 0;
00197 }
00198 }
00199
00200 static void
00201 make_method_entry_refined(rb_method_entry_t *me)
00202 {
00203 rb_method_definition_t *new_def;
00204
00205 if (me->def && me->def->type == VM_METHOD_TYPE_REFINED)
00206 return;
00207
00208 new_def = ALLOC(rb_method_definition_t);
00209 new_def->type = VM_METHOD_TYPE_REFINED;
00210 new_def->original_id = me->called_id;
00211 new_def->alias_count = 0;
00212 new_def->body.orig_me = ALLOC(rb_method_entry_t);
00213 *new_def->body.orig_me = *me;
00214 rb_vm_check_redefinition_opt_method(me, me->klass);
00215 if (me->def) me->def->alias_count++;
00216 me->flag = NOEX_WITH_SAFE(NOEX_PUBLIC);
00217 me->def = new_def;
00218 }
00219
00220 void
00221 rb_add_refined_method_entry(VALUE refined_class, ID mid)
00222 {
00223 rb_method_entry_t *me = lookup_method_table(refined_class, mid);
00224
00225 if (me) {
00226 make_method_entry_refined(me);
00227 rb_clear_method_cache_by_class(refined_class);
00228 }
00229 else {
00230 rb_add_method(refined_class, mid, VM_METHOD_TYPE_REFINED, 0,
00231 NOEX_PUBLIC);
00232 }
00233 }
00234
00235 static rb_method_entry_t *
00236 rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type,
00237 rb_method_definition_t *def, rb_method_flag_t noex,
00238 VALUE defined_class)
00239 {
00240 rb_method_entry_t *me;
00241 #if NOEX_NOREDEF
00242 VALUE rklass;
00243 #endif
00244 st_table *mtbl;
00245 st_data_t data;
00246 int make_refined = 0;
00247
00248 if (NIL_P(klass)) {
00249 klass = rb_cObject;
00250 }
00251 if (!FL_TEST(klass, FL_SINGLETON) &&
00252 type != VM_METHOD_TYPE_NOTIMPLEMENTED &&
00253 type != VM_METHOD_TYPE_ZSUPER &&
00254 (mid == idInitialize || mid == idInitialize_copy ||
00255 mid == idInitialize_clone || mid == idInitialize_dup ||
00256 mid == idRespond_to_missing)) {
00257 noex = NOEX_PRIVATE | noex;
00258 }
00259
00260 rb_check_frozen(klass);
00261 #if NOEX_NOREDEF
00262 rklass = klass;
00263 #endif
00264 if (FL_TEST(klass, RMODULE_IS_REFINEMENT)) {
00265 VALUE refined_class =
00266 rb_refinement_module_get_refined_class(klass);
00267
00268 rb_add_refined_method_entry(refined_class, mid);
00269 }
00270 if (type == VM_METHOD_TYPE_REFINED) {
00271 rb_method_entry_t *old_me =
00272 lookup_method_table(RCLASS_ORIGIN(klass), mid);
00273 if (old_me) rb_vm_check_redefinition_opt_method(old_me, klass);
00274 }
00275 else {
00276 klass = RCLASS_ORIGIN(klass);
00277 }
00278 mtbl = RCLASS_M_TBL(klass);
00279
00280
00281 if (st_lookup(mtbl, mid, &data)) {
00282 rb_method_entry_t *old_me = (rb_method_entry_t *)data;
00283 rb_method_definition_t *old_def = old_me->def;
00284
00285 if (rb_method_definition_eq(old_def, def)) return old_me;
00286 #if NOEX_NOREDEF
00287 if (old_me->flag & NOEX_NOREDEF) {
00288 rb_raise(rb_eTypeError, "cannot redefine %"PRIsVALUE"#%"PRIsVALUE,
00289 rb_class_name(rklass), rb_id2str(mid));
00290 }
00291 #endif
00292 rb_vm_check_redefinition_opt_method(old_me, klass);
00293 if (old_def->type == VM_METHOD_TYPE_REFINED)
00294 make_refined = 1;
00295
00296 if (RTEST(ruby_verbose) &&
00297 type != VM_METHOD_TYPE_UNDEF &&
00298 old_def->alias_count == 0 &&
00299 old_def->type != VM_METHOD_TYPE_UNDEF &&
00300 old_def->type != VM_METHOD_TYPE_ZSUPER) {
00301 rb_iseq_t *iseq = 0;
00302
00303 rb_warning("method redefined; discarding old %s", rb_id2name(mid));
00304 switch (old_def->type) {
00305 case VM_METHOD_TYPE_ISEQ:
00306 iseq = old_def->body.iseq;
00307 break;
00308 case VM_METHOD_TYPE_BMETHOD:
00309 iseq = rb_proc_get_iseq(old_def->body.proc, 0);
00310 break;
00311 default:
00312 break;
00313 }
00314 if (iseq && !NIL_P(iseq->location.path)) {
00315 int line = iseq->line_info_table ? FIX2INT(rb_iseq_first_lineno(iseq->self)) : 0;
00316 rb_compile_warning(RSTRING_PTR(iseq->location.path), line,
00317 "previous definition of %s was here",
00318 rb_id2name(old_def->original_id));
00319 }
00320 }
00321
00322 rb_unlink_method_entry(old_me);
00323 }
00324
00325 me = ALLOC(rb_method_entry_t);
00326
00327 rb_clear_method_cache_by_class(klass);
00328
00329 me->flag = NOEX_WITH_SAFE(noex);
00330 me->mark = 0;
00331 me->called_id = mid;
00332 RB_OBJ_WRITE(klass, &me->klass, defined_class);
00333 me->def = def;
00334
00335 if (def) {
00336 def->alias_count++;
00337
00338 switch(def->type) {
00339 case VM_METHOD_TYPE_ISEQ:
00340 RB_OBJ_WRITTEN(klass, Qundef, def->body.iseq->self);
00341 break;
00342 case VM_METHOD_TYPE_IVAR:
00343 RB_OBJ_WRITTEN(klass, Qundef, def->body.attr.location);
00344 break;
00345 case VM_METHOD_TYPE_BMETHOD:
00346 RB_OBJ_WRITTEN(klass, Qundef, def->body.proc);
00347 break;
00348 default:;
00349
00350 }
00351 }
00352
00353
00354 if (klass == rb_cObject && mid == idInitialize) {
00355 rb_warn("redefining Object#initialize may cause infinite loop");
00356 }
00357
00358 if (mid == object_id || mid == id__send__) {
00359 if (type == VM_METHOD_TYPE_ISEQ && search_method(klass, mid, 0)) {
00360 rb_warn("redefining `%s' may cause serious problems", rb_id2name(mid));
00361 }
00362 }
00363
00364 if (make_refined) {
00365 make_method_entry_refined(me);
00366 }
00367
00368 st_insert(mtbl, mid, (st_data_t) me);
00369
00370 return me;
00371 }
00372
00373 #define CALL_METHOD_HOOK(klass, hook, mid) do { \
00374 const VALUE arg = ID2SYM(mid); \
00375 VALUE recv_class = (klass); \
00376 ID hook_id = (hook); \
00377 if (FL_TEST((klass), FL_SINGLETON)) { \
00378 recv_class = rb_ivar_get((klass), attached); \
00379 hook_id = singleton_##hook; \
00380 } \
00381 rb_funcall2(recv_class, hook_id, 1, &arg); \
00382 } while (0)
00383
00384 static void
00385 method_added(VALUE klass, ID mid)
00386 {
00387 if (ruby_running) {
00388 CALL_METHOD_HOOK(klass, added, mid);
00389 }
00390 }
00391
00392 static VALUE
00393 (*call_cfunc_invoker_func(int argc))(VALUE (*func)(ANYARGS), VALUE recv, int argc, const VALUE *)
00394 {
00395 switch (argc) {
00396 case -2: return &call_cfunc_m2;
00397 case -1: return &call_cfunc_m1;
00398 case 0: return &call_cfunc_0;
00399 case 1: return &call_cfunc_1;
00400 case 2: return &call_cfunc_2;
00401 case 3: return &call_cfunc_3;
00402 case 4: return &call_cfunc_4;
00403 case 5: return &call_cfunc_5;
00404 case 6: return &call_cfunc_6;
00405 case 7: return &call_cfunc_7;
00406 case 8: return &call_cfunc_8;
00407 case 9: return &call_cfunc_9;
00408 case 10: return &call_cfunc_10;
00409 case 11: return &call_cfunc_11;
00410 case 12: return &call_cfunc_12;
00411 case 13: return &call_cfunc_13;
00412 case 14: return &call_cfunc_14;
00413 case 15: return &call_cfunc_15;
00414 default:
00415 rb_bug("call_cfunc_func: unsupported length: %d", argc);
00416 }
00417 }
00418
00419 static void
00420 setup_method_cfunc_struct(rb_method_cfunc_t *cfunc, VALUE (*func)(), int argc)
00421 {
00422 cfunc->func = func;
00423 cfunc->argc = argc;
00424 cfunc->invoker = call_cfunc_invoker_func(argc);
00425 }
00426
00427 rb_method_entry_t *
00428 rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_flag_t noex)
00429 {
00430 rb_thread_t *th;
00431 rb_control_frame_t *cfp;
00432 int line;
00433 rb_method_entry_t *me = rb_method_entry_make(klass, mid, type, 0, noex, klass);
00434 rb_method_definition_t *def = ALLOC(rb_method_definition_t);
00435 if (me->def && me->def->type == VM_METHOD_TYPE_REFINED) {
00436 me->def->body.orig_me->def = def;
00437 }
00438 else {
00439 me->def = def;
00440 }
00441 def->type = type;
00442 def->original_id = mid;
00443 def->alias_count = 0;
00444 switch (type) {
00445 case VM_METHOD_TYPE_ISEQ: {
00446 rb_iseq_t *iseq = (rb_iseq_t *)opts;
00447 *(rb_iseq_t **)&def->body.iseq = iseq;
00448 RB_OBJ_WRITTEN(klass, Qundef, iseq->self);
00449 break;
00450 }
00451 case VM_METHOD_TYPE_CFUNC:
00452 {
00453 rb_method_cfunc_t *cfunc = (rb_method_cfunc_t *)opts;
00454 setup_method_cfunc_struct(&def->body.cfunc, cfunc->func, cfunc->argc);
00455 }
00456 break;
00457 case VM_METHOD_TYPE_ATTRSET:
00458 case VM_METHOD_TYPE_IVAR:
00459 def->body.attr.id = (ID)opts;
00460 RB_OBJ_WRITE(klass, &def->body.attr.location, Qfalse);
00461 th = GET_THREAD();
00462 cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
00463 if (cfp && (line = rb_vm_get_sourceline(cfp))) {
00464 VALUE location = rb_ary_new3(2, cfp->iseq->location.path, INT2FIX(line));
00465 RB_OBJ_WRITE(klass, &def->body.attr.location, rb_ary_freeze(location));
00466 }
00467 break;
00468 case VM_METHOD_TYPE_BMETHOD:
00469 RB_OBJ_WRITE(klass, &def->body.proc, (VALUE)opts);
00470 break;
00471 case VM_METHOD_TYPE_NOTIMPLEMENTED:
00472 setup_method_cfunc_struct(&def->body.cfunc, rb_f_notimplement, -1);
00473 break;
00474 case VM_METHOD_TYPE_OPTIMIZED:
00475 def->body.optimize_type = (enum method_optimized_type)opts;
00476 break;
00477 case VM_METHOD_TYPE_ZSUPER:
00478 case VM_METHOD_TYPE_UNDEF:
00479 break;
00480 case VM_METHOD_TYPE_REFINED:
00481 def->body.orig_me = (rb_method_entry_t *) opts;
00482 break;
00483 default:
00484 rb_bug("rb_add_method: unsupported method type (%d)\n", type);
00485 }
00486 if (type != VM_METHOD_TYPE_UNDEF && type != VM_METHOD_TYPE_REFINED) {
00487 method_added(klass, mid);
00488 }
00489 return me;
00490 }
00491
00492 static rb_method_entry_t *
00493 method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me,
00494 rb_method_flag_t noex, VALUE defined_class)
00495 {
00496 rb_method_type_t type = me->def ? me->def->type : VM_METHOD_TYPE_UNDEF;
00497 rb_method_entry_t *newme = rb_method_entry_make(klass, mid, type, me->def, noex,
00498 defined_class);
00499 method_added(klass, mid);
00500 return newme;
00501 }
00502
00503 rb_method_entry_t *
00504 rb_method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me, rb_method_flag_t noex)
00505 {
00506 return method_entry_set(klass, mid, me, noex, klass);
00507 }
00508
00509 #define UNDEF_ALLOC_FUNC ((rb_alloc_func_t)-1)
00510
00511 void
00512 rb_define_alloc_func(VALUE klass, VALUE (*func)(VALUE))
00513 {
00514 Check_Type(klass, T_CLASS);
00515 RCLASS_EXT(klass)->allocator = func;
00516 }
00517
00518 void
00519 rb_undef_alloc_func(VALUE klass)
00520 {
00521 rb_define_alloc_func(klass, UNDEF_ALLOC_FUNC);
00522 }
00523
00524 rb_alloc_func_t
00525 rb_get_alloc_func(VALUE klass)
00526 {
00527 Check_Type(klass, T_CLASS);
00528
00529 for (; klass; klass = RCLASS_SUPER(klass)) {
00530 rb_alloc_func_t allocator = RCLASS_EXT(klass)->allocator;
00531 if (allocator == UNDEF_ALLOC_FUNC) break;
00532 if (allocator) return allocator;
00533 }
00534 return 0;
00535 }
00536
00537 static inline rb_method_entry_t*
00538 search_method(VALUE klass, ID id, VALUE *defined_class_ptr)
00539 {
00540 rb_method_entry_t *me;
00541
00542 for (me = 0; klass; klass = RCLASS_SUPER(klass)) {
00543 if ((me = lookup_method_table(klass, id)) != 0) break;
00544 }
00545
00546 if (defined_class_ptr)
00547 *defined_class_ptr = klass;
00548 return me;
00549 }
00550
00551 rb_method_entry_t *
00552 rb_method_entry_at(VALUE klass, ID id)
00553 {
00554 return lookup_method_table(klass, id);
00555 }
00556
00557
00558
00559
00560
00561
00562
00563 rb_method_entry_t *
00564 rb_method_entry_get_without_cache(VALUE klass, ID id,
00565 VALUE *defined_class_ptr)
00566 {
00567 VALUE defined_class;
00568 rb_method_entry_t *me = search_method(klass, id, &defined_class);
00569
00570 if (me && me->klass) {
00571 switch (BUILTIN_TYPE(me->klass)) {
00572 case T_CLASS:
00573 if (RBASIC(klass)->flags & FL_SINGLETON) break;
00574
00575 case T_ICLASS:
00576 defined_class = me->klass;
00577 }
00578 }
00579
00580 if (ruby_running) {
00581 struct cache_entry *ent;
00582 ent = GLOBAL_METHOD_CACHE(klass, id);
00583 ent->class_serial = RCLASS_EXT(klass)->class_serial;
00584 ent->method_state = GET_GLOBAL_METHOD_STATE();
00585 ent->defined_class = defined_class;
00586 ent->mid = id;
00587
00588 if (UNDEFINED_METHOD_ENTRY_P(me)) {
00589 ent->me = 0;
00590 me = 0;
00591 }
00592 else {
00593 ent->me = me;
00594 }
00595 }
00596
00597 if (defined_class_ptr)
00598 *defined_class_ptr = defined_class;
00599 return me;
00600 }
00601
00602 #if VM_DEBUG_VERIFY_METHOD_CACHE
00603 static void
00604 verify_method_cache(VALUE klass, ID id, VALUE defined_class, rb_method_entry_t *me)
00605 {
00606 VALUE actual_defined_class;
00607 rb_method_entry_t *actual_me =
00608 rb_method_entry_get_without_cache(klass, id, &actual_defined_class);
00609
00610 if (me != actual_me || defined_class != actual_defined_class) {
00611 rb_bug("method cache verification failed");
00612 }
00613 }
00614 #endif
00615
00616 rb_method_entry_t *
00617 rb_method_entry(VALUE klass, ID id, VALUE *defined_class_ptr)
00618 {
00619 #if OPT_GLOBAL_METHOD_CACHE
00620 struct cache_entry *ent;
00621 ent = GLOBAL_METHOD_CACHE(klass, id);
00622 if (ent->method_state == GET_GLOBAL_METHOD_STATE() &&
00623 ent->class_serial == RCLASS_EXT(klass)->class_serial &&
00624 ent->mid == id) {
00625 if (defined_class_ptr)
00626 *defined_class_ptr = ent->defined_class;
00627 #if VM_DEBUG_VERIFY_METHOD_CACHE
00628 verify_method_cache(klass, id, ent->defined_class, ent->me);
00629 #endif
00630 return ent->me;
00631 }
00632 #endif
00633
00634 return rb_method_entry_get_without_cache(klass, id, defined_class_ptr);
00635 }
00636
00637 static rb_method_entry_t *
00638 get_original_method_entry(VALUE refinements,
00639 const rb_method_entry_t *me,
00640 VALUE *defined_class_ptr)
00641 {
00642 VALUE super;
00643
00644 if (me->def->body.orig_me) {
00645 return me->def->body.orig_me;
00646 }
00647 else if (!(super = RCLASS_SUPER(me->klass))) {
00648 return 0;
00649 }
00650 else {
00651 rb_method_entry_t *tmp_me;
00652 tmp_me = rb_method_entry(super, me->called_id,
00653 defined_class_ptr);
00654 return rb_resolve_refined_method(refinements, tmp_me,
00655 defined_class_ptr);
00656 }
00657 }
00658
00659 rb_method_entry_t *
00660 rb_resolve_refined_method(VALUE refinements, const rb_method_entry_t *me,
00661 VALUE *defined_class_ptr)
00662 {
00663 if (me && me->def->type == VM_METHOD_TYPE_REFINED) {
00664 VALUE refinement;
00665 rb_method_entry_t *tmp_me;
00666
00667 refinement = find_refinement(refinements, me->klass);
00668 if (NIL_P(refinement)) {
00669 return get_original_method_entry(refinements, me,
00670 defined_class_ptr);
00671 }
00672 tmp_me = rb_method_entry(refinement, me->called_id,
00673 defined_class_ptr);
00674 if (tmp_me && tmp_me->def->type != VM_METHOD_TYPE_REFINED) {
00675 return tmp_me;
00676 }
00677 else {
00678 return get_original_method_entry(refinements, me,
00679 defined_class_ptr);
00680 }
00681 }
00682 else {
00683 return (rb_method_entry_t *)me;
00684 }
00685 }
00686
00687 rb_method_entry_t *
00688 rb_method_entry_with_refinements(VALUE klass, ID id,
00689 VALUE *defined_class_ptr)
00690 {
00691 VALUE defined_class;
00692 rb_method_entry_t *me = rb_method_entry(klass, id, &defined_class);
00693
00694 if (me && me->def->type == VM_METHOD_TYPE_REFINED) {
00695 NODE *cref = rb_vm_cref();
00696 VALUE refinements = cref ? cref->nd_refinements : Qnil;
00697
00698 me = rb_resolve_refined_method(refinements, me, &defined_class);
00699 }
00700 if (defined_class_ptr)
00701 *defined_class_ptr = defined_class;
00702 return me;
00703 }
00704
00705 rb_method_entry_t *
00706 rb_method_entry_without_refinements(VALUE klass, ID id,
00707 VALUE *defined_class_ptr)
00708 {
00709 VALUE defined_class;
00710 rb_method_entry_t *me = rb_method_entry(klass, id, &defined_class);
00711
00712 if (me && me->def->type == VM_METHOD_TYPE_REFINED) {
00713 me = rb_resolve_refined_method(Qnil, me, &defined_class);
00714 }
00715 if (defined_class_ptr)
00716 *defined_class_ptr = defined_class;
00717 if (UNDEFINED_METHOD_ENTRY_P(me)) {
00718 return 0;
00719 }
00720 else {
00721 return me;
00722 }
00723 }
00724
00725 static void
00726 remove_method(VALUE klass, ID mid)
00727 {
00728 st_data_t key, data;
00729 rb_method_entry_t *me = 0;
00730 VALUE self = klass;
00731
00732 klass = RCLASS_ORIGIN(klass);
00733 rb_check_frozen(klass);
00734 if (mid == object_id || mid == id__send__ || mid == idInitialize) {
00735 rb_warn("removing `%s' may cause serious problems", rb_id2name(mid));
00736 }
00737
00738 if (!st_lookup(RCLASS_M_TBL(klass), mid, &data) ||
00739 !(me = (rb_method_entry_t *)data) ||
00740 (!me->def || me->def->type == VM_METHOD_TYPE_UNDEF) ||
00741 UNDEFINED_REFINED_METHOD_P(me->def)) {
00742 rb_name_error(mid, "method `%s' not defined in %s",
00743 rb_id2name(mid), rb_class2name(klass));
00744 }
00745
00746 key = (st_data_t)mid;
00747 st_delete(RCLASS_M_TBL(klass), &key, &data);
00748
00749 rb_vm_check_redefinition_opt_method(me, klass);
00750 rb_clear_method_cache_by_class(klass);
00751 rb_unlink_method_entry(me);
00752
00753 if (me->def->type == VM_METHOD_TYPE_REFINED) {
00754 rb_add_refined_method_entry(klass, mid);
00755 }
00756
00757 CALL_METHOD_HOOK(self, removed, mid);
00758 }
00759
00760 void
00761 rb_remove_method_id(VALUE klass, ID mid)
00762 {
00763 remove_method(klass, mid);
00764 }
00765
00766 void
00767 rb_remove_method(VALUE klass, const char *name)
00768 {
00769 remove_method(klass, rb_intern(name));
00770 }
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782 static VALUE
00783 rb_mod_remove_method(int argc, VALUE *argv, VALUE mod)
00784 {
00785 int i;
00786
00787 for (i = 0; i < argc; i++) {
00788 VALUE v = argv[i];
00789 ID id = rb_check_id(&v);
00790 if (!id) {
00791 rb_name_error_str(v, "method `%s' not defined in %s",
00792 RSTRING_PTR(v), rb_class2name(mod));
00793 }
00794 remove_method(mod, id);
00795 }
00796 return mod;
00797 }
00798
00799 #undef rb_disable_super
00800 #undef rb_enable_super
00801
00802 void
00803 rb_disable_super(VALUE klass, const char *name)
00804 {
00805
00806 }
00807
00808 void
00809 rb_enable_super(VALUE klass, const char *name)
00810 {
00811 rb_warning("rb_enable_super() is obsolete");
00812 }
00813
00814 static void
00815 rb_export_method(VALUE klass, ID name, rb_method_flag_t noex)
00816 {
00817 rb_method_entry_t *me;
00818 VALUE defined_class;
00819
00820 me = search_method(klass, name, &defined_class);
00821 if (!me && RB_TYPE_P(klass, T_MODULE)) {
00822 me = search_method(rb_cObject, name, &defined_class);
00823 }
00824
00825 if (UNDEFINED_METHOD_ENTRY_P(me) ||
00826 UNDEFINED_REFINED_METHOD_P(me->def)) {
00827 rb_print_undef(klass, name, 0);
00828 }
00829
00830 if (me->flag != noex) {
00831 rb_vm_check_redefinition_opt_method(me, klass);
00832
00833 if (klass == defined_class ||
00834 RCLASS_ORIGIN(klass) == defined_class) {
00835 me->flag = noex;
00836 if (me->def->type == VM_METHOD_TYPE_REFINED) {
00837 me->def->body.orig_me->flag = noex;
00838 }
00839 rb_clear_method_cache_by_class(klass);
00840 }
00841 else {
00842 rb_add_method(klass, name, VM_METHOD_TYPE_ZSUPER, 0, noex);
00843 }
00844 }
00845 }
00846
00847 int
00848 rb_method_boundp(VALUE klass, ID id, int ex)
00849 {
00850 rb_method_entry_t *me =
00851 rb_method_entry_without_refinements(klass, id, 0);
00852
00853 if (me != 0) {
00854 if ((ex & ~NOEX_RESPONDS) &&
00855 ((me->flag & NOEX_PRIVATE) ||
00856 ((ex & NOEX_RESPONDS) && (me->flag & NOEX_PROTECTED)))) {
00857 return 0;
00858 }
00859 if (!me->def) return 0;
00860 if (me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) {
00861 if (ex & NOEX_RESPONDS) return 2;
00862 return 0;
00863 }
00864 return 1;
00865 }
00866 return 0;
00867 }
00868
00869 extern ID rb_check_attr_id(ID id);
00870
00871 void
00872 rb_attr(VALUE klass, ID id, int read, int write, int ex)
00873 {
00874 ID attriv;
00875 VALUE aname;
00876 rb_method_flag_t noex;
00877
00878 if (!ex) {
00879 noex = NOEX_PUBLIC;
00880 }
00881 else {
00882 if (SCOPE_TEST(NOEX_PRIVATE)) {
00883 noex = NOEX_PRIVATE;
00884 rb_warning((SCOPE_CHECK(NOEX_MODFUNC)) ?
00885 "attribute accessor as module_function" :
00886 "private attribute?");
00887 }
00888 else if (SCOPE_TEST(NOEX_PROTECTED)) {
00889 noex = NOEX_PROTECTED;
00890 }
00891 else {
00892 noex = NOEX_PUBLIC;
00893 }
00894 }
00895
00896 aname = rb_id2str(rb_check_attr_id(id));
00897 if (NIL_P(aname)) {
00898 rb_raise(rb_eArgError, "argument needs to be symbol or string");
00899 }
00900 attriv = rb_intern_str(rb_sprintf("@%"PRIsVALUE, aname));
00901 if (read) {
00902 rb_add_method(klass, id, VM_METHOD_TYPE_IVAR, (void *)attriv, noex);
00903 }
00904 if (write) {
00905 rb_add_method(klass, rb_id_attrset(id), VM_METHOD_TYPE_ATTRSET, (void *)attriv, noex);
00906 }
00907 }
00908
00909 void
00910 rb_undef(VALUE klass, ID id)
00911 {
00912 rb_method_entry_t *me;
00913
00914 if (NIL_P(klass)) {
00915 rb_raise(rb_eTypeError, "no class to undef method");
00916 }
00917 rb_frozen_class_p(klass);
00918 if (id == object_id || id == id__send__ || id == idInitialize) {
00919 rb_warn("undefining `%s' may cause serious problems", rb_id2name(id));
00920 }
00921
00922 me = search_method(klass, id, 0);
00923
00924 if (UNDEFINED_METHOD_ENTRY_P(me) ||
00925 UNDEFINED_REFINED_METHOD_P(me->def)) {
00926 const char *s0 = " class";
00927 VALUE c = klass;
00928
00929 if (FL_TEST(c, FL_SINGLETON)) {
00930 VALUE obj = rb_ivar_get(klass, attached);
00931
00932 if (RB_TYPE_P(obj, T_MODULE) || RB_TYPE_P(obj, T_CLASS)) {
00933 c = obj;
00934 s0 = "";
00935 }
00936 }
00937 else if (RB_TYPE_P(c, T_MODULE)) {
00938 s0 = " module";
00939 }
00940 rb_name_error(id, "undefined method `%"PRIsVALUE"' for%s `%"PRIsVALUE"'",
00941 QUOTE_ID(id), s0, rb_class_name(c));
00942 }
00943
00944 rb_add_method(klass, id, VM_METHOD_TYPE_UNDEF, 0, NOEX_PUBLIC);
00945
00946 CALL_METHOD_HOOK(klass, undefined, id);
00947 }
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994 static VALUE
00995 rb_mod_undef_method(int argc, VALUE *argv, VALUE mod)
00996 {
00997 int i;
00998 for (i = 0; i < argc; i++) {
00999 VALUE v = argv[i];
01000 ID id = rb_check_id(&v);
01001 if (!id) {
01002 rb_method_name_error(mod, v);
01003 }
01004 rb_undef(mod, id);
01005 }
01006 return mod;
01007 }
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037 static VALUE
01038 rb_mod_method_defined(VALUE mod, VALUE mid)
01039 {
01040 ID id = rb_check_id(&mid);
01041 if (!id || !rb_method_boundp(mod, id, 1)) {
01042 return Qfalse;
01043 }
01044 return Qtrue;
01045
01046 }
01047
01048 #define VISI_CHECK(x,f) (((x)&NOEX_MASK) == (f))
01049
01050 static VALUE
01051 check_definition(VALUE mod, VALUE mid, rb_method_flag_t noex)
01052 {
01053 const rb_method_entry_t *me;
01054 ID id = rb_check_id(&mid);
01055 if (!id) return Qfalse;
01056 me = rb_method_entry_without_refinements(mod, id, 0);
01057 if (me) {
01058 if (VISI_CHECK(me->flag, noex))
01059 return Qtrue;
01060 }
01061 return Qfalse;
01062 }
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092 static VALUE
01093 rb_mod_public_method_defined(VALUE mod, VALUE mid)
01094 {
01095 return check_definition(mod, mid, NOEX_PUBLIC);
01096 }
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126 static VALUE
01127 rb_mod_private_method_defined(VALUE mod, VALUE mid)
01128 {
01129 return check_definition(mod, mid, NOEX_PRIVATE);
01130 }
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160 static VALUE
01161 rb_mod_protected_method_defined(VALUE mod, VALUE mid)
01162 {
01163 return check_definition(mod, mid, NOEX_PROTECTED);
01164 }
01165
01166 int
01167 rb_method_entry_eq(const rb_method_entry_t *m1, const rb_method_entry_t *m2)
01168 {
01169 return rb_method_definition_eq(m1->def, m2->def);
01170 }
01171
01172 static int
01173 rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2)
01174 {
01175 if (d1 && d1->type == VM_METHOD_TYPE_REFINED && d1->body.orig_me)
01176 d1 = d1->body.orig_me->def;
01177 if (d2 && d2->type == VM_METHOD_TYPE_REFINED && d2->body.orig_me)
01178 d2 = d2->body.orig_me->def;
01179 if (d1 == d2) return 1;
01180 if (!d1 || !d2) return 0;
01181 if (d1->type != d2->type) {
01182 return 0;
01183 }
01184 switch (d1->type) {
01185 case VM_METHOD_TYPE_ISEQ:
01186 return d1->body.iseq == d2->body.iseq;
01187 case VM_METHOD_TYPE_CFUNC:
01188 return
01189 d1->body.cfunc.func == d2->body.cfunc.func &&
01190 d1->body.cfunc.argc == d2->body.cfunc.argc;
01191 case VM_METHOD_TYPE_ATTRSET:
01192 case VM_METHOD_TYPE_IVAR:
01193 return d1->body.attr.id == d2->body.attr.id;
01194 case VM_METHOD_TYPE_BMETHOD:
01195 return RTEST(rb_equal(d1->body.proc, d2->body.proc));
01196 case VM_METHOD_TYPE_MISSING:
01197 return d1->original_id == d2->original_id;
01198 case VM_METHOD_TYPE_ZSUPER:
01199 case VM_METHOD_TYPE_NOTIMPLEMENTED:
01200 case VM_METHOD_TYPE_UNDEF:
01201 return 1;
01202 case VM_METHOD_TYPE_OPTIMIZED:
01203 return d1->body.optimize_type == d2->body.optimize_type;
01204 default:
01205 rb_bug("rb_method_entry_eq: unsupported method type (%d)\n", d1->type);
01206 return 0;
01207 }
01208 }
01209
01210 static st_index_t
01211 rb_hash_method_definition(st_index_t hash, const rb_method_definition_t *def)
01212 {
01213 again:
01214 hash = rb_hash_uint(hash, def->type);
01215 switch (def->type) {
01216 case VM_METHOD_TYPE_ISEQ:
01217 return rb_hash_uint(hash, (st_index_t)def->body.iseq);
01218 case VM_METHOD_TYPE_CFUNC:
01219 hash = rb_hash_uint(hash, (st_index_t)def->body.cfunc.func);
01220 return rb_hash_uint(hash, def->body.cfunc.argc);
01221 case VM_METHOD_TYPE_ATTRSET:
01222 case VM_METHOD_TYPE_IVAR:
01223 return rb_hash_uint(hash, def->body.attr.id);
01224 case VM_METHOD_TYPE_BMETHOD:
01225 return rb_hash_proc(hash, def->body.proc);
01226 case VM_METHOD_TYPE_MISSING:
01227 return rb_hash_uint(hash, def->original_id);
01228 case VM_METHOD_TYPE_ZSUPER:
01229 case VM_METHOD_TYPE_NOTIMPLEMENTED:
01230 case VM_METHOD_TYPE_UNDEF:
01231 return hash;
01232 case VM_METHOD_TYPE_OPTIMIZED:
01233 return rb_hash_uint(hash, def->body.optimize_type);
01234 case VM_METHOD_TYPE_REFINED:
01235 if (def->body.orig_me) {
01236 def = def->body.orig_me->def;
01237 goto again;
01238 }
01239 else {
01240 return hash;
01241 }
01242 default:
01243 rb_bug("rb_hash_method_definition: unsupported method type (%d)\n", def->type);
01244 }
01245 return hash;
01246 }
01247
01248 st_index_t
01249 rb_hash_method_entry(st_index_t hash, const rb_method_entry_t *me)
01250 {
01251 return rb_hash_method_definition(hash, me->def);
01252 }
01253
01254 void
01255 rb_alias(VALUE klass, ID name, ID def)
01256 {
01257 VALUE target_klass = klass;
01258 VALUE defined_class;
01259 rb_method_entry_t *orig_me;
01260 rb_method_flag_t flag = NOEX_UNDEF;
01261
01262 if (NIL_P(klass)) {
01263 rb_raise(rb_eTypeError, "no class to make alias");
01264 }
01265
01266 rb_frozen_class_p(klass);
01267
01268 again:
01269 orig_me = search_method(klass, def, &defined_class);
01270
01271 if (UNDEFINED_METHOD_ENTRY_P(orig_me) ||
01272 UNDEFINED_REFINED_METHOD_P(orig_me->def)) {
01273 if ((!RB_TYPE_P(klass, T_MODULE)) ||
01274 (orig_me = search_method(rb_cObject, def, 0),
01275 UNDEFINED_METHOD_ENTRY_P(orig_me))) {
01276 rb_print_undef(klass, def, 0);
01277 }
01278 }
01279 if (orig_me->def->type == VM_METHOD_TYPE_ZSUPER) {
01280 klass = RCLASS_SUPER(klass);
01281 def = orig_me->def->original_id;
01282 flag = orig_me->flag;
01283 goto again;
01284 }
01285 if (RB_TYPE_P(defined_class, T_ICLASS)) {
01286 VALUE real_class = RBASIC_CLASS(defined_class);
01287 if (real_class && RCLASS_ORIGIN(real_class) == defined_class)
01288 defined_class = real_class;
01289 }
01290
01291 if (flag == NOEX_UNDEF) flag = orig_me->flag;
01292 method_entry_set(target_klass, name, orig_me, flag, defined_class);
01293 }
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317 static VALUE
01318 rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname)
01319 {
01320 ID oldid = rb_check_id(&oldname);
01321 if (!oldid) {
01322 rb_print_undef_str(mod, oldname);
01323 }
01324 rb_alias(mod, rb_to_id(newname), oldid);
01325 return mod;
01326 }
01327
01328 static void
01329 set_method_visibility(VALUE self, int argc, VALUE *argv, rb_method_flag_t ex)
01330 {
01331 int i;
01332
01333 if (argc == 0) {
01334 rb_warning("%"PRIsVALUE" with no argument is just ignored",
01335 QUOTE_ID(rb_frame_callee()));
01336 return;
01337 }
01338
01339 for (i = 0; i < argc; i++) {
01340 VALUE v = argv[i];
01341 ID id = rb_check_id(&v);
01342 if (!id) {
01343 rb_print_undef_str(self, v);
01344 }
01345 rb_export_method(self, id, ex);
01346 }
01347 }
01348
01349 static VALUE
01350 set_visibility(int argc, VALUE *argv, VALUE module, rb_method_flag_t ex)
01351 {
01352 if (argc == 0) {
01353 SCOPE_SET(ex);
01354 }
01355 else {
01356 set_method_visibility(module, argc, argv, ex);
01357 }
01358 return module;
01359 }
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373 static VALUE
01374 rb_mod_public(int argc, VALUE *argv, VALUE module)
01375 {
01376 return set_visibility(argc, argv, module, NOEX_PUBLIC);
01377 }
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391 static VALUE
01392 rb_mod_protected(int argc, VALUE *argv, VALUE module)
01393 {
01394 return set_visibility(argc, argv, module, NOEX_PROTECTED);
01395 }
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418 static VALUE
01419 rb_mod_private(int argc, VALUE *argv, VALUE module)
01420 {
01421 return set_visibility(argc, argv, module, NOEX_PRIVATE);
01422 }
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434 static VALUE
01435 rb_mod_public_method(int argc, VALUE *argv, VALUE obj)
01436 {
01437 set_method_visibility(rb_singleton_class(obj), argc, argv, NOEX_PUBLIC);
01438 return obj;
01439 }
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460 static VALUE
01461 rb_mod_private_method(int argc, VALUE *argv, VALUE obj)
01462 {
01463 set_method_visibility(rb_singleton_class(obj), argc, argv, NOEX_PRIVATE);
01464 return obj;
01465 }
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480 static VALUE
01481 top_public(int argc, VALUE *argv)
01482 {
01483 return rb_mod_public(argc, argv, rb_cObject);
01484 }
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498 static VALUE
01499 top_private(int argc, VALUE *argv)
01500 {
01501 return rb_mod_private(argc, argv, rb_cObject);
01502 }
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542 static VALUE
01543 rb_mod_modfunc(int argc, VALUE *argv, VALUE module)
01544 {
01545 int i;
01546 ID id;
01547 const rb_method_entry_t *me;
01548
01549 if (!RB_TYPE_P(module, T_MODULE)) {
01550 rb_raise(rb_eTypeError, "module_function must be called for modules");
01551 }
01552
01553 if (argc == 0) {
01554 SCOPE_SET(NOEX_MODFUNC);
01555 return module;
01556 }
01557
01558 set_method_visibility(module, argc, argv, NOEX_PRIVATE);
01559
01560 for (i = 0; i < argc; i++) {
01561 VALUE m = module;
01562
01563 id = rb_to_id(argv[i]);
01564 for (;;) {
01565 me = search_method(m, id, 0);
01566 if (me == 0) {
01567 me = search_method(rb_cObject, id, 0);
01568 }
01569 if (UNDEFINED_METHOD_ENTRY_P(me)) {
01570 rb_print_undef(module, id, 0);
01571 }
01572 if (me->def->type != VM_METHOD_TYPE_ZSUPER) {
01573 break;
01574 }
01575 m = RCLASS_SUPER(m);
01576 if (!m)
01577 break;
01578 }
01579 rb_method_entry_set(rb_singleton_class(module), id, me, NOEX_PUBLIC);
01580 }
01581 return module;
01582 }
01583
01584 int
01585 rb_method_basic_definition_p(VALUE klass, ID id)
01586 {
01587 const rb_method_entry_t *me = rb_method_entry(klass, id, 0);
01588 if (me && (me->flag & NOEX_BASIC))
01589 return 1;
01590 return 0;
01591 }
01592
01593 static inline int
01594 basic_obj_respond_to(VALUE obj, ID id, int pub)
01595 {
01596 VALUE klass = CLASS_OF(obj);
01597 VALUE args[2];
01598
01599 switch (rb_method_boundp(klass, id, pub|NOEX_RESPONDS)) {
01600 case 2:
01601 return FALSE;
01602 case 0:
01603 args[0] = ID2SYM(id);
01604 args[1] = pub ? Qfalse : Qtrue;
01605 return RTEST(rb_funcall2(obj, idRespond_to_missing, 2, args));
01606 default:
01607 return TRUE;
01608 }
01609 }
01610
01611 int
01612 rb_obj_respond_to(VALUE obj, ID id, int priv)
01613 {
01614 VALUE klass = CLASS_OF(obj);
01615
01616 if (rb_method_basic_definition_p(klass, idRespond_to)) {
01617 return basic_obj_respond_to(obj, id, !RTEST(priv));
01618 }
01619 else {
01620 int argc = 1;
01621 VALUE args[2];
01622 args[0] = ID2SYM(id);
01623 args[1] = Qtrue;
01624 if (priv) {
01625 if (rb_obj_method_arity(obj, idRespond_to) != 1) {
01626 argc = 2;
01627 }
01628 else if (!NIL_P(ruby_verbose)) {
01629 VALUE klass = CLASS_OF(obj);
01630 VALUE location = rb_mod_method_location(klass, idRespond_to);
01631 rb_warn("%"PRIsVALUE"%c""respond_to?(:%"PRIsVALUE") is"
01632 " old fashion which takes only one parameter",
01633 (FL_TEST(klass, FL_SINGLETON) ? obj : klass),
01634 (FL_TEST(klass, FL_SINGLETON) ? '.' : '#'),
01635 QUOTE_ID(id));
01636 if (!NIL_P(location)) {
01637 VALUE path = RARRAY_AREF(location, 0);
01638 VALUE line = RARRAY_AREF(location, 1);
01639 if (!NIL_P(path)) {
01640 rb_compile_warn(RSTRING_PTR(path), NUM2INT(line),
01641 "respond_to? is defined here");
01642 }
01643 }
01644 }
01645 }
01646 return RTEST(rb_funcall2(obj, idRespond_to, argc, args));
01647 }
01648 }
01649
01650 int
01651 rb_respond_to(VALUE obj, ID id)
01652 {
01653 return rb_obj_respond_to(obj, id, FALSE);
01654 }
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677 static VALUE
01678 obj_respond_to(int argc, VALUE *argv, VALUE obj)
01679 {
01680 VALUE mid, priv;
01681 ID id;
01682
01683 rb_scan_args(argc, argv, "11", &mid, &priv);
01684 if (!(id = rb_check_id(&mid))) {
01685 if (!rb_method_basic_definition_p(CLASS_OF(obj), idRespond_to_missing)) {
01686 VALUE args[2];
01687 args[0] = ID2SYM(rb_to_id(mid));
01688 args[1] = priv;
01689 return rb_funcall2(obj, idRespond_to_missing, 2, args);
01690 }
01691 return Qfalse;
01692 }
01693 if (basic_obj_respond_to(obj, id, !RTEST(priv)))
01694 return Qtrue;
01695 return Qfalse;
01696 }
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713 static VALUE
01714 obj_respond_to_missing(VALUE obj, VALUE mid, VALUE priv)
01715 {
01716 return Qfalse;
01717 }
01718
01719 void
01720 Init_eval_method(void)
01721 {
01722 #undef rb_intern
01723 #define rb_intern(str) rb_intern_const(str)
01724
01725 rb_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1);
01726 rb_define_method(rb_mKernel, "respond_to_missing?", obj_respond_to_missing, 2);
01727
01728 rb_define_private_method(rb_cModule, "remove_method", rb_mod_remove_method, -1);
01729 rb_define_private_method(rb_cModule, "undef_method", rb_mod_undef_method, -1);
01730 rb_define_private_method(rb_cModule, "alias_method", rb_mod_alias_method, 2);
01731 rb_define_private_method(rb_cModule, "public", rb_mod_public, -1);
01732 rb_define_private_method(rb_cModule, "protected", rb_mod_protected, -1);
01733 rb_define_private_method(rb_cModule, "private", rb_mod_private, -1);
01734 rb_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1);
01735
01736 rb_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, 1);
01737 rb_define_method(rb_cModule, "public_method_defined?", rb_mod_public_method_defined, 1);
01738 rb_define_method(rb_cModule, "private_method_defined?", rb_mod_private_method_defined, 1);
01739 rb_define_method(rb_cModule, "protected_method_defined?", rb_mod_protected_method_defined, 1);
01740 rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1);
01741 rb_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1);
01742
01743 rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
01744 "public", top_public, -1);
01745 rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
01746 "private", top_private, -1);
01747
01748 {
01749 #define REPLICATE_METHOD(klass, id, noex) \
01750 rb_method_entry_set((klass), (id), \
01751 rb_method_entry((klass), (id), 0), \
01752 (rb_method_flag_t)(noex | NOEX_BASIC | NOEX_NOREDEF))
01753 REPLICATE_METHOD(rb_eException, idMethodMissing, NOEX_PRIVATE);
01754 REPLICATE_METHOD(rb_eException, idRespond_to, NOEX_PUBLIC);
01755 REPLICATE_METHOD(rb_eException, idRespond_to_missing, NOEX_PUBLIC);
01756 }
01757 }
01758