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