Ruby 1.9.3p327(2012-11-10revision37606)
|
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 static void rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me); 00010 00011 static ID object_id, respond_to_missing; 00012 static ID removed, singleton_removed, undefined, singleton_undefined; 00013 static ID added, singleton_added, attached; 00014 00015 struct cache_entry { /* method hash table. */ 00016 VALUE filled_version; /* filled state version */ 00017 ID mid; /* method's id */ 00018 VALUE klass; /* receiver's class */ 00019 rb_method_entry_t *me; 00020 }; 00021 00022 static struct cache_entry cache[CACHE_SIZE]; 00023 #define ruby_running (GET_VM()->running) 00024 /* int ruby_running = 0; */ 00025 00026 static void 00027 vm_clear_global_method_cache(void) 00028 { 00029 struct cache_entry *ent, *end; 00030 00031 ent = cache; 00032 end = ent + CACHE_SIZE; 00033 while (ent < end) { 00034 ent->filled_version = 0; 00035 ent++; 00036 } 00037 } 00038 00039 void 00040 rb_clear_cache(void) 00041 { 00042 rb_vm_change_state(); 00043 } 00044 00045 static void 00046 rb_clear_cache_for_undef(VALUE klass, ID id) 00047 { 00048 rb_vm_change_state(); 00049 } 00050 00051 static void 00052 rb_clear_cache_by_id(ID id) 00053 { 00054 rb_vm_change_state(); 00055 } 00056 00057 void 00058 rb_clear_cache_by_class(VALUE klass) 00059 { 00060 rb_vm_change_state(); 00061 } 00062 00063 VALUE 00064 rb_f_notimplement(int argc, VALUE *argv, VALUE obj) 00065 { 00066 rb_notimplement(); 00067 } 00068 00069 static void 00070 rb_define_notimplement_method_id(VALUE mod, ID id, rb_method_flag_t noex) 00071 { 00072 rb_add_method(mod, id, VM_METHOD_TYPE_NOTIMPLEMENTED, 0, noex); 00073 } 00074 00075 void 00076 rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_flag_t noex) 00077 { 00078 if (func != rb_f_notimplement) { 00079 rb_method_cfunc_t opt; 00080 opt.func = func; 00081 opt.argc = argc; 00082 rb_add_method(klass, mid, VM_METHOD_TYPE_CFUNC, &opt, noex); 00083 } 00084 else { 00085 rb_define_notimplement_method_id(klass, mid, noex); 00086 } 00087 } 00088 00089 void 00090 rb_unlink_method_entry(rb_method_entry_t *me) 00091 { 00092 struct unlinked_method_entry_list_entry *ume = ALLOC(struct unlinked_method_entry_list_entry); 00093 ume->me = me; 00094 ume->next = GET_VM()->unlinked_method_entry_list; 00095 GET_VM()->unlinked_method_entry_list = ume; 00096 } 00097 00098 void 00099 rb_gc_mark_unlinked_live_method_entries(void *pvm) 00100 { 00101 rb_vm_t *vm = pvm; 00102 struct unlinked_method_entry_list_entry *ume = vm->unlinked_method_entry_list, *prev_ume = 0, *curr_ume; 00103 00104 while (ume) { 00105 if (ume->me->mark) { 00106 rb_mark_method_entry(ume->me); 00107 } 00108 ume = ume->next; 00109 } 00110 } 00111 00112 void 00113 rb_sweep_method_entry(void *pvm) 00114 { 00115 rb_vm_t *vm = pvm; 00116 struct unlinked_method_entry_list_entry *ume = vm->unlinked_method_entry_list, *prev_ume = 0, *curr_ume; 00117 00118 while (ume) { 00119 if (ume->me->mark) { 00120 ume->me->mark = 0; 00121 prev_ume = ume; 00122 ume = ume->next; 00123 } 00124 else { 00125 rb_free_method_entry(ume->me); 00126 00127 if (prev_ume == 0) { 00128 vm->unlinked_method_entry_list = ume->next; 00129 } 00130 else { 00131 prev_ume->next = ume->next; 00132 } 00133 00134 curr_ume = ume; 00135 ume = ume->next; 00136 xfree(curr_ume); 00137 } 00138 } 00139 } 00140 00141 void 00142 rb_free_method_entry(rb_method_entry_t *me) 00143 { 00144 rb_method_definition_t *def = me->def; 00145 00146 if (def) { 00147 if (def->alias_count == 0) { 00148 xfree(def); 00149 } 00150 else if (def->alias_count > 0) { 00151 def->alias_count--; 00152 } 00153 me->def = 0; 00154 } 00155 xfree(me); 00156 } 00157 00158 static int rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2); 00159 00160 static rb_method_entry_t * 00161 rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type, 00162 rb_method_definition_t *def, rb_method_flag_t noex) 00163 { 00164 rb_method_entry_t *me; 00165 st_table *mtbl; 00166 st_data_t data; 00167 00168 if (NIL_P(klass)) { 00169 klass = rb_cObject; 00170 } 00171 if (rb_safe_level() >= 4 && 00172 (klass == rb_cObject || !OBJ_UNTRUSTED(klass))) { 00173 rb_raise(rb_eSecurityError, "Insecure: can't define method"); 00174 } 00175 if (!FL_TEST(klass, FL_SINGLETON) && 00176 type != VM_METHOD_TYPE_NOTIMPLEMENTED && 00177 type != VM_METHOD_TYPE_ZSUPER && 00178 (mid == rb_intern("initialize") || mid == rb_intern("initialize_copy"))) { 00179 noex = NOEX_PRIVATE | noex; 00180 } 00181 else if (FL_TEST(klass, FL_SINGLETON) && 00182 type == VM_METHOD_TYPE_CFUNC && 00183 mid == rb_intern("allocate")) { 00184 rb_warn("defining %s.allocate is deprecated; use rb_define_alloc_func()", 00185 rb_class2name(rb_ivar_get(klass, attached))); 00186 mid = ID_ALLOCATOR; 00187 } 00188 00189 rb_check_frozen(klass); 00190 mtbl = RCLASS_M_TBL(klass); 00191 00192 /* check re-definition */ 00193 if (st_lookup(mtbl, mid, &data)) { 00194 rb_method_entry_t *old_me = (rb_method_entry_t *)data; 00195 rb_method_definition_t *old_def = old_me->def; 00196 00197 if (rb_method_definition_eq(old_def, def)) return old_me; 00198 rb_vm_check_redefinition_opt_method(old_me); 00199 00200 if (RTEST(ruby_verbose) && 00201 type != VM_METHOD_TYPE_UNDEF && 00202 old_def->alias_count == 0 && 00203 old_def->type != VM_METHOD_TYPE_UNDEF && 00204 old_def->type != VM_METHOD_TYPE_ZSUPER) { 00205 rb_iseq_t *iseq = 0; 00206 00207 rb_warning("method redefined; discarding old %s", rb_id2name(mid)); 00208 switch (old_def->type) { 00209 case VM_METHOD_TYPE_ISEQ: 00210 iseq = old_def->body.iseq; 00211 break; 00212 case VM_METHOD_TYPE_BMETHOD: 00213 iseq = rb_proc_get_iseq(old_def->body.proc, 0); 00214 break; 00215 default: 00216 break; 00217 } 00218 if (iseq && !NIL_P(iseq->filename)) { 00219 int line = iseq->insn_info_table ? rb_iseq_first_lineno(iseq) : 0; 00220 rb_compile_warning(RSTRING_PTR(iseq->filename), line, 00221 "previous definition of %s was here", 00222 rb_id2name(old_def->original_id)); 00223 } 00224 } 00225 00226 rb_unlink_method_entry(old_me); 00227 } 00228 00229 me = ALLOC(rb_method_entry_t); 00230 00231 rb_clear_cache_by_id(mid); 00232 00233 me->flag = NOEX_WITH_SAFE(noex); 00234 me->mark = 0; 00235 me->called_id = mid; 00236 me->klass = klass; 00237 me->def = def; 00238 if (def) def->alias_count++; 00239 00240 /* check mid */ 00241 if (klass == rb_cObject && mid == idInitialize) { 00242 rb_warn("redefining Object#initialize may cause infinite loop"); 00243 } 00244 /* check mid */ 00245 if (mid == object_id || mid == id__send__) { 00246 if (type == VM_METHOD_TYPE_ISEQ) { 00247 rb_warn("redefining `%s' may cause serious problems", rb_id2name(mid)); 00248 } 00249 } 00250 00251 st_insert(mtbl, mid, (st_data_t) me); 00252 00253 return me; 00254 } 00255 00256 #define CALL_METHOD_HOOK(klass, hook, mid) do { \ 00257 const VALUE arg = ID2SYM(mid); \ 00258 VALUE recv_class = (klass); \ 00259 ID hook_id = (hook); \ 00260 if (FL_TEST((klass), FL_SINGLETON)) { \ 00261 recv_class = rb_ivar_get((klass), attached); \ 00262 hook_id = singleton_##hook; \ 00263 } \ 00264 rb_funcall2(recv_class, hook_id, 1, &arg); \ 00265 } while (0) 00266 00267 static void 00268 method_added(VALUE klass, ID mid) 00269 { 00270 if (mid != ID_ALLOCATOR && ruby_running) { 00271 CALL_METHOD_HOOK(klass, added, mid); 00272 } 00273 } 00274 00275 rb_method_entry_t * 00276 rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_flag_t noex) 00277 { 00278 rb_thread_t *th; 00279 rb_control_frame_t *cfp; 00280 int line; 00281 rb_method_entry_t *me = rb_method_entry_make(klass, mid, type, 0, noex); 00282 rb_method_definition_t *def = ALLOC(rb_method_definition_t); 00283 me->def = def; 00284 def->type = type; 00285 def->original_id = mid; 00286 def->alias_count = 0; 00287 switch (type) { 00288 case VM_METHOD_TYPE_ISEQ: 00289 def->body.iseq = (rb_iseq_t *)opts; 00290 break; 00291 case VM_METHOD_TYPE_CFUNC: 00292 def->body.cfunc = *(rb_method_cfunc_t *)opts; 00293 break; 00294 case VM_METHOD_TYPE_ATTRSET: 00295 case VM_METHOD_TYPE_IVAR: 00296 def->body.attr.id = (ID)opts; 00297 def->body.attr.location = Qfalse; 00298 th = GET_THREAD(); 00299 cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); 00300 if (cfp && (line = rb_vm_get_sourceline(cfp))) { 00301 VALUE location = rb_ary_new3(2, cfp->iseq->filename, INT2FIX(line)); 00302 def->body.attr.location = rb_ary_freeze(location); 00303 } 00304 break; 00305 case VM_METHOD_TYPE_BMETHOD: 00306 def->body.proc = (VALUE)opts; 00307 break; 00308 case VM_METHOD_TYPE_NOTIMPLEMENTED: 00309 def->body.cfunc.func = rb_f_notimplement; 00310 def->body.cfunc.argc = -1; 00311 break; 00312 case VM_METHOD_TYPE_OPTIMIZED: 00313 def->body.optimize_type = (enum method_optimized_type)opts; 00314 break; 00315 case VM_METHOD_TYPE_ZSUPER: 00316 case VM_METHOD_TYPE_UNDEF: 00317 break; 00318 default: 00319 rb_bug("rb_add_method: unsupported method type (%d)\n", type); 00320 } 00321 if (type != VM_METHOD_TYPE_UNDEF) { 00322 method_added(klass, mid); 00323 } 00324 return me; 00325 } 00326 00327 rb_method_entry_t * 00328 rb_method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me, rb_method_flag_t noex) 00329 { 00330 rb_method_type_t type = me->def ? me->def->type : VM_METHOD_TYPE_UNDEF; 00331 rb_method_entry_t *newme = rb_method_entry_make(klass, mid, type, me->def, noex); 00332 method_added(klass, mid); 00333 return newme; 00334 } 00335 00336 void 00337 rb_define_alloc_func(VALUE klass, VALUE (*func)(VALUE)) 00338 { 00339 Check_Type(klass, T_CLASS); 00340 rb_add_method_cfunc(rb_singleton_class(klass), ID_ALLOCATOR, 00341 func, 0, NOEX_PRIVATE); 00342 } 00343 00344 void 00345 rb_undef_alloc_func(VALUE klass) 00346 { 00347 Check_Type(klass, T_CLASS); 00348 rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, VM_METHOD_TYPE_UNDEF, 0, NOEX_UNDEF); 00349 } 00350 00351 rb_alloc_func_t 00352 rb_get_alloc_func(VALUE klass) 00353 { 00354 rb_method_entry_t *me; 00355 Check_Type(klass, T_CLASS); 00356 me = rb_method_entry(CLASS_OF(klass), ID_ALLOCATOR); 00357 00358 if (me && me->def && me->def->type == VM_METHOD_TYPE_CFUNC) { 00359 return (rb_alloc_func_t)me->def->body.cfunc.func; 00360 } 00361 else { 00362 return 0; 00363 } 00364 } 00365 00366 static rb_method_entry_t* 00367 search_method(VALUE klass, ID id) 00368 { 00369 st_data_t body; 00370 if (!klass) { 00371 return 0; 00372 } 00373 00374 while (!st_lookup(RCLASS_M_TBL(klass), id, &body)) { 00375 klass = RCLASS_SUPER(klass); 00376 if (!klass) { 00377 return 0; 00378 } 00379 } 00380 00381 return (rb_method_entry_t *)body; 00382 } 00383 00384 /* 00385 * search method entry without the method cache. 00386 * 00387 * if you need method entry with method cache (normal case), use 00388 * rb_method_entry() simply. 00389 */ 00390 rb_method_entry_t * 00391 rb_method_entry_get_without_cache(VALUE klass, ID id) 00392 { 00393 rb_method_entry_t *me = search_method(klass, id); 00394 00395 if (ruby_running) { 00396 struct cache_entry *ent; 00397 ent = cache + EXPR1(klass, id); 00398 ent->filled_version = GET_VM_STATE_VERSION(); 00399 ent->klass = klass; 00400 00401 if (UNDEFINED_METHOD_ENTRY_P(me)) { 00402 ent->mid = id; 00403 ent->me = 0; 00404 me = 0; 00405 } 00406 else { 00407 ent->mid = id; 00408 ent->me = me; 00409 } 00410 } 00411 00412 return me; 00413 } 00414 00415 rb_method_entry_t * 00416 rb_method_entry(VALUE klass, ID id) 00417 { 00418 struct cache_entry *ent; 00419 00420 ent = cache + EXPR1(klass, id); 00421 if (ent->filled_version == GET_VM_STATE_VERSION() && 00422 ent->mid == id && ent->klass == klass) { 00423 return ent->me; 00424 } 00425 00426 return rb_method_entry_get_without_cache(klass, id); 00427 } 00428 00429 static void 00430 remove_method(VALUE klass, ID mid) 00431 { 00432 st_data_t key, data; 00433 rb_method_entry_t *me = 0; 00434 00435 if (klass == rb_cObject) { 00436 rb_secure(4); 00437 } 00438 if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(klass)) { 00439 rb_raise(rb_eSecurityError, "Insecure: can't remove method"); 00440 } 00441 rb_check_frozen(klass); 00442 if (mid == object_id || mid == id__send__ || mid == idInitialize) { 00443 rb_warn("removing `%s' may cause serious problems", rb_id2name(mid)); 00444 } 00445 00446 if (!st_lookup(RCLASS_M_TBL(klass), mid, &data) || 00447 !(me = (rb_method_entry_t *)data) || 00448 (!me->def || me->def->type == VM_METHOD_TYPE_UNDEF)) { 00449 rb_name_error(mid, "method `%s' not defined in %s", 00450 rb_id2name(mid), rb_class2name(klass)); 00451 } 00452 key = (st_data_t)mid; 00453 st_delete(RCLASS_M_TBL(klass), &key, &data); 00454 00455 rb_vm_check_redefinition_opt_method(me); 00456 rb_clear_cache_for_undef(klass, mid); 00457 rb_unlink_method_entry(me); 00458 00459 CALL_METHOD_HOOK(klass, removed, mid); 00460 } 00461 00462 void 00463 rb_remove_method_id(VALUE klass, ID mid) 00464 { 00465 remove_method(klass, mid); 00466 } 00467 00468 void 00469 rb_remove_method(VALUE klass, const char *name) 00470 { 00471 remove_method(klass, rb_intern(name)); 00472 } 00473 00474 /* 00475 * call-seq: 00476 * remove_method(symbol) -> self 00477 * 00478 * Removes the method identified by _symbol_ from the current 00479 * class. For an example, see <code>Module.undef_method</code>. 00480 */ 00481 00482 static VALUE 00483 rb_mod_remove_method(int argc, VALUE *argv, VALUE mod) 00484 { 00485 int i; 00486 00487 for (i = 0; i < argc; i++) { 00488 remove_method(mod, rb_to_id(argv[i])); 00489 } 00490 return mod; 00491 } 00492 00493 #undef rb_disable_super 00494 #undef rb_enable_super 00495 00496 void 00497 rb_disable_super(VALUE klass, const char *name) 00498 { 00499 /* obsolete - no use */ 00500 } 00501 00502 void 00503 rb_enable_super(VALUE klass, const char *name) 00504 { 00505 rb_warning("rb_enable_super() is obsolete"); 00506 } 00507 00508 static void 00509 rb_export_method(VALUE klass, ID name, rb_method_flag_t noex) 00510 { 00511 rb_method_entry_t *me; 00512 00513 if (klass == rb_cObject) { 00514 rb_secure(4); 00515 } 00516 00517 me = search_method(klass, name); 00518 if (!me && TYPE(klass) == T_MODULE) { 00519 me = search_method(rb_cObject, name); 00520 } 00521 00522 if (UNDEFINED_METHOD_ENTRY_P(me)) { 00523 rb_print_undef(klass, name, 0); 00524 } 00525 00526 if (me->flag != noex) { 00527 rb_vm_check_redefinition_opt_method(me); 00528 00529 if (klass == me->klass) { 00530 me->flag = noex; 00531 } 00532 else { 00533 rb_add_method(klass, name, VM_METHOD_TYPE_ZSUPER, 0, noex); 00534 } 00535 } 00536 } 00537 00538 int 00539 rb_method_boundp(VALUE klass, ID id, int ex) 00540 { 00541 rb_method_entry_t *me = rb_method_entry(klass, id); 00542 00543 if (me != 0) { 00544 if ((ex & ~NOEX_RESPONDS) && (me->flag & NOEX_PRIVATE)) { 00545 return FALSE; 00546 } 00547 if (!me->def) return 0; 00548 if (me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) { 00549 if (ex & NOEX_RESPONDS) return 2; 00550 return 0; 00551 } 00552 return 1; 00553 } 00554 return 0; 00555 } 00556 00557 void 00558 rb_attr(VALUE klass, ID id, int read, int write, int ex) 00559 { 00560 const char *name; 00561 ID attriv; 00562 VALUE aname; 00563 rb_method_flag_t noex; 00564 00565 if (!ex) { 00566 noex = NOEX_PUBLIC; 00567 } 00568 else { 00569 if (SCOPE_TEST(NOEX_PRIVATE)) { 00570 noex = NOEX_PRIVATE; 00571 rb_warning((SCOPE_CHECK(NOEX_MODFUNC)) ? 00572 "attribute accessor as module_function" : 00573 "private attribute?"); 00574 } 00575 else if (SCOPE_TEST(NOEX_PROTECTED)) { 00576 noex = NOEX_PROTECTED; 00577 } 00578 else { 00579 noex = NOEX_PUBLIC; 00580 } 00581 } 00582 00583 if (!rb_is_local_id(id) && !rb_is_const_id(id)) { 00584 rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id)); 00585 } 00586 name = rb_id2name(id); 00587 if (!name) { 00588 rb_raise(rb_eArgError, "argument needs to be symbol or string"); 00589 } 00590 aname = rb_sprintf("@%s", name); 00591 rb_enc_copy(aname, rb_id2str(id)); 00592 attriv = rb_intern_str(aname); 00593 if (read) { 00594 rb_add_method(klass, id, VM_METHOD_TYPE_IVAR, (void *)attriv, noex); 00595 } 00596 if (write) { 00597 rb_add_method(klass, rb_id_attrset(id), VM_METHOD_TYPE_ATTRSET, (void *)attriv, noex); 00598 } 00599 } 00600 00601 void 00602 rb_undef(VALUE klass, ID id) 00603 { 00604 rb_method_entry_t *me; 00605 00606 if (NIL_P(klass)) { 00607 rb_raise(rb_eTypeError, "no class to undef method"); 00608 } 00609 if (rb_vm_cbase() == rb_cObject && klass == rb_cObject) { 00610 rb_secure(4); 00611 } 00612 if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(klass)) { 00613 rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'", rb_id2name(id)); 00614 } 00615 rb_frozen_class_p(klass); 00616 if (id == object_id || id == id__send__ || id == idInitialize) { 00617 rb_warn("undefining `%s' may cause serious problems", rb_id2name(id)); 00618 } 00619 00620 me = search_method(klass, id); 00621 00622 if (UNDEFINED_METHOD_ENTRY_P(me)) { 00623 const char *s0 = " class"; 00624 VALUE c = klass; 00625 00626 if (FL_TEST(c, FL_SINGLETON)) { 00627 VALUE obj = rb_ivar_get(klass, attached); 00628 00629 switch (TYPE(obj)) { 00630 case T_MODULE: 00631 case T_CLASS: 00632 c = obj; 00633 s0 = ""; 00634 } 00635 } 00636 else if (TYPE(c) == T_MODULE) { 00637 s0 = " module"; 00638 } 00639 rb_name_error(id, "undefined method `%s' for%s `%s'", 00640 rb_id2name(id), s0, rb_class2name(c)); 00641 } 00642 00643 rb_add_method(klass, id, VM_METHOD_TYPE_UNDEF, 0, NOEX_PUBLIC); 00644 00645 CALL_METHOD_HOOK(klass, undefined, id); 00646 } 00647 00648 /* 00649 * call-seq: 00650 * undef_method(symbol) -> self 00651 * 00652 * Prevents the current class from responding to calls to the named 00653 * method. Contrast this with <code>remove_method</code>, which deletes 00654 * the method from the particular class; Ruby will still search 00655 * superclasses and mixed-in modules for a possible receiver. 00656 * 00657 * class Parent 00658 * def hello 00659 * puts "In parent" 00660 * end 00661 * end 00662 * class Child < Parent 00663 * def hello 00664 * puts "In child" 00665 * end 00666 * end 00667 * 00668 * 00669 * c = Child.new 00670 * c.hello 00671 * 00672 * 00673 * class Child 00674 * remove_method :hello # remove from child, still in parent 00675 * end 00676 * c.hello 00677 * 00678 * 00679 * class Child 00680 * undef_method :hello # prevent any calls to 'hello' 00681 * end 00682 * c.hello 00683 * 00684 * <em>produces:</em> 00685 * 00686 * In child 00687 * In parent 00688 * prog.rb:23: undefined method `hello' for #<Child:0x401b3bb4> (NoMethodError) 00689 */ 00690 00691 static VALUE 00692 rb_mod_undef_method(int argc, VALUE *argv, VALUE mod) 00693 { 00694 int i; 00695 for (i = 0; i < argc; i++) { 00696 rb_undef(mod, rb_to_id(argv[i])); 00697 } 00698 return mod; 00699 } 00700 00701 /* 00702 * call-seq: 00703 * mod.method_defined?(symbol) -> true or false 00704 * 00705 * Returns +true+ if the named method is defined by 00706 * _mod_ (or its included modules and, if _mod_ is a class, 00707 * its ancestors). Public and protected methods are matched. 00708 * 00709 * module A 00710 * def method1() end 00711 * end 00712 * class B 00713 * def method2() end 00714 * end 00715 * class C < B 00716 * include A 00717 * def method3() end 00718 * end 00719 * 00720 * A.method_defined? :method1 #=> true 00721 * C.method_defined? "method1" #=> true 00722 * C.method_defined? "method2" #=> true 00723 * C.method_defined? "method3" #=> true 00724 * C.method_defined? "method4" #=> false 00725 */ 00726 00727 static VALUE 00728 rb_mod_method_defined(VALUE mod, VALUE mid) 00729 { 00730 if (!rb_method_boundp(mod, rb_to_id(mid), 1)) { 00731 return Qfalse; 00732 } 00733 return Qtrue; 00734 00735 } 00736 00737 #define VISI_CHECK(x,f) (((x)&NOEX_MASK) == (f)) 00738 00739 static VALUE 00740 check_definition(VALUE mod, ID mid, rb_method_flag_t noex) 00741 { 00742 const rb_method_entry_t *me; 00743 me = rb_method_entry(mod, mid); 00744 if (me) { 00745 if (VISI_CHECK(me->flag, noex)) 00746 return Qtrue; 00747 } 00748 return Qfalse; 00749 } 00750 00751 /* 00752 * call-seq: 00753 * mod.public_method_defined?(symbol) -> true or false 00754 * 00755 * Returns +true+ if the named public method is defined by 00756 * _mod_ (or its included modules and, if _mod_ is a class, 00757 * its ancestors). 00758 * 00759 * module A 00760 * def method1() end 00761 * end 00762 * class B 00763 * protected 00764 * def method2() end 00765 * end 00766 * class C < B 00767 * include A 00768 * def method3() end 00769 * end 00770 * 00771 * A.method_defined? :method1 #=> true 00772 * C.public_method_defined? "method1" #=> true 00773 * C.public_method_defined? "method2" #=> false 00774 * C.method_defined? "method2" #=> true 00775 */ 00776 00777 static VALUE 00778 rb_mod_public_method_defined(VALUE mod, VALUE mid) 00779 { 00780 return check_definition(mod, rb_to_id(mid), NOEX_PUBLIC); 00781 } 00782 00783 /* 00784 * call-seq: 00785 * mod.private_method_defined?(symbol) -> true or false 00786 * 00787 * Returns +true+ if the named private method is defined by 00788 * _ mod_ (or its included modules and, if _mod_ is a class, 00789 * its ancestors). 00790 * 00791 * module A 00792 * def method1() end 00793 * end 00794 * class B 00795 * private 00796 * def method2() end 00797 * end 00798 * class C < B 00799 * include A 00800 * def method3() end 00801 * end 00802 * 00803 * A.method_defined? :method1 #=> true 00804 * C.private_method_defined? "method1" #=> false 00805 * C.private_method_defined? "method2" #=> true 00806 * C.method_defined? "method2" #=> false 00807 */ 00808 00809 static VALUE 00810 rb_mod_private_method_defined(VALUE mod, VALUE mid) 00811 { 00812 return check_definition(mod, rb_to_id(mid), NOEX_PRIVATE); 00813 } 00814 00815 /* 00816 * call-seq: 00817 * mod.protected_method_defined?(symbol) -> true or false 00818 * 00819 * Returns +true+ if the named protected method is defined 00820 * by _mod_ (or its included modules and, if _mod_ is a 00821 * class, its ancestors). 00822 * 00823 * module A 00824 * def method1() end 00825 * end 00826 * class B 00827 * protected 00828 * def method2() end 00829 * end 00830 * class C < B 00831 * include A 00832 * def method3() end 00833 * end 00834 * 00835 * A.method_defined? :method1 #=> true 00836 * C.protected_method_defined? "method1" #=> false 00837 * C.protected_method_defined? "method2" #=> true 00838 * C.method_defined? "method2" #=> true 00839 */ 00840 00841 static VALUE 00842 rb_mod_protected_method_defined(VALUE mod, VALUE mid) 00843 { 00844 return check_definition(mod, rb_to_id(mid), NOEX_PROTECTED); 00845 } 00846 00847 int 00848 rb_method_entry_eq(const rb_method_entry_t *m1, const rb_method_entry_t *m2) 00849 { 00850 return rb_method_definition_eq(m1->def, m2->def); 00851 } 00852 00853 static int 00854 rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2) 00855 { 00856 if (d1 == d2) return 1; 00857 if (!d1 || !d2) return 0; 00858 if (d1->type != d2->type) { 00859 return 0; 00860 } 00861 switch (d1->type) { 00862 case VM_METHOD_TYPE_ISEQ: 00863 return d1->body.iseq == d2->body.iseq; 00864 case VM_METHOD_TYPE_CFUNC: 00865 return 00866 d1->body.cfunc.func == d2->body.cfunc.func && 00867 d1->body.cfunc.argc == d2->body.cfunc.argc; 00868 case VM_METHOD_TYPE_ATTRSET: 00869 case VM_METHOD_TYPE_IVAR: 00870 return d1->body.attr.id == d2->body.attr.id; 00871 case VM_METHOD_TYPE_BMETHOD: 00872 return RTEST(rb_equal(d1->body.proc, d2->body.proc)); 00873 case VM_METHOD_TYPE_MISSING: 00874 return d1->original_id == d2->original_id; 00875 case VM_METHOD_TYPE_ZSUPER: 00876 case VM_METHOD_TYPE_NOTIMPLEMENTED: 00877 case VM_METHOD_TYPE_UNDEF: 00878 return 1; 00879 case VM_METHOD_TYPE_OPTIMIZED: 00880 return d1->body.optimize_type == d2->body.optimize_type; 00881 default: 00882 rb_bug("rb_method_entry_eq: unsupported method type (%d)\n", d1->type); 00883 return 0; 00884 } 00885 } 00886 00887 void 00888 rb_alias(VALUE klass, ID name, ID def) 00889 { 00890 VALUE target_klass = klass; 00891 rb_method_entry_t *orig_me; 00892 rb_method_flag_t flag = NOEX_UNDEF; 00893 00894 if (NIL_P(klass)) { 00895 rb_raise(rb_eTypeError, "no class to make alias"); 00896 } 00897 00898 rb_frozen_class_p(klass); 00899 if (klass == rb_cObject) { 00900 rb_secure(4); 00901 } 00902 00903 again: 00904 orig_me = search_method(klass, def); 00905 00906 if (UNDEFINED_METHOD_ENTRY_P(orig_me)) { 00907 if ((TYPE(klass) != T_MODULE) || 00908 (orig_me = search_method(rb_cObject, def), UNDEFINED_METHOD_ENTRY_P(orig_me))) { 00909 rb_print_undef(klass, def, 0); 00910 } 00911 } 00912 if (orig_me->def->type == VM_METHOD_TYPE_ZSUPER) { 00913 klass = RCLASS_SUPER(klass); 00914 def = orig_me->def->original_id; 00915 flag = orig_me->flag; 00916 goto again; 00917 } 00918 00919 if (flag == NOEX_UNDEF) flag = orig_me->flag; 00920 rb_method_entry_set(target_klass, name, orig_me, flag); 00921 } 00922 00923 /* 00924 * call-seq: 00925 * alias_method(new_name, old_name) -> self 00926 * 00927 * Makes <i>new_name</i> a new copy of the method <i>old_name</i>. This can 00928 * be used to retain access to methods that are overridden. 00929 * 00930 * module Mod 00931 * alias_method :orig_exit, :exit 00932 * def exit(code=0) 00933 * puts "Exiting with code #{code}" 00934 * orig_exit(code) 00935 * end 00936 * end 00937 * include Mod 00938 * exit(99) 00939 * 00940 * <em>produces:</em> 00941 * 00942 * Exiting with code 99 00943 */ 00944 00945 static VALUE 00946 rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname) 00947 { 00948 rb_alias(mod, rb_to_id(newname), rb_to_id(oldname)); 00949 return mod; 00950 } 00951 00952 static void 00953 secure_visibility(VALUE self) 00954 { 00955 if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(self)) { 00956 rb_raise(rb_eSecurityError, 00957 "Insecure: can't change method visibility"); 00958 } 00959 } 00960 00961 static void 00962 set_method_visibility(VALUE self, int argc, VALUE *argv, rb_method_flag_t ex) 00963 { 00964 int i; 00965 secure_visibility(self); 00966 00967 if (argc == 0) { 00968 rb_warning("%s with no argument is just ignored", rb_id2name(rb_frame_callee())); 00969 } 00970 00971 for (i = 0; i < argc; i++) { 00972 rb_export_method(self, rb_to_id(argv[i]), ex); 00973 } 00974 rb_clear_cache_by_class(self); 00975 } 00976 00977 /* 00978 * call-seq: 00979 * public -> self 00980 * public(symbol, ...) -> self 00981 * 00982 * With no arguments, sets the default visibility for subsequently 00983 * defined methods to public. With arguments, sets the named methods to 00984 * have public visibility. 00985 */ 00986 00987 static VALUE 00988 rb_mod_public(int argc, VALUE *argv, VALUE module) 00989 { 00990 secure_visibility(module); 00991 if (argc == 0) { 00992 SCOPE_SET(NOEX_PUBLIC); 00993 } 00994 else { 00995 set_method_visibility(module, argc, argv, NOEX_PUBLIC); 00996 } 00997 return module; 00998 } 00999 01000 /* 01001 * call-seq: 01002 * protected -> self 01003 * protected(symbol, ...) -> self 01004 * 01005 * With no arguments, sets the default visibility for subsequently 01006 * defined methods to protected. With arguments, sets the named methods 01007 * to have protected visibility. 01008 */ 01009 01010 static VALUE 01011 rb_mod_protected(int argc, VALUE *argv, VALUE module) 01012 { 01013 secure_visibility(module); 01014 if (argc == 0) { 01015 SCOPE_SET(NOEX_PROTECTED); 01016 } 01017 else { 01018 set_method_visibility(module, argc, argv, NOEX_PROTECTED); 01019 } 01020 return module; 01021 } 01022 01023 /* 01024 * call-seq: 01025 * private -> self 01026 * private(symbol, ...) -> self 01027 * 01028 * With no arguments, sets the default visibility for subsequently 01029 * defined methods to private. With arguments, sets the named methods 01030 * to have private visibility. 01031 * 01032 * module Mod 01033 * def a() end 01034 * def b() end 01035 * private 01036 * def c() end 01037 * private :a 01038 * end 01039 * Mod.private_instance_methods #=> [:a, :c] 01040 */ 01041 01042 static VALUE 01043 rb_mod_private(int argc, VALUE *argv, VALUE module) 01044 { 01045 secure_visibility(module); 01046 if (argc == 0) { 01047 SCOPE_SET(NOEX_PRIVATE); 01048 } 01049 else { 01050 set_method_visibility(module, argc, argv, NOEX_PRIVATE); 01051 } 01052 return module; 01053 } 01054 01055 /* 01056 * call-seq: 01057 * mod.public_class_method(symbol, ...) -> mod 01058 * 01059 * Makes a list of existing class methods public. 01060 */ 01061 01062 static VALUE 01063 rb_mod_public_method(int argc, VALUE *argv, VALUE obj) 01064 { 01065 set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PUBLIC); 01066 return obj; 01067 } 01068 01069 /* 01070 * call-seq: 01071 * mod.private_class_method(symbol, ...) -> mod 01072 * 01073 * Makes existing class methods private. Often used to hide the default 01074 * constructor <code>new</code>. 01075 * 01076 * class SimpleSingleton # Not thread safe 01077 * private_class_method :new 01078 * def SimpleSingleton.create(*args, &block) 01079 * @me = new(*args, &block) if ! @me 01080 * @me 01081 * end 01082 * end 01083 */ 01084 01085 static VALUE 01086 rb_mod_private_method(int argc, VALUE *argv, VALUE obj) 01087 { 01088 set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PRIVATE); 01089 return obj; 01090 } 01091 01092 /* 01093 * call-seq: 01094 * public 01095 * public(symbol, ...) 01096 * 01097 * With no arguments, sets the default visibility for subsequently 01098 * defined methods to public. With arguments, sets the named methods to 01099 * have public visibility. 01100 */ 01101 01102 static VALUE 01103 top_public(int argc, VALUE *argv) 01104 { 01105 return rb_mod_public(argc, argv, rb_cObject); 01106 } 01107 01108 static VALUE 01109 top_private(int argc, VALUE *argv) 01110 { 01111 return rb_mod_private(argc, argv, rb_cObject); 01112 } 01113 01114 /* 01115 * call-seq: 01116 * module_function(symbol, ...) -> self 01117 * 01118 * Creates module functions for the named methods. These functions may 01119 * be called with the module as a receiver, and also become available 01120 * as instance methods to classes that mix in the module. Module 01121 * functions are copies of the original, and so may be changed 01122 * independently. The instance-method versions are made private. If 01123 * used with no arguments, subsequently defined methods become module 01124 * functions. 01125 * 01126 * module Mod 01127 * def one 01128 * "This is one" 01129 * end 01130 * module_function :one 01131 * end 01132 * class Cls 01133 * include Mod 01134 * def call_one 01135 * one 01136 * end 01137 * end 01138 * Mod.one #=> "This is one" 01139 * c = Cls.new 01140 * c.call_one #=> "This is one" 01141 * module Mod 01142 * def one 01143 * "This is the new one" 01144 * end 01145 * end 01146 * Mod.one #=> "This is one" 01147 * c.call_one #=> "This is the new one" 01148 */ 01149 01150 static VALUE 01151 rb_mod_modfunc(int argc, VALUE *argv, VALUE module) 01152 { 01153 int i; 01154 ID id; 01155 const rb_method_entry_t *me; 01156 01157 if (TYPE(module) != T_MODULE) { 01158 rb_raise(rb_eTypeError, "module_function must be called for modules"); 01159 } 01160 01161 secure_visibility(module); 01162 if (argc == 0) { 01163 SCOPE_SET(NOEX_MODFUNC); 01164 return module; 01165 } 01166 01167 set_method_visibility(module, argc, argv, NOEX_PRIVATE); 01168 01169 for (i = 0; i < argc; i++) { 01170 VALUE m = module; 01171 01172 id = rb_to_id(argv[i]); 01173 for (;;) { 01174 me = search_method(m, id); 01175 if (me == 0) { 01176 me = search_method(rb_cObject, id); 01177 } 01178 if (UNDEFINED_METHOD_ENTRY_P(me)) { 01179 rb_print_undef(module, id, 0); 01180 } 01181 if (me->def->type != VM_METHOD_TYPE_ZSUPER) { 01182 break; /* normal case: need not to follow 'super' link */ 01183 } 01184 m = RCLASS_SUPER(m); 01185 if (!m) 01186 break; 01187 } 01188 rb_method_entry_set(rb_singleton_class(module), id, me, NOEX_PUBLIC); 01189 } 01190 return module; 01191 } 01192 01193 int 01194 rb_method_basic_definition_p(VALUE klass, ID id) 01195 { 01196 const rb_method_entry_t *me = rb_method_entry(klass, id); 01197 if (me && (me->flag & NOEX_BASIC)) 01198 return 1; 01199 return 0; 01200 } 01201 01202 static inline int 01203 basic_obj_respond_to(VALUE obj, ID id, int pub) 01204 { 01205 VALUE klass = CLASS_OF(obj); 01206 01207 switch (rb_method_boundp(klass, id, pub|NOEX_RESPONDS)) { 01208 case 2: 01209 return FALSE; 01210 case 0: 01211 return RTEST(rb_funcall(obj, respond_to_missing, 2, ID2SYM(id), pub ? Qfalse : Qtrue)); 01212 default: 01213 return TRUE; 01214 } 01215 } 01216 01217 int 01218 rb_obj_respond_to(VALUE obj, ID id, int priv) 01219 { 01220 VALUE klass = CLASS_OF(obj); 01221 01222 if (rb_method_basic_definition_p(klass, idRespond_to)) { 01223 return basic_obj_respond_to(obj, id, !RTEST(priv)); 01224 } 01225 else { 01226 return RTEST(rb_funcall(obj, idRespond_to, priv ? 2 : 1, ID2SYM(id), Qtrue)); 01227 } 01228 } 01229 01230 int 01231 rb_respond_to(VALUE obj, ID id) 01232 { 01233 return rb_obj_respond_to(obj, id, FALSE); 01234 } 01235 01236 01237 /* 01238 * call-seq: 01239 * obj.respond_to?(symbol, include_private=false) -> true or false 01240 * 01241 * Returns +true+ if _obj_ responds to the given 01242 * method. Private methods are included in the search only if the 01243 * optional second parameter evaluates to +true+. 01244 * 01245 * If the method is not implemented, 01246 * as Process.fork on Windows, File.lchmod on GNU/Linux, etc., 01247 * false is returned. 01248 * 01249 * If the method is not defined, <code>respond_to_missing?</code> 01250 * method is called and the result is returned. 01251 */ 01252 01253 static VALUE 01254 obj_respond_to(int argc, VALUE *argv, VALUE obj) 01255 { 01256 VALUE mid, priv; 01257 ID id; 01258 01259 rb_scan_args(argc, argv, "11", &mid, &priv); 01260 id = rb_to_id(mid); 01261 if (basic_obj_respond_to(obj, id, !RTEST(priv))) 01262 return Qtrue; 01263 return Qfalse; 01264 } 01265 01266 /* 01267 * call-seq: 01268 * obj.respond_to_missing?(symbol, include_private) -> true or false 01269 * 01270 * Hook method to return whether the _obj_ can respond to _id_ method 01271 * or not. 01272 * 01273 * See #respond_to?. 01274 */ 01275 static VALUE 01276 obj_respond_to_missing(VALUE obj, VALUE mid, VALUE priv) 01277 { 01278 return Qfalse; 01279 } 01280 01281 void 01282 Init_eval_method(void) 01283 { 01284 #undef rb_intern 01285 #define rb_intern(str) rb_intern_const(str) 01286 01287 rb_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1); 01288 rb_define_method(rb_mKernel, "respond_to_missing?", obj_respond_to_missing, 2); 01289 01290 rb_define_private_method(rb_cModule, "remove_method", rb_mod_remove_method, -1); 01291 rb_define_private_method(rb_cModule, "undef_method", rb_mod_undef_method, -1); 01292 rb_define_private_method(rb_cModule, "alias_method", rb_mod_alias_method, 2); 01293 rb_define_private_method(rb_cModule, "public", rb_mod_public, -1); 01294 rb_define_private_method(rb_cModule, "protected", rb_mod_protected, -1); 01295 rb_define_private_method(rb_cModule, "private", rb_mod_private, -1); 01296 rb_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1); 01297 01298 rb_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, 1); 01299 rb_define_method(rb_cModule, "public_method_defined?", rb_mod_public_method_defined, 1); 01300 rb_define_method(rb_cModule, "private_method_defined?", rb_mod_private_method_defined, 1); 01301 rb_define_method(rb_cModule, "protected_method_defined?", rb_mod_protected_method_defined, 1); 01302 rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1); 01303 rb_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1); 01304 01305 rb_define_singleton_method(rb_vm_top_self(), "public", top_public, -1); 01306 rb_define_singleton_method(rb_vm_top_self(), "private", top_private, -1); 01307 01308 object_id = rb_intern("object_id"); 01309 added = rb_intern("method_added"); 01310 singleton_added = rb_intern("singleton_method_added"); 01311 removed = rb_intern("method_removed"); 01312 singleton_removed = rb_intern("singleton_method_removed"); 01313 undefined = rb_intern("method_undefined"); 01314 singleton_undefined = rb_intern("singleton_method_undefined"); 01315 attached = rb_intern("__attached__"); 01316 respond_to_missing = rb_intern("respond_to_missing?"); 01317 } 01318 01319