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