|
Ruby
2.0.0p481(2014-05-08revision45883)
|
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, ID 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; 00490 if (SPECIAL_CONST_P(recv)) { 00491 rb_raise(rb_eNotImpError, 00492 "method `%"PRIsVALUE"' called on unexpected immediate object (%p)", 00493 rb_id2str(mid), (void *)recv); 00494 } 00495 flags = RBASIC(recv)->flags; 00496 if (flags == 0) { 00497 rb_raise(rb_eNotImpError, 00498 "method `%"PRIsVALUE"' called on terminated object" 00499 " (%p flags=0x%"PRIxVALUE")", 00500 rb_id2str(mid), (void *)recv, flags); 00501 } 00502 else { 00503 int type = BUILTIN_TYPE(recv); 00504 const char *typestr = rb_type_str(type); 00505 if (typestr && T_OBJECT <= type && type < T_NIL) 00506 rb_raise(rb_eNotImpError, 00507 "method `%"PRIsVALUE"' called on hidden %s object" 00508 " (%p flags=0x%"PRIxVALUE")", 00509 rb_id2str(mid), typestr, (void *)recv, flags); 00510 if (typestr) 00511 rb_raise(rb_eNotImpError, 00512 "method `%"PRIsVALUE"' called on unexpected %s object" 00513 " (%p flags=0x%"PRIxVALUE")", 00514 rb_id2str(mid), typestr, (void *)recv, flags); 00515 else 00516 rb_raise(rb_eNotImpError, 00517 "method `%"PRIsVALUE"' called on broken T_???" "(0x%02x) object" 00518 " (%p flags=0x%"PRIxVALUE")", 00519 rb_id2str(mid), type, (void *)recv, flags); 00520 } 00521 } 00522 return rb_method_entry(klass, mid, defined_class_ptr); 00523 } 00524 00525 static inline int 00526 rb_method_call_status(rb_thread_t *th, const rb_method_entry_t *me, call_type scope, VALUE self) 00527 { 00528 VALUE klass; 00529 ID oid; 00530 int noex; 00531 00532 if (UNDEFINED_METHOD_ENTRY_P(me)) { 00533 return scope == CALL_VCALL ? NOEX_VCALL : 0; 00534 } 00535 klass = me->klass; 00536 oid = me->def->original_id; 00537 noex = me->flag; 00538 00539 if (oid != idMethodMissing) { 00540 /* receiver specified form for private method */ 00541 if (UNLIKELY(noex)) { 00542 if (((noex & NOEX_MASK) & NOEX_PRIVATE) && scope == CALL_PUBLIC) { 00543 return NOEX_PRIVATE; 00544 } 00545 00546 /* self must be kind of a specified form for protected method */ 00547 if (((noex & NOEX_MASK) & NOEX_PROTECTED) && scope == CALL_PUBLIC) { 00548 VALUE defined_class = klass; 00549 00550 if (RB_TYPE_P(defined_class, T_ICLASS)) { 00551 defined_class = RBASIC(defined_class)->klass; 00552 } 00553 00554 if (self == Qundef || !rb_obj_is_kind_of(self, defined_class)) { 00555 return NOEX_PROTECTED; 00556 } 00557 } 00558 00559 if (NOEX_SAFE(noex) > th->safe_level) { 00560 rb_raise(rb_eSecurityError, "calling insecure method: %s", 00561 rb_id2name(me->called_id)); 00562 } 00563 } 00564 } 00565 return NOEX_OK; 00566 } 00567 00568 00580 static inline VALUE 00581 rb_call(VALUE recv, ID mid, int argc, const VALUE *argv, call_type scope) 00582 { 00583 rb_thread_t *th = GET_THREAD(); 00584 return rb_call0(recv, mid, argc, argv, scope, th->cfp->self); 00585 } 00586 00587 NORETURN(static void raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv, 00588 VALUE obj, int call_status)); 00589 00590 /* 00591 * call-seq: 00592 * obj.method_missing(symbol [, *args] ) -> result 00593 * 00594 * Invoked by Ruby when <i>obj</i> is sent a message it cannot handle. 00595 * <i>symbol</i> is the symbol for the method called, and <i>args</i> 00596 * are any arguments that were passed to it. By default, the interpreter 00597 * raises an error when this method is called. However, it is possible 00598 * to override the method to provide more dynamic behavior. 00599 * If it is decided that a particular method should not be handled, then 00600 * <i>super</i> should be called, so that ancestors can pick up the 00601 * missing method. 00602 * The example below creates 00603 * a class <code>Roman</code>, which responds to methods with names 00604 * consisting of roman numerals, returning the corresponding integer 00605 * values. 00606 * 00607 * class Roman 00608 * def roman_to_int(str) 00609 * # ... 00610 * end 00611 * def method_missing(methId) 00612 * str = methId.id2name 00613 * roman_to_int(str) 00614 * end 00615 * end 00616 * 00617 * r = Roman.new 00618 * r.iv #=> 4 00619 * r.xxiii #=> 23 00620 * r.mm #=> 2000 00621 */ 00622 00623 static VALUE 00624 rb_method_missing(int argc, const VALUE *argv, VALUE obj) 00625 { 00626 rb_thread_t *th = GET_THREAD(); 00627 raise_method_missing(th, argc, argv, obj, th->method_missing_reason); 00628 UNREACHABLE; 00629 } 00630 00631 #define NOEX_MISSING 0x80 00632 00633 static VALUE 00634 make_no_method_exception(VALUE exc, const char *format, VALUE obj, int argc, const VALUE *argv) 00635 { 00636 int n = 0; 00637 VALUE mesg; 00638 VALUE args[3]; 00639 00640 if (!format) { 00641 format = "undefined method `%s' for %s"; 00642 } 00643 mesg = rb_const_get(exc, rb_intern("message")); 00644 if (rb_method_basic_definition_p(CLASS_OF(mesg), '!')) { 00645 args[n++] = rb_name_err_mesg_new(mesg, rb_str_new2(format), obj, argv[0]); 00646 } 00647 else { 00648 args[n++] = rb_funcall(mesg, '!', 3, rb_str_new2(format), obj, argv[0]); 00649 } 00650 args[n++] = argv[0]; 00651 if (exc == rb_eNoMethodError) { 00652 args[n++] = rb_ary_new4(argc - 1, argv + 1); 00653 } 00654 return rb_class_new_instance(n, args, exc); 00655 } 00656 00657 static void 00658 raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv, VALUE obj, 00659 int last_call_status) 00660 { 00661 VALUE exc = rb_eNoMethodError; 00662 const char *format = 0; 00663 00664 if (argc == 0 || !SYMBOL_P(argv[0])) { 00665 rb_raise(rb_eArgError, "no id given"); 00666 } 00667 00668 stack_check(); 00669 00670 if (last_call_status & NOEX_PRIVATE) { 00671 format = "private method `%s' called for %s"; 00672 } 00673 else if (last_call_status & NOEX_PROTECTED) { 00674 format = "protected method `%s' called for %s"; 00675 } 00676 else if (last_call_status & NOEX_VCALL) { 00677 format = "undefined local variable or method `%s' for %s"; 00678 exc = rb_eNameError; 00679 } 00680 else if (last_call_status & NOEX_SUPER) { 00681 format = "super: no superclass method `%s' for %s"; 00682 } 00683 00684 { 00685 exc = make_no_method_exception(exc, format, obj, argc, argv); 00686 if (!(last_call_status & NOEX_MISSING)) { 00687 th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp); 00688 } 00689 rb_exc_raise(exc); 00690 } 00691 } 00692 00693 static inline VALUE 00694 method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status) 00695 { 00696 VALUE *nargv, result, argv_ary = 0; 00697 rb_thread_t *th = GET_THREAD(); 00698 const rb_block_t *blockptr = th->passed_block; 00699 00700 th->method_missing_reason = call_status; 00701 th->passed_block = 0; 00702 00703 if (id == idMethodMissing) { 00704 raise_method_missing(th, argc, argv, obj, call_status | NOEX_MISSING); 00705 } 00706 00707 if (argc < 0x100) { 00708 nargv = ALLOCA_N(VALUE, argc + 1); 00709 } 00710 else { 00711 argv_ary = rb_ary_tmp_new(argc + 1); 00712 nargv = RARRAY_PTR(argv_ary); 00713 } 00714 nargv[0] = ID2SYM(id); 00715 MEMCPY(nargv + 1, argv, VALUE, argc); 00716 if (argv_ary) rb_ary_set_len(argv_ary, argc + 1); 00717 00718 if (rb_method_basic_definition_p(CLASS_OF(obj) , idMethodMissing)) { 00719 raise_method_missing(th, argc+1, nargv, obj, call_status | NOEX_MISSING); 00720 } 00721 th->passed_block = blockptr; 00722 result = rb_funcall2(obj, idMethodMissing, argc + 1, nargv); 00723 if (argv_ary) rb_ary_clear(argv_ary); 00724 return result; 00725 } 00726 00727 void 00728 rb_raise_method_missing(rb_thread_t *th, int argc, VALUE *argv, 00729 VALUE obj, int call_status) 00730 { 00731 th->passed_block = 0; 00732 raise_method_missing(th, argc, argv, obj, call_status | NOEX_MISSING); 00733 } 00734 00743 VALUE 00744 rb_apply(VALUE recv, ID mid, VALUE args) 00745 { 00746 int argc; 00747 VALUE *argv, ret; 00748 00749 argc = RARRAY_LENINT(args); 00750 if (argc >= 0x100) { 00751 args = rb_ary_subseq(args, 0, argc); 00752 RBASIC(args)->klass = 0; 00753 OBJ_FREEZE(args); 00754 ret = rb_call(recv, mid, argc, RARRAY_PTR(args), CALL_FCALL); 00755 RB_GC_GUARD(args); 00756 return ret; 00757 } 00758 argv = ALLOCA_N(VALUE, argc); 00759 MEMCPY(argv, RARRAY_PTR(args), VALUE, argc); 00760 return rb_call(recv, mid, argc, argv, CALL_FCALL); 00761 } 00762 00772 VALUE 00773 rb_funcall(VALUE recv, ID mid, int n, ...) 00774 { 00775 VALUE *argv; 00776 va_list ar; 00777 00778 if (n > 0) { 00779 long i; 00780 00781 va_init_list(ar, n); 00782 00783 argv = ALLOCA_N(VALUE, n); 00784 00785 for (i = 0; i < n; i++) { 00786 argv[i] = va_arg(ar, VALUE); 00787 } 00788 va_end(ar); 00789 } 00790 else { 00791 argv = 0; 00792 } 00793 return rb_call(recv, mid, n, argv, CALL_FCALL); 00794 } 00795 00803 VALUE 00804 rb_funcall2(VALUE recv, ID mid, int argc, const VALUE *argv) 00805 { 00806 return rb_call(recv, mid, argc, argv, CALL_FCALL); 00807 } 00808 00818 VALUE 00819 rb_funcall3(VALUE recv, ID mid, int argc, const VALUE *argv) 00820 { 00821 return rb_call(recv, mid, argc, argv, CALL_PUBLIC); 00822 } 00823 00824 VALUE 00825 rb_funcall_passing_block(VALUE recv, ID mid, int argc, const VALUE *argv) 00826 { 00827 PASS_PASSED_BLOCK_TH(GET_THREAD()); 00828 00829 return rb_call(recv, mid, argc, argv, CALL_PUBLIC); 00830 } 00831 00832 VALUE 00833 rb_funcall_with_block(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE pass_procval) 00834 { 00835 if (!NIL_P(pass_procval)) { 00836 rb_thread_t *th = GET_THREAD(); 00837 rb_block_t *block = 0; 00838 00839 rb_proc_t *pass_proc; 00840 GetProcPtr(pass_procval, pass_proc); 00841 block = &pass_proc->block; 00842 00843 th->passed_block = block; 00844 } 00845 00846 return rb_call(recv, mid, argc, argv, CALL_PUBLIC); 00847 } 00848 00849 static VALUE 00850 send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope) 00851 { 00852 ID id; 00853 VALUE vid; 00854 VALUE self; 00855 rb_thread_t *th = GET_THREAD(); 00856 00857 if (scope == CALL_PUBLIC) { 00858 self = Qundef; 00859 } 00860 else { 00861 self = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp)->self; 00862 } 00863 00864 if (argc == 0) { 00865 rb_raise(rb_eArgError, "no method name given"); 00866 } 00867 00868 vid = *argv++; argc--; 00869 00870 id = rb_check_id(&vid); 00871 if (!id) { 00872 if (rb_method_basic_definition_p(CLASS_OF(recv), idMethodMissing)) { 00873 VALUE exc = make_no_method_exception(rb_eNoMethodError, NULL, 00874 recv, ++argc, --argv); 00875 rb_exc_raise(exc); 00876 } 00877 id = rb_to_id(vid); 00878 } 00879 PASS_PASSED_BLOCK_TH(th); 00880 return rb_call0(recv, id, argc, argv, scope, self); 00881 } 00882 00883 /* 00884 * call-seq: 00885 * foo.send(symbol [, args...]) -> obj 00886 * foo.__send__(symbol [, args...]) -> obj 00887 * 00888 * Invokes the method identified by _symbol_, passing it any 00889 * arguments specified. You can use <code>__send__</code> if the name 00890 * +send+ clashes with an existing method in _obj_. 00891 * 00892 * class Klass 00893 * def hello(*args) 00894 * "Hello " + args.join(' ') 00895 * end 00896 * end 00897 * k = Klass.new 00898 * k.send :hello, "gentle", "readers" #=> "Hello gentle readers" 00899 */ 00900 00901 VALUE 00902 rb_f_send(int argc, VALUE *argv, VALUE recv) 00903 { 00904 return send_internal(argc, argv, recv, CALL_FCALL); 00905 } 00906 00907 /* 00908 * call-seq: 00909 * obj.public_send(symbol [, args...]) -> obj 00910 * 00911 * Invokes the method identified by _symbol_, passing it any 00912 * arguments specified. Unlike send, public_send calls public 00913 * methods only. 00914 * 00915 * 1.public_send(:puts, "hello") # causes NoMethodError 00916 */ 00917 00918 VALUE 00919 rb_f_public_send(int argc, VALUE *argv, VALUE recv) 00920 { 00921 return send_internal(argc, argv, recv, CALL_PUBLIC); 00922 } 00923 00924 /* yield */ 00925 00926 static inline VALUE 00927 rb_yield_0(int argc, const VALUE * argv) 00928 { 00929 return vm_yield(GET_THREAD(), argc, argv); 00930 } 00931 00932 VALUE 00933 rb_yield(VALUE val) 00934 { 00935 if (val == Qundef) { 00936 return rb_yield_0(0, 0); 00937 } 00938 else { 00939 return rb_yield_0(1, &val); 00940 } 00941 } 00942 00943 VALUE 00944 rb_yield_values(int n, ...) 00945 { 00946 if (n == 0) { 00947 return rb_yield_0(0, 0); 00948 } 00949 else { 00950 int i; 00951 VALUE *argv; 00952 va_list args; 00953 argv = ALLOCA_N(VALUE, n); 00954 00955 va_init_list(args, n); 00956 for (i=0; i<n; i++) { 00957 argv[i] = va_arg(args, VALUE); 00958 } 00959 va_end(args); 00960 00961 return rb_yield_0(n, argv); 00962 } 00963 } 00964 00965 VALUE 00966 rb_yield_values2(int argc, const VALUE *argv) 00967 { 00968 return rb_yield_0(argc, argv); 00969 } 00970 00971 VALUE 00972 rb_yield_splat(VALUE values) 00973 { 00974 VALUE tmp = rb_check_array_type(values); 00975 volatile VALUE v; 00976 if (NIL_P(tmp)) { 00977 rb_raise(rb_eArgError, "not an array"); 00978 } 00979 v = rb_yield_0(RARRAY_LENINT(tmp), RARRAY_PTR(tmp)); 00980 return v; 00981 } 00982 00983 static VALUE 00984 loop_i(void) 00985 { 00986 for (;;) { 00987 rb_yield_0(0, 0); 00988 } 00989 return Qnil; 00990 } 00991 00992 static VALUE 00993 rb_f_loop_size(VALUE self, VALUE args) 00994 { 00995 return DBL2NUM(INFINITY); 00996 } 00997 00998 /* 00999 * call-seq: 01000 * loop { block } 01001 * loop -> an_enumerator 01002 * 01003 * Repeatedly executes the block. 01004 * 01005 * If no block is given, an enumerator is returned instead. 01006 * 01007 * loop do 01008 * print "Input: " 01009 * line = gets 01010 * break if !line or line =~ /^qQ/ 01011 * # ... 01012 * end 01013 * 01014 * StopIteration raised in the block breaks the loop. 01015 */ 01016 01017 static VALUE 01018 rb_f_loop(VALUE self) 01019 { 01020 RETURN_SIZED_ENUMERATOR(self, 0, 0, rb_f_loop_size); 01021 rb_rescue2(loop_i, (VALUE)0, 0, 0, rb_eStopIteration, (VALUE)0); 01022 return Qnil; /* dummy */ 01023 } 01024 01025 #if VMDEBUG 01026 static const char * 01027 vm_frametype_name(const rb_control_frame_t *cfp); 01028 #endif 01029 01030 VALUE 01031 rb_iterate(VALUE (* it_proc) (VALUE), VALUE data1, 01032 VALUE (* bl_proc) (ANYARGS), VALUE data2) 01033 { 01034 int state; 01035 volatile VALUE retval = Qnil; 01036 NODE *node = NEW_IFUNC(bl_proc, data2); 01037 rb_thread_t *th = GET_THREAD(); 01038 rb_control_frame_t *volatile cfp = th->cfp; 01039 01040 node->nd_aid = rb_frame_this_func(); 01041 TH_PUSH_TAG(th); 01042 state = TH_EXEC_TAG(); 01043 if (state == 0) { 01044 iter_retry: 01045 { 01046 rb_block_t *blockptr; 01047 if (bl_proc) { 01048 blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(th->cfp); 01049 blockptr->iseq = (void *)node; 01050 blockptr->proc = 0; 01051 } 01052 else { 01053 blockptr = VM_CF_BLOCK_PTR(th->cfp); 01054 } 01055 th->passed_block = blockptr; 01056 } 01057 retval = (*it_proc) (data1); 01058 } 01059 else { 01060 VALUE err = th->errinfo; 01061 if (state == TAG_BREAK) { 01062 VALUE *escape_ep = GET_THROWOBJ_CATCH_POINT(err); 01063 VALUE *cep = cfp->ep; 01064 01065 if (cep == escape_ep) { 01066 state = 0; 01067 th->state = 0; 01068 th->errinfo = Qnil; 01069 retval = GET_THROWOBJ_VAL(err); 01070 01071 /* check skipped frame */ 01072 while (th->cfp != cfp) { 01073 #if VMDEBUG 01074 printf("skipped frame: %s\n", vm_frametype_name(th->cfp)); 01075 #endif 01076 if (UNLIKELY(VM_FRAME_TYPE(th->cfp) == VM_FRAME_MAGIC_CFUNC)) { 01077 const rb_method_entry_t *me = th->cfp->me; 01078 EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, th->cfp->self, me->called_id, me->klass, Qnil); 01079 RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, me->klass, me->called_id); 01080 } 01081 01082 th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp); 01083 } 01084 } 01085 else{ 01086 /* SDR(); printf("%p, %p\n", cdfp, escape_dfp); */ 01087 } 01088 } 01089 else if (state == TAG_RETRY) { 01090 VALUE *escape_ep = GET_THROWOBJ_CATCH_POINT(err); 01091 VALUE *cep = cfp->ep; 01092 01093 if (cep == escape_ep) { 01094 state = 0; 01095 th->state = 0; 01096 th->errinfo = Qnil; 01097 th->cfp = cfp; 01098 goto iter_retry; 01099 } 01100 } 01101 } 01102 TH_POP_TAG(); 01103 01104 switch (state) { 01105 case 0: 01106 break; 01107 default: 01108 TH_JUMP_TAG(th, state); 01109 } 01110 return retval; 01111 } 01112 01113 struct iter_method_arg { 01114 VALUE obj; 01115 ID mid; 01116 int argc; 01117 VALUE *argv; 01118 }; 01119 01120 static VALUE 01121 iterate_method(VALUE obj) 01122 { 01123 const struct iter_method_arg * arg = 01124 (struct iter_method_arg *) obj; 01125 01126 return rb_call(arg->obj, arg->mid, arg->argc, arg->argv, CALL_FCALL); 01127 } 01128 01129 VALUE 01130 rb_block_call(VALUE obj, ID mid, int argc, VALUE * argv, 01131 VALUE (*bl_proc) (ANYARGS), VALUE data2) 01132 { 01133 struct iter_method_arg arg; 01134 01135 arg.obj = obj; 01136 arg.mid = mid; 01137 arg.argc = argc; 01138 arg.argv = argv; 01139 return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2); 01140 } 01141 01142 static VALUE 01143 iterate_check_method(VALUE obj) 01144 { 01145 const struct iter_method_arg * arg = 01146 (struct iter_method_arg *) obj; 01147 01148 return rb_check_funcall(arg->obj, arg->mid, arg->argc, arg->argv); 01149 } 01150 01151 VALUE 01152 rb_check_block_call(VALUE obj, ID mid, int argc, VALUE * argv, 01153 VALUE (*bl_proc) (ANYARGS), VALUE data2) 01154 { 01155 struct iter_method_arg arg; 01156 01157 arg.obj = obj; 01158 arg.mid = mid; 01159 arg.argc = argc; 01160 arg.argv = argv; 01161 return rb_iterate(iterate_check_method, (VALUE)&arg, bl_proc, data2); 01162 } 01163 01164 VALUE 01165 rb_each(VALUE obj) 01166 { 01167 return rb_call(obj, idEach, 0, 0, CALL_FCALL); 01168 } 01169 01170 static VALUE 01171 eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *cref, volatile VALUE file, volatile int line) 01172 { 01173 int state; 01174 VALUE result = Qundef; 01175 VALUE envval; 01176 rb_thread_t *th = GET_THREAD(); 01177 rb_env_t *env = NULL; 01178 rb_block_t block, *base_block; 01179 volatile int parse_in_eval; 01180 volatile int mild_compile_error; 01181 01182 if (file == 0) { 01183 file = rb_sourcefilename(); 01184 line = rb_sourceline(); 01185 } 01186 01187 parse_in_eval = th->parse_in_eval; 01188 mild_compile_error = th->mild_compile_error; 01189 TH_PUSH_TAG(th); 01190 if ((state = TH_EXEC_TAG()) == 0) { 01191 rb_binding_t *bind = 0; 01192 rb_iseq_t *iseq; 01193 volatile VALUE iseqval; 01194 VALUE absolute_path = Qnil; 01195 VALUE fname; 01196 01197 if (file != Qundef) { 01198 absolute_path = file; 01199 } 01200 01201 if (scope != Qnil) { 01202 if (rb_obj_is_kind_of(scope, rb_cBinding)) { 01203 GetBindingPtr(scope, bind); 01204 envval = bind->env; 01205 if (NIL_P(absolute_path) && !NIL_P(bind->path)) { 01206 file = bind->path; 01207 line = bind->first_lineno; 01208 absolute_path = rb_current_realfilepath(); 01209 } 01210 } 01211 else { 01212 rb_raise(rb_eTypeError, 01213 "wrong argument type %s (expected Binding)", 01214 rb_obj_classname(scope)); 01215 } 01216 GetEnvPtr(envval, env); 01217 base_block = &env->block; 01218 } 01219 else { 01220 rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); 01221 01222 if (cfp != 0) { 01223 block = *RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp); 01224 base_block = █ 01225 base_block->self = self; 01226 base_block->iseq = cfp->iseq; /* TODO */ 01227 } 01228 else { 01229 rb_raise(rb_eRuntimeError, "Can't eval on top of Fiber or Thread"); 01230 } 01231 } 01232 01233 if ((fname = file) == Qundef) { 01234 fname = rb_usascii_str_new_cstr("(eval)"); 01235 } 01236 01237 /* make eval iseq */ 01238 th->parse_in_eval++; 01239 th->mild_compile_error++; 01240 iseqval = rb_iseq_compile_with_option(src, fname, absolute_path, INT2FIX(line), base_block, Qnil); 01241 th->mild_compile_error--; 01242 th->parse_in_eval--; 01243 01244 vm_set_eval_stack(th, iseqval, cref, base_block); 01245 01246 if (0) { /* for debug */ 01247 VALUE disasm = rb_iseq_disasm(iseqval); 01248 printf("%s\n", StringValuePtr(disasm)); 01249 } 01250 01251 /* save new env */ 01252 GetISeqPtr(iseqval, iseq); 01253 if (bind && iseq->local_table_size > 0) { 01254 bind->env = rb_vm_make_env_object(th, th->cfp); 01255 } 01256 01257 /* kick */ 01258 CHECK_VM_STACK_OVERFLOW(th->cfp, iseq->stack_max); 01259 result = vm_exec(th); 01260 } 01261 TH_POP_TAG(); 01262 th->mild_compile_error = mild_compile_error; 01263 th->parse_in_eval = parse_in_eval; 01264 01265 if (state) { 01266 if (state == TAG_RAISE) { 01267 VALUE errinfo = th->errinfo; 01268 if (file == Qundef) { 01269 VALUE mesg, errat, bt2; 01270 ID id_mesg; 01271 01272 CONST_ID(id_mesg, "mesg"); 01273 errat = rb_get_backtrace(errinfo); 01274 mesg = rb_attr_get(errinfo, id_mesg); 01275 if (!NIL_P(errat) && RB_TYPE_P(errat, T_ARRAY) && 01276 (bt2 = vm_backtrace_str_ary(th, 0, 0), RARRAY_LEN(bt2) > 0)) { 01277 if (!NIL_P(mesg) && RB_TYPE_P(mesg, T_STRING) && !RSTRING_LEN(mesg)) { 01278 if (OBJ_FROZEN(mesg)) { 01279 VALUE m = rb_str_cat(rb_str_dup(RARRAY_PTR(errat)[0]), ": ", 2); 01280 rb_ivar_set(errinfo, id_mesg, rb_str_append(m, mesg)); 01281 } 01282 else { 01283 rb_str_update(mesg, 0, 0, rb_str_new2(": ")); 01284 rb_str_update(mesg, 0, 0, RARRAY_PTR(errat)[0]); 01285 } 01286 } 01287 RARRAY_PTR(errat)[0] = RARRAY_PTR(bt2)[0]; 01288 } 01289 } 01290 rb_exc_raise(errinfo); 01291 } 01292 JUMP_TAG(state); 01293 } 01294 return result; 01295 } 01296 01297 static VALUE 01298 eval_string(VALUE self, VALUE src, VALUE scope, VALUE file, int line) 01299 { 01300 return eval_string_with_cref(self, src, scope, 0, file, line); 01301 } 01302 01303 /* 01304 * call-seq: 01305 * eval(string [, binding [, filename [,lineno]]]) -> obj 01306 * 01307 * Evaluates the Ruby expression(s) in <em>string</em>. If 01308 * <em>binding</em> is given, which must be a <code>Binding</code> 01309 * object, the evaluation is performed in its context. If the 01310 * optional <em>filename</em> and <em>lineno</em> parameters are 01311 * present, they will be used when reporting syntax errors. 01312 * 01313 * def get_binding(str) 01314 * return binding 01315 * end 01316 * str = "hello" 01317 * eval "str + ' Fred'" #=> "hello Fred" 01318 * eval "str + ' Fred'", get_binding("bye") #=> "bye Fred" 01319 */ 01320 01321 VALUE 01322 rb_f_eval(int argc, VALUE *argv, VALUE self) 01323 { 01324 VALUE src, scope, vfile, vline; 01325 VALUE file = Qundef; 01326 int line = 1; 01327 01328 rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline); 01329 if (rb_safe_level() >= 4) { 01330 StringValue(src); 01331 if (!NIL_P(scope) && !OBJ_TAINTED(scope)) { 01332 rb_raise(rb_eSecurityError, 01333 "Insecure: can't modify trusted binding"); 01334 } 01335 } 01336 else { 01337 SafeStringValue(src); 01338 } 01339 if (argc >= 3) { 01340 StringValue(vfile); 01341 } 01342 if (argc >= 4) { 01343 line = NUM2INT(vline); 01344 } 01345 01346 if (!NIL_P(vfile)) 01347 file = vfile; 01348 return eval_string(self, src, scope, file, line); 01349 } 01350 01352 VALUE 01353 ruby_eval_string_from_file(const char *str, const char *filename) 01354 { 01355 VALUE file = filename ? rb_str_new_cstr(filename) : 0; 01356 return eval_string(rb_vm_top_self(), rb_str_new2(str), Qnil, file, 1); 01357 } 01358 01359 struct eval_string_from_file_arg { 01360 VALUE str; 01361 VALUE filename; 01362 }; 01363 01364 static VALUE 01365 eval_string_from_file_helper(void *data) 01366 { 01367 const struct eval_string_from_file_arg *const arg = (struct eval_string_from_file_arg*)data; 01368 return eval_string(rb_vm_top_self(), arg->str, Qnil, arg->filename, 1); 01369 } 01370 01371 VALUE 01372 ruby_eval_string_from_file_protect(const char *str, const char *filename, int *state) 01373 { 01374 struct eval_string_from_file_arg arg; 01375 arg.str = rb_str_new_cstr(str); 01376 arg.filename = filename ? rb_str_new_cstr(filename) : 0; 01377 return rb_protect((VALUE (*)(VALUE))eval_string_from_file_helper, (VALUE)&arg, state); 01378 } 01379 01392 VALUE 01393 rb_eval_string(const char *str) 01394 { 01395 return ruby_eval_string_from_file(str, "eval"); 01396 } 01397 01408 VALUE 01409 rb_eval_string_protect(const char *str, int *state) 01410 { 01411 return rb_protect((VALUE (*)(VALUE))rb_eval_string, (VALUE)str, state); 01412 } 01413 01425 VALUE 01426 rb_eval_string_wrap(const char *str, int *state) 01427 { 01428 int status; 01429 rb_thread_t *th = GET_THREAD(); 01430 VALUE self = th->top_self; 01431 VALUE wrapper = th->top_wrapper; 01432 VALUE val; 01433 01434 th->top_wrapper = rb_module_new(); 01435 th->top_self = rb_obj_clone(rb_vm_top_self()); 01436 rb_extend_object(th->top_self, th->top_wrapper); 01437 01438 val = rb_eval_string_protect(str, &status); 01439 01440 th->top_self = self; 01441 th->top_wrapper = wrapper; 01442 01443 if (state) { 01444 *state = status; 01445 } 01446 else if (status) { 01447 JUMP_TAG(status); 01448 } 01449 return val; 01450 } 01451 01452 VALUE 01453 rb_eval_cmd(VALUE cmd, VALUE arg, int level) 01454 { 01455 int state; 01456 VALUE val = Qnil; /* OK */ 01457 volatile int safe = rb_safe_level(); 01458 01459 if (OBJ_TAINTED(cmd)) { 01460 level = 4; 01461 } 01462 01463 if (!RB_TYPE_P(cmd, T_STRING)) { 01464 PUSH_TAG(); 01465 rb_set_safe_level_force(level); 01466 if ((state = EXEC_TAG()) == 0) { 01467 val = rb_funcall2(cmd, rb_intern("call"), RARRAY_LENINT(arg), 01468 RARRAY_PTR(arg)); 01469 } 01470 POP_TAG(); 01471 01472 rb_set_safe_level_force(safe); 01473 01474 if (state) 01475 JUMP_TAG(state); 01476 return val; 01477 } 01478 01479 PUSH_TAG(); 01480 if ((state = EXEC_TAG()) == 0) { 01481 val = eval_string(rb_vm_top_self(), cmd, Qnil, 0, 0); 01482 } 01483 POP_TAG(); 01484 01485 rb_set_safe_level_force(safe); 01486 if (state) JUMP_TAG(state); 01487 return val; 01488 } 01489 01490 /* block eval under the class/module context */ 01491 01492 static VALUE 01493 yield_under(VALUE under, VALUE self, VALUE values) 01494 { 01495 rb_thread_t *th = GET_THREAD(); 01496 rb_block_t block, *blockptr; 01497 NODE *cref; 01498 01499 if ((blockptr = VM_CF_BLOCK_PTR(th->cfp)) != 0) { 01500 block = *blockptr; 01501 block.self = self; 01502 VM_CF_LEP(th->cfp)[0] = VM_ENVVAL_BLOCK_PTR(&block); 01503 } 01504 cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr); 01505 cref->flags |= NODE_FL_CREF_PUSHED_BY_EVAL; 01506 01507 if (values == Qundef) { 01508 return vm_yield_with_cref(th, 1, &self, cref); 01509 } 01510 else { 01511 return vm_yield_with_cref(th, RARRAY_LENINT(values), RARRAY_PTR(values), cref); 01512 } 01513 } 01514 01515 VALUE 01516 rb_yield_refine_block(VALUE refinement, VALUE refinements) 01517 { 01518 rb_thread_t *th = GET_THREAD(); 01519 rb_block_t block, *blockptr; 01520 NODE *cref; 01521 01522 if ((blockptr = VM_CF_BLOCK_PTR(th->cfp)) != 0) { 01523 block = *blockptr; 01524 block.self = refinement; 01525 VM_CF_LEP(th->cfp)[0] = VM_ENVVAL_BLOCK_PTR(&block); 01526 } 01527 cref = vm_cref_push(th, refinement, NOEX_PUBLIC, blockptr); 01528 cref->flags |= NODE_FL_CREF_PUSHED_BY_EVAL; 01529 cref->nd_refinements = refinements; 01530 01531 return vm_yield_with_cref(th, 0, NULL, cref); 01532 } 01533 01534 /* string eval under the class/module context */ 01535 static VALUE 01536 eval_under(VALUE under, VALUE self, VALUE src, VALUE file, int line) 01537 { 01538 NODE *cref = vm_cref_push(GET_THREAD(), under, NOEX_PUBLIC, NULL); 01539 01540 if (SPECIAL_CONST_P(self) && !NIL_P(under)) { 01541 cref->flags |= NODE_FL_CREF_PUSHED_BY_EVAL; 01542 } 01543 if (rb_safe_level() >= 4) { 01544 StringValue(src); 01545 } 01546 else { 01547 SafeStringValue(src); 01548 } 01549 01550 return eval_string_with_cref(self, src, Qnil, cref, file, line); 01551 } 01552 01553 static VALUE 01554 specific_eval(int argc, VALUE *argv, VALUE klass, VALUE self) 01555 { 01556 if (rb_block_given_p()) { 01557 rb_check_arity(argc, 0, 0); 01558 return yield_under(klass, self, Qundef); 01559 } 01560 else { 01561 VALUE file = Qundef; 01562 int line = 1; 01563 01564 rb_check_arity(argc, 1, 3); 01565 if (rb_safe_level() >= 4) { 01566 StringValue(argv[0]); 01567 } 01568 else { 01569 SafeStringValue(argv[0]); 01570 } 01571 if (argc > 2) 01572 line = NUM2INT(argv[2]); 01573 if (argc > 1) { 01574 file = argv[1]; 01575 if (!NIL_P(file)) StringValue(file); 01576 } 01577 return eval_under(klass, self, argv[0], file, line); 01578 } 01579 } 01580 01581 /* 01582 * call-seq: 01583 * obj.instance_eval(string [, filename [, lineno]] ) -> obj 01584 * obj.instance_eval {| | block } -> obj 01585 * 01586 * Evaluates a string containing Ruby source code, or the given block, 01587 * within the context of the receiver (_obj_). In order to set the 01588 * context, the variable +self+ is set to _obj_ while 01589 * the code is executing, giving the code access to _obj_'s 01590 * instance variables. In the version of <code>instance_eval</code> 01591 * that takes a +String+, the optional second and third 01592 * parameters supply a filename and starting line number that are used 01593 * when reporting compilation errors. 01594 * 01595 * class KlassWithSecret 01596 * def initialize 01597 * @secret = 99 01598 * end 01599 * end 01600 * k = KlassWithSecret.new 01601 * k.instance_eval { @secret } #=> 99 01602 */ 01603 01604 VALUE 01605 rb_obj_instance_eval(int argc, VALUE *argv, VALUE self) 01606 { 01607 VALUE klass; 01608 01609 if (SPECIAL_CONST_P(self)) { 01610 klass = rb_special_singleton_class(self); 01611 } 01612 else { 01613 klass = rb_singleton_class(self); 01614 } 01615 return specific_eval(argc, argv, klass, self); 01616 } 01617 01618 /* 01619 * call-seq: 01620 * obj.instance_exec(arg...) {|var...| block } -> obj 01621 * 01622 * Executes the given block within the context of the receiver 01623 * (_obj_). In order to set the context, the variable +self+ is set 01624 * to _obj_ while the code is executing, giving the code access to 01625 * _obj_'s instance variables. Arguments are passed as block parameters. 01626 * 01627 * class KlassWithSecret 01628 * def initialize 01629 * @secret = 99 01630 * end 01631 * end 01632 * k = KlassWithSecret.new 01633 * k.instance_exec(5) {|x| @secret+x } #=> 104 01634 */ 01635 01636 VALUE 01637 rb_obj_instance_exec(int argc, VALUE *argv, VALUE self) 01638 { 01639 VALUE klass; 01640 01641 if (SPECIAL_CONST_P(self)) { 01642 klass = rb_special_singleton_class(self); 01643 } 01644 else { 01645 klass = rb_singleton_class(self); 01646 } 01647 return yield_under(klass, self, rb_ary_new4(argc, argv)); 01648 } 01649 01650 /* 01651 * call-seq: 01652 * mod.class_eval(string [, filename [, lineno]]) -> obj 01653 * mod.module_eval {|| block } -> obj 01654 * 01655 * Evaluates the string or block in the context of _mod_, except that when 01656 * a block is given, constant/class variable lookup is not affected. This 01657 * can be used to add methods to a class. <code>module_eval</code> returns 01658 * the result of evaluating its argument. The optional _filename_ and 01659 * _lineno_ parameters set the text for error messages. 01660 * 01661 * class Thing 01662 * end 01663 * a = %q{def hello() "Hello there!" end} 01664 * Thing.module_eval(a) 01665 * puts Thing.new.hello() 01666 * Thing.module_eval("invalid code", "dummy", 123) 01667 * 01668 * <em>produces:</em> 01669 * 01670 * Hello there! 01671 * dummy:123:in `module_eval': undefined local variable 01672 * or method `code' for Thing:Class 01673 */ 01674 01675 VALUE 01676 rb_mod_module_eval(int argc, VALUE *argv, VALUE mod) 01677 { 01678 return specific_eval(argc, argv, mod, mod); 01679 } 01680 01681 /* 01682 * call-seq: 01683 * mod.module_exec(arg...) {|var...| block } -> obj 01684 * mod.class_exec(arg...) {|var...| block } -> obj 01685 * 01686 * Evaluates the given block in the context of the class/module. 01687 * The method defined in the block will belong to the receiver. 01688 * 01689 * class Thing 01690 * end 01691 * Thing.class_exec{ 01692 * def hello() "Hello there!" end 01693 * } 01694 * puts Thing.new.hello() 01695 * 01696 * <em>produces:</em> 01697 * 01698 * Hello there! 01699 */ 01700 01701 VALUE 01702 rb_mod_module_exec(int argc, VALUE *argv, VALUE mod) 01703 { 01704 return yield_under(mod, mod, rb_ary_new4(argc, argv)); 01705 } 01706 01707 /* 01708 * call-seq: 01709 * throw(tag [, obj]) 01710 * 01711 * Transfers control to the end of the active +catch+ block 01712 * waiting for _tag_. Raises +ArgumentError+ if there 01713 * is no +catch+ block for the _tag_. The optional second 01714 * parameter supplies a return value for the +catch+ block, 01715 * which otherwise defaults to +nil+. For examples, see 01716 * <code>Kernel::catch</code>. 01717 */ 01718 01719 static VALUE 01720 rb_f_throw(int argc, VALUE *argv) 01721 { 01722 VALUE tag, value; 01723 01724 rb_scan_args(argc, argv, "11", &tag, &value); 01725 rb_throw_obj(tag, value); 01726 UNREACHABLE; 01727 } 01728 01729 void 01730 rb_throw_obj(VALUE tag, VALUE value) 01731 { 01732 rb_thread_t *th = GET_THREAD(); 01733 struct rb_vm_tag *tt = th->tag; 01734 01735 while (tt) { 01736 if (tt->tag == tag) { 01737 tt->retval = value; 01738 break; 01739 } 01740 tt = tt->prev; 01741 } 01742 if (!tt) { 01743 VALUE desc = rb_inspect(tag); 01744 RB_GC_GUARD(desc); 01745 rb_raise(rb_eArgError, "uncaught throw %s", RSTRING_PTR(desc)); 01746 } 01747 th->errinfo = NEW_THROW_OBJECT(tag, 0, TAG_THROW); 01748 01749 JUMP_TAG(TAG_THROW); 01750 } 01751 01752 void 01753 rb_throw(const char *tag, VALUE val) 01754 { 01755 rb_throw_obj(ID2SYM(rb_intern(tag)), val); 01756 } 01757 01758 static VALUE 01759 catch_i(VALUE tag, VALUE data) 01760 { 01761 return rb_yield_0(1, &tag); 01762 } 01763 01764 /* 01765 * call-seq: 01766 * catch([arg]) {|tag| block } -> obj 01767 * 01768 * +catch+ executes its block. If a +throw+ is 01769 * executed, Ruby searches up its stack for a +catch+ block 01770 * with a tag corresponding to the +throw+'s 01771 * _tag_. If found, that block is terminated, and 01772 * +catch+ returns the value given to +throw+. If 01773 * +throw+ is not called, the block terminates normally, and 01774 * the value of +catch+ is the value of the last expression 01775 * evaluated. +catch+ expressions may be nested, and the 01776 * +throw+ call need not be in lexical scope. 01777 * 01778 * def routine(n) 01779 * puts n 01780 * throw :done if n <= 0 01781 * routine(n-1) 01782 * end 01783 * 01784 * 01785 * catch(:done) { routine(3) } 01786 * 01787 * <em>produces:</em> 01788 * 01789 * 3 01790 * 2 01791 * 1 01792 * 0 01793 * 01794 * when _arg_ is given, +catch+ yields it as is, or when no 01795 * _arg_ is given, +catch+ assigns a new unique object to 01796 * +throw+. this is useful for nested +catch+. _arg_ can 01797 * be an arbitrary object, not only Symbol. 01798 * 01799 */ 01800 01801 static VALUE 01802 rb_f_catch(int argc, VALUE *argv) 01803 { 01804 VALUE tag; 01805 01806 if (argc == 0) { 01807 tag = rb_obj_alloc(rb_cObject); 01808 } 01809 else { 01810 rb_scan_args(argc, argv, "01", &tag); 01811 } 01812 return rb_catch_obj(tag, catch_i, 0); 01813 } 01814 01815 VALUE 01816 rb_catch(const char *tag, VALUE (*func)(), VALUE data) 01817 { 01818 VALUE vtag = tag ? ID2SYM(rb_intern(tag)) : rb_obj_alloc(rb_cObject); 01819 return rb_catch_obj(vtag, func, data); 01820 } 01821 01822 VALUE 01823 rb_catch_obj(VALUE tag, VALUE (*func)(), VALUE data) 01824 { 01825 int state; 01826 volatile VALUE val = Qnil; /* OK */ 01827 rb_thread_t *th = GET_THREAD(); 01828 rb_control_frame_t *saved_cfp = th->cfp; 01829 01830 TH_PUSH_TAG(th); 01831 01832 th->tag->tag = tag; 01833 01834 if ((state = TH_EXEC_TAG()) == 0) { 01835 /* call with argc=1, argv = [tag], block = Qnil to insure compatibility */ 01836 val = (*func)(tag, data, 1, &tag, Qnil); 01837 } 01838 else if (state == TAG_THROW && RNODE(th->errinfo)->u1.value == tag) { 01839 th->cfp = saved_cfp; 01840 val = th->tag->retval; 01841 th->errinfo = Qnil; 01842 state = 0; 01843 } 01844 TH_POP_TAG(); 01845 if (state) 01846 JUMP_TAG(state); 01847 01848 return val; 01849 } 01850 01851 /* 01852 * call-seq: 01853 * local_variables -> array 01854 * 01855 * Returns the names of the current local variables. 01856 * 01857 * fred = 1 01858 * for i in 1..10 01859 * # ... 01860 * end 01861 * local_variables #=> [:fred, :i] 01862 */ 01863 01864 static VALUE 01865 rb_f_local_variables(void) 01866 { 01867 VALUE ary = rb_ary_new(); 01868 rb_thread_t *th = GET_THREAD(); 01869 rb_control_frame_t *cfp = 01870 vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp)); 01871 int i; 01872 01873 while (cfp) { 01874 if (cfp->iseq) { 01875 for (i = 0; i < cfp->iseq->local_table_size; i++) { 01876 ID lid = cfp->iseq->local_table[i]; 01877 if (lid) { 01878 const char *vname = rb_id2name(lid); 01879 /* should skip temporary variable */ 01880 if (vname) { 01881 rb_ary_push(ary, ID2SYM(lid)); 01882 } 01883 } 01884 } 01885 } 01886 if (!VM_EP_LEP_P(cfp->ep)) { 01887 /* block */ 01888 VALUE *ep = VM_CF_PREV_EP(cfp); 01889 01890 if (vm_collect_local_variables_in_heap(th, ep, ary)) { 01891 break; 01892 } 01893 else { 01894 while (cfp->ep != ep) { 01895 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); 01896 } 01897 } 01898 } 01899 else { 01900 break; 01901 } 01902 } 01903 return ary; 01904 } 01905 01906 /* 01907 * call-seq: 01908 * block_given? -> true or false 01909 * iterator? -> true or false 01910 * 01911 * Returns <code>true</code> if <code>yield</code> would execute a 01912 * block in the current context. The <code>iterator?</code> form 01913 * is mildly deprecated. 01914 * 01915 * def try 01916 * if block_given? 01917 * yield 01918 * else 01919 * "no block" 01920 * end 01921 * end 01922 * try #=> "no block" 01923 * try { "hello" } #=> "hello" 01924 * try do "hello" end #=> "hello" 01925 */ 01926 01927 01928 VALUE 01929 rb_f_block_given_p(void) 01930 { 01931 rb_thread_t *th = GET_THREAD(); 01932 rb_control_frame_t *cfp = th->cfp; 01933 cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)); 01934 01935 if (cfp != 0 && VM_CF_BLOCK_PTR(cfp)) { 01936 return Qtrue; 01937 } 01938 else { 01939 return Qfalse; 01940 } 01941 } 01942 01943 VALUE 01944 rb_current_realfilepath(void) 01945 { 01946 rb_thread_t *th = GET_THREAD(); 01947 rb_control_frame_t *cfp = th->cfp; 01948 cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)); 01949 if (cfp != 0) return cfp->iseq->location.absolute_path; 01950 return Qnil; 01951 } 01952 01953 void 01954 Init_vm_eval(void) 01955 { 01956 rb_define_global_function("eval", rb_f_eval, -1); 01957 rb_define_global_function("local_variables", rb_f_local_variables, 0); 01958 rb_define_global_function("iterator?", rb_f_block_given_p, 0); 01959 rb_define_global_function("block_given?", rb_f_block_given_p, 0); 01960 01961 rb_define_global_function("catch", rb_f_catch, -1); 01962 rb_define_global_function("throw", rb_f_throw, -1); 01963 01964 rb_define_global_function("loop", rb_f_loop, 0); 01965 01966 rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval, -1); 01967 rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1); 01968 rb_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1); 01969 01970 #if 1 01971 rb_add_method(rb_cBasicObject, rb_intern("__send__"), 01972 VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, 0); 01973 rb_add_method(rb_mKernel, rb_intern("send"), 01974 VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, 0); 01975 #else 01976 rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1); 01977 rb_define_method(rb_mKernel, "send", rb_f_send, -1); 01978 #endif 01979 rb_define_method(rb_mKernel, "public_send", rb_f_public_send, -1); 01980 01981 rb_define_method(rb_cModule, "module_exec", rb_mod_module_exec, -1); 01982 rb_define_method(rb_cModule, "class_exec", rb_mod_module_exec, -1); 01983 rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1); 01984 rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1); 01985 } 01986
1.7.6.1