Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# vm_eval.c

Go to the documentation of this file.

    00001 /**********************************************************************
    00002
    00003   vm_eval.c -
    00004
    00005   $Author: yugui $
    00006   created at: Sat May 24 16:02:32 JST 2008
    00007
    00008   Copyright (C) 1993-2007 Yukihiro Matsumoto
    00009   Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
    00010   Copyright (C) 2000  Information-technology Promotion Agency, Japan
    00011
    00012 **********************************************************************/
    00013
    00014 static inline VALUE method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status);
    00015 static inline VALUE rb_vm_set_finish_env(rb_thread_t * th);
    00016 static inline VALUE vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *argv, const NODE *cref);
    00017 static inline VALUE vm_yield(rb_thread_t *th, int argc, const VALUE *argv);
    00018 static inline VALUE vm_backtrace(rb_thread_t *th, int lev);
    00019 static int vm_backtrace_each(rb_thread_t *th, int lev, void (*init)(void *), rb_backtrace_iter_func *iter, void *arg);
    00020 static NODE *vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr);
    00021 static VALUE vm_exec(rb_thread_t *th);
    00022 static void vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const NODE *cref);
    00023 static int vm_collect_local_variables_in_heap(rb_thread_t *th, VALUE *dfp, VALUE ary);
    00024
    00025 typedef enum call_type {
    00026     CALL_PUBLIC,
    00027     CALL_FCALL,
    00028     CALL_VCALL,
    00029     CALL_TYPE_MAX
    00030 } call_type;
    00031
    00032 static VALUE send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope);
    00033
    00034 static inline VALUE
    00035 vm_call0(rb_thread_t* th, VALUE recv, VALUE id, int argc, const VALUE *argv,
    00036          const rb_method_entry_t *me)
    00037 {
    00038     const rb_method_definition_t *def = me->def;
    00039     VALUE val;
    00040     VALUE klass = me->klass;
    00041     const rb_block_t *blockptr = 0;
    00042
    00043     if (!def) return Qnil;
    00044     if (th->passed_block) {
    00045         blockptr = th->passed_block;
    00046         th->passed_block = 0;
    00047     }
    00048
    00049   again:
    00050     switch (def->type) {
    00051       case VM_METHOD_TYPE_ISEQ: {
    00052         rb_control_frame_t *reg_cfp;
    00053         int i;
    00054
    00055         rb_vm_set_finish_env(th);
    00056         reg_cfp = th->cfp;
    00057
    00058         CHECK_STACK_OVERFLOW(reg_cfp, argc + 1);
    00059
    00060         *reg_cfp->sp++ = recv;
    00061         for (i = 0; i < argc; i++) {
    00062             *reg_cfp->sp++ = argv[i];
    00063         }
    00064
    00065         vm_setup_method(th, reg_cfp, recv, argc, blockptr, 0 /* flag */, me);
    00066         val = vm_exec(th);
    00067         break;
    00068       }
    00069       case VM_METHOD_TYPE_NOTIMPLEMENTED:
    00070       case VM_METHOD_TYPE_CFUNC: {
    00071         EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, id, klass);
    00072         {
    00073             rb_control_frame_t *reg_cfp = th->cfp;
    00074             rb_control_frame_t *cfp =
    00075                 vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC,
    00076                               recv, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1);
    00077
    00078             cfp->me = me;
    00079             val = call_cfunc(def->body.cfunc.func, recv, def->body.cfunc.argc, argc, argv);
    00080
    00081             if (reg_cfp != th->cfp + 1) {
    00082                 rb_bug("cfp consistency error - call0");
    00083             }
    00084             vm_pop_frame(th);
    00085         }
    00086         EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, recv, id, klass);
    00087         break;
    00088       }
    00089       case VM_METHOD_TYPE_ATTRSET: {
    00090         if (argc != 1) {
    00091             rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
    00092         }
    00093         val = rb_ivar_set(recv, def->body.attr.id, argv[0]);
    00094         break;
    00095       }
    00096       case VM_METHOD_TYPE_IVAR: {
    00097         if (argc != 0) {
    00098             rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
    00099         }
    00100         val = rb_attr_get(recv, def->body.attr.id);
    00101         break;
    00102       }
    00103       case VM_METHOD_TYPE_BMETHOD: {
    00104         val = vm_call_bmethod(th, recv, argc, argv, blockptr, me);
    00105         break;
    00106       }
    00107       case VM_METHOD_TYPE_ZSUPER: {
    00108         klass = RCLASS_SUPER(klass);
    00109         if (!klass || !(me = rb_method_entry(klass, id))) {
    00110             return method_missing(recv, id, argc, argv, NOEX_SUPER);
    00111         }
    00112         RUBY_VM_CHECK_INTS();
    00113         if (!(def = me->def)) return Qnil;
    00114         goto again;
    00115       }
    00116       case VM_METHOD_TYPE_MISSING: {
    00117         VALUE new_args = rb_ary_new4(argc, argv);
    00118
    00119         RB_GC_GUARD(new_args);
    00120         rb_ary_unshift(new_args, ID2SYM(id));
    00121         return rb_funcall2(recv, idMethodMissing,
    00122                            argc+1, RARRAY_PTR(new_args));
    00123       }
    00124       case VM_METHOD_TYPE_OPTIMIZED: {
    00125         switch (def->body.optimize_type) {
    00126           case OPTIMIZED_METHOD_TYPE_SEND:
    00127             val = send_internal(argc, argv, recv, CALL_FCALL);
    00128             break;
    00129           case OPTIMIZED_METHOD_TYPE_CALL: {
    00130             rb_proc_t *proc;
    00131             GetProcPtr(recv, proc);
    00132             val = rb_vm_invoke_proc(th, proc, proc->block.self, argc, argv, blockptr);
    00133             break;
    00134           }
    00135           default:
    00136             rb_bug("vm_call0: unsupported optimized method type (%d)", def->body.optimize_type);
    00137             val = Qundef;
    00138             break;
    00139         }
    00140         break;
    00141       }
    00142       default:
    00143         rb_bug("vm_call0: unsupported method type (%d)", def->type);
    00144         val = Qundef;
    00145     }
    00146     RUBY_VM_CHECK_INTS();
    00147     return val;
    00148 }
    00149
    00150 VALUE
    00151 rb_vm_call(rb_thread_t *th, VALUE recv, VALUE id, int argc, const VALUE *argv,
    00152            const rb_method_entry_t *me)
    00153 {
    00154     return vm_call0(th, recv, id, argc, argv, me);
    00155 }
    00156
    00157 static inline VALUE
    00158 vm_call_super(rb_thread_t *th, int argc, const VALUE *argv)
    00159 {
    00160     VALUE recv = th->cfp->self;
    00161     VALUE klass;
    00162     ID id;
    00163     rb_method_entry_t *me;
    00164     rb_control_frame_t *cfp = th->cfp;
    00165
    00166     if (!cfp->iseq) {
    00167         klass = cfp->me->klass;
    00168         klass = RCLASS_SUPER(klass);
    00169
    00170         if (klass == 0) {
    00171             klass = vm_search_normal_superclass(cfp->me->klass, recv);
    00172         }
    00173         id = cfp->me->def->original_id;
    00174     }
    00175     else {
    00176         rb_bug("vm_call_super: should not be reached");
    00177     }
    00178
    00179     me = rb_method_entry(klass, id);
    00180     if (!me) {
    00181         return method_missing(recv, id, argc, argv, NOEX_SUPER);
    00182     }
    00183
    00184     return vm_call0(th, recv, id, argc, argv, me);
    00185 }
    00186
    00187 VALUE
    00188 rb_call_super(int argc, const VALUE *argv)
    00189 {
    00190     PASS_PASSED_BLOCK();
    00191     return vm_call_super(GET_THREAD(), argc, argv);
    00192 }
    00193
    00194 static inline void
    00195 stack_check(void)
    00196 {
    00197     rb_thread_t *th = GET_THREAD();
    00198
    00199     if (!rb_thread_raised_p(th, RAISED_STACKOVERFLOW) && ruby_stack_check()) {
    00200         rb_thread_raised_set(th, RAISED_STACKOVERFLOW);
    00201         rb_exc_raise(sysstack_error);
    00202     }
    00203 }
    00204
    00205 static inline rb_method_entry_t *rb_search_method_entry(VALUE recv, ID mid);
    00206 static inline int rb_method_call_status(rb_thread_t *th, rb_method_entry_t *me, call_type scope, VALUE self);
    00207 #define NOEX_OK NOEX_NOSUPER
    00208
    00223 static inline VALUE
    00224 rb_call0(VALUE recv, ID mid, int argc, const VALUE *argv,
    00225          call_type scope, VALUE self)
    00226 {
    00227     rb_method_entry_t *me = rb_search_method_entry(recv, mid);
    00228     rb_thread_t *th = GET_THREAD();
    00229     int call_status = rb_method_call_status(th, me, scope, self);
    00230
    00231     if (call_status != NOEX_OK) {
    00232         return method_missing(recv, mid, argc, argv, call_status);
    00233     }
    00234     stack_check();
    00235     return vm_call0(th, recv, mid, argc, argv, me);
    00236 }
    00237
    00238 struct rescue_funcall_args {
    00239     VALUE recv;
    00240     VALUE sym;
    00241     int argc;
    00242     VALUE *argv;
    00243 };
    00244
    00245 static VALUE
    00246 check_funcall_exec(struct rescue_funcall_args *args)
    00247 {
    00248     VALUE new_args = rb_ary_new4(args->argc, args->argv);
    00249
    00250     RB_GC_GUARD(new_args);
    00251     rb_ary_unshift(new_args, args->sym);
    00252     return rb_funcall2(args->recv, idMethodMissing,
    00253                        args->argc+1, RARRAY_PTR(new_args));
    00254 }
    00255
    00256 static VALUE
    00257 check_funcall_failed(struct rescue_funcall_args *args, VALUE e)
    00258 {
    00259     if (rb_respond_to(args->recv, SYM2ID(args->sym))) {
    00260         rb_exc_raise(e);
    00261     }
    00262     return Qundef;
    00263 }
    00264
    00265 static VALUE
    00266 check_funcall(VALUE recv, ID mid, int argc, VALUE *argv)
    00267 {
    00268     rb_method_entry_t *me = rb_search_method_entry(recv, mid);
    00269     rb_thread_t *th = GET_THREAD();
    00270     int call_status = rb_method_call_status(th, me, CALL_FCALL, Qundef);
    00271
    00272     if (call_status != NOEX_OK) {
    00273         if (rb_method_basic_definition_p(CLASS_OF(recv), idMethodMissing)) {
    00274             return Qundef;
    00275         }
    00276         else {
    00277             struct rescue_funcall_args args;
    00278
    00279             th->method_missing_reason = 0;
    00280             args.recv = recv;
    00281             args.sym = ID2SYM(mid);
    00282             args.argc = argc;
    00283             args.argv = argv;
    00284             return rb_rescue2(check_funcall_exec, (VALUE)&args,
    00285                               check_funcall_failed, (VALUE)&args,
    00286                               rb_eNoMethodError, (VALUE)0);
    00287         }
    00288     }
    00289     stack_check();
    00290     return vm_call0(th, recv, mid, argc, argv, me);
    00291 }
    00292
    00293 VALUE
    00294 rb_check_funcall(VALUE recv, ID mid, int argc, VALUE *argv)
    00295 {
    00296     return check_funcall(recv, mid, argc, argv);
    00297 }
    00298
    00299 static const char *
    00300 rb_type_str(enum ruby_value_type type)
    00301 {
    00302 #define type_case(t) case t: return #t;
    00303     switch (type) {
    00304       type_case(T_NONE)
    00305       type_case(T_OBJECT)
    00306       type_case(T_CLASS)
    00307       type_case(T_MODULE)
    00308       type_case(T_FLOAT)
    00309       type_case(T_STRING)
    00310       type_case(T_REGEXP)
    00311       type_case(T_ARRAY)
    00312       type_case(T_HASH)
    00313       type_case(T_STRUCT)
    00314       type_case(T_BIGNUM)
    00315       type_case(T_FILE)
    00316       type_case(T_DATA)
    00317       type_case(T_MATCH)
    00318       type_case(T_COMPLEX)
    00319       type_case(T_RATIONAL)
    00320       type_case(T_NIL)
    00321       type_case(T_TRUE)
    00322       type_case(T_FALSE)
    00323       type_case(T_SYMBOL)
    00324       type_case(T_FIXNUM)
    00325       type_case(T_UNDEF)
    00326       type_case(T_NODE)
    00327       type_case(T_ICLASS)
    00328       type_case(T_ZOMBIE)
    00329       default: return NULL;
    00330     }
    00331 #undef type_case
    00332 }
    00333
    00334 static inline rb_method_entry_t *
    00335 rb_search_method_entry(VALUE recv, ID mid)
    00336 {
    00337     VALUE klass = CLASS_OF(recv);
    00338
    00339     if (!klass) {
    00340         VALUE flags, klass;
    00341         if (IMMEDIATE_P(recv)) {
    00342             rb_raise(rb_eNotImpError,
    00343                      "method `%s' called on unexpected immediate object (%p)",
    00344                      rb_id2name(mid), (void *)recv);
    00345         }
    00346         flags = RBASIC(recv)->flags;
    00347         klass = RBASIC(recv)->klass;
    00348         if (flags == 0) {
    00349             rb_raise(rb_eNotImpError,
    00350                      "method `%s' called on terminated object"
    00351                      " (%p flags=0x%"PRIxVALUE" klass=0x%"PRIxVALUE")",
    00352                      rb_id2name(mid), (void *)recv, flags, klass);
    00353         }
    00354         else {
    00355             int type = BUILTIN_TYPE(recv);
    00356             const char *typestr = rb_type_str(type);
    00357             if (typestr && T_OBJECT <= type && type < T_NIL)
    00358                 rb_raise(rb_eNotImpError,
    00359                          "method `%s' called on hidden %s object"
    00360                          " (%p flags=0x%"PRIxVALUE" klass=0x%"PRIxVALUE")",
    00361                          rb_id2name(mid), typestr, (void *)recv, flags, klass);
    00362             if (typestr)
    00363                 rb_raise(rb_eNotImpError,
    00364                          "method `%s' called on unexpected %s object"
    00365                          " (%p flags=0x%"PRIxVALUE" klass=0x%"PRIxVALUE")",
    00366                          rb_id2name(mid), typestr, (void *)recv, flags, klass);
    00367             else
    00368                 rb_raise(rb_eNotImpError,
    00369                          "method `%s' called on broken T_???" "(0x%02x) object"
    00370                          " (%p flags=0x%"PRIxVALUE" klass=0x%"PRIxVALUE")",
    00371                          rb_id2name(mid), type, (void *)recv, flags, klass);
    00372         }
    00373     }
    00374     return rb_method_entry(klass, mid);
    00375 }
    00376
    00377 static inline int
    00378 rb_method_call_status(rb_thread_t *th, rb_method_entry_t *me, call_type scope, VALUE self)
    00379 {
    00380     VALUE klass;
    00381     ID oid;
    00382     int noex;
    00383
    00384     if (UNDEFINED_METHOD_ENTRY_P(me)) {
    00385         return scope == CALL_VCALL ? NOEX_VCALL : 0;
    00386     }
    00387     klass = me->klass;
    00388     oid = me->def->original_id;
    00389     noex = me->flag;
    00390
    00391     if (oid != idMethodMissing) {
    00392         /* receiver specified form for private method */
    00393         if (UNLIKELY(noex)) {
    00394             if (((noex & NOEX_MASK) & NOEX_PRIVATE) && scope == CALL_PUBLIC) {
    00395                 return NOEX_PRIVATE;
    00396             }
    00397
    00398             /* self must be kind of a specified form for protected method */
    00399             if (((noex & NOEX_MASK) & NOEX_PROTECTED) && scope == CALL_PUBLIC) {
    00400                 VALUE defined_class = klass;
    00401
    00402                 if (TYPE(defined_class) == T_ICLASS) {
    00403                     defined_class = RBASIC(defined_class)->klass;
    00404                 }
    00405
    00406                 if (self == Qundef) {
    00407                     self = th->cfp->self;
    00408                 }
    00409                 if (!rb_obj_is_kind_of(self, defined_class)) {
    00410                     return NOEX_PROTECTED;
    00411                 }
    00412             }
    00413
    00414             if (NOEX_SAFE(noex) > th->safe_level) {
    00415                 rb_raise(rb_eSecurityError, "calling insecure method: %s",
    00416                          rb_id2name(me->called_id));
    00417             }
    00418         }
    00419     }
    00420     return NOEX_OK;
    00421 }
    00422
    00423
    00435 static inline VALUE
    00436 rb_call(VALUE recv, ID mid, int argc, const VALUE *argv, call_type scope)
    00437 {
    00438     return rb_call0(recv, mid, argc, argv, scope, Qundef);
    00439 }
    00440
    00441 NORETURN(static void raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv,
    00442                                           VALUE obj, int call_status));
    00443
    00444 /*
    00445  *  call-seq:
    00446  *     obj.method_missing(symbol [, *args] )   -> result
    00447  *
    00448  *  Invoked by Ruby when <i>obj</i> is sent a message it cannot handle.
    00449  *  <i>symbol</i> is the symbol for the method called, and <i>args</i>
    00450  *  are any arguments that were passed to it. By default, the interpreter
    00451  *  raises an error when this method is called. However, it is possible
    00452  *  to override the method to provide more dynamic behavior.
    00453  *  If it is decided that a particular method should not be handled, then
    00454  *  <i>super</i> should be called, so that ancestors can pick up the
    00455  *  missing method.
    00456  *  The example below creates
    00457  *  a class <code>Roman</code>, which responds to methods with names
    00458  *  consisting of roman numerals, returning the corresponding integer
    00459  *  values.
    00460  *
    00461  *     class Roman
    00462  *       def romanToInt(str)
    00463  *         # ...
    00464  *       end
    00465  *       def method_missing(methId)
    00466  *         str = methId.id2name
    00467  *         romanToInt(str)
    00468  *       end
    00469  *     end
    00470  *
    00471  *     r = Roman.new
    00472  *     r.iv      #=> 4
    00473  *     r.xxiii   #=> 23
    00474  *     r.mm      #=> 2000
    00475  */
    00476
    00477 static VALUE
    00478 rb_method_missing(int argc, const VALUE *argv, VALUE obj)
    00479 {
    00480     rb_thread_t *th = GET_THREAD();
    00481     raise_method_missing(th, argc, argv, obj, th->method_missing_reason);
    00482     return Qnil;                /* not reached */
    00483 }
    00484
    00485 #define NOEX_MISSING   0x80
    00486
    00487 static void
    00488 raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv, VALUE obj,
    00489                      int last_call_status)
    00490 {
    00491     ID id;
    00492     VALUE exc = rb_eNoMethodError;
    00493     const char *format = 0;
    00494
    00495     if (argc == 0 || !SYMBOL_P(argv[0])) {
    00496         rb_raise(rb_eArgError, "no id given");
    00497     }
    00498
    00499     stack_check();
    00500
    00501     id = SYM2ID(argv[0]);
    00502
    00503     if (last_call_status & NOEX_PRIVATE) {
    00504         format = "private method `%s' called for %s";
    00505     }
    00506     else if (last_call_status & NOEX_PROTECTED) {
    00507         format = "protected method `%s' called for %s";
    00508     }
    00509     else if (last_call_status & NOEX_VCALL) {
    00510         format = "undefined local variable or method `%s' for %s";
    00511         exc = rb_eNameError;
    00512     }
    00513     else if (last_call_status & NOEX_SUPER) {
    00514         format = "super: no superclass method `%s' for %s";
    00515     }
    00516     if (!format) {
    00517         format = "undefined method `%s' for %s";
    00518     }
    00519
    00520     {
    00521         int n = 0;
    00522         VALUE mesg;
    00523         VALUE args[3];
    00524
    00525         mesg = rb_const_get(exc, rb_intern("message"));
    00526         if (rb_method_basic_definition_p(CLASS_OF(mesg), '!')) {
    00527             args[n++] = rb_name_err_mesg_new(mesg, rb_str_new2(format), obj, argv[0]);
    00528         }
    00529         else {
    00530             args[n++] = rb_funcall(mesg, '!', 3, rb_str_new2(format), obj, argv[0]);
    00531         }
    00532         args[n++] = argv[0];
    00533         if (exc == rb_eNoMethodError) {
    00534             args[n++] = rb_ary_new4(argc - 1, argv + 1);
    00535         }
    00536         exc = rb_class_new_instance(n, args, exc);
    00537
    00538         if (!(last_call_status & NOEX_MISSING)) {
    00539             th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
    00540         }
    00541         rb_exc_raise(exc);
    00542     }
    00543 }
    00544
    00545 static inline VALUE
    00546 method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status)
    00547 {
    00548     VALUE *nargv, result, argv_ary = 0;
    00549     rb_thread_t *th = GET_THREAD();
    00550
    00551     th->method_missing_reason = call_status;
    00552     th->passed_block = 0;
    00553
    00554     if (id == idMethodMissing) {
    00555         raise_method_missing(th, argc, argv, obj, call_status | NOEX_MISSING);
    00556     }
    00557     else if (id == ID_ALLOCATOR) {
    00558         rb_raise(rb_eTypeError, "allocator undefined for %s",
    00559                  rb_class2name(obj));
    00560     }
    00561
    00562     if (argc < 0x100) {
    00563         nargv = ALLOCA_N(VALUE, argc + 1);
    00564     }
    00565     else {
    00566         argv_ary = rb_ary_tmp_new(argc + 1);
    00567         nargv = RARRAY_PTR(argv_ary);
    00568     }
    00569     nargv[0] = ID2SYM(id);
    00570     MEMCPY(nargv + 1, argv, VALUE, argc);
    00571
    00572     if (rb_method_basic_definition_p(CLASS_OF(obj) , idMethodMissing)) {
    00573         raise_method_missing(th, argc+1, nargv, obj, call_status | NOEX_MISSING);
    00574     }
    00575     result = rb_funcall2(obj, idMethodMissing, argc + 1, nargv);
    00576     if (argv_ary) rb_ary_clear(argv_ary);
    00577     return result;
    00578 }
    00579
    00580 void
    00581 rb_raise_method_missing(rb_thread_t *th, int argc, VALUE *argv,
    00582                         VALUE obj, int call_status)
    00583 {
    00584     th->passed_block = 0;
    00585     raise_method_missing(th, argc, argv, obj, call_status | NOEX_MISSING);
    00586 }
    00587
    00596 VALUE
    00597 rb_apply(VALUE recv, ID mid, VALUE args)
    00598 {
    00599     int argc;
    00600     VALUE *argv;
    00601
    00602     argc = RARRAY_LENINT(args);
    00603     argv = ALLOCA_N(VALUE, argc);
    00604     MEMCPY(argv, RARRAY_PTR(args), VALUE, argc);
    00605     return rb_call(recv, mid, argc, argv, CALL_FCALL);
    00606 }
    00607
    00617 VALUE
    00618 rb_funcall(VALUE recv, ID mid, int n, ...)
    00619 {
    00620     VALUE *argv;
    00621     va_list ar;
    00622
    00623     if (n > 0) {
    00624         long i;
    00625
    00626         va_init_list(ar, n);
    00627
    00628         argv = ALLOCA_N(VALUE, n);
    00629
    00630         for (i = 0; i < n; i++) {
    00631             argv[i] = va_arg(ar, VALUE);
    00632         }
    00633         va_end(ar);
    00634     }
    00635     else {
    00636         argv = 0;
    00637     }
    00638     return rb_call(recv, mid, n, argv, CALL_FCALL);
    00639 }
    00640
    00648 VALUE
    00649 rb_funcall2(VALUE recv, ID mid, int argc, const VALUE *argv)
    00650 {
    00651     return rb_call(recv, mid, argc, argv, CALL_FCALL);
    00652 }
    00653
    00663 VALUE
    00664 rb_funcall3(VALUE recv, ID mid, int argc, const VALUE *argv)
    00665 {
    00666     return rb_call(recv, mid, argc, argv, CALL_PUBLIC);
    00667 }
    00668
    00669 VALUE
    00670 rb_funcall_passing_block(VALUE recv, ID mid, int argc, const VALUE *argv)
    00671 {
    00672     PASS_PASSED_BLOCK_TH(GET_THREAD());
    00673
    00674     return rb_call(recv, mid, argc, argv, CALL_PUBLIC);
    00675 }
    00676
    00677 static VALUE
    00678 send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope)
    00679 {
    00680     VALUE vid;
    00681     VALUE self = RUBY_VM_PREVIOUS_CONTROL_FRAME(GET_THREAD()->cfp)->self;
    00682     rb_thread_t *th = GET_THREAD();
    00683
    00684     if (argc == 0) {
    00685         rb_raise(rb_eArgError, "no method name given");
    00686     }
    00687
    00688     vid = *argv++; argc--;
    00689     PASS_PASSED_BLOCK_TH(th);
    00690
    00691     return rb_call0(recv, rb_to_id(vid), argc, argv, scope, self);
    00692 }
    00693
    00694 /*
    00695  *  call-seq:
    00696  *     obj.send(symbol [, args...])        -> obj
    00697  *     obj.__send__(symbol [, args...])      -> obj
    00698  *
    00699  *  Invokes the method identified by _symbol_, passing it any
    00700  *  arguments specified. You can use <code>__send__</code> if the name
    00701  *  +send+ clashes with an existing method in _obj_.
    00702  *
    00703  *     class Klass
    00704  *       def hello(*args)
    00705  *         "Hello " + args.join(' ')
    00706  *       end
    00707  *     end
    00708  *     k = Klass.new
    00709  *     k.send :hello, "gentle", "readers"   #=> "Hello gentle readers"
    00710  */
    00711
    00712 VALUE
    00713 rb_f_send(int argc, VALUE *argv, VALUE recv)
    00714 {
    00715     return send_internal(argc, argv, recv, CALL_FCALL);
    00716 }
    00717
    00718 /*
    00719  *  call-seq:
    00720  *     obj.public_send(symbol [, args...])  -> obj
    00721  *
    00722  *  Invokes the method identified by _symbol_, passing it any
    00723  *  arguments specified. Unlike send, public_send calls public
    00724  *  methods only.
    00725  *
    00726  *     1.public_send(:puts, "hello")  # causes NoMethodError
    00727  */
    00728
    00729 VALUE
    00730 rb_f_public_send(int argc, VALUE *argv, VALUE recv)
    00731 {
    00732     return send_internal(argc, argv, recv, CALL_PUBLIC);
    00733 }
    00734
    00735 /* yield */
    00736
    00737 static inline VALUE
    00738 rb_yield_0(int argc, const VALUE * argv)
    00739 {
    00740     return vm_yield(GET_THREAD(), argc, argv);
    00741 }
    00742
    00743 VALUE
    00744 rb_yield(VALUE val)
    00745 {
    00746     if (val == Qundef) {
    00747         return rb_yield_0(0, 0);
    00748     }
    00749     else {
    00750         return rb_yield_0(1, &val);
    00751     }
    00752 }
    00753
    00754 VALUE
    00755 rb_yield_values(int n, ...)
    00756 {
    00757     if (n == 0) {
    00758         return rb_yield_0(0, 0);
    00759     }
    00760     else {
    00761         int i;
    00762         VALUE *argv;
    00763         va_list args;
    00764         argv = ALLOCA_N(VALUE, n);
    00765
    00766         va_init_list(args, n);
    00767         for (i=0; i<n; i++) {
    00768             argv[i] = va_arg(args, VALUE);
    00769         }
    00770         va_end(args);
    00771
    00772         return rb_yield_0(n, argv);
    00773     }
    00774 }
    00775
    00776 VALUE
    00777 rb_yield_values2(int argc, const VALUE *argv)
    00778 {
    00779     return rb_yield_0(argc, argv);
    00780 }
    00781
    00782 VALUE
    00783 rb_yield_splat(VALUE values)
    00784 {
    00785     VALUE tmp = rb_check_array_type(values);
    00786     volatile VALUE v;
    00787     if (NIL_P(tmp)) {
    00788         rb_raise(rb_eArgError, "not an array");
    00789     }
    00790     v = rb_yield_0(RARRAY_LENINT(tmp), RARRAY_PTR(tmp));
    00791     return v;
    00792 }
    00793
    00794 static VALUE
    00795 loop_i(void)
    00796 {
    00797     for (;;) {
    00798         rb_yield_0(0, 0);
    00799     }
    00800     return Qnil;
    00801 }
    00802
    00803 /*
    00804  *  call-seq:
    00805  *     loop { block }
    00806  *     loop            -> an_enumerator
    00807  *
    00808  *  Repeatedly executes the block.
    00809  *
    00810  *  If no block is given, an enumerator is returned instead.
    00811  *
    00812  *     loop do
    00813  *       print "Input: "
    00814  *       line = gets
    00815  *       break if !line or line =~ /^qQ/
    00816  *       # ...
    00817  *     end
    00818  *
    00819  *  StopIteration raised in the block breaks the loop.
    00820  */
    00821
    00822 static VALUE
    00823 rb_f_loop(VALUE self)
    00824 {
    00825     RETURN_ENUMERATOR(self, 0, 0);
    00826     rb_rescue2(loop_i, (VALUE)0, 0, 0, rb_eStopIteration, (VALUE)0);
    00827     return Qnil;                /* dummy */
    00828 }
    00829
    00830 #if VMDEBUG
    00831 static const char *
    00832 vm_frametype_name(const rb_control_frame_t *cfp);
    00833 #endif
    00834
    00835 VALUE
    00836 rb_iterate(VALUE (* it_proc) (VALUE), VALUE data1,
    00837            VALUE (* bl_proc) (ANYARGS), VALUE data2)
    00838 {
    00839     int state;
    00840     volatile VALUE retval = Qnil;
    00841     NODE *node = NEW_IFUNC(bl_proc, data2);
    00842     rb_thread_t *th = GET_THREAD();
    00843     rb_control_frame_t *volatile cfp = th->cfp;
    00844
    00845     TH_PUSH_TAG(th);
    00846     state = TH_EXEC_TAG();
    00847     if (state == 0) {
    00848       iter_retry:
    00849         {
    00850             rb_block_t *blockptr;
    00851             if (bl_proc) {
    00852                 blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(th->cfp);
    00853                 blockptr->iseq = (void *)node;
    00854                 blockptr->proc = 0;
    00855             }
    00856             else {
    00857                 blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0]);
    00858             }
    00859             th->passed_block = blockptr;
    00860         }
    00861         retval = (*it_proc) (data1);
    00862     }
    00863     else {
    00864         VALUE err = th->errinfo;
    00865         if (state == TAG_BREAK) {
    00866             VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
    00867             VALUE *cdfp = cfp->dfp;
    00868
    00869             if (cdfp == escape_dfp) {
    00870                 state = 0;
    00871                 th->state = 0;
    00872                 th->errinfo = Qnil;
    00873
    00874                 /* check skipped frame */
    00875                 while (th->cfp != cfp) {
    00876 #if VMDEBUG
    00877                     printf("skipped frame: %s\n", vm_frametype_name(th->cfp));
    00878 #endif
    00879                     if (UNLIKELY(VM_FRAME_TYPE(th->cfp) == VM_FRAME_MAGIC_CFUNC)) {
    00880                         const rb_method_entry_t *me = th->cfp->me;
    00881                         EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, th->cfp->self, me->called_id, me->klass);
    00882                     }
    00883
    00884                     th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
    00885                 }
    00886             }
    00887             else{
    00888                 /* SDR(); printf("%p, %p\n", cdfp, escape_dfp); */
    00889             }
    00890         }
    00891         else if (state == TAG_RETRY) {
    00892             VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
    00893             VALUE *cdfp = cfp->dfp;
    00894
    00895             if (cdfp == escape_dfp) {
    00896                 state = 0;
    00897                 th->state = 0;
    00898                 th->errinfo = Qnil;
    00899                 th->cfp = cfp;
    00900                 goto iter_retry;
    00901             }
    00902         }
    00903     }
    00904     TH_POP_TAG();
    00905
    00906     switch (state) {
    00907       case 0:
    00908         break;
    00909       default:
    00910         TH_JUMP_TAG(th, state);
    00911     }
    00912     return retval;
    00913 }
    00914
    00915 struct iter_method_arg {
    00916     VALUE obj;
    00917     ID mid;
    00918     int argc;
    00919     VALUE *argv;
    00920 };
    00921
    00922 static VALUE
    00923 iterate_method(VALUE obj)
    00924 {
    00925     const struct iter_method_arg * arg =
    00926       (struct iter_method_arg *) obj;
    00927
    00928     return rb_call(arg->obj, arg->mid, arg->argc, arg->argv, CALL_FCALL);
    00929 }
    00930
    00931 VALUE
    00932 rb_block_call(VALUE obj, ID mid, int argc, VALUE * argv,
    00933               VALUE (*bl_proc) (ANYARGS), VALUE data2)
    00934 {
    00935     struct iter_method_arg arg;
    00936
    00937     arg.obj = obj;
    00938     arg.mid = mid;
    00939     arg.argc = argc;
    00940     arg.argv = argv;
    00941     return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2);
    00942 }
    00943
    00944 VALUE
    00945 rb_each(VALUE obj)
    00946 {
    00947     return rb_call(obj, idEach, 0, 0, CALL_FCALL);
    00948 }
    00949
    00950 static VALUE
    00951 eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *cref, const char *volatile file, volatile int line)
    00952 {
    00953     int state;
    00954     VALUE result = Qundef;
    00955     VALUE envval;
    00956     rb_binding_t *bind = 0;
    00957     rb_thread_t *th = GET_THREAD();
    00958     rb_env_t *env = NULL;
    00959     rb_block_t block;
    00960     volatile int parse_in_eval;
    00961     volatile int mild_compile_error;
    00962
    00963     if (file == 0) {
    00964         file = rb_sourcefile();
    00965         line = rb_sourceline();
    00966     }
    00967
    00968     parse_in_eval = th->parse_in_eval;
    00969     mild_compile_error = th->mild_compile_error;
    00970     PUSH_TAG();
    00971     if ((state = EXEC_TAG()) == 0) {
    00972         rb_iseq_t *iseq;
    00973         volatile VALUE iseqval;
    00974
    00975         if (scope != Qnil) {
    00976             if (rb_obj_is_kind_of(scope, rb_cBinding)) {
    00977                 GetBindingPtr(scope, bind);
    00978                 envval = bind->env;
    00979                 if (strcmp(file, "(eval)") == 0 && bind->filename != Qnil) {
    00980                     file = RSTRING_PTR(bind->filename);
    00981                     line = bind->line_no;
    00982                 }
    00983             }
    00984             else {
    00985                 rb_raise(rb_eTypeError,
    00986                          "wrong argument type %s (expected Binding)",
    00987                          rb_obj_classname(scope));
    00988             }
    00989             GetEnvPtr(envval, env);
    00990             th->base_block = &env->block;
    00991         }
    00992         else {
    00993             rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
    00994
    00995             if (cfp != 0) {
    00996                 block = *RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
    00997                 th->base_block = &block;
    00998                 th->base_block->self = self;
    00999                 th->base_block->iseq = cfp->iseq;       /* TODO */
    01000             }
    01001             else {
    01002                 rb_raise(rb_eRuntimeError, "Can't eval on top of Fiber or Thread");
    01003             }
    01004         }
    01005
    01006         /* make eval iseq */
    01007         th->parse_in_eval++;
    01008         th->mild_compile_error++;
    01009         iseqval = rb_iseq_compile(src, rb_str_new2(file), INT2FIX(line));
    01010         th->mild_compile_error--;
    01011         th->parse_in_eval--;
    01012
    01013         vm_set_eval_stack(th, iseqval, cref);
    01014         th->base_block = 0;
    01015
    01016         if (0) {                /* for debug */
    01017             printf("%s\n", RSTRING_PTR(rb_iseq_disasm(iseqval)));
    01018         }
    01019
    01020         /* save new env */
    01021         GetISeqPtr(iseqval, iseq);
    01022         if (bind && iseq->local_table_size > 0) {
    01023             bind->env = rb_vm_make_env_object(th, th->cfp);
    01024         }
    01025
    01026         /* kick */
    01027         CHECK_STACK_OVERFLOW(th->cfp, iseq->stack_max);
    01028         result = vm_exec(th);
    01029     }
    01030     POP_TAG();
    01031     th->mild_compile_error = mild_compile_error;
    01032     th->parse_in_eval = parse_in_eval;
    01033
    01034     if (state) {
    01035         if (state == TAG_RAISE) {
    01036             VALUE errinfo = th->errinfo;
    01037             if (strcmp(file, "(eval)") == 0) {
    01038                 VALUE mesg, errat, bt2;
    01039                 extern VALUE rb_get_backtrace(VALUE info);
    01040                 ID id_mesg;
    01041
    01042                 CONST_ID(id_mesg, "mesg");
    01043                 errat = rb_get_backtrace(errinfo);
    01044                 mesg = rb_attr_get(errinfo, id_mesg);
    01045                 if (!NIL_P(errat) && TYPE(errat) == T_ARRAY &&
    01046                     (bt2 = vm_backtrace(th, -2), RARRAY_LEN(bt2) > 0)) {
    01047                     if (!NIL_P(mesg) && TYPE(mesg) == T_STRING && !RSTRING_LEN(mesg)) {
    01048                         if (OBJ_FROZEN(mesg)) {
    01049                             VALUE m = rb_str_cat(rb_str_dup(RARRAY_PTR(errat)[0]), ": ", 2);
    01050                             rb_ivar_set(errinfo, id_mesg, rb_str_append(m, mesg));
    01051                         }
    01052                         else {
    01053                             rb_str_update(mesg, 0, 0, rb_str_new2(": "));
    01054                             rb_str_update(mesg, 0, 0, RARRAY_PTR(errat)[0]);
    01055                         }
    01056                     }
    01057                     RARRAY_PTR(errat)[0] = RARRAY_PTR(bt2)[0];
    01058                 }
    01059             }
    01060             rb_exc_raise(errinfo);
    01061         }
    01062         JUMP_TAG(state);
    01063     }
    01064     return result;
    01065 }
    01066
    01067 static VALUE
    01068 eval_string(VALUE self, VALUE src, VALUE scope, const char *file, int line)
    01069 {
    01070     return eval_string_with_cref(self, src, scope, 0, file, line);
    01071 }
    01072
    01073 /*
    01074  *  call-seq:
    01075  *     eval(string [, binding [, filename [,lineno]]])  -> obj
    01076  *
    01077  *  Evaluates the Ruby expression(s) in <em>string</em>. If
    01078  *  <em>binding</em> is given, which must be a <code>Binding</code>
    01079  *  object, the evaluation is performed in its context. If the
    01080  *  optional <em>filename</em> and <em>lineno</em> parameters are
    01081  *  present, they will be used when reporting syntax errors.
    01082  *
    01083  *     def getBinding(str)
    01084  *       return binding
    01085  *     end
    01086  *     str = "hello"
    01087  *     eval "str + ' Fred'"                      #=> "hello Fred"
    01088  *     eval "str + ' Fred'", getBinding("bye")   #=> "bye Fred"
    01089  */
    01090
    01091 VALUE
    01092 rb_f_eval(int argc, VALUE *argv, VALUE self)
    01093 {
    01094     VALUE src, scope, vfile, vline;
    01095     const char *file = "(eval)";
    01096     int line = 1;
    01097
    01098     rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
    01099     if (rb_safe_level() >= 4) {
    01100         StringValue(src);
    01101         if (!NIL_P(scope) && !OBJ_TAINTED(scope)) {
    01102             rb_raise(rb_eSecurityError,
    01103                      "Insecure: can't modify trusted binding");
    01104         }
    01105     }
    01106     else {
    01107         SafeStringValue(src);
    01108     }
    01109     if (argc >= 3) {
    01110         StringValue(vfile);
    01111     }
    01112     if (argc >= 4) {
    01113         line = NUM2INT(vline);
    01114     }
    01115
    01116     if (!NIL_P(vfile))
    01117         file = RSTRING_PTR(vfile);
    01118     return eval_string(self, src, scope, file, line);
    01119 }
    01120
    01121 VALUE
    01122 rb_eval_string(const char *str)
    01123 {
    01124     return eval_string(rb_vm_top_self(), rb_str_new2(str), Qnil, "(eval)", 1);
    01125 }
    01126
    01127 VALUE
    01128 rb_eval_string_protect(const char *str, int *state)
    01129 {
    01130     return rb_protect((VALUE (*)(VALUE))rb_eval_string, (VALUE)str, state);
    01131 }
    01132
    01133 VALUE
    01134 rb_eval_string_wrap(const char *str, int *state)
    01135 {
    01136     int status;
    01137     rb_thread_t *th = GET_THREAD();
    01138     VALUE self = th->top_self;
    01139     VALUE wrapper = th->top_wrapper;
    01140     VALUE val;
    01141
    01142     th->top_wrapper = rb_module_new();
    01143     th->top_self = rb_obj_clone(rb_vm_top_self());
    01144     rb_extend_object(th->top_self, th->top_wrapper);
    01145
    01146     val = rb_eval_string_protect(str, &status);
    01147
    01148     th->top_self = self;
    01149     th->top_wrapper = wrapper;
    01150
    01151     if (state) {
    01152         *state = status;
    01153     }
    01154     else if (status) {
    01155         JUMP_TAG(status);
    01156     }
    01157     return val;
    01158 }
    01159
    01160 VALUE
    01161 rb_eval_cmd(VALUE cmd, VALUE arg, int level)
    01162 {
    01163     int state;
    01164     VALUE val = Qnil;           /* OK */
    01165     volatile int safe = rb_safe_level();
    01166
    01167     if (OBJ_TAINTED(cmd)) {
    01168         level = 4;
    01169     }
    01170
    01171     if (TYPE(cmd) != T_STRING) {
    01172         PUSH_TAG();
    01173         rb_set_safe_level_force(level);
    01174         if ((state = EXEC_TAG()) == 0) {
    01175             val = rb_funcall2(cmd, rb_intern("call"), RARRAY_LENINT(arg),
    01176                               RARRAY_PTR(arg));
    01177         }
    01178         POP_TAG();
    01179
    01180         rb_set_safe_level_force(safe);
    01181
    01182         if (state)
    01183           JUMP_TAG(state);
    01184         return val;
    01185     }
    01186
    01187     PUSH_TAG();
    01188     if ((state = EXEC_TAG()) == 0) {
    01189         val = eval_string(rb_vm_top_self(), cmd, Qnil, 0, 0);
    01190     }
    01191     POP_TAG();
    01192
    01193     rb_set_safe_level_force(safe);
    01194     if (state) rb_vm_jump_tag_but_local_jump(state, val);
    01195     return val;
    01196 }
    01197
    01198 /* block eval under the class/module context */
    01199
    01200 static VALUE
    01201 yield_under(VALUE under, VALUE self, VALUE values)
    01202 {
    01203     rb_thread_t *th = GET_THREAD();
    01204     rb_block_t block, *blockptr;
    01205     NODE *cref;
    01206
    01207     if ((blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0])) != 0) {
    01208         block = *blockptr;
    01209         block.self = self;
    01210         th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
    01211     }
    01212     cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr);
    01213     cref->flags |= NODE_FL_CREF_PUSHED_BY_EVAL;
    01214
    01215     if (values == Qundef) {
    01216         return vm_yield_with_cref(th, 1, &self, cref);
    01217     }
    01218     else {
    01219         return vm_yield_with_cref(th, RARRAY_LENINT(values), RARRAY_PTR(values), cref);
    01220     }
    01221 }
    01222
    01223 /* string eval under the class/module context */
    01224 static VALUE
    01225 eval_under(VALUE under, VALUE self, VALUE src, const char *file, int line)
    01226 {
    01227     NODE *cref = vm_cref_push(GET_THREAD(), under, NOEX_PUBLIC, NULL);
    01228
    01229     if (rb_safe_level() >= 4) {
    01230         StringValue(src);
    01231     }
    01232     else {
    01233         SafeStringValue(src);
    01234     }
    01235
    01236     return eval_string_with_cref(self, src, Qnil, cref, file, line);
    01237 }
    01238
    01239 static VALUE
    01240 specific_eval(int argc, VALUE *argv, VALUE klass, VALUE self)
    01241 {
    01242     if (rb_block_given_p()) {
    01243         if (argc > 0) {
    01244             rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
    01245         }
    01246         return yield_under(klass, self, Qundef);
    01247     }
    01248     else {
    01249         const char *file = "(eval)";
    01250         int line = 1;
    01251
    01252         if (argc == 0) {
    01253             rb_raise(rb_eArgError, "block not supplied");
    01254         }
    01255         else {
    01256             if (rb_safe_level() >= 4) {
    01257                 StringValue(argv[0]);
    01258             }
    01259             else {
    01260                 SafeStringValue(argv[0]);
    01261             }
    01262             if (argc > 3) {
    01263                 const char *name = rb_id2name(rb_frame_callee());
    01264                 rb_raise(rb_eArgError,
    01265                          "wrong number of arguments: %s(src) or %s{..}",
    01266                          name, name);
    01267             }
    01268             if (argc > 2)
    01269                 line = NUM2INT(argv[2]);
    01270             if (argc > 1) {
    01271                 file = StringValuePtr(argv[1]);
    01272             }
    01273         }
    01274         return eval_under(klass, self, argv[0], file, line);
    01275     }
    01276 }
    01277
    01278 /*
    01279  *  call-seq:
    01280  *     obj.instance_eval(string [, filename [, lineno]] )   -> obj
    01281  *     obj.instance_eval {| | block }                       -> obj
    01282  *
    01283  *  Evaluates a string containing Ruby source code, or the given block,
    01284  *  within the context of the receiver (_obj_). In order to set the
    01285  *  context, the variable +self+ is set to _obj_ while
    01286  *  the code is executing, giving the code access to _obj_'s
    01287  *  instance variables. In the version of <code>instance_eval</code>
    01288  *  that takes a +String+, the optional second and third
    01289  *  parameters supply a filename and starting line number that are used
    01290  *  when reporting compilation errors.
    01291  *
    01292  *     class KlassWithSecret
    01293  *       def initialize
    01294  *         @secret = 99
    01295  *       end
    01296  *     end
    01297  *     k = KlassWithSecret.new
    01298  *     k.instance_eval { @secret }   #=> 99
    01299  */
    01300
    01301 VALUE
    01302 rb_obj_instance_eval(int argc, VALUE *argv, VALUE self)
    01303 {
    01304     VALUE klass;
    01305
    01306     if (SPECIAL_CONST_P(self)) {
    01307         klass = Qnil;
    01308     }
    01309     else {
    01310         klass = rb_singleton_class(self);
    01311     }
    01312     return specific_eval(argc, argv, klass, self);
    01313 }
    01314
    01315 /*
    01316  *  call-seq:
    01317  *     obj.instance_exec(arg...) {|var...| block }                       -> obj
    01318  *
    01319  *  Executes the given block within the context of the receiver
    01320  *  (_obj_). In order to set the context, the variable +self+ is set
    01321  *  to _obj_ while the code is executing, giving the code access to
    01322  *  _obj_'s instance variables.  Arguments are passed as block parameters.
    01323  *
    01324  *     class KlassWithSecret
    01325  *       def initialize
    01326  *         @secret = 99
    01327  *       end
    01328  *     end
    01329  *     k = KlassWithSecret.new
    01330  *     k.instance_exec(5) {|x| @secret+x }   #=> 104
    01331  */
    01332
    01333 VALUE
    01334 rb_obj_instance_exec(int argc, VALUE *argv, VALUE self)
    01335 {
    01336     VALUE klass;
    01337
    01338     if (SPECIAL_CONST_P(self)) {
    01339         klass = Qnil;
    01340     }
    01341     else {
    01342         klass = rb_singleton_class(self);
    01343     }
    01344     return yield_under(klass, self, rb_ary_new4(argc, argv));
    01345 }
    01346
    01347 /*
    01348  *  call-seq:
    01349  *     mod.class_eval(string [, filename [, lineno]])  -> obj
    01350  *     mod.module_eval {|| block }                     -> obj
    01351  *
    01352  *  Evaluates the string or block in the context of _mod_. This can
    01353  *  be used to add methods to a class. <code>module_eval</code> returns
    01354  *  the result of evaluating its argument. The optional _filename_
    01355  *  and _lineno_ parameters set the text for error messages.
    01356  *
    01357  *     class Thing
    01358  *     end
    01359  *     a = %q{def hello() "Hello there!" end}
    01360  *     Thing.module_eval(a)
    01361  *     puts Thing.new.hello()
    01362  *     Thing.module_eval("invalid code", "dummy", 123)
    01363  *
    01364  *  <em>produces:</em>
    01365  *
    01366  *     Hello there!
    01367  *     dummy:123:in `module_eval': undefined local variable
    01368  *         or method `code' for Thing:Class
    01369  */
    01370
    01371 VALUE
    01372 rb_mod_module_eval(int argc, VALUE *argv, VALUE mod)
    01373 {
    01374     return specific_eval(argc, argv, mod, mod);
    01375 }
    01376
    01377 /*
    01378  *  call-seq:
    01379  *     mod.module_exec(arg...) {|var...| block }       -> obj
    01380  *     mod.class_exec(arg...) {|var...| block }        -> obj
    01381  *
    01382  *  Evaluates the given block in the context of the class/module.
    01383  *  The method defined in the block will belong to the receiver.
    01384  *
    01385  *     class Thing
    01386  *     end
    01387  *     Thing.class_exec{
    01388  *       def hello() "Hello there!" end
    01389  *     }
    01390  *     puts Thing.new.hello()
    01391  *
    01392  *  <em>produces:</em>
    01393  *
    01394  *     Hello there!
    01395  */
    01396
    01397 VALUE
    01398 rb_mod_module_exec(int argc, VALUE *argv, VALUE mod)
    01399 {
    01400     return yield_under(mod, mod, rb_ary_new4(argc, argv));
    01401 }
    01402
    01403 /*
    01404  *  call-seq:
    01405  *     throw(tag [, obj])
    01406  *
    01407  *  Transfers control to the end of the active +catch+ block
    01408  *  waiting for _tag_. Raises +ArgumentError+ if there
    01409  *  is no +catch+ block for the _tag_. The optional second
    01410  *  parameter supplies a return value for the +catch+ block,
    01411  *  which otherwise defaults to +nil+. For examples, see
    01412  *  <code>Kernel::catch</code>.
    01413  */
    01414
    01415 static VALUE
    01416 rb_f_throw(int argc, VALUE *argv)
    01417 {
    01418     VALUE tag, value;
    01419
    01420     rb_scan_args(argc, argv, "11", &tag, &value);
    01421     rb_throw_obj(tag, value);
    01422     return Qnil;                /* not reached */
    01423 }
    01424
    01425 void
    01426 rb_throw_obj(VALUE tag, VALUE value)
    01427 {
    01428     rb_thread_t *th = GET_THREAD();
    01429     struct rb_vm_tag *tt = th->tag;
    01430
    01431     while (tt) {
    01432         if (tt->tag == tag) {
    01433             tt->retval = value;
    01434             break;
    01435         }
    01436         tt = tt->prev;
    01437     }
    01438     if (!tt) {
    01439         VALUE desc = rb_inspect(tag);
    01440         rb_raise(rb_eArgError, "uncaught throw %s", RSTRING_PTR(desc));
    01441     }
    01442     rb_trap_restore_mask();
    01443     th->errinfo = NEW_THROW_OBJECT(tag, 0, TAG_THROW);
    01444
    01445     JUMP_TAG(TAG_THROW);
    01446 }
    01447
    01448 void
    01449 rb_throw(const char *tag, VALUE val)
    01450 {
    01451     rb_throw_obj(ID2SYM(rb_intern(tag)), val);
    01452 }
    01453
    01454 static VALUE
    01455 catch_i(VALUE tag, VALUE data)
    01456 {
    01457     return rb_yield_0(1, &tag);
    01458 }
    01459
    01460 /*
    01461  *  call-seq:
    01462  *     catch([arg]) {|tag| block }  -> obj
    01463  *
    01464  *  +catch+ executes its block. If a +throw+ is
    01465  *  executed, Ruby searches up its stack for a +catch+ block
    01466  *  with a tag corresponding to the +throw+'s
    01467  *  _tag_. If found, that block is terminated, and
    01468  *  +catch+ returns the value given to +throw+. If
    01469  *  +throw+ is not called, the block terminates normally, and
    01470  *  the value of +catch+ is the value of the last expression
    01471  *  evaluated. +catch+ expressions may be nested, and the
    01472  *  +throw+ call need not be in lexical scope.
    01473  *
    01474  *     def routine(n)
    01475  *       puts n
    01476  *       throw :done if n <= 0
    01477  *       routine(n-1)
    01478  *     end
    01479  *
    01480  *
    01481  *     catch(:done) { routine(3) }
    01482  *
    01483  *  <em>produces:</em>
    01484  *
    01485  *     3
    01486  *     2
    01487  *     1
    01488  *     0
    01489  *
    01490  *  when _arg_ is given, +catch+ yields it as is, or when no
    01491  *  _arg_ is given, +catch+ assigns a new unique object to
    01492  *  +throw+.  this is useful for nested +catch+.  _arg_ can
    01493  *  be an arbitrary object, not only Symbol.
    01494  *
    01495  */
    01496
    01497 static VALUE
    01498 rb_f_catch(int argc, VALUE *argv)
    01499 {
    01500     VALUE tag;
    01501
    01502     if (argc == 0) {
    01503         tag = rb_obj_alloc(rb_cObject);
    01504     }
    01505     else {
    01506         rb_scan_args(argc, argv, "01", &tag);
    01507     }
    01508     return rb_catch_obj(tag, catch_i, 0);
    01509 }
    01510
    01511 VALUE
    01512 rb_catch(const char *tag, VALUE (*func)(), VALUE data)
    01513 {
    01514     VALUE vtag = tag ? ID2SYM(rb_intern(tag)) : rb_obj_alloc(rb_cObject);
    01515     return rb_catch_obj(vtag, func, data);
    01516 }
    01517
    01518 VALUE
    01519 rb_catch_obj(VALUE tag, VALUE (*func)(), VALUE data)
    01520 {
    01521     int state;
    01522     volatile VALUE val = Qnil;          /* OK */
    01523     rb_thread_t *th = GET_THREAD();
    01524     rb_control_frame_t *saved_cfp = th->cfp;
    01525
    01526     PUSH_TAG();
    01527
    01528     th->tag->tag = tag;
    01529
    01530     if ((state = EXEC_TAG()) == 0) {
    01531         /* call with argc=1, argv = [tag], block = Qnil to insure compatibility */
    01532         val = (*func)(tag, data, 1, &tag, Qnil);
    01533     }
    01534     else if (state == TAG_THROW && RNODE(th->errinfo)->u1.value == tag) {
    01535         th->cfp = saved_cfp;
    01536         val = th->tag->retval;
    01537         th->errinfo = Qnil;
    01538         state = 0;
    01539     }
    01540     POP_TAG();
    01541     if (state)
    01542         JUMP_TAG(state);
    01543
    01544     return val;
    01545 }
    01546
    01547 /*
    01548  *  call-seq:
    01549  *     caller(start=1)    -> array or nil
    01550  *
    01551  *  Returns the current execution stack---an array containing strings in
    01552  *  the form ``<em>file:line</em>'' or ``<em>file:line: in
    01553  *  `method'</em>''. The optional _start_ parameter
    01554  *  determines the number of initial stack entries to omit from the
    01555  *  result.
    01556  *
    01557  *  Returns +nil+ if _start_ is greater than the size of
    01558  *  current execution stack.
    01559  *
    01560  *     def a(skip)
    01561  *       caller(skip)
    01562  *     end
    01563  *     def b(skip)
    01564  *       a(skip)
    01565  *     end
    01566  *     def c(skip)
    01567  *       b(skip)
    01568  *     end
    01569  *     c(0)   #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10:in `<main>'"]
    01570  *     c(1)   #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11:in `<main>'"]
    01571  *     c(2)   #=> ["prog:8:in `c'", "prog:12:in `<main>'"]
    01572  *     c(3)   #=> ["prog:13:in `<main>'"]
    01573  *     c(4)   #=> []
    01574  *     c(5)   #=> nil
    01575  */
    01576
    01577 static VALUE
    01578 rb_f_caller(int argc, VALUE *argv)
    01579 {
    01580     VALUE level;
    01581     int lev;
    01582
    01583     rb_scan_args(argc, argv, "01", &level);
    01584
    01585     if (NIL_P(level))
    01586         lev = 1;
    01587     else
    01588         lev = NUM2INT(level);
    01589     if (lev < 0)
    01590         rb_raise(rb_eArgError, "negative level (%d)", lev);
    01591
    01592     return vm_backtrace(GET_THREAD(), lev);
    01593 }
    01594
    01595 static int
    01596 print_backtrace(void *arg, VALUE file, int line, VALUE method)
    01597 {
    01598     FILE *fp = arg;
    01599     const char *filename = NIL_P(file) ? "ruby" : RSTRING_PTR(file);
    01600     if (NIL_P(method)) {
    01601         fprintf(fp, "\tfrom %s:%d:in unknown method\n",
    01602                 filename, line);
    01603     }
    01604     else {
    01605         fprintf(fp, "\tfrom %s:%d:in `%s'\n",
    01606                 filename, line, RSTRING_PTR(method));
    01607     }
    01608     return FALSE;
    01609 }
    01610
    01611 void
    01612 rb_backtrace(void)
    01613 {
    01614     vm_backtrace_each(GET_THREAD(), -1, NULL, print_backtrace, stderr);
    01615 }
    01616
    01617 VALUE
    01618 rb_make_backtrace(void)
    01619 {
    01620     return vm_backtrace(GET_THREAD(), -1);
    01621 }
    01622
    01623 VALUE
    01624 rb_thread_backtrace(VALUE thval)
    01625 {
    01626     rb_thread_t *th;
    01627     GetThreadPtr(thval, th);
    01628
    01629     switch (th->status) {
    01630       case THREAD_RUNNABLE:
    01631       case THREAD_STOPPED:
    01632       case THREAD_STOPPED_FOREVER:
    01633         break;
    01634       case THREAD_TO_KILL:
    01635       case THREAD_KILLED:
    01636         return Qnil;
    01637     }
    01638
    01639     return vm_backtrace(th, 0);
    01640 }
    01641
    01642 int
    01643 rb_backtrace_each(rb_backtrace_iter_func *iter, void *arg)
    01644 {
    01645     return vm_backtrace_each(GET_THREAD(), -1, NULL, iter, arg);
    01646 }
    01647
    01648 /*
    01649  *  call-seq:
    01650  *     local_variables    -> array
    01651  *
    01652  *  Returns the names of the current local variables.
    01653  *
    01654  *     fred = 1
    01655  *     for i in 1..10
    01656  *        # ...
    01657  *     end
    01658  *     local_variables   #=> [:fred, :i]
    01659  */
    01660
    01661 static VALUE
    01662 rb_f_local_variables(void)
    01663 {
    01664     VALUE ary = rb_ary_new();
    01665     rb_thread_t *th = GET_THREAD();
    01666     rb_control_frame_t *cfp =
    01667         vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp));
    01668     int i;
    01669
    01670     while (cfp) {
    01671         if (cfp->iseq) {
    01672             for (i = 0; i < cfp->iseq->local_table_size; i++) {
    01673                 ID lid = cfp->iseq->local_table[i];
    01674                 if (lid) {
    01675                     const char *vname = rb_id2name(lid);
    01676                     /* should skip temporary variable */
    01677                     if (vname) {
    01678                         rb_ary_push(ary, ID2SYM(lid));
    01679                     }
    01680                 }
    01681             }
    01682         }
    01683         if (cfp->lfp != cfp->dfp) {
    01684             /* block */
    01685             VALUE *dfp = GC_GUARDED_PTR_REF(cfp->dfp[0]);
    01686
    01687             if (vm_collect_local_variables_in_heap(th, dfp, ary)) {
    01688                 break;
    01689             }
    01690             else {
    01691                 while (cfp->dfp != dfp) {
    01692                     cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
    01693                 }
    01694             }
    01695         }
    01696         else {
    01697             break;
    01698         }
    01699     }
    01700     return ary;
    01701 }
    01702
    01703 /*
    01704  *  call-seq:
    01705  *     block_given?   -> true or false
    01706  *     iterator?      -> true or false
    01707  *
    01708  *  Returns <code>true</code> if <code>yield</code> would execute a
    01709  *  block in the current context. The <code>iterator?</code> form
    01710  *  is mildly deprecated.
    01711  *
    01712  *     def try
    01713  *       if block_given?
    01714  *         yield
    01715  *       else
    01716  *         "no block"
    01717  *       end
    01718  *     end
    01719  *     try                  #=> "no block"
    01720  *     try { "hello" }      #=> "hello"
    01721  *     try do "hello" end   #=> "hello"
    01722  */
    01723
    01724
    01725 VALUE
    01726 rb_f_block_given_p(void)
    01727 {
    01728     rb_thread_t *th = GET_THREAD();
    01729     rb_control_frame_t *cfp = th->cfp;
    01730     cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
    01731
    01732     if (cfp != 0 &&
    01733         (cfp->lfp[0] & 0x02) == 0 &&
    01734         GC_GUARDED_PTR_REF(cfp->lfp[0])) {
    01735         return Qtrue;
    01736     }
    01737     else {
    01738         return Qfalse;
    01739     }
    01740 }
    01741
    01742 VALUE
    01743 rb_current_realfilepath(void)
    01744 {
    01745     rb_thread_t *th = GET_THREAD();
    01746     rb_control_frame_t *cfp = th->cfp;
    01747     cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
    01748     if (cfp != 0) return cfp->iseq->filepath;
    01749     return Qnil;
    01750 }
    01751
    01752 void
    01753 Init_vm_eval(void)
    01754 {
    01755     rb_define_global_function("eval", rb_f_eval, -1);
    01756     rb_define_global_function("local_variables", rb_f_local_variables, 0);
    01757     rb_define_global_function("iterator?", rb_f_block_given_p, 0);
    01758     rb_define_global_function("block_given?", rb_f_block_given_p, 0);
    01759
    01760     rb_define_global_function("catch", rb_f_catch, -1);
    01761     rb_define_global_function("throw", rb_f_throw, -1);
    01762
    01763     rb_define_global_function("loop", rb_f_loop, 0);
    01764
    01765     rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval, -1);
    01766     rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1);
    01767     rb_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
    01768
    01769 #if 1
    01770     rb_add_method(rb_cBasicObject, rb_intern("__send__"),
    01771                   VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, 0);
    01772     rb_add_method(rb_mKernel, rb_intern("send"),
    01773                   VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, 0);
    01774 #else
    01775     rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
    01776     rb_define_method(rb_mKernel, "send", rb_f_send, -1);
    01777 #endif
    01778     rb_define_method(rb_mKernel, "public_send", rb_f_public_send, -1);
    01779
    01780     rb_define_method(rb_cModule, "module_exec", rb_mod_module_exec, -1);
    01781     rb_define_method(rb_cModule, "class_exec", rb_mod_module_exec, -1);
    01782     rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1);
    01783     rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
    01784
    01785     rb_define_global_function("caller", rb_f_caller, -1);
    01786 }
    01787
    01788