Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# vm_method.c

Go to the documentation of this file.

    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