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