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