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