|
Ruby 1.9.2p180(2011-02-18revision30909)
|
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 printf("%s\n", RSTRING_PTR(rb_iseq_disasm(iseqval))); 01018 } 01019 01020 /* save new env */ 01021 GetISeqPtr(iseqval, iseq); 01022 if (bind && iseq->local_table_size > 0) { 01023 bind->env = rb_vm_make_env_object(th, th->cfp); 01024 } 01025 01026 /* kick */ 01027 CHECK_STACK_OVERFLOW(th->cfp, iseq->stack_max); 01028 result = vm_exec(th); 01029 } 01030 POP_TAG(); 01031 th->mild_compile_error = mild_compile_error; 01032 th->parse_in_eval = parse_in_eval; 01033 01034 if (state) { 01035 if (state == TAG_RAISE) { 01036 VALUE errinfo = th->errinfo; 01037 if (strcmp(file, "(eval)") == 0) { 01038 VALUE mesg, errat, bt2; 01039 extern VALUE rb_get_backtrace(VALUE info); 01040 ID id_mesg; 01041 01042 CONST_ID(id_mesg, "mesg"); 01043 errat = rb_get_backtrace(errinfo); 01044 mesg = rb_attr_get(errinfo, id_mesg); 01045 if (!NIL_P(errat) && TYPE(errat) == T_ARRAY && 01046 (bt2 = vm_backtrace(th, -2), RARRAY_LEN(bt2) > 0)) { 01047 if (!NIL_P(mesg) && TYPE(mesg) == T_STRING && !RSTRING_LEN(mesg)) { 01048 if (OBJ_FROZEN(mesg)) { 01049 VALUE m = rb_str_cat(rb_str_dup(RARRAY_PTR(errat)[0]), ": ", 2); 01050 rb_ivar_set(errinfo, id_mesg, rb_str_append(m, mesg)); 01051 } 01052 else { 01053 rb_str_update(mesg, 0, 0, rb_str_new2(": ")); 01054 rb_str_update(mesg, 0, 0, RARRAY_PTR(errat)[0]); 01055 } 01056 } 01057 RARRAY_PTR(errat)[0] = RARRAY_PTR(bt2)[0]; 01058 } 01059 } 01060 rb_exc_raise(errinfo); 01061 } 01062 JUMP_TAG(state); 01063 } 01064 return result; 01065 } 01066 01067 static VALUE 01068 eval_string(VALUE self, VALUE src, VALUE scope, const char *file, int line) 01069 { 01070 return eval_string_with_cref(self, src, scope, 0, file, line); 01071 } 01072 01073 /* 01074 * call-seq: 01075 * eval(string [, binding [, filename [,lineno]]]) -> obj 01076 * 01077 * Evaluates the Ruby expression(s) in <em>string</em>. If 01078 * <em>binding</em> is given, which must be a <code>Binding</code> 01079 * object, the evaluation is performed in its context. If the 01080 * optional <em>filename</em> and <em>lineno</em> parameters are 01081 * present, they will be used when reporting syntax errors. 01082 * 01083 * def getBinding(str) 01084 * return binding 01085 * end 01086 * str = "hello" 01087 * eval "str + ' Fred'" #=> "hello Fred" 01088 * eval "str + ' Fred'", getBinding("bye") #=> "bye Fred" 01089 */ 01090 01091 VALUE 01092 rb_f_eval(int argc, VALUE *argv, VALUE self) 01093 { 01094 VALUE src, scope, vfile, vline; 01095 const char *file = "(eval)"; 01096 int line = 1; 01097 01098 rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline); 01099 if (rb_safe_level() >= 4) { 01100 StringValue(src); 01101 if (!NIL_P(scope) && !OBJ_TAINTED(scope)) { 01102 rb_raise(rb_eSecurityError, 01103 "Insecure: can't modify trusted binding"); 01104 } 01105 } 01106 else { 01107 SafeStringValue(src); 01108 } 01109 if (argc >= 3) { 01110 StringValue(vfile); 01111 } 01112 if (argc >= 4) { 01113 line = NUM2INT(vline); 01114 } 01115 01116 if (!NIL_P(vfile)) 01117 file = RSTRING_PTR(vfile); 01118 return eval_string(self, src, scope, file, line); 01119 } 01120 01121 VALUE 01122 rb_eval_string(const char *str) 01123 { 01124 return eval_string(rb_vm_top_self(), rb_str_new2(str), Qnil, "(eval)", 1); 01125 } 01126 01127 VALUE 01128 rb_eval_string_protect(const char *str, int *state) 01129 { 01130 return rb_protect((VALUE (*)(VALUE))rb_eval_string, (VALUE)str, state); 01131 } 01132 01133 VALUE 01134 rb_eval_string_wrap(const char *str, int *state) 01135 { 01136 int status; 01137 rb_thread_t *th = GET_THREAD(); 01138 VALUE self = th->top_self; 01139 VALUE wrapper = th->top_wrapper; 01140 VALUE val; 01141 01142 th->top_wrapper = rb_module_new(); 01143 th->top_self = rb_obj_clone(rb_vm_top_self()); 01144 rb_extend_object(th->top_self, th->top_wrapper); 01145 01146 val = rb_eval_string_protect(str, &status); 01147 01148 th->top_self = self; 01149 th->top_wrapper = wrapper; 01150 01151 if (state) { 01152 *state = status; 01153 } 01154 else if (status) { 01155 JUMP_TAG(status); 01156 } 01157 return val; 01158 } 01159 01160 VALUE 01161 rb_eval_cmd(VALUE cmd, VALUE arg, int level) 01162 { 01163 int state; 01164 VALUE val = Qnil; /* OK */ 01165 volatile int safe = rb_safe_level(); 01166 01167 if (OBJ_TAINTED(cmd)) { 01168 level = 4; 01169 } 01170 01171 if (TYPE(cmd) != T_STRING) { 01172 PUSH_TAG(); 01173 rb_set_safe_level_force(level); 01174 if ((state = EXEC_TAG()) == 0) { 01175 val = rb_funcall2(cmd, rb_intern("call"), RARRAY_LENINT(arg), 01176 RARRAY_PTR(arg)); 01177 } 01178 POP_TAG(); 01179 01180 rb_set_safe_level_force(safe); 01181 01182 if (state) 01183 JUMP_TAG(state); 01184 return val; 01185 } 01186 01187 PUSH_TAG(); 01188 if ((state = EXEC_TAG()) == 0) { 01189 val = eval_string(rb_vm_top_self(), cmd, Qnil, 0, 0); 01190 } 01191 POP_TAG(); 01192 01193 rb_set_safe_level_force(safe); 01194 if (state) rb_vm_jump_tag_but_local_jump(state, val); 01195 return val; 01196 } 01197 01198 /* block eval under the class/module context */ 01199 01200 static VALUE 01201 yield_under(VALUE under, VALUE self, VALUE values) 01202 { 01203 rb_thread_t *th = GET_THREAD(); 01204 rb_block_t block, *blockptr; 01205 NODE *cref; 01206 01207 if ((blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0])) != 0) { 01208 block = *blockptr; 01209 block.self = self; 01210 th->cfp->lfp[0] = GC_GUARDED_PTR(&block); 01211 } 01212 cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr); 01213 cref->flags |= NODE_FL_CREF_PUSHED_BY_EVAL; 01214 01215 if (values == Qundef) { 01216 return vm_yield_with_cref(th, 1, &self, cref); 01217 } 01218 else { 01219 return vm_yield_with_cref(th, RARRAY_LENINT(values), RARRAY_PTR(values), cref); 01220 } 01221 } 01222 01223 /* string eval under the class/module context */ 01224 static VALUE 01225 eval_under(VALUE under, VALUE self, VALUE src, const char *file, int line) 01226 { 01227 NODE *cref = vm_cref_push(GET_THREAD(), under, NOEX_PUBLIC, NULL); 01228 01229 if (rb_safe_level() >= 4) { 01230 StringValue(src); 01231 } 01232 else { 01233 SafeStringValue(src); 01234 } 01235 01236 return eval_string_with_cref(self, src, Qnil, cref, file, line); 01237 } 01238 01239 static VALUE 01240 specific_eval(int argc, VALUE *argv, VALUE klass, VALUE self) 01241 { 01242 if (rb_block_given_p()) { 01243 if (argc > 0) { 01244 rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc); 01245 } 01246 return yield_under(klass, self, Qundef); 01247 } 01248 else { 01249 const char *file = "(eval)"; 01250 int line = 1; 01251 01252 if (argc == 0) { 01253 rb_raise(rb_eArgError, "block not supplied"); 01254 } 01255 else { 01256 if (rb_safe_level() >= 4) { 01257 StringValue(argv[0]); 01258 } 01259 else { 01260 SafeStringValue(argv[0]); 01261 } 01262 if (argc > 3) { 01263 const char *name = rb_id2name(rb_frame_callee()); 01264 rb_raise(rb_eArgError, 01265 "wrong number of arguments: %s(src) or %s{..}", 01266 name, name); 01267 } 01268 if (argc > 2) 01269 line = NUM2INT(argv[2]); 01270 if (argc > 1) { 01271 file = StringValuePtr(argv[1]); 01272 } 01273 } 01274 return eval_under(klass, self, argv[0], file, line); 01275 } 01276 } 01277 01278 /* 01279 * call-seq: 01280 * obj.instance_eval(string [, filename [, lineno]] ) -> obj 01281 * obj.instance_eval {| | block } -> obj 01282 * 01283 * Evaluates a string containing Ruby source code, or the given block, 01284 * within the context of the receiver (_obj_). In order to set the 01285 * context, the variable +self+ is set to _obj_ while 01286 * the code is executing, giving the code access to _obj_'s 01287 * instance variables. In the version of <code>instance_eval</code> 01288 * that takes a +String+, the optional second and third 01289 * parameters supply a filename and starting line number that are used 01290 * when reporting compilation errors. 01291 * 01292 * class KlassWithSecret 01293 * def initialize 01294 * @secret = 99 01295 * end 01296 * end 01297 * k = KlassWithSecret.new 01298 * k.instance_eval { @secret } #=> 99 01299 */ 01300 01301 VALUE 01302 rb_obj_instance_eval(int argc, VALUE *argv, VALUE self) 01303 { 01304 VALUE klass; 01305 01306 if (SPECIAL_CONST_P(self)) { 01307 klass = Qnil; 01308 } 01309 else { 01310 klass = rb_singleton_class(self); 01311 } 01312 return specific_eval(argc, argv, klass, self); 01313 } 01314 01315 /* 01316 * call-seq: 01317 * obj.instance_exec(arg...) {|var...| block } -> obj 01318 * 01319 * Executes the given block within the context of the receiver 01320 * (_obj_). In order to set the context, the variable +self+ is set 01321 * to _obj_ while the code is executing, giving the code access to 01322 * _obj_'s instance variables. Arguments are passed as block parameters. 01323 * 01324 * class KlassWithSecret 01325 * def initialize 01326 * @secret = 99 01327 * end 01328 * end 01329 * k = KlassWithSecret.new 01330 * k.instance_exec(5) {|x| @secret+x } #=> 104 01331 */ 01332 01333 VALUE 01334 rb_obj_instance_exec(int argc, VALUE *argv, VALUE self) 01335 { 01336 VALUE klass; 01337 01338 if (SPECIAL_CONST_P(self)) { 01339 klass = Qnil; 01340 } 01341 else { 01342 klass = rb_singleton_class(self); 01343 } 01344 return yield_under(klass, self, rb_ary_new4(argc, argv)); 01345 } 01346 01347 /* 01348 * call-seq: 01349 * mod.class_eval(string [, filename [, lineno]]) -> obj 01350 * mod.module_eval {|| block } -> obj 01351 * 01352 * Evaluates the string or block in the context of _mod_. This can 01353 * be used to add methods to a class. <code>module_eval</code> returns 01354 * the result of evaluating its argument. The optional _filename_ 01355 * and _lineno_ parameters set the text for error messages. 01356 * 01357 * class Thing 01358 * end 01359 * a = %q{def hello() "Hello there!" end} 01360 * Thing.module_eval(a) 01361 * puts Thing.new.hello() 01362 * Thing.module_eval("invalid code", "dummy", 123) 01363 * 01364 * <em>produces:</em> 01365 * 01366 * Hello there! 01367 * dummy:123:in `module_eval': undefined local variable 01368 * or method `code' for Thing:Class 01369 */ 01370 01371 VALUE 01372 rb_mod_module_eval(int argc, VALUE *argv, VALUE mod) 01373 { 01374 return specific_eval(argc, argv, mod, mod); 01375 } 01376 01377 /* 01378 * call-seq: 01379 * mod.module_exec(arg...) {|var...| block } -> obj 01380 * mod.class_exec(arg...) {|var...| block } -> obj 01381 * 01382 * Evaluates the given block in the context of the class/module. 01383 * The method defined in the block will belong to the receiver. 01384 * 01385 * class Thing 01386 * end 01387 * Thing.class_exec{ 01388 * def hello() "Hello there!" end 01389 * } 01390 * puts Thing.new.hello() 01391 * 01392 * <em>produces:</em> 01393 * 01394 * Hello there! 01395 */ 01396 01397 VALUE 01398 rb_mod_module_exec(int argc, VALUE *argv, VALUE mod) 01399 { 01400 return yield_under(mod, mod, rb_ary_new4(argc, argv)); 01401 } 01402 01403 /* 01404 * call-seq: 01405 * throw(tag [, obj]) 01406 * 01407 * Transfers control to the end of the active +catch+ block 01408 * waiting for _tag_. Raises +ArgumentError+ if there 01409 * is no +catch+ block for the _tag_. The optional second 01410 * parameter supplies a return value for the +catch+ block, 01411 * which otherwise defaults to +nil+. For examples, see 01412 * <code>Kernel::catch</code>. 01413 */ 01414 01415 static VALUE 01416 rb_f_throw(int argc, VALUE *argv) 01417 { 01418 VALUE tag, value; 01419 01420 rb_scan_args(argc, argv, "11", &tag, &value); 01421 rb_throw_obj(tag, value); 01422 return Qnil; /* not reached */ 01423 } 01424 01425 void 01426 rb_throw_obj(VALUE tag, VALUE value) 01427 { 01428 rb_thread_t *th = GET_THREAD(); 01429 struct rb_vm_tag *tt = th->tag; 01430 01431 while (tt) { 01432 if (tt->tag == tag) { 01433 tt->retval = value; 01434 break; 01435 } 01436 tt = tt->prev; 01437 } 01438 if (!tt) { 01439 VALUE desc = rb_inspect(tag); 01440 RB_GC_GUARD(desc); 01441 rb_raise(rb_eArgError, "uncaught throw %s", RSTRING_PTR(desc)); 01442 } 01443 rb_trap_restore_mask(); 01444 th->errinfo = NEW_THROW_OBJECT(tag, 0, TAG_THROW); 01445 01446 JUMP_TAG(TAG_THROW); 01447 } 01448 01449 void 01450 rb_throw(const char *tag, VALUE val) 01451 { 01452 rb_throw_obj(ID2SYM(rb_intern(tag)), val); 01453 } 01454 01455 static VALUE 01456 catch_i(VALUE tag, VALUE data) 01457 { 01458 return rb_yield_0(1, &tag); 01459 } 01460 01461 /* 01462 * call-seq: 01463 * catch([arg]) {|tag| block } -> obj 01464 * 01465 * +catch+ executes its block. If a +throw+ is 01466 * executed, Ruby searches up its stack for a +catch+ block 01467 * with a tag corresponding to the +throw+'s 01468 * _tag_. If found, that block is terminated, and 01469 * +catch+ returns the value given to +throw+. If 01470 * +throw+ is not called, the block terminates normally, and 01471 * the value of +catch+ is the value of the last expression 01472 * evaluated. +catch+ expressions may be nested, and the 01473 * +throw+ call need not be in lexical scope. 01474 * 01475 * def routine(n) 01476 * puts n 01477 * throw :done if n <= 0 01478 * routine(n-1) 01479 * end 01480 * 01481 * 01482 * catch(:done) { routine(3) } 01483 * 01484 * <em>produces:</em> 01485 * 01486 * 3 01487 * 2 01488 * 1 01489 * 0 01490 * 01491 * when _arg_ is given, +catch+ yields it as is, or when no 01492 * _arg_ is given, +catch+ assigns a new unique object to 01493 * +throw+. this is useful for nested +catch+. _arg_ can 01494 * be an arbitrary object, not only Symbol. 01495 * 01496 */ 01497 01498 static VALUE 01499 rb_f_catch(int argc, VALUE *argv) 01500 { 01501 VALUE tag; 01502 01503 if (argc == 0) { 01504 tag = rb_obj_alloc(rb_cObject); 01505 } 01506 else { 01507 rb_scan_args(argc, argv, "01", &tag); 01508 } 01509 return rb_catch_obj(tag, catch_i, 0); 01510 } 01511 01512 VALUE 01513 rb_catch(const char *tag, VALUE (*func)(), VALUE data) 01514 { 01515 VALUE vtag = tag ? ID2SYM(rb_intern(tag)) : rb_obj_alloc(rb_cObject); 01516 return rb_catch_obj(vtag, func, data); 01517 } 01518 01519 VALUE 01520 rb_catch_obj(VALUE tag, VALUE (*func)(), VALUE data) 01521 { 01522 int state; 01523 volatile VALUE val = Qnil; /* OK */ 01524 rb_thread_t *th = GET_THREAD(); 01525 rb_control_frame_t *saved_cfp = th->cfp; 01526 01527 PUSH_TAG(); 01528 01529 th->tag->tag = tag; 01530 01531 if ((state = EXEC_TAG()) == 0) { 01532 /* call with argc=1, argv = [tag], block = Qnil to insure compatibility */ 01533 val = (*func)(tag, data, 1, &tag, Qnil); 01534 } 01535 else if (state == TAG_THROW && RNODE(th->errinfo)->u1.value == tag) { 01536 th->cfp = saved_cfp; 01537 val = th->tag->retval; 01538 th->errinfo = Qnil; 01539 state = 0; 01540 } 01541 POP_TAG(); 01542 if (state) 01543 JUMP_TAG(state); 01544 01545 return val; 01546 } 01547 01548 /* 01549 * call-seq: 01550 * caller(start=1) -> array or nil 01551 * 01552 * Returns the current execution stack---an array containing strings in 01553 * the form ``<em>file:line</em>'' or ``<em>file:line: in 01554 * `method'</em>''. The optional _start_ parameter 01555 * determines the number of initial stack entries to omit from the 01556 * result. 01557 * 01558 * Returns +nil+ if _start_ is greater than the size of 01559 * current execution stack. 01560 * 01561 * def a(skip) 01562 * caller(skip) 01563 * end 01564 * def b(skip) 01565 * a(skip) 01566 * end 01567 * def c(skip) 01568 * b(skip) 01569 * end 01570 * c(0) #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10:in `<main>'"] 01571 * c(1) #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11:in `<main>'"] 01572 * c(2) #=> ["prog:8:in `c'", "prog:12:in `<main>'"] 01573 * c(3) #=> ["prog:13:in `<main>'"] 01574 * c(4) #=> [] 01575 * c(5) #=> nil 01576 */ 01577 01578 static VALUE 01579 rb_f_caller(int argc, VALUE *argv) 01580 { 01581 VALUE level; 01582 int lev; 01583 01584 rb_scan_args(argc, argv, "01", &level); 01585 01586 if (NIL_P(level)) 01587 lev = 1; 01588 else 01589 lev = NUM2INT(level); 01590 if (lev < 0) 01591 rb_raise(rb_eArgError, "negative level (%d)", lev); 01592 01593 return vm_backtrace(GET_THREAD(), lev); 01594 } 01595 01596 static int 01597 print_backtrace(void *arg, VALUE file, int line, VALUE method) 01598 { 01599 FILE *fp = arg; 01600 const char *filename = NIL_P(file) ? "ruby" : RSTRING_PTR(file); 01601 if (NIL_P(method)) { 01602 fprintf(fp, "\tfrom %s:%d:in unknown method\n", 01603 filename, line); 01604 } 01605 else { 01606 fprintf(fp, "\tfrom %s:%d:in `%s'\n", 01607 filename, line, RSTRING_PTR(method)); 01608 } 01609 return FALSE; 01610 } 01611 01612 void 01613 rb_backtrace(void) 01614 { 01615 vm_backtrace_each(GET_THREAD(), -1, NULL, print_backtrace, stderr); 01616 } 01617 01618 VALUE 01619 rb_make_backtrace(void) 01620 { 01621 return vm_backtrace(GET_THREAD(), -1); 01622 } 01623 01624 VALUE 01625 rb_thread_backtrace(VALUE thval) 01626 { 01627 rb_thread_t *th; 01628 GetThreadPtr(thval, th); 01629 01630 switch (th->status) { 01631 case THREAD_RUNNABLE: 01632 case THREAD_STOPPED: 01633 case THREAD_STOPPED_FOREVER: 01634 break; 01635 case THREAD_TO_KILL: 01636 case THREAD_KILLED: 01637 return Qnil; 01638 } 01639 01640 return vm_backtrace(th, 0); 01641 } 01642 01643 int 01644 rb_backtrace_each(rb_backtrace_iter_func *iter, void *arg) 01645 { 01646 return vm_backtrace_each(GET_THREAD(), -1, NULL, iter, arg); 01647 } 01648 01649 /* 01650 * call-seq: 01651 * local_variables -> array 01652 * 01653 * Returns the names of the current local variables. 01654 * 01655 * fred = 1 01656 * for i in 1..10 01657 * # ... 01658 * end 01659 * local_variables #=> [:fred, :i] 01660 */ 01661 01662 static VALUE 01663 rb_f_local_variables(void) 01664 { 01665 VALUE ary = rb_ary_new(); 01666 rb_thread_t *th = GET_THREAD(); 01667 rb_control_frame_t *cfp = 01668 vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp)); 01669 int i; 01670 01671 while (cfp) { 01672 if (cfp->iseq) { 01673 for (i = 0; i < cfp->iseq->local_table_size; i++) { 01674 ID lid = cfp->iseq->local_table[i]; 01675 if (lid) { 01676 const char *vname = rb_id2name(lid); 01677 /* should skip temporary variable */ 01678 if (vname) { 01679 rb_ary_push(ary, ID2SYM(lid)); 01680 } 01681 } 01682 } 01683 } 01684 if (cfp->lfp != cfp->dfp) { 01685 /* block */ 01686 VALUE *dfp = GC_GUARDED_PTR_REF(cfp->dfp[0]); 01687 01688 if (vm_collect_local_variables_in_heap(th, dfp, ary)) { 01689 break; 01690 } 01691 else { 01692 while (cfp->dfp != dfp) { 01693 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); 01694 } 01695 } 01696 } 01697 else { 01698 break; 01699 } 01700 } 01701 return ary; 01702 } 01703 01704 /* 01705 * call-seq: 01706 * block_given? -> true or false 01707 * iterator? -> true or false 01708 * 01709 * Returns <code>true</code> if <code>yield</code> would execute a 01710 * block in the current context. The <code>iterator?</code> form 01711 * is mildly deprecated. 01712 * 01713 * def try 01714 * if block_given? 01715 * yield 01716 * else 01717 * "no block" 01718 * end 01719 * end 01720 * try #=> "no block" 01721 * try { "hello" } #=> "hello" 01722 * try do "hello" end #=> "hello" 01723 */ 01724 01725 01726 VALUE 01727 rb_f_block_given_p(void) 01728 { 01729 rb_thread_t *th = GET_THREAD(); 01730 rb_control_frame_t *cfp = th->cfp; 01731 cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)); 01732 01733 if (cfp != 0 && 01734 (cfp->lfp[0] & 0x02) == 0 && 01735 GC_GUARDED_PTR_REF(cfp->lfp[0])) { 01736 return Qtrue; 01737 } 01738 else { 01739 return Qfalse; 01740 } 01741 } 01742 01743 VALUE 01744 rb_current_realfilepath(void) 01745 { 01746 rb_thread_t *th = GET_THREAD(); 01747 rb_control_frame_t *cfp = th->cfp; 01748 cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)); 01749 if (cfp != 0) return cfp->iseq->filepath; 01750 return Qnil; 01751 } 01752 01753 void 01754 Init_vm_eval(void) 01755 { 01756 rb_define_global_function("eval", rb_f_eval, -1); 01757 rb_define_global_function("local_variables", rb_f_local_variables, 0); 01758 rb_define_global_function("iterator?", rb_f_block_given_p, 0); 01759 rb_define_global_function("block_given?", rb_f_block_given_p, 0); 01760 01761 rb_define_global_function("catch", rb_f_catch, -1); 01762 rb_define_global_function("throw", rb_f_throw, -1); 01763 01764 rb_define_global_function("loop", rb_f_loop, 0); 01765 01766 rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval, -1); 01767 rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1); 01768 rb_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1); 01769 01770 #if 1 01771 rb_add_method(rb_cBasicObject, rb_intern("__send__"), 01772 VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, 0); 01773 rb_add_method(rb_mKernel, rb_intern("send"), 01774 VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, 0); 01775 #else 01776 rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1); 01777 rb_define_method(rb_mKernel, "send", rb_f_send, -1); 01778 #endif 01779 rb_define_method(rb_mKernel, "public_send", rb_f_public_send, -1); 01780 01781 rb_define_method(rb_cModule, "module_exec", rb_mod_module_exec, -1); 01782 rb_define_method(rb_cModule, "class_exec", rb_mod_module_exec, -1); 01783 rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1); 01784 rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1); 01785 01786 rb_define_global_function("caller", rb_f_caller, -1); 01787 } 01788 01789
1.7.3