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