vm_eval.c

Go to the documentation of this file.
00001 /**********************************************************************
00002 
00003   vm_eval.c -
00004 
00005   $Author: nagachika $
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 vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *argv, const NODE *cref);
00016 static inline VALUE vm_yield(rb_thread_t *th, int argc, const VALUE *argv);
00017 static inline VALUE vm_yield_with_block(rb_thread_t *th, int argc, const VALUE *argv, const rb_block_t *blockargptr);
00018 static NODE *vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr);
00019 static VALUE vm_exec(rb_thread_t *th);
00020 static void vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const NODE *cref, rb_block_t *base_block);
00021 static int vm_collect_local_variables_in_heap(rb_thread_t *th, VALUE *dfp, VALUE ary);
00022 
00023 /* vm_backtrace.c */
00024 VALUE rb_vm_backtrace_str_ary(rb_thread_t *th, int lev, int n);
00025 
00026 typedef enum call_type {
00027     CALL_PUBLIC,
00028     CALL_FCALL,
00029     CALL_VCALL,
00030     CALL_TYPE_MAX
00031 } call_type;
00032 
00033 static VALUE send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope);
00034 
00035 static VALUE vm_call0_body(rb_thread_t* th, rb_call_info_t *ci, const VALUE *argv);
00036 
00037 static VALUE
00038 vm_call0(rb_thread_t* th, VALUE recv, ID id, int argc, const VALUE *argv,
00039          const rb_method_entry_t *me, VALUE defined_class)
00040 {
00041     rb_call_info_t ci_entry, *ci = &ci_entry;
00042 
00043     ci->flag = 0;
00044     ci->mid = id;
00045     ci->recv = recv;
00046     ci->defined_class = defined_class;
00047     ci->argc = argc;
00048     ci->me = me;
00049 
00050     return vm_call0_body(th, ci, argv);
00051 }
00052 
00053 #if OPT_CALL_CFUNC_WITHOUT_FRAME
00054 static VALUE
00055 vm_call0_cfunc(rb_thread_t* th, rb_call_info_t *ci, const VALUE *argv)
00056 {
00057     VALUE val;
00058 
00059     RUBY_DTRACE_CMETHOD_ENTRY_HOOK(th, ci->defined_class, ci->mid);
00060     EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, ci->recv, ci->mid, ci->defined_class, Qnil);
00061     {
00062         rb_control_frame_t *reg_cfp = th->cfp;
00063         const rb_method_entry_t *me = ci->me;
00064         const rb_method_cfunc_t *cfunc = &me->def->body.cfunc;
00065         int len = cfunc->argc;
00066 
00067         if (len >= 0) rb_check_arity(ci->argc, len, len);
00068 
00069         th->passed_ci = ci;
00070         ci->aux.inc_sp = 0;
00071         VM_PROFILE_UP(2);
00072         val = (*cfunc->invoker)(cfunc->func, ci, argv);
00073 
00074         if (reg_cfp == th->cfp) {
00075             if (UNLIKELY(th->passed_ci != ci)) {
00076                 rb_bug("vm_call0_cfunc: passed_ci error (ci: %p, passed_ci: %p)", ci, th->passed_ci);
00077             }
00078             th->passed_ci = 0;
00079         }
00080         else {
00081             if (reg_cfp != th->cfp + 1) {
00082                 rb_bug("vm_call0_cfunc: cfp consistency error");
00083             }
00084             VM_PROFILE_UP(3);
00085             vm_pop_frame(th);
00086         }
00087     }
00088     EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, ci->recv, ci->mid, ci->defined_class, val);
00089     RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, ci->defined_class, ci->mid);
00090 
00091     return val;
00092 }
00093 #else
00094 static VALUE
00095 vm_call0_cfunc_with_frame(rb_thread_t* th, rb_call_info_t *ci, const VALUE *argv)
00096 {
00097     VALUE val;
00098     const rb_method_entry_t *me = ci->me;
00099     const rb_method_cfunc_t *cfunc = &me->def->body.cfunc;
00100     int len = cfunc->argc;
00101     VALUE recv = ci->recv;
00102     VALUE defined_class = ci->defined_class;
00103     int argc = ci->argc;
00104     ID mid = ci->mid;
00105     rb_block_t *blockptr = ci->blockptr;
00106 
00107     RUBY_DTRACE_CMETHOD_ENTRY_HOOK(th, defined_class, mid);
00108     EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, mid, defined_class, Qnil);
00109     {
00110         rb_control_frame_t *reg_cfp = th->cfp;
00111 
00112         vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC, recv, defined_class,
00113                       VM_ENVVAL_BLOCK_PTR(blockptr), 0, reg_cfp->sp, 1, me, 0);
00114 
00115         if (len >= 0) rb_check_arity(argc, len, len);
00116 
00117         VM_PROFILE_UP(2);
00118         val = (*cfunc->invoker)(cfunc->func, recv, argc, argv);
00119 
00120         if (UNLIKELY(reg_cfp != th->cfp + 1)) {
00121                 rb_bug("vm_call0_cfunc_with_frame: cfp consistency error");
00122         }
00123         VM_PROFILE_UP(3);
00124         vm_pop_frame(th);
00125     }
00126     EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, recv, mid, defined_class, val);
00127     RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, defined_class, mid);
00128 
00129     return val;
00130 }
00131 
00132 static VALUE
00133 vm_call0_cfunc(rb_thread_t* th, rb_call_info_t *ci, const VALUE *argv)
00134 {
00135     return vm_call0_cfunc_with_frame(th, ci, argv);
00136 }
00137 #endif
00138 
00139 /* `ci' should point temporal value (on stack value) */
00140 static VALUE
00141 vm_call0_body(rb_thread_t* th, rb_call_info_t *ci, const VALUE *argv)
00142 {
00143     VALUE ret;
00144 
00145     if (!ci->me->def) return Qnil;
00146 
00147     if (th->passed_block) {
00148         ci->blockptr = (rb_block_t *)th->passed_block;
00149         th->passed_block = 0;
00150     }
00151     else {
00152         ci->blockptr = 0;
00153     }
00154 
00155   again:
00156     switch (ci->me->def->type) {
00157       case VM_METHOD_TYPE_ISEQ:
00158         {
00159             rb_control_frame_t *reg_cfp = th->cfp;
00160             int i;
00161 
00162             CHECK_VM_STACK_OVERFLOW(reg_cfp, ci->argc + 1);
00163 
00164             *reg_cfp->sp++ = ci->recv;
00165             for (i = 0; i < ci->argc; i++) {
00166                 *reg_cfp->sp++ = argv[i];
00167             }
00168 
00169             vm_call_iseq_setup(th, reg_cfp, ci);
00170             th->cfp->flag |= VM_FRAME_FLAG_FINISH;
00171             return vm_exec(th); /* CHECK_INTS in this function */
00172         }
00173       case VM_METHOD_TYPE_NOTIMPLEMENTED:
00174       case VM_METHOD_TYPE_CFUNC:
00175         ret = vm_call0_cfunc(th, ci, argv);
00176         goto success;
00177       case VM_METHOD_TYPE_ATTRSET:
00178         rb_check_arity(ci->argc, 1, 1);
00179         ret = rb_ivar_set(ci->recv, ci->me->def->body.attr.id, argv[0]);
00180         goto success;
00181       case VM_METHOD_TYPE_IVAR:
00182         rb_check_arity(ci->argc, 0, 0);
00183         ret = rb_attr_get(ci->recv, ci->me->def->body.attr.id);
00184         goto success;
00185       case VM_METHOD_TYPE_BMETHOD:
00186         ret = vm_call_bmethod_body(th, ci, argv);
00187         goto success;
00188       case VM_METHOD_TYPE_ZSUPER:
00189       case VM_METHOD_TYPE_REFINED:
00190         {
00191             if (ci->me->def->type == VM_METHOD_TYPE_REFINED &&
00192                 ci->me->def->body.orig_me) {
00193                 ci->me = ci->me->def->body.orig_me;
00194                 goto again;
00195             }
00196 
00197             ci->defined_class = RCLASS_SUPER(ci->defined_class);
00198 
00199             if (!ci->defined_class || !(ci->me = rb_method_entry(ci->defined_class, ci->mid, &ci->defined_class))) {
00200                 ret = method_missing(ci->recv, ci->mid, ci->argc, argv, NOEX_SUPER);
00201                 goto success;
00202             }
00203             RUBY_VM_CHECK_INTS(th);
00204             if (!ci->me->def) return Qnil;
00205             goto again;
00206         }
00207       case VM_METHOD_TYPE_MISSING:
00208         {
00209             VALUE new_args = rb_ary_new4(ci->argc, argv);
00210 
00211             RB_GC_GUARD(new_args);
00212             rb_ary_unshift(new_args, ID2SYM(ci->mid));
00213             th->passed_block = ci->blockptr;
00214             return rb_funcall2(ci->recv, idMethodMissing, ci->argc+1, RARRAY_PTR(new_args));
00215         }
00216       case VM_METHOD_TYPE_OPTIMIZED:
00217         switch (ci->me->def->body.optimize_type) {
00218           case OPTIMIZED_METHOD_TYPE_SEND:
00219             ret = send_internal(ci->argc, argv, ci->recv, CALL_FCALL);
00220             goto success;
00221           case OPTIMIZED_METHOD_TYPE_CALL:
00222             {
00223                 rb_proc_t *proc;
00224                 GetProcPtr(ci->recv, proc);
00225                 ret = rb_vm_invoke_proc(th, proc, ci->argc, argv, ci->blockptr);
00226                 goto success;
00227             }
00228           default:
00229             rb_bug("vm_call0: unsupported optimized method type (%d)", ci->me->def->body.optimize_type);
00230         }
00231         break;
00232       case VM_METHOD_TYPE_UNDEF:
00233         break;
00234     }
00235     rb_bug("vm_call0: unsupported method type (%d)", ci->me->def->type);
00236     return Qundef;
00237 
00238   success:
00239     RUBY_VM_CHECK_INTS(th);
00240     return ret;
00241 }
00242 
00243 VALUE
00244 rb_vm_call(rb_thread_t *th, VALUE recv, VALUE id, int argc, const VALUE *argv,
00245            const rb_method_entry_t *me, VALUE defined_class)
00246 {
00247     return vm_call0(th, recv, id, argc, argv, me, defined_class);
00248 }
00249 
00250 static inline VALUE
00251 vm_call_super(rb_thread_t *th, int argc, const VALUE *argv)
00252 {
00253     VALUE recv = th->cfp->self;
00254     VALUE klass;
00255     ID id;
00256     rb_method_entry_t *me;
00257     rb_control_frame_t *cfp = th->cfp;
00258 
00259     if (cfp->iseq || NIL_P(cfp->klass)) {
00260         rb_bug("vm_call_super: should not be reached");
00261     }
00262 
00263     klass = RCLASS_SUPER(cfp->klass);
00264     id = cfp->me->def->original_id;
00265     me = rb_method_entry(klass, id, &klass);
00266     if (!me) {
00267         return method_missing(recv, id, argc, argv, NOEX_SUPER);
00268     }
00269 
00270     return vm_call0(th, recv, id, argc, argv, me, klass);
00271 }
00272 
00273 VALUE
00274 rb_call_super(int argc, const VALUE *argv)
00275 {
00276     PASS_PASSED_BLOCK();
00277     return vm_call_super(GET_THREAD(), argc, argv);
00278 }
00279 
00280 static inline void
00281 stack_check(void)
00282 {
00283     rb_thread_t *th = GET_THREAD();
00284 
00285     if (!rb_thread_raised_p(th, RAISED_STACKOVERFLOW) && ruby_stack_check()) {
00286         rb_thread_raised_set(th, RAISED_STACKOVERFLOW);
00287         rb_exc_raise(sysstack_error);
00288     }
00289 }
00290 
00291 static inline rb_method_entry_t *
00292     rb_search_method_entry(VALUE recv, ID mid, VALUE *defined_class_ptr);
00293 static inline int rb_method_call_status(rb_thread_t *th, const rb_method_entry_t *me, call_type scope, VALUE self);
00294 #define NOEX_OK NOEX_NOSUPER
00295 
00311 static inline VALUE
00312 rb_call0(VALUE recv, ID mid, int argc, const VALUE *argv,
00313          call_type scope, VALUE self)
00314 {
00315     VALUE defined_class;
00316     rb_method_entry_t *me =
00317         rb_search_method_entry(recv, mid, &defined_class);
00318     rb_thread_t *th = GET_THREAD();
00319     int call_status = rb_method_call_status(th, me, scope, self);
00320 
00321     if (call_status != NOEX_OK) {
00322         return method_missing(recv, mid, argc, argv, call_status);
00323     }
00324     stack_check();
00325     return vm_call0(th, recv, mid, argc, argv, me, defined_class);
00326 }
00327 
00328 struct rescue_funcall_args {
00329     VALUE recv;
00330     VALUE sym;
00331     int argc;
00332     const VALUE *argv;
00333 };
00334 
00335 static VALUE
00336 check_funcall_exec(struct rescue_funcall_args *args)
00337 {
00338     VALUE new_args = rb_ary_new4(args->argc, args->argv);
00339 
00340     RB_GC_GUARD(new_args);
00341     rb_ary_unshift(new_args, args->sym);
00342     return rb_funcall2(args->recv, idMethodMissing,
00343                        args->argc+1, RARRAY_PTR(new_args));
00344 }
00345 
00346 static VALUE
00347 check_funcall_failed(struct rescue_funcall_args *args, VALUE e)
00348 {
00349     if (rb_respond_to(args->recv, SYM2ID(args->sym))) {
00350         rb_exc_raise(e);
00351     }
00352     return Qundef;
00353 }
00354 
00355 static int
00356 check_funcall_respond_to(rb_thread_t *th, VALUE klass, VALUE recv, ID mid)
00357 {
00358     VALUE defined_class;
00359     const rb_method_entry_t *me = rb_method_entry(klass, idRespond_to, &defined_class);
00360 
00361     if (me && !(me->flag & NOEX_BASIC)) {
00362         const rb_block_t *passed_block = th->passed_block;
00363         VALUE args[2], result;
00364         int arity = rb_method_entry_arity(me);
00365 
00366         if (arity > 2)
00367             rb_raise(rb_eArgError, "respond_to? must accept 1 or 2 arguments (requires %d)", arity);
00368 
00369         if (arity < 1) arity = 2;
00370 
00371         args[0] = ID2SYM(mid);
00372         args[1] = Qtrue;
00373         result = vm_call0(th, recv, idRespond_to, arity, args, me, defined_class);
00374         th->passed_block = passed_block;
00375         if (!RTEST(result)) {
00376             return FALSE;
00377         }
00378     }
00379     return TRUE;
00380 }
00381 
00382 static int
00383 check_funcall_callable(rb_thread_t *th, const rb_method_entry_t *me)
00384 {
00385     return rb_method_call_status(th, me, CALL_FCALL, th->cfp->self) == NOEX_OK;
00386 }
00387 
00388 static VALUE
00389 check_funcall_missing(rb_thread_t *th, VALUE klass, VALUE recv, ID mid, int argc, const VALUE *argv)
00390 {
00391     if (rb_method_basic_definition_p(klass, idMethodMissing)) {
00392         return Qundef;
00393     }
00394     else {
00395         struct rescue_funcall_args args;
00396 
00397         th->method_missing_reason = 0;
00398         args.recv = recv;
00399         args.sym = ID2SYM(mid);
00400         args.argc = argc;
00401         args.argv = argv;
00402         return rb_rescue2(check_funcall_exec, (VALUE)&args,
00403                           check_funcall_failed, (VALUE)&args,
00404                           rb_eNoMethodError, (VALUE)0);
00405     }
00406 }
00407 
00408 VALUE
00409 rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv)
00410 {
00411     VALUE klass = CLASS_OF(recv);
00412     const rb_method_entry_t *me;
00413     rb_thread_t *th = GET_THREAD();
00414     VALUE defined_class;
00415 
00416     if (!check_funcall_respond_to(th, klass, recv, mid))
00417         return Qundef;
00418 
00419     me = rb_search_method_entry(recv, mid, &defined_class);
00420     if (check_funcall_callable(th, me) != NOEX_OK) {
00421         return check_funcall_missing(th, klass, recv, mid, argc, argv);
00422     }
00423     stack_check();
00424     return vm_call0(th, recv, mid, argc, argv, me, defined_class);
00425 }
00426 
00427 VALUE
00428 rb_check_funcall_with_hook(VALUE recv, ID mid, int argc, const VALUE *argv,
00429                            rb_check_funcall_hook *hook, VALUE arg)
00430 {
00431     VALUE klass = CLASS_OF(recv);
00432     const rb_method_entry_t *me;
00433     rb_thread_t *th = GET_THREAD();
00434     VALUE defined_class;
00435 
00436     if (!check_funcall_respond_to(th, klass, recv, mid))
00437         return Qundef;
00438 
00439     me = rb_search_method_entry(recv, mid, &defined_class);
00440     if (check_funcall_callable(th, me) != NOEX_OK) {
00441         (*hook)(FALSE, recv, mid, argc, argv, arg);
00442         return check_funcall_missing(th, klass, recv, mid, argc, argv);
00443     }
00444     stack_check();
00445     (*hook)(TRUE, recv, mid, argc, argv, arg);
00446     return vm_call0(th, recv, mid, argc, argv, me, defined_class);
00447 }
00448 
00449 static const char *
00450 rb_type_str(enum ruby_value_type type)
00451 {
00452 #define type_case(t) case t: return #t;
00453     switch (type) {
00454       type_case(T_NONE)
00455       type_case(T_OBJECT)
00456       type_case(T_CLASS)
00457       type_case(T_MODULE)
00458       type_case(T_FLOAT)
00459       type_case(T_STRING)
00460       type_case(T_REGEXP)
00461       type_case(T_ARRAY)
00462       type_case(T_HASH)
00463       type_case(T_STRUCT)
00464       type_case(T_BIGNUM)
00465       type_case(T_FILE)
00466       type_case(T_DATA)
00467       type_case(T_MATCH)
00468       type_case(T_COMPLEX)
00469       type_case(T_RATIONAL)
00470       type_case(T_NIL)
00471       type_case(T_TRUE)
00472       type_case(T_FALSE)
00473       type_case(T_SYMBOL)
00474       type_case(T_FIXNUM)
00475       type_case(T_UNDEF)
00476       type_case(T_NODE)
00477       type_case(T_ICLASS)
00478       type_case(T_ZOMBIE)
00479       default: return NULL;
00480     }
00481 #undef type_case
00482 }
00483 
00484 static inline rb_method_entry_t *
00485 rb_search_method_entry(VALUE recv, ID mid, VALUE *defined_class_ptr)
00486 {
00487     VALUE klass = CLASS_OF(recv);
00488 
00489     if (!klass) {
00490         VALUE flags, klass;
00491         if (IMMEDIATE_P(recv)) {
00492             rb_raise(rb_eNotImpError,
00493                      "method `%s' called on unexpected immediate object (%p)",
00494                      rb_id2name(mid), (void *)recv);
00495         }
00496         flags = RBASIC(recv)->flags;
00497         klass = RBASIC(recv)->klass;
00498         if (flags == 0) {
00499             rb_raise(rb_eNotImpError,
00500                      "method `%s' called on terminated object"
00501                      " (%p flags=0x%"PRIxVALUE" klass=0x%"PRIxVALUE")",
00502                      rb_id2name(mid), (void *)recv, flags, klass);
00503         }
00504         else {
00505             int type = BUILTIN_TYPE(recv);
00506             const char *typestr = rb_type_str(type);
00507             if (typestr && T_OBJECT <= type && type < T_NIL)
00508                 rb_raise(rb_eNotImpError,
00509                          "method `%s' called on hidden %s object"
00510                          " (%p flags=0x%"PRIxVALUE" klass=0x%"PRIxVALUE")",
00511                          rb_id2name(mid), typestr, (void *)recv, flags, klass);
00512             if (typestr)
00513                 rb_raise(rb_eNotImpError,
00514                          "method `%s' called on unexpected %s object"
00515                          " (%p flags=0x%"PRIxVALUE" klass=0x%"PRIxVALUE")",
00516                          rb_id2name(mid), typestr, (void *)recv, flags, klass);
00517             else
00518                 rb_raise(rb_eNotImpError,
00519                          "method `%s' called on broken T_???" "(0x%02x) object"
00520                          " (%p flags=0x%"PRIxVALUE" klass=0x%"PRIxVALUE")",
00521                          rb_id2name(mid), type, (void *)recv, flags, klass);
00522         }
00523     }
00524     return rb_method_entry(klass, mid, defined_class_ptr);
00525 }
00526 
00527 static inline int
00528 rb_method_call_status(rb_thread_t *th, const rb_method_entry_t *me, call_type scope, VALUE self)
00529 {
00530     VALUE klass;
00531     ID oid;
00532     int noex;
00533 
00534     if (UNDEFINED_METHOD_ENTRY_P(me)) {
00535         return scope == CALL_VCALL ? NOEX_VCALL : 0;
00536     }
00537     klass = me->klass;
00538     oid = me->def->original_id;
00539     noex = me->flag;
00540 
00541     if (oid != idMethodMissing) {
00542         /* receiver specified form for private method */
00543         if (UNLIKELY(noex)) {
00544             if (((noex & NOEX_MASK) & NOEX_PRIVATE) && scope == CALL_PUBLIC) {
00545                 return NOEX_PRIVATE;
00546             }
00547 
00548             /* self must be kind of a specified form for protected method */
00549             if (((noex & NOEX_MASK) & NOEX_PROTECTED) && scope == CALL_PUBLIC) {
00550                 VALUE defined_class = klass;
00551 
00552                 if (RB_TYPE_P(defined_class, T_ICLASS)) {
00553                     defined_class = RBASIC(defined_class)->klass;
00554                 }
00555 
00556                 if (self == Qundef || !rb_obj_is_kind_of(self, defined_class)) {
00557                     return NOEX_PROTECTED;
00558                 }
00559             }
00560 
00561             if (NOEX_SAFE(noex) > th->safe_level) {
00562                 rb_raise(rb_eSecurityError, "calling insecure method: %s",
00563                          rb_id2name(me->called_id));
00564             }
00565         }
00566     }
00567     return NOEX_OK;
00568 }
00569 
00570 
00582 static inline VALUE
00583 rb_call(VALUE recv, ID mid, int argc, const VALUE *argv, call_type scope)
00584 {
00585     rb_thread_t *th = GET_THREAD();
00586     return rb_call0(recv, mid, argc, argv, scope, th->cfp->self);
00587 }
00588 
00589 NORETURN(static void raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv,
00590                                           VALUE obj, int call_status));
00591 
00592 /*
00593  *  call-seq:
00594  *     obj.method_missing(symbol [, *args] )   -> result
00595  *
00596  *  Invoked by Ruby when <i>obj</i> is sent a message it cannot handle.
00597  *  <i>symbol</i> is the symbol for the method called, and <i>args</i>
00598  *  are any arguments that were passed to it. By default, the interpreter
00599  *  raises an error when this method is called. However, it is possible
00600  *  to override the method to provide more dynamic behavior.
00601  *  If it is decided that a particular method should not be handled, then
00602  *  <i>super</i> should be called, so that ancestors can pick up the
00603  *  missing method.
00604  *  The example below creates
00605  *  a class <code>Roman</code>, which responds to methods with names
00606  *  consisting of roman numerals, returning the corresponding integer
00607  *  values.
00608  *
00609  *     class Roman
00610  *       def roman_to_int(str)
00611  *         # ...
00612  *       end
00613  *       def method_missing(methId)
00614  *         str = methId.id2name
00615  *         roman_to_int(str)
00616  *       end
00617  *     end
00618  *
00619  *     r = Roman.new
00620  *     r.iv      #=> 4
00621  *     r.xxiii   #=> 23
00622  *     r.mm      #=> 2000
00623  */
00624 
00625 static VALUE
00626 rb_method_missing(int argc, const VALUE *argv, VALUE obj)
00627 {
00628     rb_thread_t *th = GET_THREAD();
00629     raise_method_missing(th, argc, argv, obj, th->method_missing_reason);
00630     UNREACHABLE;
00631 }
00632 
00633 #define NOEX_MISSING   0x80
00634 
00635 static VALUE
00636 make_no_method_exception(VALUE exc, const char *format, VALUE obj, int argc, const VALUE *argv)
00637 {
00638     int n = 0;
00639     VALUE mesg;
00640     VALUE args[3];
00641 
00642     if (!format) {
00643         format = "undefined method `%s' for %s";
00644     }
00645     mesg = rb_const_get(exc, rb_intern("message"));
00646     if (rb_method_basic_definition_p(CLASS_OF(mesg), '!')) {
00647         args[n++] = rb_name_err_mesg_new(mesg, rb_str_new2(format), obj, argv[0]);
00648     }
00649     else {
00650         args[n++] = rb_funcall(mesg, '!', 3, rb_str_new2(format), obj, argv[0]);
00651     }
00652     args[n++] = argv[0];
00653     if (exc == rb_eNoMethodError) {
00654         args[n++] = rb_ary_new4(argc - 1, argv + 1);
00655     }
00656     return rb_class_new_instance(n, args, exc);
00657 }
00658 
00659 static void
00660 raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv, VALUE obj,
00661                      int last_call_status)
00662 {
00663     VALUE exc = rb_eNoMethodError;
00664     const char *format = 0;
00665 
00666     if (argc == 0 || !SYMBOL_P(argv[0])) {
00667         rb_raise(rb_eArgError, "no id given");
00668     }
00669 
00670     stack_check();
00671 
00672     if (last_call_status & NOEX_PRIVATE) {
00673         format = "private method `%s' called for %s";
00674     }
00675     else if (last_call_status & NOEX_PROTECTED) {
00676         format = "protected method `%s' called for %s";
00677     }
00678     else if (last_call_status & NOEX_VCALL) {
00679         format = "undefined local variable or method `%s' for %s";
00680         exc = rb_eNameError;
00681     }
00682     else if (last_call_status & NOEX_SUPER) {
00683         format = "super: no superclass method `%s' for %s";
00684     }
00685 
00686     {
00687         exc = make_no_method_exception(exc, format, obj, argc, argv);
00688         if (!(last_call_status & NOEX_MISSING)) {
00689             rb_vm_pop_cfunc_frame();
00690         }
00691         rb_exc_raise(exc);
00692     }
00693 }
00694 
00695 static inline VALUE
00696 method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status)
00697 {
00698     VALUE *nargv, result, argv_ary = 0;
00699     rb_thread_t *th = GET_THREAD();
00700     const rb_block_t *blockptr = th->passed_block;
00701 
00702     th->method_missing_reason = call_status;
00703     th->passed_block = 0;
00704 
00705     if (id == idMethodMissing) {
00706         raise_method_missing(th, argc, argv, obj, call_status | NOEX_MISSING);
00707     }
00708 
00709     if (argc < 0x100) {
00710         nargv = ALLOCA_N(VALUE, argc + 1);
00711     }
00712     else {
00713         argv_ary = rb_ary_tmp_new(argc + 1);
00714         nargv = RARRAY_PTR(argv_ary);
00715     }
00716     nargv[0] = ID2SYM(id);
00717     MEMCPY(nargv + 1, argv, VALUE, argc);
00718     if (argv_ary) rb_ary_set_len(argv_ary, argc + 1);
00719 
00720     if (rb_method_basic_definition_p(CLASS_OF(obj) , idMethodMissing)) {
00721         raise_method_missing(th, argc+1, nargv, obj, call_status | NOEX_MISSING);
00722     }
00723     th->passed_block = blockptr;
00724     result = rb_funcall2(obj, idMethodMissing, argc + 1, nargv);
00725     if (argv_ary) rb_ary_clear(argv_ary);
00726     return result;
00727 }
00728 
00729 void
00730 rb_raise_method_missing(rb_thread_t *th, int argc, VALUE *argv,
00731                         VALUE obj, int call_status)
00732 {
00733     th->passed_block = 0;
00734     raise_method_missing(th, argc, argv, obj, call_status | NOEX_MISSING);
00735 }
00736 
00745 VALUE
00746 rb_apply(VALUE recv, ID mid, VALUE args)
00747 {
00748     int argc;
00749     VALUE *argv, ret;
00750 
00751     argc = RARRAY_LENINT(args);
00752     if (argc >= 0x100) {
00753         args = rb_ary_subseq(args, 0, argc);
00754         RBASIC_CLEAR_CLASS(args);
00755         OBJ_FREEZE(args);
00756         ret = rb_call(recv, mid, argc, RARRAY_PTR(args), CALL_FCALL);
00757         RB_GC_GUARD(args);
00758         return ret;
00759     }
00760     argv = ALLOCA_N(VALUE, argc);
00761     MEMCPY(argv, RARRAY_CONST_PTR(args), VALUE, argc);
00762     return rb_call(recv, mid, argc, argv, CALL_FCALL);
00763 }
00764 
00774 VALUE
00775 rb_funcall(VALUE recv, ID mid, int n, ...)
00776 {
00777     VALUE *argv;
00778     va_list ar;
00779 
00780     if (n > 0) {
00781         long i;
00782 
00783         va_init_list(ar, n);
00784 
00785         argv = ALLOCA_N(VALUE, n);
00786 
00787         for (i = 0; i < n; i++) {
00788             argv[i] = va_arg(ar, VALUE);
00789         }
00790         va_end(ar);
00791     }
00792     else {
00793         argv = 0;
00794     }
00795     return rb_call(recv, mid, n, argv, CALL_FCALL);
00796 }
00797 
00805 VALUE
00806 rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
00807 {
00808     return rb_call(recv, mid, argc, argv, CALL_FCALL);
00809 }
00810 
00820 VALUE
00821 rb_funcallv_public(VALUE recv, ID mid, int argc, const VALUE *argv)
00822 {
00823     return rb_call(recv, mid, argc, argv, CALL_PUBLIC);
00824 }
00825 
00826 VALUE
00827 rb_funcall_passing_block(VALUE recv, ID mid, int argc, const VALUE *argv)
00828 {
00829     PASS_PASSED_BLOCK_TH(GET_THREAD());
00830 
00831     return rb_call(recv, mid, argc, argv, CALL_PUBLIC);
00832 }
00833 
00834 VALUE
00835 rb_funcall_with_block(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE pass_procval)
00836 {
00837     if (!NIL_P(pass_procval)) {
00838         rb_thread_t *th = GET_THREAD();
00839         rb_block_t *block = 0;
00840 
00841         rb_proc_t *pass_proc;
00842         GetProcPtr(pass_procval, pass_proc);
00843         block = &pass_proc->block;
00844 
00845         th->passed_block = block;
00846     }
00847 
00848     return rb_call(recv, mid, argc, argv, CALL_PUBLIC);
00849 }
00850 
00851 static VALUE
00852 send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope)
00853 {
00854     ID id;
00855     VALUE vid;
00856     VALUE self;
00857     rb_thread_t *th = GET_THREAD();
00858 
00859     if (scope == CALL_PUBLIC) {
00860         self = Qundef;
00861     }
00862     else {
00863         self = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp)->self;
00864     }
00865 
00866     if (argc == 0) {
00867         rb_raise(rb_eArgError, "no method name given");
00868     }
00869 
00870     vid = *argv++; argc--;
00871 
00872     id = rb_check_id(&vid);
00873     if (!id) {
00874         if (rb_method_basic_definition_p(CLASS_OF(recv), idMethodMissing)) {
00875             VALUE exc = make_no_method_exception(rb_eNoMethodError, NULL,
00876                                                  recv, ++argc, --argv);
00877             rb_exc_raise(exc);
00878         }
00879         id = rb_to_id(vid);
00880     }
00881     PASS_PASSED_BLOCK_TH(th);
00882     return rb_call0(recv, id, argc, argv, scope, self);
00883 }
00884 
00885 /*
00886  * call-seq:
00887  *    foo.send(symbol [, args...])       -> obj
00888  *    foo.__send__(symbol [, args...])   -> obj
00889  *    foo.send(string [, args...])       -> obj
00890  *    foo.__send__(string [, args...])   -> obj
00891  *
00892  *  Invokes the method identified by _symbol_, passing it any
00893  *  arguments specified. You can use <code>__send__</code> if the name
00894  *  +send+ clashes with an existing method in _obj_.
00895  *  When the method is identified by a string, the string is converted
00896  *  to a symbol.
00897  *
00898  *     class Klass
00899  *       def hello(*args)
00900  *         "Hello " + args.join(' ')
00901  *       end
00902  *     end
00903  *     k = Klass.new
00904  *     k.send :hello, "gentle", "readers"   #=> "Hello gentle readers"
00905  */
00906 
00907 VALUE
00908 rb_f_send(int argc, VALUE *argv, VALUE recv)
00909 {
00910     return send_internal(argc, argv, recv, CALL_FCALL);
00911 }
00912 
00913 /*
00914  *  call-seq:
00915  *     obj.public_send(symbol [, args...])  -> obj
00916  *     obj.public_send(string [, args...])  -> obj
00917  *
00918  *  Invokes the method identified by _symbol_, passing it any
00919  *  arguments specified. Unlike send, public_send calls public
00920  *  methods only.
00921  *  When the method is identified by a string, the string is converted
00922  *  to a symbol.
00923  *
00924  *     1.public_send(:puts, "hello")  # causes NoMethodError
00925  */
00926 
00927 VALUE
00928 rb_f_public_send(int argc, VALUE *argv, VALUE recv)
00929 {
00930     return send_internal(argc, argv, recv, CALL_PUBLIC);
00931 }
00932 
00933 /* yield */
00934 
00935 static inline VALUE
00936 rb_yield_0(int argc, const VALUE * argv)
00937 {
00938     return vm_yield(GET_THREAD(), argc, argv);
00939 }
00940 
00941 VALUE
00942 rb_yield(VALUE val)
00943 {
00944     if (val == Qundef) {
00945         return rb_yield_0(0, 0);
00946     }
00947     else {
00948         return rb_yield_0(1, &val);
00949     }
00950 }
00951 
00952 VALUE
00953 rb_yield_values(int n, ...)
00954 {
00955     if (n == 0) {
00956         return rb_yield_0(0, 0);
00957     }
00958     else {
00959         int i;
00960         VALUE *argv;
00961         va_list args;
00962         argv = ALLOCA_N(VALUE, n);
00963 
00964         va_init_list(args, n);
00965         for (i=0; i<n; i++) {
00966             argv[i] = va_arg(args, VALUE);
00967         }
00968         va_end(args);
00969 
00970         return rb_yield_0(n, argv);
00971     }
00972 }
00973 
00974 VALUE
00975 rb_yield_values2(int argc, const VALUE *argv)
00976 {
00977     return rb_yield_0(argc, argv);
00978 }
00979 
00980 VALUE
00981 rb_yield_splat(VALUE values)
00982 {
00983     VALUE tmp = rb_check_array_type(values);
00984     volatile VALUE v;
00985     if (NIL_P(tmp)) {
00986         rb_raise(rb_eArgError, "not an array");
00987     }
00988     v = rb_yield_0(RARRAY_LENINT(tmp), RARRAY_CONST_PTR(tmp));
00989     return v;
00990 }
00991 
00992 VALUE
00993 rb_yield_block(VALUE val, VALUE arg, int argc, const VALUE *argv, VALUE blockarg)
00994 {
00995     const rb_block_t *blockptr = 0;
00996     if (!NIL_P(blockarg)) {
00997         rb_proc_t *blockproc;
00998         GetProcPtr(blockarg, blockproc);
00999         blockptr = &blockproc->block;
01000     }
01001     return vm_yield_with_block(GET_THREAD(), argc, argv, blockptr);
01002 }
01003 
01004 static VALUE
01005 loop_i(void)
01006 {
01007     for (;;) {
01008         rb_yield_0(0, 0);
01009     }
01010     return Qnil;
01011 }
01012 
01013 static VALUE
01014 rb_f_loop_size(VALUE self, VALUE args, VALUE eobj)
01015 {
01016     return DBL2NUM(INFINITY);
01017 }
01018 
01019 /*
01020  *  call-seq:
01021  *     loop { block }
01022  *     loop            -> an_enumerator
01023  *
01024  *  Repeatedly executes the block.
01025  *
01026  *  If no block is given, an enumerator is returned instead.
01027  *
01028  *     loop do
01029  *       print "Input: "
01030  *       line = gets
01031  *       break if !line or line =~ /^qQ/
01032  *       # ...
01033  *     end
01034  *
01035  *  StopIteration raised in the block breaks the loop.
01036  */
01037 
01038 static VALUE
01039 rb_f_loop(VALUE self)
01040 {
01041     RETURN_SIZED_ENUMERATOR(self, 0, 0, rb_f_loop_size);
01042     rb_rescue2(loop_i, (VALUE)0, 0, 0, rb_eStopIteration, (VALUE)0);
01043     return Qnil;                /* dummy */
01044 }
01045 
01046 #if VMDEBUG
01047 static const char *
01048 vm_frametype_name(const rb_control_frame_t *cfp);
01049 #endif
01050 
01051 VALUE
01052 rb_iterate(VALUE (* it_proc) (VALUE), VALUE data1,
01053            VALUE (* bl_proc) (ANYARGS), VALUE data2)
01054 {
01055     int state;
01056     volatile VALUE retval = Qnil;
01057     NODE *node = NEW_IFUNC(bl_proc, data2);
01058     rb_thread_t *th = GET_THREAD();
01059     rb_control_frame_t *volatile cfp = th->cfp;
01060 
01061     node->nd_aid = rb_frame_this_func();
01062     TH_PUSH_TAG(th);
01063     state = TH_EXEC_TAG();
01064     if (state == 0) {
01065       iter_retry:
01066         {
01067             rb_block_t *blockptr;
01068             if (bl_proc) {
01069                 blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(th->cfp);
01070                 blockptr->iseq = (void *)node;
01071                 blockptr->proc = 0;
01072             }
01073             else {
01074                 blockptr = VM_CF_BLOCK_PTR(th->cfp);
01075             }
01076             th->passed_block = blockptr;
01077         }
01078         retval = (*it_proc) (data1);
01079     }
01080     else {
01081         VALUE err = th->errinfo;
01082         if (state == TAG_BREAK) {
01083             VALUE *escape_ep = GET_THROWOBJ_CATCH_POINT(err);
01084             VALUE *cep = cfp->ep;
01085 
01086             if (cep == escape_ep) {
01087                 state = 0;
01088                 th->state = 0;
01089                 th->errinfo = Qnil;
01090                 retval = GET_THROWOBJ_VAL(err);
01091 
01092                 rb_vm_rewind_cfp(th, cfp);
01093             }
01094             else{
01095                 /* SDR(); printf("%p, %p\n", cdfp, escape_dfp); */
01096             }
01097         }
01098         else if (state == TAG_RETRY) {
01099             VALUE *escape_ep = GET_THROWOBJ_CATCH_POINT(err);
01100             VALUE *cep = cfp->ep;
01101 
01102             if (cep == escape_ep) {
01103                 rb_vm_rewind_cfp(th, cfp);
01104 
01105                 state = 0;
01106                 th->state = 0;
01107                 th->errinfo = Qnil;
01108                 goto iter_retry;
01109             }
01110         }
01111     }
01112     TH_POP_TAG();
01113 
01114     switch (state) {
01115       case 0:
01116         break;
01117       default:
01118         TH_JUMP_TAG(th, state);
01119     }
01120     return retval;
01121 }
01122 
01123 struct iter_method_arg {
01124     VALUE obj;
01125     ID mid;
01126     int argc;
01127     const VALUE *argv;
01128 };
01129 
01130 static VALUE
01131 iterate_method(VALUE obj)
01132 {
01133     const struct iter_method_arg * arg =
01134       (struct iter_method_arg *) obj;
01135 
01136     return rb_call(arg->obj, arg->mid, arg->argc, arg->argv, CALL_FCALL);
01137 }
01138 
01139 VALUE
01140 rb_block_call(VALUE obj, ID mid, int argc, const VALUE * argv,
01141               VALUE (*bl_proc) (ANYARGS), VALUE data2)
01142 {
01143     struct iter_method_arg arg;
01144 
01145     arg.obj = obj;
01146     arg.mid = mid;
01147     arg.argc = argc;
01148     arg.argv = argv;
01149     return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2);
01150 }
01151 
01152 static VALUE
01153 iterate_check_method(VALUE obj)
01154 {
01155     const struct iter_method_arg * arg =
01156       (struct iter_method_arg *) obj;
01157 
01158     return rb_check_funcall(arg->obj, arg->mid, arg->argc, arg->argv);
01159 }
01160 
01161 VALUE
01162 rb_check_block_call(VALUE obj, ID mid, int argc, const VALUE *argv,
01163                     VALUE (*bl_proc) (ANYARGS), VALUE data2)
01164 {
01165     struct iter_method_arg arg;
01166 
01167     arg.obj = obj;
01168     arg.mid = mid;
01169     arg.argc = argc;
01170     arg.argv = argv;
01171     return rb_iterate(iterate_check_method, (VALUE)&arg, bl_proc, data2);
01172 }
01173 
01174 VALUE
01175 rb_each(VALUE obj)
01176 {
01177     return rb_call(obj, idEach, 0, 0, CALL_FCALL);
01178 }
01179 
01180 static VALUE
01181 eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *const cref_arg, volatile VALUE file, volatile int line)
01182 {
01183     int state;
01184     VALUE result = Qundef;
01185     VALUE envval;
01186     rb_thread_t *th = GET_THREAD();
01187     rb_env_t *env = NULL;
01188     rb_block_t block, *base_block;
01189     volatile int parse_in_eval;
01190     volatile int mild_compile_error;
01191     NODE *orig_cref;
01192     VALUE crefval;
01193 
01194     if (file == 0) {
01195         file = rb_sourcefilename();
01196         line = rb_sourceline();
01197     }
01198 
01199     parse_in_eval = th->parse_in_eval;
01200     mild_compile_error = th->mild_compile_error;
01201     TH_PUSH_TAG(th);
01202     if ((state = TH_EXEC_TAG()) == 0) {
01203         NODE *cref = cref_arg;
01204         rb_binding_t *bind = 0;
01205         rb_iseq_t *iseq;
01206         volatile VALUE iseqval;
01207         VALUE absolute_path = Qnil;
01208         VALUE fname;
01209 
01210         if (file != Qundef) {
01211             absolute_path = file;
01212         }
01213 
01214         if (!NIL_P(scope)) {
01215             bind = Check_TypedStruct(scope, &ruby_binding_data_type);
01216             {
01217                 envval = bind->env;
01218                 if (NIL_P(absolute_path) && !NIL_P(bind->path)) {
01219                     file = bind->path;
01220                     line = bind->first_lineno;
01221                     absolute_path = rb_current_realfilepath();
01222                 }
01223             }
01224             GetEnvPtr(envval, env);
01225             base_block = &env->block;
01226         }
01227         else {
01228             rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
01229 
01230             if (cfp != 0) {
01231                 block = *RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
01232                 base_block = &block;
01233                 base_block->self = self;
01234                 base_block->iseq = cfp->iseq;   /* TODO */
01235             }
01236             else {
01237                 rb_raise(rb_eRuntimeError, "Can't eval on top of Fiber or Thread");
01238             }
01239         }
01240 
01241         if ((fname = file) == Qundef) {
01242             fname = rb_usascii_str_new_cstr("(eval)");
01243         }
01244 
01245         if (RTEST(fname))
01246             fname = rb_fstring(fname);
01247         if (RTEST(absolute_path))
01248             absolute_path = rb_fstring(absolute_path);
01249 
01250         /* make eval iseq */
01251         th->parse_in_eval++;
01252         th->mild_compile_error++;
01253         iseqval = rb_iseq_compile_with_option(src, fname, absolute_path, INT2FIX(line), base_block, Qnil);
01254         th->mild_compile_error--;
01255         th->parse_in_eval--;
01256 
01257         if (!cref && base_block->iseq) {
01258             orig_cref = rb_vm_get_cref(base_block->iseq, base_block->ep);
01259             cref = NEW_CREF(Qnil);
01260             crefval = (VALUE) cref;
01261             COPY_CREF(cref, orig_cref);
01262         }
01263         vm_set_eval_stack(th, iseqval, cref, base_block);
01264         th->cfp->klass = CLASS_OF(base_block->self);
01265         RB_GC_GUARD(crefval);
01266 
01267         if (0) {                /* for debug */
01268             VALUE disasm = rb_iseq_disasm(iseqval);
01269             printf("%s\n", StringValuePtr(disasm));
01270         }
01271 
01272         /* save new env */
01273         GetISeqPtr(iseqval, iseq);
01274         if (bind && iseq->local_table_size > 0) {
01275             bind->env = rb_vm_make_env_object(th, th->cfp);
01276         }
01277 
01278         /* kick */
01279         result = vm_exec(th);
01280     }
01281     TH_POP_TAG();
01282     th->mild_compile_error = mild_compile_error;
01283     th->parse_in_eval = parse_in_eval;
01284 
01285     if (state) {
01286         if (state == TAG_RAISE) {
01287             VALUE errinfo = th->errinfo;
01288             if (file == Qundef) {
01289                 VALUE mesg, errat, bt2;
01290                 ID id_mesg;
01291 
01292                 CONST_ID(id_mesg, "mesg");
01293                 errat = rb_get_backtrace(errinfo);
01294                 mesg = rb_attr_get(errinfo, id_mesg);
01295                 if (!NIL_P(errat) && RB_TYPE_P(errat, T_ARRAY) &&
01296                     (bt2 = rb_vm_backtrace_str_ary(th, 0, 0), RARRAY_LEN(bt2) > 0)) {
01297                     if (!NIL_P(mesg) && RB_TYPE_P(mesg, T_STRING) && !RSTRING_LEN(mesg)) {
01298                         if (OBJ_FROZEN(mesg)) {
01299                             VALUE m = rb_str_cat(rb_str_dup(RARRAY_AREF(errat, 0)), ": ", 2);
01300                             rb_ivar_set(errinfo, id_mesg, rb_str_append(m, mesg));
01301                         }
01302                         else {
01303                             rb_str_update(mesg, 0, 0, rb_str_new2(": "));
01304                             rb_str_update(mesg, 0, 0, RARRAY_AREF(errat, 0));
01305                         }
01306                     }
01307                     RARRAY_ASET(errat, 0, RARRAY_AREF(bt2, 0));
01308                 }
01309             }
01310             rb_exc_raise(errinfo);
01311         }
01312         JUMP_TAG(state);
01313     }
01314     return result;
01315 }
01316 
01317 static VALUE
01318 eval_string(VALUE self, VALUE src, VALUE scope, VALUE file, int line)
01319 {
01320     return eval_string_with_cref(self, src, scope, 0, file, line);
01321 }
01322 
01323 /*
01324  *  call-seq:
01325  *     eval(string [, binding [, filename [,lineno]]])  -> obj
01326  *
01327  *  Evaluates the Ruby expression(s) in <em>string</em>. If
01328  *  <em>binding</em> is given, which must be a <code>Binding</code>
01329  *  object, the evaluation is performed in its context. If the
01330  *  optional <em>filename</em> and <em>lineno</em> parameters are
01331  *  present, they will be used when reporting syntax errors.
01332  *
01333  *     def get_binding(str)
01334  *       return binding
01335  *     end
01336  *     str = "hello"
01337  *     eval "str + ' Fred'"                      #=> "hello Fred"
01338  *     eval "str + ' Fred'", get_binding("bye")  #=> "bye Fred"
01339  */
01340 
01341 VALUE
01342 rb_f_eval(int argc, VALUE *argv, VALUE self)
01343 {
01344     VALUE src, scope, vfile, vline;
01345     VALUE file = Qundef;
01346     int line = 1;
01347 
01348     rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
01349     SafeStringValue(src);
01350     if (argc >= 3) {
01351         StringValue(vfile);
01352     }
01353     if (argc >= 4) {
01354         line = NUM2INT(vline);
01355     }
01356 
01357     if (!NIL_P(vfile))
01358         file = vfile;
01359     return eval_string(self, src, scope, file, line);
01360 }
01361 
01363 VALUE
01364 ruby_eval_string_from_file(const char *str, const char *filename)
01365 {
01366     VALUE file = filename ? rb_str_new_cstr(filename) : 0;
01367     return eval_string(rb_vm_top_self(), rb_str_new2(str), Qnil, file, 1);
01368 }
01369 
01370 struct eval_string_from_file_arg {
01371     VALUE str;
01372     VALUE filename;
01373 };
01374 
01375 static VALUE
01376 eval_string_from_file_helper(VALUE data)
01377 {
01378     const struct eval_string_from_file_arg *const arg = (struct eval_string_from_file_arg*)data;
01379     return eval_string(rb_vm_top_self(), arg->str, Qnil, arg->filename, 1);
01380 }
01381 
01382 VALUE
01383 ruby_eval_string_from_file_protect(const char *str, const char *filename, int *state)
01384 {
01385     struct eval_string_from_file_arg arg;
01386     arg.str = rb_str_new_cstr(str);
01387     arg.filename = filename ? rb_str_new_cstr(filename) : 0;
01388     return rb_protect(eval_string_from_file_helper, (VALUE)&arg, state);
01389 }
01390 
01403 VALUE
01404 rb_eval_string(const char *str)
01405 {
01406     return ruby_eval_string_from_file(str, "eval");
01407 }
01408 
01419 VALUE
01420 rb_eval_string_protect(const char *str, int *state)
01421 {
01422     return rb_protect((VALUE (*)(VALUE))rb_eval_string, (VALUE)str, state);
01423 }
01424 
01436 VALUE
01437 rb_eval_string_wrap(const char *str, int *state)
01438 {
01439     int status;
01440     rb_thread_t *th = GET_THREAD();
01441     VALUE self = th->top_self;
01442     VALUE wrapper = th->top_wrapper;
01443     VALUE val;
01444 
01445     th->top_wrapper = rb_module_new();
01446     th->top_self = rb_obj_clone(rb_vm_top_self());
01447     rb_extend_object(th->top_self, th->top_wrapper);
01448 
01449     val = rb_eval_string_protect(str, &status);
01450 
01451     th->top_self = self;
01452     th->top_wrapper = wrapper;
01453 
01454     if (state) {
01455         *state = status;
01456     }
01457     else if (status) {
01458         JUMP_TAG(status);
01459     }
01460     return val;
01461 }
01462 
01463 VALUE
01464 rb_eval_cmd(VALUE cmd, VALUE arg, int level)
01465 {
01466     int state;
01467     volatile VALUE val = Qnil;          /* OK */
01468     volatile int safe = rb_safe_level();
01469 
01470     if (OBJ_TAINTED(cmd)) {
01471         level = 4;
01472     }
01473 
01474     if (!RB_TYPE_P(cmd, T_STRING)) {
01475         PUSH_TAG();
01476         rb_set_safe_level_force(level);
01477         if ((state = EXEC_TAG()) == 0) {
01478             val = rb_funcall2(cmd, rb_intern("call"), RARRAY_LENINT(arg),
01479                               RARRAY_PTR(arg));
01480         }
01481         POP_TAG();
01482 
01483         rb_set_safe_level_force(safe);
01484 
01485         if (state)
01486             JUMP_TAG(state);
01487         return val;
01488     }
01489 
01490     PUSH_TAG();
01491     if ((state = EXEC_TAG()) == 0) {
01492         val = eval_string(rb_vm_top_self(), cmd, Qnil, 0, 0);
01493     }
01494     POP_TAG();
01495 
01496     rb_set_safe_level_force(safe);
01497     if (state) JUMP_TAG(state);
01498     return val;
01499 }
01500 
01501 /* block eval under the class/module context */
01502 
01503 static VALUE
01504 yield_under(VALUE under, VALUE self, VALUE values)
01505 {
01506     rb_thread_t *th = GET_THREAD();
01507     rb_block_t block, *blockptr;
01508     NODE *cref;
01509 
01510     if ((blockptr = VM_CF_BLOCK_PTR(th->cfp)) != 0) {
01511         block = *blockptr;
01512         block.self = self;
01513         VM_CF_LEP(th->cfp)[0] = VM_ENVVAL_BLOCK_PTR(&block);
01514     }
01515     cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr);
01516     cref->flags |= NODE_FL_CREF_PUSHED_BY_EVAL;
01517 
01518     if (values == Qundef) {
01519         return vm_yield_with_cref(th, 1, &self, cref);
01520     }
01521     else {
01522         return vm_yield_with_cref(th, RARRAY_LENINT(values), RARRAY_CONST_PTR(values), cref);
01523     }
01524 }
01525 
01526 VALUE
01527 rb_yield_refine_block(VALUE refinement, VALUE refinements)
01528 {
01529     rb_thread_t *th = GET_THREAD();
01530     rb_block_t block, *blockptr;
01531     NODE *cref;
01532 
01533     if ((blockptr = VM_CF_BLOCK_PTR(th->cfp)) != 0) {
01534         block = *blockptr;
01535         block.self = refinement;
01536         VM_CF_LEP(th->cfp)[0] = VM_ENVVAL_BLOCK_PTR(&block);
01537     }
01538     cref = vm_cref_push(th, refinement, NOEX_PUBLIC, blockptr);
01539     cref->flags |= NODE_FL_CREF_PUSHED_BY_EVAL;
01540     RB_OBJ_WRITE(cref, &cref->nd_refinements, refinements);
01541 
01542     return vm_yield_with_cref(th, 0, NULL, cref);
01543 }
01544 
01545 /* string eval under the class/module context */
01546 static VALUE
01547 eval_under(VALUE under, VALUE self, VALUE src, VALUE file, int line)
01548 {
01549     NODE *cref = vm_cref_push(GET_THREAD(), under, NOEX_PUBLIC, NULL);
01550 
01551     if (SPECIAL_CONST_P(self) && !NIL_P(under)) {
01552         cref->flags |= NODE_FL_CREF_PUSHED_BY_EVAL;
01553     }
01554     SafeStringValue(src);
01555 
01556     return eval_string_with_cref(self, src, Qnil, cref, file, line);
01557 }
01558 
01559 static VALUE
01560 specific_eval(int argc, VALUE *argv, VALUE klass, VALUE self)
01561 {
01562     if (rb_block_given_p()) {
01563         rb_check_arity(argc, 0, 0);
01564         return yield_under(klass, self, Qundef);
01565     }
01566     else {
01567         VALUE file = Qundef;
01568         int line = 1;
01569 
01570         rb_check_arity(argc, 1, 3);
01571         SafeStringValue(argv[0]);
01572         if (argc > 2)
01573             line = NUM2INT(argv[2]);
01574         if (argc > 1) {
01575             file = argv[1];
01576             if (!NIL_P(file)) StringValue(file);
01577         }
01578         return eval_under(klass, self, argv[0], file, line);
01579     }
01580 }
01581 
01582 /*
01583  *  call-seq:
01584  *     obj.instance_eval(string [, filename [, lineno]] )   -> obj
01585  *     obj.instance_eval {| | block }                       -> obj
01586  *
01587  *  Evaluates a string containing Ruby source code, or the given block,
01588  *  within the context of the receiver (_obj_). In order to set the
01589  *  context, the variable +self+ is set to _obj_ while
01590  *  the code is executing, giving the code access to _obj_'s
01591  *  instance variables. In the version of <code>instance_eval</code>
01592  *  that takes a +String+, the optional second and third
01593  *  parameters supply a filename and starting line number that are used
01594  *  when reporting compilation errors.
01595  *
01596  *     class KlassWithSecret
01597  *       def initialize
01598  *         @secret = 99
01599  *       end
01600  *     end
01601  *     k = KlassWithSecret.new
01602  *     k.instance_eval { @secret }   #=> 99
01603  */
01604 
01605 VALUE
01606 rb_obj_instance_eval(int argc, VALUE *argv, VALUE self)
01607 {
01608     VALUE klass;
01609 
01610     if (SPECIAL_CONST_P(self)) {
01611         klass = rb_special_singleton_class(self);
01612     }
01613     else {
01614         klass = rb_singleton_class(self);
01615     }
01616     return specific_eval(argc, argv, klass, self);
01617 }
01618 
01619 /*
01620  *  call-seq:
01621  *     obj.instance_exec(arg...) {|var...| block }                       -> obj
01622  *
01623  *  Executes the given block within the context of the receiver
01624  *  (_obj_). In order to set the context, the variable +self+ is set
01625  *  to _obj_ while the code is executing, giving the code access to
01626  *  _obj_'s instance variables.  Arguments are passed as block parameters.
01627  *
01628  *     class KlassWithSecret
01629  *       def initialize
01630  *         @secret = 99
01631  *       end
01632  *     end
01633  *     k = KlassWithSecret.new
01634  *     k.instance_exec(5) {|x| @secret+x }   #=> 104
01635  */
01636 
01637 VALUE
01638 rb_obj_instance_exec(int argc, VALUE *argv, VALUE self)
01639 {
01640     VALUE klass;
01641 
01642     if (SPECIAL_CONST_P(self)) {
01643         klass = rb_special_singleton_class(self);
01644     }
01645     else {
01646         klass = rb_singleton_class(self);
01647     }
01648     return yield_under(klass, self, rb_ary_new4(argc, argv));
01649 }
01650 
01651 /*
01652  *  call-seq:
01653  *     mod.class_eval(string [, filename [, lineno]])  -> obj
01654  *     mod.module_eval {|| block }                     -> obj
01655  *
01656  *  Evaluates the string or block in the context of _mod_, except that when
01657  *  a block is given, constant/class variable lookup is not affected. This
01658  *  can be used to add methods to a class. <code>module_eval</code> returns
01659  *  the result of evaluating its argument. The optional _filename_ and
01660  *  _lineno_ parameters set the text for error messages.
01661  *
01662  *     class Thing
01663  *     end
01664  *     a = %q{def hello() "Hello there!" end}
01665  *     Thing.module_eval(a)
01666  *     puts Thing.new.hello()
01667  *     Thing.module_eval("invalid code", "dummy", 123)
01668  *
01669  *  <em>produces:</em>
01670  *
01671  *     Hello there!
01672  *     dummy:123:in `module_eval': undefined local variable
01673  *         or method `code' for Thing:Class
01674  */
01675 
01676 VALUE
01677 rb_mod_module_eval(int argc, VALUE *argv, VALUE mod)
01678 {
01679     return specific_eval(argc, argv, mod, mod);
01680 }
01681 
01682 /*
01683  *  call-seq:
01684  *     mod.module_exec(arg...) {|var...| block }       -> obj
01685  *     mod.class_exec(arg...) {|var...| block }        -> obj
01686  *
01687  *  Evaluates the given block in the context of the class/module.
01688  *  The method defined in the block will belong to the receiver.
01689  *  Any arguments passed to the method will be passed to the block.
01690  *  This can be used if the block needs to access instance variables.
01691  *
01692  *     class Thing
01693  *     end
01694  *     Thing.class_exec{
01695  *       def hello() "Hello there!" end
01696  *     }
01697  *     puts Thing.new.hello()
01698  *
01699  *  <em>produces:</em>
01700  *
01701  *     Hello there!
01702  */
01703 
01704 VALUE
01705 rb_mod_module_exec(int argc, VALUE *argv, VALUE mod)
01706 {
01707     return yield_under(mod, mod, rb_ary_new4(argc, argv));
01708 }
01709 
01710 /*
01711  *  call-seq:
01712  *     throw(tag [, obj])
01713  *
01714  *  Transfers control to the end of the active +catch+ block
01715  *  waiting for _tag_. Raises +ArgumentError+ if there
01716  *  is no +catch+ block for the _tag_. The optional second
01717  *  parameter supplies a return value for the +catch+ block,
01718  *  which otherwise defaults to +nil+. For examples, see
01719  *  <code>Kernel::catch</code>.
01720  */
01721 
01722 static VALUE
01723 rb_f_throw(int argc, VALUE *argv)
01724 {
01725     VALUE tag, value;
01726 
01727     rb_scan_args(argc, argv, "11", &tag, &value);
01728     rb_throw_obj(tag, value);
01729     UNREACHABLE;
01730 }
01731 
01732 void
01733 rb_throw_obj(VALUE tag, VALUE value)
01734 {
01735     rb_thread_t *th = GET_THREAD();
01736     struct rb_vm_tag *tt = th->tag;
01737 
01738     while (tt) {
01739         if (tt->tag == tag) {
01740             tt->retval = value;
01741             break;
01742         }
01743         tt = tt->prev;
01744     }
01745     if (!tt) {
01746         VALUE desc = rb_inspect(tag);
01747         rb_raise(rb_eArgError, "uncaught throw %"PRIsVALUE, desc);
01748     }
01749     th->errinfo = NEW_THROW_OBJECT(tag, 0, TAG_THROW);
01750 
01751     JUMP_TAG(TAG_THROW);
01752 }
01753 
01754 void
01755 rb_throw(const char *tag, VALUE val)
01756 {
01757     rb_throw_obj(ID2SYM(rb_intern(tag)), val);
01758 }
01759 
01760 static VALUE
01761 catch_i(VALUE tag, VALUE data)
01762 {
01763     return rb_yield_0(1, &tag);
01764 }
01765 
01766 /*
01767  *  call-seq:
01768  *     catch([arg]) {|tag| block }  -> obj
01769  *
01770  *  +catch+ executes its block. If a +throw+ is
01771  *  executed, Ruby searches up its stack for a +catch+ block
01772  *  with a tag corresponding to the +throw+'s
01773  *  _tag_. If found, that block is terminated, and
01774  *  +catch+ returns the value given to +throw+. If
01775  *  +throw+ is not called, the block terminates normally, and
01776  *  the value of +catch+ is the value of the last expression
01777  *  evaluated. +catch+ expressions may be nested, and the
01778  *  +throw+ call need not be in lexical scope.
01779  *
01780  *     def routine(n)
01781  *       puts n
01782  *       throw :done if n <= 0
01783  *       routine(n-1)
01784  *     end
01785  *
01786  *
01787  *     catch(:done) { routine(3) }
01788  *
01789  *  <em>produces:</em>
01790  *
01791  *     3
01792  *     2
01793  *     1
01794  *     0
01795  *
01796  *  when _arg_ is given, +catch+ yields it as is, or when no
01797  *  _arg_ is given, +catch+ assigns a new unique object to
01798  *  +throw+.  this is useful for nested +catch+.  _arg_ can
01799  *  be an arbitrary object, not only Symbol.
01800  *
01801  */
01802 
01803 static VALUE
01804 rb_f_catch(int argc, VALUE *argv)
01805 {
01806     VALUE tag;
01807 
01808     if (argc == 0) {
01809         tag = rb_obj_alloc(rb_cObject);
01810     }
01811     else {
01812         rb_scan_args(argc, argv, "01", &tag);
01813     }
01814     return rb_catch_obj(tag, catch_i, 0);
01815 }
01816 
01817 VALUE
01818 rb_catch(const char *tag, VALUE (*func)(), VALUE data)
01819 {
01820     VALUE vtag = tag ? ID2SYM(rb_intern(tag)) : rb_obj_alloc(rb_cObject);
01821     return rb_catch_obj(vtag, func, data);
01822 }
01823 
01824 VALUE
01825 rb_catch_obj(VALUE t, VALUE (*func)(), VALUE data)
01826 {
01827     int state;
01828     VALUE val = rb_catch_protect(t, (rb_block_call_func *)func, data, &state);
01829     if (state)
01830         JUMP_TAG(state);
01831     return val;
01832 }
01833 
01834 VALUE
01835 rb_catch_protect(VALUE t, rb_block_call_func *func, VALUE data, int *stateptr)
01836 {
01837     int state;
01838     volatile VALUE val = Qnil;          /* OK */
01839     rb_thread_t *th = GET_THREAD();
01840     rb_control_frame_t *saved_cfp = th->cfp;
01841     volatile VALUE tag = t;
01842 
01843     TH_PUSH_TAG(th);
01844 
01845     _tag.tag = tag;
01846 
01847     if ((state = TH_EXEC_TAG()) == 0) {
01848         /* call with argc=1, argv = [tag], block = Qnil to insure compatibility */
01849         val = (*func)(tag, data, 1, (const VALUE *)&tag, Qnil);
01850     }
01851     else if (state == TAG_THROW && RNODE(th->errinfo)->u1.value == tag) {
01852         rb_vm_rewind_cfp(th, saved_cfp);
01853         val = th->tag->retval;
01854         th->errinfo = Qnil;
01855         state = 0;
01856     }
01857     TH_POP_TAG();
01858     if (stateptr)
01859         *stateptr = state;
01860 
01861     return val;
01862 }
01863 
01864 /*
01865  *  call-seq:
01866  *     local_variables    -> array
01867  *
01868  *  Returns the names of the current local variables.
01869  *
01870  *     fred = 1
01871  *     for i in 1..10
01872  *        # ...
01873  *     end
01874  *     local_variables   #=> [:fred, :i]
01875  */
01876 
01877 static VALUE
01878 rb_f_local_variables(void)
01879 {
01880     VALUE ary = rb_ary_new();
01881     rb_thread_t *th = GET_THREAD();
01882     rb_control_frame_t *cfp =
01883         vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp));
01884     int i;
01885 
01886     while (cfp) {
01887         if (cfp->iseq) {
01888             for (i = 0; i < cfp->iseq->local_table_size; i++) {
01889                 ID lid = cfp->iseq->local_table[i];
01890                 if (lid) {
01891                     const char *vname = rb_id2name(lid);
01892                     /* should skip temporary variable */
01893                     if (vname) {
01894                         rb_ary_push(ary, ID2SYM(lid));
01895                     }
01896                 }
01897             }
01898         }
01899         if (!VM_EP_LEP_P(cfp->ep)) {
01900             /* block */
01901             VALUE *ep = VM_CF_PREV_EP(cfp);
01902 
01903             if (vm_collect_local_variables_in_heap(th, ep, ary)) {
01904                 break;
01905             }
01906             else {
01907                 while (cfp->ep != ep) {
01908                     cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
01909                 }
01910             }
01911         }
01912         else {
01913             break;
01914         }
01915     }
01916     return ary;
01917 }
01918 
01919 /*
01920  *  call-seq:
01921  *     block_given?   -> true or false
01922  *     iterator?      -> true or false
01923  *
01924  *  Returns <code>true</code> if <code>yield</code> would execute a
01925  *  block in the current context. The <code>iterator?</code> form
01926  *  is mildly deprecated.
01927  *
01928  *     def try
01929  *       if block_given?
01930  *         yield
01931  *       else
01932  *         "no block"
01933  *       end
01934  *     end
01935  *     try                  #=> "no block"
01936  *     try { "hello" }      #=> "hello"
01937  *     try do "hello" end   #=> "hello"
01938  */
01939 
01940 
01941 VALUE
01942 rb_f_block_given_p(void)
01943 {
01944     rb_thread_t *th = GET_THREAD();
01945     rb_control_frame_t *cfp = th->cfp;
01946     cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
01947 
01948     if (cfp != 0 && VM_CF_BLOCK_PTR(cfp)) {
01949         return Qtrue;
01950     }
01951     else {
01952         return Qfalse;
01953     }
01954 }
01955 
01956 VALUE
01957 rb_current_realfilepath(void)
01958 {
01959     rb_thread_t *th = GET_THREAD();
01960     rb_control_frame_t *cfp = th->cfp;
01961     cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
01962     if (cfp != 0) return cfp->iseq->location.absolute_path;
01963     return Qnil;
01964 }
01965 
01966 void
01967 Init_vm_eval(void)
01968 {
01969     rb_define_global_function("eval", rb_f_eval, -1);
01970     rb_define_global_function("local_variables", rb_f_local_variables, 0);
01971     rb_define_global_function("iterator?", rb_f_block_given_p, 0);
01972     rb_define_global_function("block_given?", rb_f_block_given_p, 0);
01973 
01974     rb_define_global_function("catch", rb_f_catch, -1);
01975     rb_define_global_function("throw", rb_f_throw, -1);
01976 
01977     rb_define_global_function("loop", rb_f_loop, 0);
01978 
01979     rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval, -1);
01980     rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1);
01981     rb_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
01982 
01983 #if 1
01984     rb_add_method(rb_cBasicObject, rb_intern("__send__"),
01985                   VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, 0);
01986     rb_add_method(rb_mKernel, rb_intern("send"),
01987                   VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, 0);
01988 #else
01989     rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
01990     rb_define_method(rb_mKernel, "send", rb_f_send, -1);
01991 #endif
01992     rb_define_method(rb_mKernel, "public_send", rb_f_public_send, -1);
01993 
01994     rb_define_method(rb_cModule, "module_exec", rb_mod_module_exec, -1);
01995     rb_define_method(rb_cModule, "class_exec", rb_mod_module_exec, -1);
01996     rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1);
01997     rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
01998 }
01999 

Generated on 19 Jul 2016 for Ruby by  doxygen 1.4.7