|
Ruby
2.0.0p353(2013-11-22revision43784)
|
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 const 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, const 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 (rb_method_entry_t *)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 if (UNDEFINED_METHOD_ENTRY_P(me)) { 00644 return 0; 00645 } 00646 else { 00647 return me; 00648 } 00649 } 00650 00651 static void 00652 remove_method(VALUE klass, ID mid) 00653 { 00654 st_data_t key, data; 00655 rb_method_entry_t *me = 0; 00656 VALUE self = klass; 00657 00658 klass = RCLASS_ORIGIN(klass); 00659 if (klass == rb_cObject) { 00660 rb_secure(4); 00661 } 00662 if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(klass)) { 00663 rb_raise(rb_eSecurityError, "Insecure: can't remove method"); 00664 } 00665 rb_check_frozen(klass); 00666 if (mid == object_id || mid == id__send__ || mid == idInitialize) { 00667 rb_warn("removing `%s' may cause serious problems", rb_id2name(mid)); 00668 } 00669 00670 if (!st_lookup(RCLASS_M_TBL(klass), mid, &data) || 00671 !(me = (rb_method_entry_t *)data) || 00672 (!me->def || me->def->type == VM_METHOD_TYPE_UNDEF)) { 00673 rb_name_error(mid, "method `%s' not defined in %s", 00674 rb_id2name(mid), rb_class2name(klass)); 00675 } 00676 key = (st_data_t)mid; 00677 st_delete(RCLASS_M_TBL(klass), &key, &data); 00678 00679 rb_vm_check_redefinition_opt_method(me, klass); 00680 rb_clear_cache_for_undef(klass, mid); 00681 rb_unlink_method_entry(me); 00682 00683 CALL_METHOD_HOOK(self, removed, mid); 00684 } 00685 00686 void 00687 rb_remove_method_id(VALUE klass, ID mid) 00688 { 00689 remove_method(klass, mid); 00690 } 00691 00692 void 00693 rb_remove_method(VALUE klass, const char *name) 00694 { 00695 remove_method(klass, rb_intern(name)); 00696 } 00697 00698 /* 00699 * call-seq: 00700 * remove_method(symbol) -> self 00701 * 00702 * Removes the method identified by _symbol_ from the current 00703 * class. For an example, see <code>Module.undef_method</code>. 00704 */ 00705 00706 static VALUE 00707 rb_mod_remove_method(int argc, VALUE *argv, VALUE mod) 00708 { 00709 int i; 00710 00711 for (i = 0; i < argc; i++) { 00712 VALUE v = argv[i]; 00713 ID id = rb_check_id(&v); 00714 if (!id) { 00715 rb_name_error_str(v, "method `%s' not defined in %s", 00716 RSTRING_PTR(v), rb_class2name(mod)); 00717 } 00718 remove_method(mod, id); 00719 } 00720 return mod; 00721 } 00722 00723 #undef rb_disable_super 00724 #undef rb_enable_super 00725 00726 void 00727 rb_disable_super(VALUE klass, const char *name) 00728 { 00729 /* obsolete - no use */ 00730 } 00731 00732 void 00733 rb_enable_super(VALUE klass, const char *name) 00734 { 00735 rb_warning("rb_enable_super() is obsolete"); 00736 } 00737 00738 static void 00739 rb_export_method(VALUE klass, ID name, rb_method_flag_t noex) 00740 { 00741 rb_method_entry_t *me; 00742 VALUE defined_class; 00743 00744 if (klass == rb_cObject) { 00745 rb_secure(4); 00746 } 00747 00748 me = search_method(klass, name, &defined_class); 00749 if (!me && RB_TYPE_P(klass, T_MODULE)) { 00750 me = search_method(rb_cObject, name, &defined_class); 00751 } 00752 00753 if (UNDEFINED_METHOD_ENTRY_P(me)) { 00754 rb_print_undef(klass, name, 0); 00755 } 00756 00757 if (me->flag != noex) { 00758 rb_vm_check_redefinition_opt_method(me, klass); 00759 00760 if (klass == defined_class || 00761 RCLASS_ORIGIN(klass) == defined_class) { 00762 me->flag = noex; 00763 if (me->def->type == VM_METHOD_TYPE_REFINED) { 00764 me->def->body.orig_me->flag = noex; 00765 } 00766 } 00767 else { 00768 rb_add_method(klass, name, VM_METHOD_TYPE_ZSUPER, 0, noex); 00769 } 00770 } 00771 } 00772 00773 int 00774 rb_method_boundp(VALUE klass, ID id, int ex) 00775 { 00776 rb_method_entry_t *me = 00777 rb_method_entry_without_refinements(klass, id, 0); 00778 00779 if (me != 0) { 00780 if ((ex & ~NOEX_RESPONDS) && 00781 ((me->flag & NOEX_PRIVATE) || 00782 ((ex & NOEX_RESPONDS) && (me->flag & NOEX_PROTECTED)))) { 00783 return 0; 00784 } 00785 if (!me->def) return 0; 00786 if (me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) { 00787 if (ex & NOEX_RESPONDS) return 2; 00788 return 0; 00789 } 00790 return 1; 00791 } 00792 return 0; 00793 } 00794 00795 void 00796 rb_attr(VALUE klass, ID id, int read, int write, int ex) 00797 { 00798 const char *name; 00799 ID attriv; 00800 VALUE aname; 00801 rb_method_flag_t noex; 00802 00803 if (!ex) { 00804 noex = NOEX_PUBLIC; 00805 } 00806 else { 00807 if (SCOPE_TEST(NOEX_PRIVATE)) { 00808 noex = NOEX_PRIVATE; 00809 rb_warning((SCOPE_CHECK(NOEX_MODFUNC)) ? 00810 "attribute accessor as module_function" : 00811 "private attribute?"); 00812 } 00813 else if (SCOPE_TEST(NOEX_PROTECTED)) { 00814 noex = NOEX_PROTECTED; 00815 } 00816 else { 00817 noex = NOEX_PUBLIC; 00818 } 00819 } 00820 00821 if (!rb_is_local_id(id) && !rb_is_const_id(id)) { 00822 rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id)); 00823 } 00824 name = rb_id2name(id); 00825 if (!name) { 00826 rb_raise(rb_eArgError, "argument needs to be symbol or string"); 00827 } 00828 aname = rb_sprintf("@%s", name); 00829 rb_enc_copy(aname, rb_id2str(id)); 00830 attriv = rb_intern_str(aname); 00831 if (read) { 00832 rb_add_method(klass, id, VM_METHOD_TYPE_IVAR, (void *)attriv, noex); 00833 } 00834 if (write) { 00835 rb_add_method(klass, rb_id_attrset(id), VM_METHOD_TYPE_ATTRSET, (void *)attriv, noex); 00836 } 00837 } 00838 00839 void 00840 rb_undef(VALUE klass, ID id) 00841 { 00842 rb_method_entry_t *me; 00843 00844 if (NIL_P(klass)) { 00845 rb_raise(rb_eTypeError, "no class to undef method"); 00846 } 00847 if (rb_vm_cbase() == rb_cObject && klass == rb_cObject) { 00848 rb_secure(4); 00849 } 00850 if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(klass)) { 00851 rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'", rb_id2name(id)); 00852 } 00853 rb_frozen_class_p(klass); 00854 if (id == object_id || id == id__send__ || id == idInitialize) { 00855 rb_warn("undefining `%s' may cause serious problems", rb_id2name(id)); 00856 } 00857 00858 me = search_method(klass, id, 0); 00859 00860 if (UNDEFINED_METHOD_ENTRY_P(me) || 00861 (me->def->type == VM_METHOD_TYPE_REFINED && 00862 UNDEFINED_METHOD_ENTRY_P(me->def->body.orig_me))) { 00863 const char *s0 = " class"; 00864 VALUE c = klass; 00865 00866 if (FL_TEST(c, FL_SINGLETON)) { 00867 VALUE obj = rb_ivar_get(klass, attached); 00868 00869 if (RB_TYPE_P(obj, T_MODULE) || RB_TYPE_P(obj, T_CLASS)) { 00870 c = obj; 00871 s0 = ""; 00872 } 00873 } 00874 else if (RB_TYPE_P(c, T_MODULE)) { 00875 s0 = " module"; 00876 } 00877 rb_name_error(id, "undefined method `%"PRIsVALUE"' for%s `%"PRIsVALUE"'", 00878 QUOTE_ID(id), s0, rb_class_name(c)); 00879 } 00880 00881 rb_add_method(klass, id, VM_METHOD_TYPE_UNDEF, 0, NOEX_PUBLIC); 00882 00883 CALL_METHOD_HOOK(klass, undefined, id); 00884 } 00885 00886 /* 00887 * call-seq: 00888 * undef_method(symbol) -> self 00889 * 00890 * Prevents the current class from responding to calls to the named 00891 * method. Contrast this with <code>remove_method</code>, which deletes 00892 * the method from the particular class; Ruby will still search 00893 * superclasses and mixed-in modules for a possible receiver. 00894 * 00895 * class Parent 00896 * def hello 00897 * puts "In parent" 00898 * end 00899 * end 00900 * class Child < Parent 00901 * def hello 00902 * puts "In child" 00903 * end 00904 * end 00905 * 00906 * 00907 * c = Child.new 00908 * c.hello 00909 * 00910 * 00911 * class Child 00912 * remove_method :hello # remove from child, still in parent 00913 * end 00914 * c.hello 00915 * 00916 * 00917 * class Child 00918 * undef_method :hello # prevent any calls to 'hello' 00919 * end 00920 * c.hello 00921 * 00922 * <em>produces:</em> 00923 * 00924 * In child 00925 * In parent 00926 * prog.rb:23: undefined method `hello' for #<Child:0x401b3bb4> (NoMethodError) 00927 */ 00928 00929 static VALUE 00930 rb_mod_undef_method(int argc, VALUE *argv, VALUE mod) 00931 { 00932 int i; 00933 for (i = 0; i < argc; i++) { 00934 VALUE v = argv[i]; 00935 ID id = rb_check_id(&v); 00936 if (!id) { 00937 rb_method_name_error(mod, v); 00938 } 00939 rb_undef(mod, id); 00940 } 00941 return mod; 00942 } 00943 00944 /* 00945 * call-seq: 00946 * mod.method_defined?(symbol) -> true or false 00947 * 00948 * Returns +true+ if the named method is defined by 00949 * _mod_ (or its included modules and, if _mod_ is a class, 00950 * its ancestors). Public and protected methods are matched. 00951 * 00952 * module A 00953 * def method1() end 00954 * end 00955 * class B 00956 * def method2() end 00957 * end 00958 * class C < B 00959 * include A 00960 * def method3() end 00961 * end 00962 * 00963 * A.method_defined? :method1 #=> true 00964 * C.method_defined? "method1" #=> true 00965 * C.method_defined? "method2" #=> true 00966 * C.method_defined? "method3" #=> true 00967 * C.method_defined? "method4" #=> false 00968 */ 00969 00970 static VALUE 00971 rb_mod_method_defined(VALUE mod, VALUE mid) 00972 { 00973 ID id = rb_check_id(&mid); 00974 if (!id || !rb_method_boundp(mod, id, 1)) { 00975 return Qfalse; 00976 } 00977 return Qtrue; 00978 00979 } 00980 00981 #define VISI_CHECK(x,f) (((x)&NOEX_MASK) == (f)) 00982 00983 static VALUE 00984 check_definition(VALUE mod, VALUE mid, rb_method_flag_t noex) 00985 { 00986 const rb_method_entry_t *me; 00987 ID id = rb_check_id(&mid); 00988 if (!id) return Qfalse; 00989 me = rb_method_entry(mod, id, 0); 00990 if (me) { 00991 if (VISI_CHECK(me->flag, noex)) 00992 return Qtrue; 00993 } 00994 return Qfalse; 00995 } 00996 00997 /* 00998 * call-seq: 00999 * mod.public_method_defined?(symbol) -> true or false 01000 * 01001 * Returns +true+ if the named public method is defined by 01002 * _mod_ (or its included modules and, if _mod_ is a class, 01003 * its ancestors). 01004 * 01005 * module A 01006 * def method1() end 01007 * end 01008 * class B 01009 * protected 01010 * def method2() end 01011 * end 01012 * class C < B 01013 * include A 01014 * def method3() end 01015 * end 01016 * 01017 * A.method_defined? :method1 #=> true 01018 * C.public_method_defined? "method1" #=> true 01019 * C.public_method_defined? "method2" #=> false 01020 * C.method_defined? "method2" #=> true 01021 */ 01022 01023 static VALUE 01024 rb_mod_public_method_defined(VALUE mod, VALUE mid) 01025 { 01026 return check_definition(mod, mid, NOEX_PUBLIC); 01027 } 01028 01029 /* 01030 * call-seq: 01031 * mod.private_method_defined?(symbol) -> true or false 01032 * 01033 * Returns +true+ if the named private method is defined by 01034 * _ mod_ (or its included modules and, if _mod_ is a class, 01035 * its ancestors). 01036 * 01037 * module A 01038 * def method1() end 01039 * end 01040 * class B 01041 * private 01042 * def method2() end 01043 * end 01044 * class C < B 01045 * include A 01046 * def method3() end 01047 * end 01048 * 01049 * A.method_defined? :method1 #=> true 01050 * C.private_method_defined? "method1" #=> false 01051 * C.private_method_defined? "method2" #=> true 01052 * C.method_defined? "method2" #=> false 01053 */ 01054 01055 static VALUE 01056 rb_mod_private_method_defined(VALUE mod, VALUE mid) 01057 { 01058 return check_definition(mod, mid, NOEX_PRIVATE); 01059 } 01060 01061 /* 01062 * call-seq: 01063 * mod.protected_method_defined?(symbol) -> true or false 01064 * 01065 * Returns +true+ if the named protected method is defined 01066 * by _mod_ (or its included modules and, if _mod_ is a 01067 * class, its ancestors). 01068 * 01069 * module A 01070 * def method1() end 01071 * end 01072 * class B 01073 * protected 01074 * def method2() end 01075 * end 01076 * class C < B 01077 * include A 01078 * def method3() end 01079 * end 01080 * 01081 * A.method_defined? :method1 #=> true 01082 * C.protected_method_defined? "method1" #=> false 01083 * C.protected_method_defined? "method2" #=> true 01084 * C.method_defined? "method2" #=> true 01085 */ 01086 01087 static VALUE 01088 rb_mod_protected_method_defined(VALUE mod, VALUE mid) 01089 { 01090 return check_definition(mod, mid, NOEX_PROTECTED); 01091 } 01092 01093 int 01094 rb_method_entry_eq(const rb_method_entry_t *m1, const rb_method_entry_t *m2) 01095 { 01096 return rb_method_definition_eq(m1->def, m2->def); 01097 } 01098 01099 static int 01100 rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2) 01101 { 01102 if (d1 && d1->type == VM_METHOD_TYPE_REFINED && d1->body.orig_me) 01103 d1 = d1->body.orig_me->def; 01104 if (d2 && d2->type == VM_METHOD_TYPE_REFINED && d2->body.orig_me) 01105 d2 = d2->body.orig_me->def; 01106 if (d1 == d2) return 1; 01107 if (!d1 || !d2) return 0; 01108 if (d1->type != d2->type) { 01109 return 0; 01110 } 01111 switch (d1->type) { 01112 case VM_METHOD_TYPE_ISEQ: 01113 return d1->body.iseq == d2->body.iseq; 01114 case VM_METHOD_TYPE_CFUNC: 01115 return 01116 d1->body.cfunc.func == d2->body.cfunc.func && 01117 d1->body.cfunc.argc == d2->body.cfunc.argc; 01118 case VM_METHOD_TYPE_ATTRSET: 01119 case VM_METHOD_TYPE_IVAR: 01120 return d1->body.attr.id == d2->body.attr.id; 01121 case VM_METHOD_TYPE_BMETHOD: 01122 return RTEST(rb_equal(d1->body.proc, d2->body.proc)); 01123 case VM_METHOD_TYPE_MISSING: 01124 return d1->original_id == d2->original_id; 01125 case VM_METHOD_TYPE_ZSUPER: 01126 case VM_METHOD_TYPE_NOTIMPLEMENTED: 01127 case VM_METHOD_TYPE_UNDEF: 01128 return 1; 01129 case VM_METHOD_TYPE_OPTIMIZED: 01130 return d1->body.optimize_type == d2->body.optimize_type; 01131 default: 01132 rb_bug("rb_method_entry_eq: unsupported method type (%d)\n", d1->type); 01133 return 0; 01134 } 01135 } 01136 01137 static st_index_t 01138 rb_hash_method_definition(st_index_t hash, const rb_method_definition_t *def) 01139 { 01140 again: 01141 hash = rb_hash_uint(hash, def->type); 01142 switch (def->type) { 01143 case VM_METHOD_TYPE_ISEQ: 01144 return rb_hash_uint(hash, (st_index_t)def->body.iseq); 01145 case VM_METHOD_TYPE_CFUNC: 01146 hash = rb_hash_uint(hash, (st_index_t)def->body.cfunc.func); 01147 return rb_hash_uint(hash, def->body.cfunc.argc); 01148 case VM_METHOD_TYPE_ATTRSET: 01149 case VM_METHOD_TYPE_IVAR: 01150 return rb_hash_uint(hash, def->body.attr.id); 01151 case VM_METHOD_TYPE_BMETHOD: 01152 return rb_hash_proc(hash, def->body.proc); 01153 case VM_METHOD_TYPE_MISSING: 01154 return rb_hash_uint(hash, def->original_id); 01155 case VM_METHOD_TYPE_ZSUPER: 01156 case VM_METHOD_TYPE_NOTIMPLEMENTED: 01157 case VM_METHOD_TYPE_UNDEF: 01158 return hash; 01159 case VM_METHOD_TYPE_OPTIMIZED: 01160 return rb_hash_uint(hash, def->body.optimize_type); 01161 case VM_METHOD_TYPE_REFINED: 01162 if (def->body.orig_me) { 01163 def = def->body.orig_me->def; 01164 goto again; 01165 } 01166 else { 01167 return hash; 01168 } 01169 default: 01170 rb_bug("rb_hash_method_definition: unsupported method type (%d)\n", def->type); 01171 } 01172 return hash; 01173 } 01174 01175 st_index_t 01176 rb_hash_method_entry(st_index_t hash, const rb_method_entry_t *me) 01177 { 01178 return rb_hash_method_definition(hash, me->def); 01179 } 01180 01181 void 01182 rb_alias(VALUE klass, ID name, ID def) 01183 { 01184 VALUE target_klass = klass; 01185 rb_method_entry_t *orig_me; 01186 rb_method_flag_t flag = NOEX_UNDEF; 01187 01188 if (NIL_P(klass)) { 01189 rb_raise(rb_eTypeError, "no class to make alias"); 01190 } 01191 01192 rb_frozen_class_p(klass); 01193 if (klass == rb_cObject) { 01194 rb_secure(4); 01195 } 01196 01197 again: 01198 orig_me = search_method(klass, def, 0); 01199 01200 if (UNDEFINED_METHOD_ENTRY_P(orig_me)) { 01201 if ((!RB_TYPE_P(klass, T_MODULE)) || 01202 (orig_me = search_method(rb_cObject, def, 0), 01203 UNDEFINED_METHOD_ENTRY_P(orig_me))) { 01204 rb_print_undef(klass, def, 0); 01205 } 01206 } 01207 if (orig_me->def->type == VM_METHOD_TYPE_ZSUPER) { 01208 klass = RCLASS_SUPER(klass); 01209 def = orig_me->def->original_id; 01210 flag = orig_me->flag; 01211 goto again; 01212 } 01213 01214 if (flag == NOEX_UNDEF) flag = orig_me->flag; 01215 rb_method_entry_set(target_klass, name, orig_me, flag); 01216 } 01217 01218 /* 01219 * call-seq: 01220 * alias_method(new_name, old_name) -> self 01221 * 01222 * Makes <i>new_name</i> a new copy of the method <i>old_name</i>. This can 01223 * be used to retain access to methods that are overridden. 01224 * 01225 * module Mod 01226 * alias_method :orig_exit, :exit 01227 * def exit(code=0) 01228 * puts "Exiting with code #{code}" 01229 * orig_exit(code) 01230 * end 01231 * end 01232 * include Mod 01233 * exit(99) 01234 * 01235 * <em>produces:</em> 01236 * 01237 * Exiting with code 99 01238 */ 01239 01240 static VALUE 01241 rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname) 01242 { 01243 ID oldid = rb_check_id(&oldname); 01244 if (!oldid) { 01245 rb_print_undef_str(mod, oldname); 01246 } 01247 rb_alias(mod, rb_to_id(newname), oldid); 01248 return mod; 01249 } 01250 01251 static void 01252 secure_visibility(VALUE self) 01253 { 01254 if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(self)) { 01255 rb_raise(rb_eSecurityError, 01256 "Insecure: can't change method visibility"); 01257 } 01258 } 01259 01260 static void 01261 set_method_visibility(VALUE self, int argc, VALUE *argv, rb_method_flag_t ex) 01262 { 01263 int i; 01264 secure_visibility(self); 01265 01266 if (argc == 0) { 01267 rb_warning("%s with no argument is just ignored", rb_id2name(rb_frame_callee())); 01268 } 01269 01270 for (i = 0; i < argc; i++) { 01271 VALUE v = argv[i]; 01272 ID id = rb_check_id(&v); 01273 if (!id) { 01274 rb_print_undef_str(self, v); 01275 } 01276 rb_export_method(self, id, ex); 01277 } 01278 rb_clear_cache_by_class(self); 01279 } 01280 01281 /* 01282 * call-seq: 01283 * public -> self 01284 * public(symbol, ...) -> self 01285 * 01286 * With no arguments, sets the default visibility for subsequently 01287 * defined methods to public. With arguments, sets the named methods to 01288 * have public visibility. 01289 */ 01290 01291 static VALUE 01292 rb_mod_public(int argc, VALUE *argv, VALUE module) 01293 { 01294 secure_visibility(module); 01295 if (argc == 0) { 01296 SCOPE_SET(NOEX_PUBLIC); 01297 } 01298 else { 01299 set_method_visibility(module, argc, argv, NOEX_PUBLIC); 01300 } 01301 return module; 01302 } 01303 01304 /* 01305 * call-seq: 01306 * protected -> self 01307 * protected(symbol, ...) -> self 01308 * 01309 * With no arguments, sets the default visibility for subsequently 01310 * defined methods to protected. With arguments, sets the named methods 01311 * to have protected visibility. 01312 */ 01313 01314 static VALUE 01315 rb_mod_protected(int argc, VALUE *argv, VALUE module) 01316 { 01317 secure_visibility(module); 01318 if (argc == 0) { 01319 SCOPE_SET(NOEX_PROTECTED); 01320 } 01321 else { 01322 set_method_visibility(module, argc, argv, NOEX_PROTECTED); 01323 } 01324 return module; 01325 } 01326 01327 /* 01328 * call-seq: 01329 * private -> self 01330 * private(symbol, ...) -> self 01331 * 01332 * With no arguments, sets the default visibility for subsequently 01333 * defined methods to private. With arguments, sets the named methods 01334 * to have private visibility. 01335 * 01336 * module Mod 01337 * def a() end 01338 * def b() end 01339 * private 01340 * def c() end 01341 * private :a 01342 * end 01343 * Mod.private_instance_methods #=> [:a, :c] 01344 */ 01345 01346 static VALUE 01347 rb_mod_private(int argc, VALUE *argv, VALUE module) 01348 { 01349 secure_visibility(module); 01350 if (argc == 0) { 01351 SCOPE_SET(NOEX_PRIVATE); 01352 } 01353 else { 01354 set_method_visibility(module, argc, argv, NOEX_PRIVATE); 01355 } 01356 return module; 01357 } 01358 01359 /* 01360 * call-seq: 01361 * mod.public_class_method(symbol, ...) -> mod 01362 * 01363 * Makes a list of existing class methods public. 01364 */ 01365 01366 static VALUE 01367 rb_mod_public_method(int argc, VALUE *argv, VALUE obj) 01368 { 01369 set_method_visibility(rb_singleton_class(obj), argc, argv, NOEX_PUBLIC); 01370 return obj; 01371 } 01372 01373 /* 01374 * call-seq: 01375 * mod.private_class_method(symbol, ...) -> mod 01376 * 01377 * Makes existing class methods private. Often used to hide the default 01378 * constructor <code>new</code>. 01379 * 01380 * class SimpleSingleton # Not thread safe 01381 * private_class_method :new 01382 * def SimpleSingleton.create(*args, &block) 01383 * @me = new(*args, &block) if ! @me 01384 * @me 01385 * end 01386 * end 01387 */ 01388 01389 static VALUE 01390 rb_mod_private_method(int argc, VALUE *argv, VALUE obj) 01391 { 01392 set_method_visibility(rb_singleton_class(obj), argc, argv, NOEX_PRIVATE); 01393 return obj; 01394 } 01395 01396 /* 01397 * call-seq: 01398 * public 01399 * public(symbol, ...) 01400 * 01401 * With no arguments, sets the default visibility for subsequently 01402 * defined methods to public. With arguments, sets the named methods to 01403 * have public visibility. 01404 */ 01405 01406 static VALUE 01407 top_public(int argc, VALUE *argv) 01408 { 01409 return rb_mod_public(argc, argv, rb_cObject); 01410 } 01411 01412 static VALUE 01413 top_private(int argc, VALUE *argv) 01414 { 01415 return rb_mod_private(argc, argv, rb_cObject); 01416 } 01417 01418 /* 01419 * call-seq: 01420 * module_function(symbol, ...) -> self 01421 * 01422 * Creates module functions for the named methods. These functions may 01423 * be called with the module as a receiver, and also become available 01424 * as instance methods to classes that mix in the module. Module 01425 * functions are copies of the original, and so may be changed 01426 * independently. The instance-method versions are made private. If 01427 * used with no arguments, subsequently defined methods become module 01428 * functions. 01429 * 01430 * module Mod 01431 * def one 01432 * "This is one" 01433 * end 01434 * module_function :one 01435 * end 01436 * class Cls 01437 * include Mod 01438 * def call_one 01439 * one 01440 * end 01441 * end 01442 * Mod.one #=> "This is one" 01443 * c = Cls.new 01444 * c.call_one #=> "This is one" 01445 * module Mod 01446 * def one 01447 * "This is the new one" 01448 * end 01449 * end 01450 * Mod.one #=> "This is one" 01451 * c.call_one #=> "This is the new one" 01452 */ 01453 01454 static VALUE 01455 rb_mod_modfunc(int argc, VALUE *argv, VALUE module) 01456 { 01457 int i; 01458 ID id; 01459 const rb_method_entry_t *me; 01460 01461 if (!RB_TYPE_P(module, T_MODULE)) { 01462 rb_raise(rb_eTypeError, "module_function must be called for modules"); 01463 } 01464 01465 secure_visibility(module); 01466 if (argc == 0) { 01467 SCOPE_SET(NOEX_MODFUNC); 01468 return module; 01469 } 01470 01471 set_method_visibility(module, argc, argv, NOEX_PRIVATE); 01472 01473 for (i = 0; i < argc; i++) { 01474 VALUE m = module; 01475 01476 id = rb_to_id(argv[i]); 01477 for (;;) { 01478 me = search_method(m, id, 0); 01479 if (me == 0) { 01480 me = search_method(rb_cObject, id, 0); 01481 } 01482 if (UNDEFINED_METHOD_ENTRY_P(me)) { 01483 rb_print_undef(module, id, 0); 01484 } 01485 if (me->def->type != VM_METHOD_TYPE_ZSUPER) { 01486 break; /* normal case: need not to follow 'super' link */ 01487 } 01488 m = RCLASS_SUPER(m); 01489 if (!m) 01490 break; 01491 } 01492 rb_method_entry_set(rb_singleton_class(module), id, me, NOEX_PUBLIC); 01493 } 01494 return module; 01495 } 01496 01497 int 01498 rb_method_basic_definition_p(VALUE klass, ID id) 01499 { 01500 const rb_method_entry_t *me = rb_method_entry(klass, id, 0); 01501 if (me && (me->flag & NOEX_BASIC)) 01502 return 1; 01503 return 0; 01504 } 01505 01506 static inline int 01507 basic_obj_respond_to(VALUE obj, ID id, int pub) 01508 { 01509 VALUE klass = CLASS_OF(obj); 01510 VALUE args[2]; 01511 01512 switch (rb_method_boundp(klass, id, pub|NOEX_RESPONDS)) { 01513 case 2: 01514 return FALSE; 01515 case 0: 01516 args[0] = ID2SYM(id); 01517 args[1] = pub ? Qfalse : Qtrue; 01518 return RTEST(rb_funcall2(obj, idRespond_to_missing, 2, args)); 01519 default: 01520 return TRUE; 01521 } 01522 } 01523 01524 int 01525 rb_obj_respond_to(VALUE obj, ID id, int priv) 01526 { 01527 VALUE klass = CLASS_OF(obj); 01528 01529 if (rb_method_basic_definition_p(klass, idRespond_to)) { 01530 return basic_obj_respond_to(obj, id, !RTEST(priv)); 01531 } 01532 else { 01533 int argc = 1; 01534 VALUE args[2]; 01535 args[0] = ID2SYM(id); 01536 args[1] = Qtrue; 01537 if (priv) { 01538 if (rb_obj_method_arity(obj, idRespond_to) != 1) { 01539 argc = 2; 01540 } 01541 else if (!NIL_P(ruby_verbose)) { 01542 VALUE klass = CLASS_OF(obj); 01543 VALUE location = rb_mod_method_location(klass, idRespond_to); 01544 rb_warn("%"PRIsVALUE"%c""respond_to?(:%"PRIsVALUE") is" 01545 " old fashion which takes only one parameter", 01546 (FL_TEST(klass, FL_SINGLETON) ? obj : klass), 01547 (FL_TEST(klass, FL_SINGLETON) ? '.' : '#'), 01548 QUOTE_ID(id)); 01549 if (!NIL_P(location)) { 01550 VALUE path = RARRAY_PTR(location)[0]; 01551 VALUE line = RARRAY_PTR(location)[1]; 01552 if (!NIL_P(path)) { 01553 rb_compile_warn(RSTRING_PTR(path), NUM2INT(line), 01554 "respond_to? is defined here"); 01555 } 01556 } 01557 } 01558 } 01559 return RTEST(rb_funcall2(obj, idRespond_to, argc, args)); 01560 } 01561 } 01562 01563 int 01564 rb_respond_to(VALUE obj, ID id) 01565 { 01566 return rb_obj_respond_to(obj, id, FALSE); 01567 } 01568 01569 01570 /* 01571 * call-seq: 01572 * obj.respond_to?(symbol, include_all=false) -> true or false 01573 * 01574 * Returns +true+ if _obj_ responds to the given method. Private and 01575 * protected methods are included in the search only if the optional 01576 * second parameter evaluates to +true+. 01577 * 01578 * If the method is not implemented, 01579 * as Process.fork on Windows, File.lchmod on GNU/Linux, etc., 01580 * false is returned. 01581 * 01582 * If the method is not defined, <code>respond_to_missing?</code> 01583 * method is called and the result is returned. 01584 */ 01585 01586 static VALUE 01587 obj_respond_to(int argc, VALUE *argv, VALUE obj) 01588 { 01589 VALUE mid, priv; 01590 ID id; 01591 01592 rb_scan_args(argc, argv, "11", &mid, &priv); 01593 if (!(id = rb_check_id(&mid))) { 01594 if (!rb_method_basic_definition_p(CLASS_OF(obj), idRespond_to_missing)) { 01595 VALUE args[2]; 01596 args[0] = ID2SYM(rb_to_id(mid)); 01597 args[1] = priv; 01598 return rb_funcall2(obj, idRespond_to_missing, 2, args); 01599 } 01600 return Qfalse; 01601 } 01602 if (basic_obj_respond_to(obj, id, !RTEST(priv))) 01603 return Qtrue; 01604 return Qfalse; 01605 } 01606 01607 /* 01608 * call-seq: 01609 * obj.respond_to_missing?(symbol, include_all) -> true or false 01610 * 01611 * DO NOT USE THIS DIRECTLY. 01612 * 01613 * Hook method to return whether the _obj_ can respond to _id_ method 01614 * or not. 01615 * 01616 * See #respond_to?. 01617 */ 01618 static VALUE 01619 obj_respond_to_missing(VALUE obj, VALUE mid, VALUE priv) 01620 { 01621 return Qfalse; 01622 } 01623 01624 void 01625 Init_eval_method(void) 01626 { 01627 #undef rb_intern 01628 #define rb_intern(str) rb_intern_const(str) 01629 01630 rb_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1); 01631 rb_define_method(rb_mKernel, "respond_to_missing?", obj_respond_to_missing, 2); 01632 01633 rb_define_private_method(rb_cModule, "remove_method", rb_mod_remove_method, -1); 01634 rb_define_private_method(rb_cModule, "undef_method", rb_mod_undef_method, -1); 01635 rb_define_private_method(rb_cModule, "alias_method", rb_mod_alias_method, 2); 01636 rb_define_private_method(rb_cModule, "public", rb_mod_public, -1); 01637 rb_define_private_method(rb_cModule, "protected", rb_mod_protected, -1); 01638 rb_define_private_method(rb_cModule, "private", rb_mod_private, -1); 01639 rb_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1); 01640 01641 rb_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, 1); 01642 rb_define_method(rb_cModule, "public_method_defined?", rb_mod_public_method_defined, 1); 01643 rb_define_method(rb_cModule, "private_method_defined?", rb_mod_private_method_defined, 1); 01644 rb_define_method(rb_cModule, "protected_method_defined?", rb_mod_protected_method_defined, 1); 01645 rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1); 01646 rb_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1); 01647 01648 rb_define_private_method(rb_singleton_class(rb_vm_top_self()), 01649 "public", top_public, -1); 01650 rb_define_private_method(rb_singleton_class(rb_vm_top_self()), 01651 "private", top_private, -1); 01652 01653 object_id = rb_intern("object_id"); 01654 added = rb_intern("method_added"); 01655 singleton_added = rb_intern("singleton_method_added"); 01656 removed = rb_intern("method_removed"); 01657 singleton_removed = rb_intern("singleton_method_removed"); 01658 undefined = rb_intern("method_undefined"); 01659 singleton_undefined = rb_intern("singleton_method_undefined"); 01660 attached = rb_intern("__attached__"); 01661 01662 { 01663 #define REPLICATE_METHOD(klass, id, noex) \ 01664 rb_method_entry_set((klass), (id), \ 01665 rb_method_entry((klass), (id), 0), \ 01666 (rb_method_flag_t)(noex | NOEX_BASIC | NOEX_NOREDEF)) 01667 REPLICATE_METHOD(rb_eException, idMethodMissing, NOEX_PRIVATE); 01668 REPLICATE_METHOD(rb_eException, idRespond_to, NOEX_PUBLIC); 01669 REPLICATE_METHOD(rb_eException, idRespond_to_missing, NOEX_PUBLIC); 01670 } 01671 } 01672
1.7.6.1