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