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