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