00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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 , 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
00393 if (UNLIKELY(noex)) {
00394 if (((noex & NOEX_MASK) & NOEX_PRIVATE) && scope == CALL_PUBLIC) {
00395 return NOEX_PRIVATE;
00396 }
00397
00398
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
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
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;
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 va_init_list(ar, n);
00623
00624 if (n > 0) {
00625 long i;
00626
00627 argv = ALLOCA_N(VALUE, n);
00628
00629 for (i = 0; i < n; i++) {
00630 argv[i] = va_arg(ar, VALUE);
00631 }
00632 va_end(ar);
00633 }
00634 else {
00635 argv = 0;
00636 }
00637 return rb_call(recv, mid, n, argv, CALL_FCALL);
00638 }
00639
00647 VALUE
00648 rb_funcall2(VALUE recv, ID mid, int argc, const VALUE *argv)
00649 {
00650 return rb_call(recv, mid, argc, argv, CALL_FCALL);
00651 }
00652
00662 VALUE
00663 rb_funcall3(VALUE recv, ID mid, int argc, const VALUE *argv)
00664 {
00665 return rb_call(recv, mid, argc, argv, CALL_PUBLIC);
00666 }
00667
00668 static VALUE
00669 send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope)
00670 {
00671 VALUE vid;
00672 VALUE self = RUBY_VM_PREVIOUS_CONTROL_FRAME(GET_THREAD()->cfp)->self;
00673 rb_thread_t *th = GET_THREAD();
00674
00675 if (argc == 0) {
00676 rb_raise(rb_eArgError, "no method name given");
00677 }
00678
00679 vid = *argv++; argc--;
00680 PASS_PASSED_BLOCK_TH(th);
00681
00682 return rb_call0(recv, rb_to_id(vid), argc, argv, scope, self);
00683 }
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703 VALUE
00704 rb_f_send(int argc, VALUE *argv, VALUE recv)
00705 {
00706 return send_internal(argc, argv, recv, CALL_FCALL);
00707 }
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720 VALUE
00721 rb_f_public_send(int argc, VALUE *argv, VALUE recv)
00722 {
00723 return send_internal(argc, argv, recv, CALL_PUBLIC);
00724 }
00725
00726
00727
00728 static inline VALUE
00729 rb_yield_0(int argc, const VALUE * argv)
00730 {
00731 return vm_yield(GET_THREAD(), argc, argv);
00732 }
00733
00734 VALUE
00735 rb_yield(VALUE val)
00736 {
00737 if (val == Qundef) {
00738 return rb_yield_0(0, 0);
00739 }
00740 else {
00741 return rb_yield_0(1, &val);
00742 }
00743 }
00744
00745 VALUE
00746 rb_yield_values(int n, ...)
00747 {
00748 if (n == 0) {
00749 return rb_yield_0(0, 0);
00750 }
00751 else {
00752 int i;
00753 VALUE *argv;
00754 va_list args;
00755 argv = ALLOCA_N(VALUE, n);
00756
00757 va_init_list(args, n);
00758 for (i=0; i<n; i++) {
00759 argv[i] = va_arg(args, VALUE);
00760 }
00761 va_end(args);
00762
00763 return rb_yield_0(n, argv);
00764 }
00765 }
00766
00767 VALUE
00768 rb_yield_values2(int argc, const VALUE *argv)
00769 {
00770 return rb_yield_0(argc, argv);
00771 }
00772
00773 VALUE
00774 rb_yield_splat(VALUE values)
00775 {
00776 VALUE tmp = rb_check_array_type(values);
00777 volatile VALUE v;
00778 if (NIL_P(tmp)) {
00779 rb_raise(rb_eArgError, "not an array");
00780 }
00781 v = rb_yield_0(RARRAY_LENINT(tmp), RARRAY_PTR(tmp));
00782 return v;
00783 }
00784
00785 static VALUE
00786 loop_i(void)
00787 {
00788 for (;;) {
00789 rb_yield_0(0, 0);
00790 }
00791 return Qnil;
00792 }
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813 static VALUE
00814 rb_f_loop(VALUE self)
00815 {
00816 RETURN_ENUMERATOR(self, 0, 0);
00817 rb_rescue2(loop_i, (VALUE)0, 0, 0, rb_eStopIteration, (VALUE)0);
00818 return Qnil;
00819 }
00820
00821 #if VMDEBUG
00822 static const char *
00823 vm_frametype_name(const rb_control_frame_t *cfp);
00824 #endif
00825
00826 VALUE
00827 rb_iterate(VALUE (* it_proc) (VALUE), VALUE data1,
00828 VALUE (* bl_proc) (ANYARGS), VALUE data2)
00829 {
00830 int state;
00831 volatile VALUE retval = Qnil;
00832 NODE *node = NEW_IFUNC(bl_proc, data2);
00833 rb_thread_t *th = GET_THREAD();
00834 rb_control_frame_t *volatile cfp = th->cfp;
00835
00836 TH_PUSH_TAG(th);
00837 state = TH_EXEC_TAG();
00838 if (state == 0) {
00839 iter_retry:
00840 {
00841 rb_block_t *blockptr;
00842 if (bl_proc) {
00843 blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(th->cfp);
00844 blockptr->iseq = (void *)node;
00845 blockptr->proc = 0;
00846 }
00847 else {
00848 blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0]);
00849 }
00850 th->passed_block = blockptr;
00851 }
00852 retval = (*it_proc) (data1);
00853 }
00854 else {
00855 VALUE err = th->errinfo;
00856 if (state == TAG_BREAK) {
00857 VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
00858 VALUE *cdfp = cfp->dfp;
00859
00860 if (cdfp == escape_dfp) {
00861 state = 0;
00862 th->state = 0;
00863 th->errinfo = Qnil;
00864
00865
00866 while (th->cfp != cfp) {
00867 #if VMDEBUG
00868 printf("skipped frame: %s\n", vm_frametype_name(th->cfp));
00869 #endif
00870 if (UNLIKELY(VM_FRAME_TYPE(th->cfp) == VM_FRAME_MAGIC_CFUNC)) {
00871 const rb_method_entry_t *me = th->cfp->me;
00872 EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, th->cfp->self, me->called_id, me->klass);
00873 }
00874
00875 th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
00876 }
00877 }
00878 else{
00879
00880 }
00881 }
00882 else if (state == TAG_RETRY) {
00883 VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
00884 VALUE *cdfp = cfp->dfp;
00885
00886 if (cdfp == escape_dfp) {
00887 state = 0;
00888 th->state = 0;
00889 th->errinfo = Qnil;
00890 th->cfp = cfp;
00891 goto iter_retry;
00892 }
00893 }
00894 }
00895 TH_POP_TAG();
00896
00897 switch (state) {
00898 case 0:
00899 break;
00900 default:
00901 TH_JUMP_TAG(th, state);
00902 }
00903 return retval;
00904 }
00905
00906 struct iter_method_arg {
00907 VALUE obj;
00908 ID mid;
00909 int argc;
00910 VALUE *argv;
00911 };
00912
00913 static VALUE
00914 iterate_method(VALUE obj)
00915 {
00916 const struct iter_method_arg * arg =
00917 (struct iter_method_arg *) obj;
00918
00919 return rb_call(arg->obj, arg->mid, arg->argc, arg->argv, CALL_FCALL);
00920 }
00921
00922 VALUE
00923 rb_block_call(VALUE obj, ID mid, int argc, VALUE * argv,
00924 VALUE (*bl_proc) (ANYARGS), VALUE data2)
00925 {
00926 struct iter_method_arg arg;
00927
00928 arg.obj = obj;
00929 arg.mid = mid;
00930 arg.argc = argc;
00931 arg.argv = argv;
00932 return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2);
00933 }
00934
00935 VALUE
00936 rb_each(VALUE obj)
00937 {
00938 return rb_call(obj, idEach, 0, 0, CALL_FCALL);
00939 }
00940
00941 static VALUE
00942 eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *cref, const char *volatile file, volatile int line)
00943 {
00944 int state;
00945 VALUE result = Qundef;
00946 VALUE envval;
00947 rb_binding_t *bind = 0;
00948 rb_thread_t *th = GET_THREAD();
00949 rb_env_t *env = NULL;
00950 rb_block_t block;
00951 volatile int parse_in_eval;
00952 volatile int mild_compile_error;
00953
00954 if (file == 0) {
00955 file = rb_sourcefile();
00956 line = rb_sourceline();
00957 }
00958
00959 parse_in_eval = th->parse_in_eval;
00960 mild_compile_error = th->mild_compile_error;
00961 PUSH_TAG();
00962 if ((state = EXEC_TAG()) == 0) {
00963 rb_iseq_t *iseq;
00964 volatile VALUE iseqval;
00965
00966 if (scope != Qnil) {
00967 if (rb_obj_is_kind_of(scope, rb_cBinding)) {
00968 GetBindingPtr(scope, bind);
00969 envval = bind->env;
00970 if (strcmp(file, "(eval)") == 0 && bind->filename != Qnil) {
00971 file = RSTRING_PTR(bind->filename);
00972 line = bind->line_no;
00973 }
00974 }
00975 else {
00976 rb_raise(rb_eTypeError,
00977 "wrong argument type %s (expected Binding)",
00978 rb_obj_classname(scope));
00979 }
00980 GetEnvPtr(envval, env);
00981 th->base_block = &env->block;
00982 }
00983 else {
00984 rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
00985
00986 if (cfp != 0) {
00987 block = *RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
00988 th->base_block = █
00989 th->base_block->self = self;
00990 th->base_block->iseq = cfp->iseq;
00991 }
00992 else {
00993 rb_raise(rb_eRuntimeError, "Can't eval on top of Fiber or Thread");
00994 }
00995 }
00996
00997
00998 th->parse_in_eval++;
00999 th->mild_compile_error++;
01000 iseqval = rb_iseq_compile(src, rb_str_new2(file), INT2FIX(line));
01001 th->mild_compile_error--;
01002 th->parse_in_eval--;
01003
01004 vm_set_eval_stack(th, iseqval, cref);
01005 th->base_block = 0;
01006
01007 if (0) {
01008 printf("%s\n", RSTRING_PTR(rb_iseq_disasm(iseqval)));
01009 }
01010
01011
01012 GetISeqPtr(iseqval, iseq);
01013 if (bind && iseq->local_table_size > 0) {
01014 bind->env = rb_vm_make_env_object(th, th->cfp);
01015 }
01016
01017
01018 CHECK_STACK_OVERFLOW(th->cfp, iseq->stack_max);
01019 result = vm_exec(th);
01020 }
01021 POP_TAG();
01022 th->mild_compile_error = mild_compile_error;
01023 th->parse_in_eval = parse_in_eval;
01024
01025 if (state) {
01026 if (state == TAG_RAISE) {
01027 VALUE errinfo = th->errinfo;
01028 if (strcmp(file, "(eval)") == 0) {
01029 VALUE mesg, errat, bt2;
01030 extern VALUE rb_get_backtrace(VALUE info);
01031 ID id_mesg;
01032
01033 CONST_ID(id_mesg, "mesg");
01034 errat = rb_get_backtrace(errinfo);
01035 mesg = rb_attr_get(errinfo, id_mesg);
01036 if (!NIL_P(errat) && TYPE(errat) == T_ARRAY &&
01037 (bt2 = vm_backtrace(th, -2), RARRAY_LEN(bt2) > 0)) {
01038 if (!NIL_P(mesg) && TYPE(mesg) == T_STRING && !RSTRING_LEN(mesg)) {
01039 if (OBJ_FROZEN(mesg)) {
01040 VALUE m = rb_str_cat(rb_str_dup(RARRAY_PTR(errat)[0]), ": ", 2);
01041 rb_ivar_set(errinfo, id_mesg, rb_str_append(m, mesg));
01042 }
01043 else {
01044 rb_str_update(mesg, 0, 0, rb_str_new2(": "));
01045 rb_str_update(mesg, 0, 0, RARRAY_PTR(errat)[0]);
01046 }
01047 }
01048 RARRAY_PTR(errat)[0] = RARRAY_PTR(bt2)[0];
01049 }
01050 }
01051 rb_exc_raise(errinfo);
01052 }
01053 JUMP_TAG(state);
01054 }
01055 return result;
01056 }
01057
01058 static VALUE
01059 eval_string(VALUE self, VALUE src, VALUE scope, const char *file, int line)
01060 {
01061 return eval_string_with_cref(self, src, scope, 0, file, line);
01062 }
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082 VALUE
01083 rb_f_eval(int argc, VALUE *argv, VALUE self)
01084 {
01085 VALUE src, scope, vfile, vline;
01086 const char *file = "(eval)";
01087 int line = 1;
01088
01089 rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
01090 if (rb_safe_level() >= 4) {
01091 StringValue(src);
01092 if (!NIL_P(scope) && !OBJ_TAINTED(scope)) {
01093 rb_raise(rb_eSecurityError,
01094 "Insecure: can't modify trusted binding");
01095 }
01096 }
01097 else {
01098 SafeStringValue(src);
01099 }
01100 if (argc >= 3) {
01101 StringValue(vfile);
01102 }
01103 if (argc >= 4) {
01104 line = NUM2INT(vline);
01105 }
01106
01107 if (!NIL_P(vfile))
01108 file = RSTRING_PTR(vfile);
01109 return eval_string(self, src, scope, file, line);
01110 }
01111
01112 VALUE
01113 rb_eval_string(const char *str)
01114 {
01115 return eval_string(rb_vm_top_self(), rb_str_new2(str), Qnil, "(eval)", 1);
01116 }
01117
01118 VALUE
01119 rb_eval_string_protect(const char *str, int *state)
01120 {
01121 return rb_protect((VALUE (*)(VALUE))rb_eval_string, (VALUE)str, state);
01122 }
01123
01124 VALUE
01125 rb_eval_string_wrap(const char *str, int *state)
01126 {
01127 int status;
01128 rb_thread_t *th = GET_THREAD();
01129 VALUE self = th->top_self;
01130 VALUE wrapper = th->top_wrapper;
01131 VALUE val;
01132
01133 th->top_wrapper = rb_module_new();
01134 th->top_self = rb_obj_clone(rb_vm_top_self());
01135 rb_extend_object(th->top_self, th->top_wrapper);
01136
01137 val = rb_eval_string_protect(str, &status);
01138
01139 th->top_self = self;
01140 th->top_wrapper = wrapper;
01141
01142 if (state) {
01143 *state = status;
01144 }
01145 else if (status) {
01146 JUMP_TAG(status);
01147 }
01148 return val;
01149 }
01150
01151 VALUE
01152 rb_eval_cmd(VALUE cmd, VALUE arg, int level)
01153 {
01154 int state;
01155 VALUE val = Qnil;
01156 volatile int safe = rb_safe_level();
01157
01158 if (OBJ_TAINTED(cmd)) {
01159 level = 4;
01160 }
01161
01162 if (TYPE(cmd) != T_STRING) {
01163 PUSH_TAG();
01164 rb_set_safe_level_force(level);
01165 if ((state = EXEC_TAG()) == 0) {
01166 val = rb_funcall2(cmd, rb_intern("call"), RARRAY_LENINT(arg),
01167 RARRAY_PTR(arg));
01168 }
01169 POP_TAG();
01170
01171 rb_set_safe_level_force(safe);
01172
01173 if (state)
01174 JUMP_TAG(state);
01175 return val;
01176 }
01177
01178 PUSH_TAG();
01179 if ((state = EXEC_TAG()) == 0) {
01180 val = eval_string(rb_vm_top_self(), cmd, Qnil, 0, 0);
01181 }
01182 POP_TAG();
01183
01184 rb_set_safe_level_force(safe);
01185 if (state) rb_vm_jump_tag_but_local_jump(state, val);
01186 return val;
01187 }
01188
01189
01190
01191 static VALUE
01192 yield_under(VALUE under, VALUE self, VALUE values)
01193 {
01194 rb_thread_t *th = GET_THREAD();
01195 rb_block_t block, *blockptr;
01196 NODE *cref;
01197
01198 if ((blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0])) != 0) {
01199 block = *blockptr;
01200 block.self = self;
01201 th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
01202 }
01203 cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr);
01204 cref->flags |= NODE_FL_CREF_PUSHED_BY_EVAL;
01205
01206 if (values == Qundef) {
01207 return vm_yield_with_cref(th, 1, &self, cref);
01208 }
01209 else {
01210 return vm_yield_with_cref(th, RARRAY_LENINT(values), RARRAY_PTR(values), cref);
01211 }
01212 }
01213
01214
01215 static VALUE
01216 eval_under(VALUE under, VALUE self, VALUE src, const char *file, int line)
01217 {
01218 NODE *cref = vm_cref_push(GET_THREAD(), under, NOEX_PUBLIC, NULL);
01219
01220 if (rb_safe_level() >= 4) {
01221 StringValue(src);
01222 }
01223 else {
01224 SafeStringValue(src);
01225 }
01226
01227 return eval_string_with_cref(self, src, Qnil, cref, file, line);
01228 }
01229
01230 static VALUE
01231 specific_eval(int argc, VALUE *argv, VALUE klass, VALUE self)
01232 {
01233 if (rb_block_given_p()) {
01234 if (argc > 0) {
01235 rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
01236 }
01237 return yield_under(klass, self, Qundef);
01238 }
01239 else {
01240 const char *file = "(eval)";
01241 int line = 1;
01242
01243 if (argc == 0) {
01244 rb_raise(rb_eArgError, "block not supplied");
01245 }
01246 else {
01247 if (rb_safe_level() >= 4) {
01248 StringValue(argv[0]);
01249 }
01250 else {
01251 SafeStringValue(argv[0]);
01252 }
01253 if (argc > 3) {
01254 const char *name = rb_id2name(rb_frame_callee());
01255 rb_raise(rb_eArgError,
01256 "wrong number of arguments: %s(src) or %s{..}",
01257 name, name);
01258 }
01259 if (argc > 2)
01260 line = NUM2INT(argv[2]);
01261 if (argc > 1) {
01262 file = StringValuePtr(argv[1]);
01263 }
01264 }
01265 return eval_under(klass, self, argv[0], file, line);
01266 }
01267 }
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292 VALUE
01293 rb_obj_instance_eval(int argc, VALUE *argv, VALUE self)
01294 {
01295 VALUE klass;
01296
01297 if (SPECIAL_CONST_P(self)) {
01298 klass = Qnil;
01299 }
01300 else {
01301 klass = rb_singleton_class(self);
01302 }
01303 return specific_eval(argc, argv, klass, self);
01304 }
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324 VALUE
01325 rb_obj_instance_exec(int argc, VALUE *argv, VALUE self)
01326 {
01327 VALUE klass;
01328
01329 if (SPECIAL_CONST_P(self)) {
01330 klass = Qnil;
01331 }
01332 else {
01333 klass = rb_singleton_class(self);
01334 }
01335 return yield_under(klass, self, rb_ary_new4(argc, argv));
01336 }
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362 VALUE
01363 rb_mod_module_eval(int argc, VALUE *argv, VALUE mod)
01364 {
01365 return specific_eval(argc, argv, mod, mod);
01366 }
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388 VALUE
01389 rb_mod_module_exec(int argc, VALUE *argv, VALUE mod)
01390 {
01391 return yield_under(mod, mod, rb_ary_new4(argc, argv));
01392 }
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406 static VALUE
01407 rb_f_throw(int argc, VALUE *argv)
01408 {
01409 VALUE tag, value;
01410
01411 rb_scan_args(argc, argv, "11", &tag, &value);
01412 rb_throw_obj(tag, value);
01413 return Qnil;
01414 }
01415
01416 void
01417 rb_throw_obj(VALUE tag, VALUE value)
01418 {
01419 rb_thread_t *th = GET_THREAD();
01420 struct rb_vm_tag *tt = th->tag;
01421
01422 while (tt) {
01423 if (tt->tag == tag) {
01424 tt->retval = value;
01425 break;
01426 }
01427 tt = tt->prev;
01428 }
01429 if (!tt) {
01430 VALUE desc = rb_inspect(tag);
01431 rb_raise(rb_eArgError, "uncaught throw %s", RSTRING_PTR(desc));
01432 }
01433 rb_trap_restore_mask();
01434 th->errinfo = NEW_THROW_OBJECT(tag, 0, TAG_THROW);
01435
01436 JUMP_TAG(TAG_THROW);
01437 }
01438
01439 void
01440 rb_throw(const char *tag, VALUE val)
01441 {
01442 rb_throw_obj(ID2SYM(rb_intern(tag)), val);
01443 }
01444
01445 static VALUE
01446 catch_i(VALUE tag, VALUE data)
01447 {
01448 return rb_yield_0(1, &tag);
01449 }
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488 static VALUE
01489 rb_f_catch(int argc, VALUE *argv)
01490 {
01491 VALUE tag;
01492
01493 if (argc == 0) {
01494 tag = rb_obj_alloc(rb_cObject);
01495 }
01496 else {
01497 rb_scan_args(argc, argv, "01", &tag);
01498 }
01499 return rb_catch_obj(tag, catch_i, 0);
01500 }
01501
01502 VALUE
01503 rb_catch(const char *tag, VALUE (*func)(), VALUE data)
01504 {
01505 VALUE vtag = tag ? ID2SYM(rb_intern(tag)) : rb_obj_alloc(rb_cObject);
01506 return rb_catch_obj(vtag, func, data);
01507 }
01508
01509 VALUE
01510 rb_catch_obj(VALUE tag, VALUE (*func)(), VALUE data)
01511 {
01512 int state;
01513 volatile VALUE val = Qnil;
01514 rb_thread_t *th = GET_THREAD();
01515 rb_control_frame_t *saved_cfp = th->cfp;
01516
01517 PUSH_TAG();
01518
01519 th->tag->tag = tag;
01520
01521 if ((state = EXEC_TAG()) == 0) {
01522
01523 val = (*func)(tag, data, 1, &tag, Qnil);
01524 }
01525 else if (state == TAG_THROW && RNODE(th->errinfo)->u1.value == tag) {
01526 th->cfp = saved_cfp;
01527 val = th->tag->retval;
01528 th->errinfo = Qnil;
01529 state = 0;
01530 }
01531 POP_TAG();
01532 if (state)
01533 JUMP_TAG(state);
01534
01535 return val;
01536 }
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568 static VALUE
01569 rb_f_caller(int argc, VALUE *argv)
01570 {
01571 VALUE level;
01572 int lev;
01573
01574 rb_scan_args(argc, argv, "01", &level);
01575
01576 if (NIL_P(level))
01577 lev = 1;
01578 else
01579 lev = NUM2INT(level);
01580 if (lev < 0)
01581 rb_raise(rb_eArgError, "negative level (%d)", lev);
01582
01583 return vm_backtrace(GET_THREAD(), lev);
01584 }
01585
01586 static int
01587 print_backtrace(void *arg, VALUE file, int line, VALUE method)
01588 {
01589 FILE *fp = arg;
01590 const char *filename = NIL_P(file) ? "ruby" : RSTRING_PTR(file);
01591 if (NIL_P(method)) {
01592 fprintf(fp, "\tfrom %s:%d:in unknown method\n",
01593 filename, line);
01594 }
01595 else {
01596 fprintf(fp, "\tfrom %s:%d:in `%s'\n",
01597 filename, line, RSTRING_PTR(method));
01598 }
01599 return FALSE;
01600 }
01601
01602 void
01603 rb_backtrace(void)
01604 {
01605 vm_backtrace_each(GET_THREAD(), -1, NULL, print_backtrace, stderr);
01606 }
01607
01608 VALUE
01609 rb_make_backtrace(void)
01610 {
01611 return vm_backtrace(GET_THREAD(), -1);
01612 }
01613
01614 VALUE
01615 rb_thread_backtrace(VALUE thval)
01616 {
01617 rb_thread_t *th;
01618 GetThreadPtr(thval, th);
01619
01620 switch (th->status) {
01621 case THREAD_RUNNABLE:
01622 case THREAD_STOPPED:
01623 case THREAD_STOPPED_FOREVER:
01624 break;
01625 case THREAD_TO_KILL:
01626 case THREAD_KILLED:
01627 return Qnil;
01628 }
01629
01630 return vm_backtrace(th, 0);
01631 }
01632
01633 int
01634 rb_backtrace_each(rb_backtrace_iter_func *iter, void *arg)
01635 {
01636 return vm_backtrace_each(GET_THREAD(), -1, NULL, iter, arg);
01637 }
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652 static VALUE
01653 rb_f_local_variables(void)
01654 {
01655 VALUE ary = rb_ary_new();
01656 rb_thread_t *th = GET_THREAD();
01657 rb_control_frame_t *cfp =
01658 vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp));
01659 int i;
01660
01661 while (cfp) {
01662 if (cfp->iseq) {
01663 for (i = 0; i < cfp->iseq->local_table_size; i++) {
01664 ID lid = cfp->iseq->local_table[i];
01665 if (lid) {
01666 const char *vname = rb_id2name(lid);
01667
01668 if (vname) {
01669 rb_ary_push(ary, ID2SYM(lid));
01670 }
01671 }
01672 }
01673 }
01674 if (cfp->lfp != cfp->dfp) {
01675
01676 VALUE *dfp = GC_GUARDED_PTR_REF(cfp->dfp[0]);
01677
01678 if (vm_collect_local_variables_in_heap(th, dfp, ary)) {
01679 break;
01680 }
01681 else {
01682 while (cfp->dfp != dfp) {
01683 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
01684 }
01685 }
01686 }
01687 else {
01688 break;
01689 }
01690 }
01691 return ary;
01692 }
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716 VALUE
01717 rb_f_block_given_p(void)
01718 {
01719 rb_thread_t *th = GET_THREAD();
01720 rb_control_frame_t *cfp = th->cfp;
01721 cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
01722
01723 if (cfp != 0 &&
01724 (cfp->lfp[0] & 0x02) == 0 &&
01725 GC_GUARDED_PTR_REF(cfp->lfp[0])) {
01726 return Qtrue;
01727 }
01728 else {
01729 return Qfalse;
01730 }
01731 }
01732
01733 VALUE
01734 rb_current_realfilepath(void)
01735 {
01736 rb_thread_t *th = GET_THREAD();
01737 rb_control_frame_t *cfp = th->cfp;
01738 cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
01739 if (cfp != 0) return cfp->iseq->filepath;
01740 return Qnil;
01741 }
01742
01743 void
01744 Init_vm_eval(void)
01745 {
01746 rb_define_global_function("eval", rb_f_eval, -1);
01747 rb_define_global_function("local_variables", rb_f_local_variables, 0);
01748 rb_define_global_function("iterator?", rb_f_block_given_p, 0);
01749 rb_define_global_function("block_given?", rb_f_block_given_p, 0);
01750
01751 rb_define_global_function("catch", rb_f_catch, -1);
01752 rb_define_global_function("throw", rb_f_throw, -1);
01753
01754 rb_define_global_function("loop", rb_f_loop, 0);
01755
01756 rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval, -1);
01757 rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1);
01758 rb_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
01759
01760 #if 1
01761 rb_add_method(rb_cBasicObject, rb_intern("__send__"),
01762 VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, 0);
01763 rb_add_method(rb_mKernel, rb_intern("send"),
01764 VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, 0);
01765 #else
01766 rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
01767 rb_define_method(rb_mKernel, "send", rb_f_send, -1);
01768 #endif
01769 rb_define_method(rb_mKernel, "public_send", rb_f_public_send, -1);
01770
01771 rb_define_method(rb_cModule, "module_exec", rb_mod_module_exec, -1);
01772 rb_define_method(rb_cModule, "class_exec", rb_mod_module_exec, -1);
01773 rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1);
01774 rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
01775
01776 rb_define_global_function("caller", rb_f_caller, -1);
01777 }
01778
01779