00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "eval_intern.h"
00015 #include "iseq.h"
00016 #include "gc.h"
00017 #include "ruby/vm.h"
00018 #include "ruby/encoding.h"
00019 #include "internal.h"
00020 #include "vm_core.h"
00021 #include "probes_helper.h"
00022
00023 #define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
00024
00025 NORETURN(void rb_raise_jump(VALUE));
00026
00027 NODE *rb_vm_get_cref(const rb_iseq_t *, const VALUE *);
00028
00029 VALUE rb_eLocalJumpError;
00030 VALUE rb_eSysStackError;
00031
00032 #define exception_error GET_VM()->special_exceptions[ruby_error_reenter]
00033
00034 #include "eval_error.c"
00035 #include "eval_jump.c"
00036
00037
00038
00039
00040
00041 int
00042 ruby_setup(void)
00043 {
00044 static int initialized = 0;
00045 int state;
00046
00047 if (initialized)
00048 return 0;
00049 initialized = 1;
00050
00051 ruby_init_stack((void *)&state);
00052 Init_BareVM();
00053 Init_heap();
00054
00055 PUSH_TAG();
00056 if ((state = EXEC_TAG()) == 0) {
00057 rb_call_inits();
00058 ruby_prog_init();
00059 GET_VM()->running = 1;
00060 }
00061 POP_TAG();
00062
00063 return state;
00064 }
00065
00066
00067
00068
00069
00070 void
00071 ruby_init(void)
00072 {
00073 int state = ruby_setup();
00074 if (state) {
00075 error_print();
00076 exit(EXIT_FAILURE);
00077 }
00078 }
00079
00090 void *
00091 ruby_options(int argc, char **argv)
00092 {
00093 int state;
00094 void *volatile iseq = 0;
00095
00096 ruby_init_stack((void *)&iseq);
00097 PUSH_TAG();
00098 if ((state = EXEC_TAG()) == 0) {
00099 SAVE_ROOT_JMPBUF(GET_THREAD(), iseq = ruby_process_options(argc, argv));
00100 }
00101 else {
00102 rb_clear_trace_func();
00103 state = error_handle(state);
00104 iseq = (void *)INT2FIX(state);
00105 }
00106 POP_TAG();
00107 return iseq;
00108 }
00109
00110 static void
00111 ruby_finalize_0(void)
00112 {
00113 PUSH_TAG();
00114 if (EXEC_TAG() == 0) {
00115 rb_trap_exit();
00116 }
00117 POP_TAG();
00118 rb_exec_end_proc();
00119 rb_clear_trace_func();
00120 }
00121
00122 static void
00123 ruby_finalize_1(void)
00124 {
00125 ruby_sig_finalize();
00126 GET_THREAD()->errinfo = Qnil;
00127 rb_gc_call_finalizer_at_exit();
00128 }
00129
00137 void
00138 ruby_finalize(void)
00139 {
00140 ruby_finalize_0();
00141 ruby_finalize_1();
00142 }
00143
00154 int
00155 ruby_cleanup(volatile int ex)
00156 {
00157 int state;
00158 volatile VALUE errs[2];
00159 rb_thread_t *th = GET_THREAD();
00160 int nerr;
00161
00162 rb_threadptr_interrupt(th);
00163 rb_threadptr_check_signal(th);
00164 PUSH_TAG();
00165 if ((state = EXEC_TAG()) == 0) {
00166 SAVE_ROOT_JMPBUF(th, { RUBY_VM_CHECK_INTS(th); });
00167 }
00168 POP_TAG();
00169
00170 errs[1] = th->errinfo;
00171 th->safe_level = 0;
00172 ruby_init_stack(&errs[STACK_UPPER(errs, 0, 1)]);
00173
00174 PUSH_TAG();
00175 if ((state = EXEC_TAG()) == 0) {
00176 SAVE_ROOT_JMPBUF(th, ruby_finalize_0());
00177 }
00178 POP_TAG();
00179
00180
00181 th->status = THREAD_KILLED;
00182
00183 errs[0] = th->errinfo;
00184 PUSH_TAG();
00185 if ((state = EXEC_TAG()) == 0) {
00186 SAVE_ROOT_JMPBUF(th, rb_thread_terminate_all());
00187 }
00188 else if (ex == 0) {
00189 ex = state;
00190 }
00191 th->errinfo = errs[1];
00192 ex = error_handle(ex);
00193 ruby_finalize_1();
00194
00195
00196 rb_threadptr_unlock_all_locking_mutexes(GET_THREAD());
00197 POP_TAG();
00198 rb_thread_stop_timer_thread(1);
00199
00200 #if EXIT_SUCCESS != 0 || EXIT_FAILURE != 1
00201 switch (ex) {
00202 #if EXIT_SUCCESS != 0
00203 case 0: ex = EXIT_SUCCESS; break;
00204 #endif
00205 #if EXIT_FAILURE != 1
00206 case 1: ex = EXIT_FAILURE; break;
00207 #endif
00208 }
00209 #endif
00210
00211 state = 0;
00212 for (nerr = 0; nerr < numberof(errs); ++nerr) {
00213 VALUE err = errs[nerr];
00214
00215 if (!RTEST(err)) continue;
00216
00217
00218 if (RB_TYPE_P(err, T_NODE)) continue;
00219
00220 if (rb_obj_is_kind_of(err, rb_eSystemExit)) {
00221 ex = sysexit_status(err);
00222 break;
00223 }
00224 else if (rb_obj_is_kind_of(err, rb_eSignal)) {
00225 VALUE sig = rb_iv_get(err, "signo");
00226 state = NUM2INT(sig);
00227 break;
00228 }
00229 else if (ex == EXIT_SUCCESS) {
00230 ex = EXIT_FAILURE;
00231 }
00232 }
00233 ruby_vm_destruct(GET_VM());
00234 if (state) ruby_default_signal(state);
00235
00236 return ex;
00237 }
00238
00239 static int
00240 ruby_exec_internal(void *n)
00241 {
00242 volatile int state;
00243 VALUE iseq = (VALUE)n;
00244 rb_thread_t *th = GET_THREAD();
00245
00246 if (!n) return 0;
00247
00248 PUSH_TAG();
00249 if ((state = EXEC_TAG()) == 0) {
00250 SAVE_ROOT_JMPBUF(th, {
00251 th->base_block = 0;
00252 rb_iseq_eval_main(iseq);
00253 });
00254 }
00255 POP_TAG();
00256 return state;
00257 }
00258
00260 void
00261 ruby_stop(int ex)
00262 {
00263 exit(ruby_cleanup(ex));
00264 }
00265
00278 int
00279 ruby_executable_node(void *n, int *status)
00280 {
00281 VALUE v = (VALUE)n;
00282 int s;
00283
00284 switch (v) {
00285 case Qtrue: s = EXIT_SUCCESS; break;
00286 case Qfalse: s = EXIT_FAILURE; break;
00287 default:
00288 if (!FIXNUM_P(v)) return TRUE;
00289 s = FIX2INT(v);
00290 }
00291 if (status) *status = s;
00292 return FALSE;
00293 }
00294
00299 int
00300 ruby_run_node(void *n)
00301 {
00302 int status;
00303 if (!ruby_executable_node(n, &status)) {
00304 ruby_cleanup(0);
00305 return status;
00306 }
00307 return ruby_cleanup(ruby_exec_node(n));
00308 }
00309
00311 int
00312 ruby_exec_node(void *n)
00313 {
00314 ruby_init_stack((void *)&n);
00315 return ruby_exec_internal(n);
00316 }
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333 static VALUE
00334 rb_mod_nesting(void)
00335 {
00336 VALUE ary = rb_ary_new();
00337 const NODE *cref = rb_vm_cref();
00338
00339 while (cref && cref->nd_next) {
00340 VALUE klass = cref->nd_clss;
00341 if (!(cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) &&
00342 !NIL_P(klass)) {
00343 rb_ary_push(ary, klass);
00344 }
00345 cref = cref->nd_next;
00346 }
00347 return ary;
00348 }
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 static VALUE
00373 rb_mod_s_constants(int argc, VALUE *argv, VALUE mod)
00374 {
00375 const NODE *cref = rb_vm_cref();
00376 VALUE klass;
00377 VALUE cbase = 0;
00378 void *data = 0;
00379
00380 if (argc > 0 || mod != rb_cModule) {
00381 return rb_mod_constants(argc, argv, mod);
00382 }
00383
00384 while (cref) {
00385 klass = cref->nd_clss;
00386 if (!(cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) &&
00387 !NIL_P(klass)) {
00388 data = rb_mod_const_at(cref->nd_clss, data);
00389 if (!cbase) {
00390 cbase = klass;
00391 }
00392 }
00393 cref = cref->nd_next;
00394 }
00395
00396 if (cbase) {
00397 data = rb_mod_const_of(cbase, data);
00398 }
00399 return rb_const_list(data);
00400 }
00401
00402 void
00403 rb_frozen_class_p(VALUE klass)
00404 {
00405 const char *desc = "something(?!)";
00406
00407 if (OBJ_FROZEN(klass)) {
00408 if (FL_TEST(klass, FL_SINGLETON))
00409 desc = "object";
00410 else {
00411 switch (TYPE(klass)) {
00412 case T_MODULE:
00413 case T_ICLASS:
00414 desc = "module";
00415 break;
00416 case T_CLASS:
00417 desc = "class";
00418 break;
00419 }
00420 }
00421 rb_error_frozen(desc);
00422 }
00423 }
00424
00425 NORETURN(static void rb_longjmp(int, volatile VALUE));
00426
00427 static void
00428 setup_exception(rb_thread_t *th, int tag, volatile VALUE mesg)
00429 {
00430 VALUE at;
00431 VALUE e;
00432 const char *file;
00433 volatile int line = 0;
00434
00435 if (NIL_P(mesg)) {
00436 mesg = th->errinfo;
00437 if (INTERNAL_EXCEPTION_P(mesg)) JUMP_TAG(TAG_FATAL);
00438 }
00439 if (NIL_P(mesg)) {
00440 mesg = rb_exc_new(rb_eRuntimeError, 0, 0);
00441 }
00442
00443 file = rb_sourcefile();
00444 if (file) line = rb_sourceline();
00445 if (file && !NIL_P(mesg)) {
00446 if (mesg == sysstack_error) {
00447 at = rb_enc_sprintf(rb_usascii_encoding(), "%s:%d", file, line);
00448 at = rb_ary_new3(1, at);
00449 rb_iv_set(mesg, "bt", at);
00450 }
00451 else {
00452 at = get_backtrace(mesg);
00453 if (NIL_P(at)) {
00454 at = rb_vm_backtrace_object();
00455 if (OBJ_FROZEN(mesg)) {
00456 mesg = rb_obj_dup(mesg);
00457 }
00458 set_backtrace(mesg, at);
00459 }
00460 }
00461 }
00462 if (!NIL_P(mesg)) {
00463 th->errinfo = mesg;
00464 }
00465
00466 if (RTEST(ruby_debug) && !NIL_P(e = th->errinfo) &&
00467 !rb_obj_is_kind_of(e, rb_eSystemExit)) {
00468 int status;
00469
00470 mesg = e;
00471 PUSH_TAG();
00472 if ((status = EXEC_TAG()) == 0) {
00473 th->errinfo = Qnil;
00474 e = rb_obj_as_string(mesg);
00475 th->errinfo = mesg;
00476 if (file && line) {
00477 warn_printf("Exception `%"PRIsVALUE"' at %s:%d - %"PRIsVALUE"\n",
00478 rb_obj_class(mesg), file, line, e);
00479 }
00480 else if (file) {
00481 warn_printf("Exception `%"PRIsVALUE"' at %s - %"PRIsVALUE"\n",
00482 rb_obj_class(mesg), file, e);
00483 }
00484 else {
00485 warn_printf("Exception `%"PRIsVALUE"' - %"PRIsVALUE"\n",
00486 rb_obj_class(mesg), e);
00487 }
00488 }
00489 POP_TAG();
00490 if (status == TAG_FATAL && th->errinfo == exception_error) {
00491 th->errinfo = mesg;
00492 }
00493 else if (status) {
00494 rb_threadptr_reset_raised(th);
00495 JUMP_TAG(status);
00496 }
00497 }
00498
00499 if (rb_threadptr_set_raised(th)) {
00500 th->errinfo = exception_error;
00501 rb_threadptr_reset_raised(th);
00502 JUMP_TAG(TAG_FATAL);
00503 }
00504
00505 if (tag != TAG_FATAL) {
00506 if (RUBY_DTRACE_RAISE_ENABLED()) {
00507 RUBY_DTRACE_RAISE(rb_obj_classname(th->errinfo),
00508 rb_sourcefile(),
00509 rb_sourceline());
00510 }
00511 EXEC_EVENT_HOOK(th, RUBY_EVENT_RAISE, th->cfp->self, 0, 0, mesg);
00512 }
00513 }
00514
00515 static void
00516 rb_longjmp(int tag, volatile VALUE mesg)
00517 {
00518 rb_thread_t *th = GET_THREAD();
00519 setup_exception(th, tag, mesg);
00520 rb_thread_raised_clear(th);
00521 JUMP_TAG(tag);
00522 }
00523
00524 static VALUE make_exception(int argc, VALUE *argv, int isstr);
00525
00526 void
00527 rb_exc_raise(VALUE mesg)
00528 {
00529 if (!NIL_P(mesg)) {
00530 mesg = make_exception(1, &mesg, FALSE);
00531 }
00532 rb_longjmp(TAG_RAISE, mesg);
00533 }
00534
00535 void
00536 rb_exc_fatal(VALUE mesg)
00537 {
00538 if (!NIL_P(mesg)) {
00539 mesg = make_exception(1, &mesg, FALSE);
00540 }
00541 rb_longjmp(TAG_FATAL, mesg);
00542 }
00543
00544 void
00545 rb_interrupt(void)
00546 {
00547 rb_raise(rb_eInterrupt, "%s", "");
00548 }
00549
00550 static VALUE get_errinfo(void);
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576 static VALUE
00577 rb_f_raise(int argc, VALUE *argv)
00578 {
00579 VALUE err;
00580 if (argc == 0) {
00581 err = get_errinfo();
00582 if (!NIL_P(err)) {
00583 argc = 1;
00584 argv = &err;
00585 }
00586 }
00587 rb_raise_jump(rb_make_exception(argc, argv));
00588
00589 UNREACHABLE;
00590 }
00591
00592 static VALUE
00593 make_exception(int argc, VALUE *argv, int isstr)
00594 {
00595 VALUE mesg;
00596 ID exception;
00597 int n;
00598
00599 mesg = Qnil;
00600 switch (argc) {
00601 case 0:
00602 break;
00603 case 1:
00604 if (NIL_P(argv[0]))
00605 break;
00606 if (isstr) {
00607 mesg = rb_check_string_type(argv[0]);
00608 if (!NIL_P(mesg)) {
00609 mesg = rb_exc_new3(rb_eRuntimeError, mesg);
00610 break;
00611 }
00612 }
00613 n = 0;
00614 goto exception_call;
00615
00616 case 2:
00617 case 3:
00618 n = 1;
00619 exception_call:
00620 if (argv[0] == sysstack_error) return argv[0];
00621 CONST_ID(exception, "exception");
00622 mesg = rb_check_funcall(argv[0], exception, n, argv+1);
00623 if (mesg == Qundef) {
00624 rb_raise(rb_eTypeError, "exception class/object expected");
00625 }
00626 break;
00627 default:
00628 rb_check_arity(argc, 0, 3);
00629 break;
00630 }
00631 if (argc > 0) {
00632 if (!rb_obj_is_kind_of(mesg, rb_eException))
00633 rb_raise(rb_eTypeError, "exception object expected");
00634 if (argc > 2)
00635 set_backtrace(mesg, argv[2]);
00636 }
00637
00638 return mesg;
00639 }
00640
00641 VALUE
00642 rb_make_exception(int argc, VALUE *argv)
00643 {
00644 return make_exception(argc, argv, TRUE);
00645 }
00646
00647 void
00648 rb_raise_jump(VALUE mesg)
00649 {
00650 rb_thread_t *th = GET_THREAD();
00651 rb_control_frame_t *cfp = th->cfp;
00652 VALUE klass = cfp->me->klass;
00653 VALUE self = cfp->self;
00654 ID mid = cfp->me->called_id;
00655
00656 th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
00657
00658 setup_exception(th, TAG_RAISE, mesg);
00659
00660 EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, self, mid, klass, Qnil);
00661 rb_thread_raised_clear(th);
00662 JUMP_TAG(TAG_RAISE);
00663 }
00664
00665 void
00666 rb_jump_tag(int tag)
00667 {
00668 JUMP_TAG(tag);
00669 }
00670
00671 int
00672 rb_block_given_p(void)
00673 {
00674 rb_thread_t *th = GET_THREAD();
00675
00676 if (rb_vm_control_frame_block_ptr(th->cfp)) {
00677 return TRUE;
00678 }
00679 else {
00680 return FALSE;
00681 }
00682 }
00683
00684 int
00685 rb_iterator_p(void)
00686 {
00687 return rb_block_given_p();
00688 }
00689
00690 VALUE rb_eThreadError;
00691
00692 void
00693 rb_need_block(void)
00694 {
00695 if (!rb_block_given_p()) {
00696 rb_vm_localjump_error("no block given", Qnil, 0);
00697 }
00698 }
00699
00700 VALUE
00701 rb_rescue2(VALUE (* b_proc) (ANYARGS), VALUE data1,
00702 VALUE (* r_proc) (ANYARGS), VALUE data2, ...)
00703 {
00704 int state;
00705 rb_thread_t *th = GET_THREAD();
00706 rb_control_frame_t *cfp = th->cfp;
00707 volatile VALUE result;
00708 volatile VALUE e_info = th->errinfo;
00709 va_list args;
00710
00711 TH_PUSH_TAG(th);
00712 if ((state = TH_EXEC_TAG()) == 0) {
00713 retry_entry:
00714 result = (*b_proc) (data1);
00715 }
00716 else {
00717 rb_vm_rewind_cfp(th, cfp);
00718
00719 if (state == TAG_RAISE) {
00720 int handle = FALSE;
00721 VALUE eclass;
00722
00723 va_init_list(args, data2);
00724 while ((eclass = va_arg(args, VALUE)) != 0) {
00725 if (rb_obj_is_kind_of(th->errinfo, eclass)) {
00726 handle = TRUE;
00727 break;
00728 }
00729 }
00730 va_end(args);
00731
00732 if (handle) {
00733 if (r_proc) {
00734 PUSH_TAG();
00735 if ((state = EXEC_TAG()) == 0) {
00736 result = (*r_proc) (data2, th->errinfo);
00737 }
00738 POP_TAG();
00739 if (state == TAG_RETRY) {
00740 state = 0;
00741 th->errinfo = Qnil;
00742 goto retry_entry;
00743 }
00744 }
00745 else {
00746 result = Qnil;
00747 state = 0;
00748 }
00749 if (state == 0) {
00750 th->errinfo = e_info;
00751 }
00752 }
00753 }
00754 }
00755 TH_POP_TAG();
00756 if (state)
00757 JUMP_TAG(state);
00758
00759 return result;
00760 }
00761
00762 VALUE
00763 rb_rescue(VALUE (* b_proc)(ANYARGS), VALUE data1,
00764 VALUE (* r_proc)(ANYARGS), VALUE data2)
00765 {
00766 return rb_rescue2(b_proc, data1, r_proc, data2, rb_eStandardError,
00767 (VALUE)0);
00768 }
00769
00770 VALUE
00771 rb_protect(VALUE (* proc) (VALUE), VALUE data, int * state)
00772 {
00773 volatile VALUE result = Qnil;
00774 int status;
00775 rb_thread_t *th = GET_THREAD();
00776 rb_control_frame_t *cfp = th->cfp;
00777 struct rb_vm_protect_tag protect_tag;
00778 rb_jmpbuf_t org_jmpbuf;
00779
00780 protect_tag.prev = th->protect_tag;
00781
00782 TH_PUSH_TAG(th);
00783 th->protect_tag = &protect_tag;
00784 MEMCPY(&org_jmpbuf, &(th)->root_jmpbuf, rb_jmpbuf_t, 1);
00785 if ((status = TH_EXEC_TAG()) == 0) {
00786 SAVE_ROOT_JMPBUF(th, result = (*proc) (data));
00787 }
00788 MEMCPY(&(th)->root_jmpbuf, &org_jmpbuf, rb_jmpbuf_t, 1);
00789 th->protect_tag = protect_tag.prev;
00790 TH_POP_TAG();
00791
00792 if (state) {
00793 *state = status;
00794 }
00795 if (status != 0) {
00796 rb_vm_rewind_cfp(th, cfp);
00797 return Qnil;
00798 }
00799
00800 return result;
00801 }
00802
00803 VALUE
00804 rb_ensure(VALUE (*b_proc)(ANYARGS), VALUE data1, VALUE (*e_proc)(ANYARGS), VALUE data2)
00805 {
00806 int state;
00807 volatile VALUE result = Qnil;
00808 volatile VALUE errinfo;
00809 rb_thread_t *const th = GET_THREAD();
00810
00811 PUSH_TAG();
00812 if ((state = EXEC_TAG()) == 0) {
00813 result = (*b_proc) (data1);
00814 }
00815 POP_TAG();
00816
00817
00818 errinfo = th->errinfo;
00819 (*e_proc) (data2);
00820 th->errinfo = errinfo;
00821 if (state)
00822 JUMP_TAG(state);
00823 return result;
00824 }
00825
00826 static const rb_method_entry_t *
00827 method_entry_of_iseq(rb_control_frame_t *cfp, rb_iseq_t *iseq)
00828 {
00829 rb_thread_t *th = GET_THREAD();
00830 rb_control_frame_t *cfp_limit;
00831
00832 cfp_limit = (rb_control_frame_t *)(th->stack + th->stack_size);
00833 while (cfp_limit > cfp) {
00834 if (cfp->iseq == iseq)
00835 return cfp->me;
00836 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
00837 }
00838 return 0;
00839 }
00840
00841 static ID
00842 frame_func_id(rb_control_frame_t *cfp)
00843 {
00844 const rb_method_entry_t *me_local;
00845 rb_iseq_t *iseq = cfp->iseq;
00846 if (cfp->me) {
00847 return cfp->me->def->original_id;
00848 }
00849 while (iseq) {
00850 if (RUBY_VM_IFUNC_P(iseq)) {
00851 NODE *ifunc = (NODE *)iseq;
00852 if (ifunc->nd_aid) return ifunc->nd_aid;
00853 return rb_intern("<ifunc>");
00854 }
00855 me_local = method_entry_of_iseq(cfp, iseq);
00856 if (me_local) {
00857 cfp->me = me_local;
00858 return me_local->def->original_id;
00859 }
00860 if (iseq->defined_method_id) {
00861 return iseq->defined_method_id;
00862 }
00863 if (iseq->local_iseq == iseq) {
00864 break;
00865 }
00866 iseq = iseq->parent_iseq;
00867 }
00868 return 0;
00869 }
00870
00871 static ID
00872 frame_called_id(rb_control_frame_t *cfp)
00873 {
00874 const rb_method_entry_t *me_local;
00875 rb_iseq_t *iseq = cfp->iseq;
00876 if (cfp->me) {
00877 return cfp->me->called_id;
00878 }
00879 while (iseq) {
00880 if (RUBY_VM_IFUNC_P(iseq)) {
00881 NODE *ifunc = (NODE *)iseq;
00882 if (ifunc->nd_aid) return ifunc->nd_aid;
00883 return rb_intern("<ifunc>");
00884 }
00885 me_local = method_entry_of_iseq(cfp, iseq);
00886 if (me_local) {
00887 cfp->me = me_local;
00888 return me_local->called_id;
00889 }
00890 if (iseq->defined_method_id) {
00891 return iseq->defined_method_id;
00892 }
00893 if (iseq->local_iseq == iseq) {
00894 break;
00895 }
00896 iseq = iseq->parent_iseq;
00897 }
00898 return 0;
00899 }
00900
00901 ID
00902 rb_frame_this_func(void)
00903 {
00904 return frame_func_id(GET_THREAD()->cfp);
00905 }
00906
00907 static rb_control_frame_t *
00908 previous_frame(rb_thread_t *th)
00909 {
00910 rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
00911
00912 if ((void *)(th->stack + th->stack_size) == (void *)(prev_cfp)) {
00913 return 0;
00914 }
00915 return prev_cfp;
00916 }
00917
00918 ID
00919 rb_frame_callee(void)
00920 {
00921 rb_control_frame_t *prev_cfp = previous_frame(GET_THREAD());
00922 if (!prev_cfp) return 0;
00923 return frame_called_id(prev_cfp);
00924 }
00925
00926 static ID
00927 rb_frame_caller(void)
00928 {
00929 rb_control_frame_t *prev_cfp = previous_frame(GET_THREAD());
00930 if (!prev_cfp) return 0;
00931 return frame_func_id(prev_cfp);
00932 }
00933
00934 ID
00935 rb_frame_last_func(void)
00936 {
00937 rb_thread_t *th = GET_THREAD();
00938 rb_control_frame_t *cfp = th->cfp;
00939 ID mid;
00940
00941 while (!(mid = frame_func_id(cfp)) &&
00942 (cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp),
00943 !RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)));
00944 return mid;
00945 }
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959 static VALUE
00960 rb_mod_append_features(VALUE module, VALUE include)
00961 {
00962 switch (TYPE(include)) {
00963 case T_CLASS:
00964 case T_MODULE:
00965 break;
00966 default:
00967 Check_Type(include, T_CLASS);
00968 break;
00969 }
00970 rb_include_module(include, module);
00971
00972 return module;
00973 }
00974
00975
00976
00977
00978
00979
00980
00981
00982 static VALUE
00983 rb_mod_include(int argc, VALUE *argv, VALUE module)
00984 {
00985 int i;
00986 ID id_append_features, id_included;
00987
00988 CONST_ID(id_append_features, "append_features");
00989 CONST_ID(id_included, "included");
00990
00991 for (i = 0; i < argc; i++)
00992 Check_Type(argv[i], T_MODULE);
00993 while (argc--) {
00994 rb_funcall(argv[argc], id_append_features, 1, module);
00995 rb_funcall(argv[argc], id_included, 1, module);
00996 }
00997 return module;
00998 }
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012 static VALUE
01013 rb_mod_prepend_features(VALUE module, VALUE prepend)
01014 {
01015 switch (TYPE(prepend)) {
01016 case T_CLASS:
01017 case T_MODULE:
01018 break;
01019 default:
01020 Check_Type(prepend, T_CLASS);
01021 break;
01022 }
01023 rb_prepend_module(prepend, module);
01024
01025 return module;
01026 }
01027
01028
01029
01030
01031
01032
01033
01034
01035 static VALUE
01036 rb_mod_prepend(int argc, VALUE *argv, VALUE module)
01037 {
01038 int i;
01039 ID id_prepend_features, id_prepended;
01040
01041 CONST_ID(id_prepend_features, "prepend_features");
01042 CONST_ID(id_prepended, "prepended");
01043 for (i = 0; i < argc; i++)
01044 Check_Type(argv[i], T_MODULE);
01045 while (argc--) {
01046 rb_funcall(argv[argc], id_prepend_features, 1, module);
01047 rb_funcall(argv[argc], id_prepended, 1, module);
01048 }
01049 return module;
01050 }
01051
01052 static void
01053 warn_refinements_once()
01054 {
01055 static int warned = 0;
01056
01057 if (warned)
01058 return;
01059 rb_warn("Refinements are experimental, and the behavior may change in future versions of Ruby!");
01060 warned = 1;
01061 }
01062
01063 static VALUE
01064 hidden_identity_hash_new()
01065 {
01066 VALUE hash = rb_hash_new();
01067
01068 rb_funcall(hash, rb_intern("compare_by_identity"), 0);
01069 RBASIC(hash)->klass = 0;
01070 return hash;
01071 }
01072
01073 void
01074 rb_using_refinement(NODE *cref, VALUE klass, VALUE module)
01075 {
01076 VALUE iclass, c, superclass = klass;
01077
01078 Check_Type(klass, T_CLASS);
01079 Check_Type(module, T_MODULE);
01080 if (NIL_P(cref->nd_refinements)) {
01081 cref->nd_refinements = hidden_identity_hash_new();
01082 }
01083 else {
01084 if (cref->flags & NODE_FL_CREF_OMOD_SHARED) {
01085 cref->nd_refinements = rb_hash_dup(cref->nd_refinements);
01086 cref->flags &= ~NODE_FL_CREF_OMOD_SHARED;
01087 }
01088 if (!NIL_P(c = rb_hash_lookup(cref->nd_refinements, klass))) {
01089 superclass = c;
01090 while (c && RB_TYPE_P(c, T_ICLASS)) {
01091 if (RBASIC(c)->klass == module) {
01092
01093 return;
01094 }
01095 c = RCLASS_SUPER(c);
01096 }
01097 }
01098 }
01099 FL_SET(module, RMODULE_IS_OVERLAID);
01100 c = iclass = rb_include_class_new(module, superclass);
01101 RCLASS_REFINED_CLASS(c) = klass;
01102 RCLASS_M_TBL(c) = RCLASS_M_TBL(module);
01103 module = RCLASS_SUPER(module);
01104 while (module && module != klass) {
01105 FL_SET(module, RMODULE_IS_OVERLAID);
01106 c = RCLASS_SUPER(c) = rb_include_class_new(module, RCLASS_SUPER(c));
01107 RCLASS_REFINED_CLASS(c) = klass;
01108 module = RCLASS_SUPER(module);
01109 }
01110 rb_hash_aset(cref->nd_refinements, klass, iclass);
01111 }
01112
01113 static int
01114 using_refinement(VALUE klass, VALUE module, VALUE arg)
01115 {
01116 NODE *cref = (NODE *) arg;
01117
01118 rb_using_refinement(cref, klass, module);
01119 return ST_CONTINUE;
01120 }
01121
01122 void
01123 rb_using_module(NODE *cref, VALUE module)
01124 {
01125 ID id_refinements;
01126 VALUE refinements;
01127
01128 Check_Type(module, T_MODULE);
01129 CONST_ID(id_refinements, "__refinements__");
01130 refinements = rb_attr_get(module, id_refinements);
01131 if (NIL_P(refinements)) return;
01132 rb_hash_foreach(refinements, using_refinement, (VALUE) cref);
01133 }
01134
01135 VALUE rb_refinement_module_get_refined_class(VALUE module)
01136 {
01137 ID id_refined_class;
01138
01139 CONST_ID(id_refined_class, "__refined_class__");
01140 return rb_attr_get(module, id_refined_class);
01141 }
01142
01143 static void
01144 add_activated_refinement(VALUE activated_refinements,
01145 VALUE klass, VALUE refinement)
01146 {
01147 VALUE iclass, c, superclass = klass;
01148
01149 if (!NIL_P(c = rb_hash_lookup(activated_refinements, klass))) {
01150 superclass = c;
01151 while (c && RB_TYPE_P(c, T_ICLASS)) {
01152 if (RBASIC(c)->klass == refinement) {
01153
01154 return;
01155 }
01156 c = RCLASS_SUPER(c);
01157 }
01158 }
01159 FL_SET(refinement, RMODULE_IS_OVERLAID);
01160 c = iclass = rb_include_class_new(refinement, superclass);
01161 RCLASS_REFINED_CLASS(c) = klass;
01162 refinement = RCLASS_SUPER(refinement);
01163 while (refinement) {
01164 FL_SET(refinement, RMODULE_IS_OVERLAID);
01165 c = RCLASS_SUPER(c) =
01166 rb_include_class_new(refinement, RCLASS_SUPER(c));
01167 RCLASS_REFINED_CLASS(c) = klass;
01168 refinement = RCLASS_SUPER(refinement);
01169 }
01170 rb_hash_aset(activated_refinements, klass, iclass);
01171 }
01172
01173 VALUE rb_yield_refine_block(VALUE refinement, VALUE refinements);
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184 static VALUE
01185 rb_mod_refine(VALUE module, VALUE klass)
01186 {
01187 VALUE refinement;
01188 ID id_refinements, id_activated_refinements,
01189 id_refined_class, id_defined_at;
01190 VALUE refinements, activated_refinements;
01191 rb_thread_t *th = GET_THREAD();
01192 rb_block_t *block = rb_vm_control_frame_block_ptr(th->cfp);
01193
01194 warn_refinements_once();
01195 if (!block) {
01196 rb_raise(rb_eArgError, "no block given");
01197 }
01198 if (block->proc) {
01199 rb_raise(rb_eArgError,
01200 "can't pass a Proc as a block to Module#refine");
01201 }
01202 Check_Type(klass, T_CLASS);
01203 CONST_ID(id_refinements, "__refinements__");
01204 refinements = rb_attr_get(module, id_refinements);
01205 if (NIL_P(refinements)) {
01206 refinements = hidden_identity_hash_new();
01207 rb_ivar_set(module, id_refinements, refinements);
01208 }
01209 CONST_ID(id_activated_refinements, "__activated_refinements__");
01210 activated_refinements = rb_attr_get(module, id_activated_refinements);
01211 if (NIL_P(activated_refinements)) {
01212 activated_refinements = hidden_identity_hash_new();
01213 rb_ivar_set(module, id_activated_refinements,
01214 activated_refinements);
01215 }
01216 refinement = rb_hash_lookup(refinements, klass);
01217 if (NIL_P(refinement)) {
01218 refinement = rb_module_new();
01219 RCLASS_SUPER(refinement) = klass;
01220 FL_SET(refinement, RMODULE_IS_REFINEMENT);
01221 CONST_ID(id_refined_class, "__refined_class__");
01222 rb_ivar_set(refinement, id_refined_class, klass);
01223 CONST_ID(id_defined_at, "__defined_at__");
01224 rb_ivar_set(refinement, id_defined_at, module);
01225 rb_hash_aset(refinements, klass, refinement);
01226 add_activated_refinement(activated_refinements, klass, refinement);
01227 }
01228 rb_yield_refine_block(refinement, activated_refinements);
01229 return refinement;
01230 }
01231
01232 void
01233 rb_obj_call_init(VALUE obj, int argc, VALUE *argv)
01234 {
01235 PASS_PASSED_BLOCK();
01236 rb_funcall2(obj, idInitialize, argc, argv);
01237 }
01238
01239 void
01240 rb_extend_object(VALUE obj, VALUE module)
01241 {
01242 rb_include_module(rb_singleton_class(obj), module);
01243 }
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272 static VALUE
01273 rb_mod_extend_object(VALUE mod, VALUE obj)
01274 {
01275 rb_extend_object(obj, mod);
01276 return obj;
01277 }
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304 static VALUE
01305 rb_obj_extend(int argc, VALUE *argv, VALUE obj)
01306 {
01307 int i;
01308 ID id_extend_object, id_extended;
01309
01310 CONST_ID(id_extend_object, "extend_object");
01311 CONST_ID(id_extended, "extended");
01312
01313 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
01314 for (i = 0; i < argc; i++)
01315 Check_Type(argv[i], T_MODULE);
01316 while (argc--) {
01317 rb_funcall(argv[argc], id_extend_object, 1, obj);
01318 rb_funcall(argv[argc], id_extended, 1, obj);
01319 }
01320 return obj;
01321 }
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332 static VALUE
01333 top_include(int argc, VALUE *argv, VALUE self)
01334 {
01335 rb_thread_t *th = GET_THREAD();
01336
01337 rb_secure(4);
01338 if (th->top_wrapper) {
01339 rb_warning("main.include in the wrapped load is effective only in wrapper module");
01340 return rb_mod_include(argc, argv, th->top_wrapper);
01341 }
01342 return rb_mod_include(argc, argv, rb_cObject);
01343 }
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353 static VALUE
01354 top_using(VALUE self, VALUE module)
01355 {
01356 NODE *cref = rb_vm_cref();
01357 rb_control_frame_t *prev_cfp = previous_frame(GET_THREAD());
01358
01359 warn_refinements_once();
01360 if (cref->nd_next || (prev_cfp && prev_cfp->me)) {
01361 rb_raise(rb_eRuntimeError, "using is permitted only at toplevel");
01362 }
01363 Check_Type(module, T_MODULE);
01364 rb_using_module(cref, module);
01365 rb_clear_cache();
01366 return self;
01367 }
01368
01369 static VALUE *
01370 errinfo_place(rb_thread_t *th)
01371 {
01372 rb_control_frame_t *cfp = th->cfp;
01373 rb_control_frame_t *end_cfp = RUBY_VM_END_CONTROL_FRAME(th);
01374
01375 while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, end_cfp)) {
01376 if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
01377 if (cfp->iseq->type == ISEQ_TYPE_RESCUE) {
01378 return &cfp->ep[-2];
01379 }
01380 else if (cfp->iseq->type == ISEQ_TYPE_ENSURE &&
01381 !RB_TYPE_P(cfp->ep[-2], T_NODE) &&
01382 !FIXNUM_P(cfp->ep[-2])) {
01383 return &cfp->ep[-2];
01384 }
01385 }
01386 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
01387 }
01388 return 0;
01389 }
01390
01391 static VALUE
01392 get_thread_errinfo(rb_thread_t *th)
01393 {
01394 VALUE *ptr = errinfo_place(th);
01395 if (ptr) {
01396 return *ptr;
01397 }
01398 else {
01399 return th->errinfo;
01400 }
01401 }
01402
01403 static VALUE
01404 get_errinfo(void)
01405 {
01406 return get_thread_errinfo(GET_THREAD());
01407 }
01408
01409 static VALUE
01410 errinfo_getter(ID id)
01411 {
01412 return get_errinfo();
01413 }
01414
01415 #if 0
01416 static void
01417 errinfo_setter(VALUE val, ID id, VALUE *var)
01418 {
01419 if (!NIL_P(val) && !rb_obj_is_kind_of(val, rb_eException)) {
01420 rb_raise(rb_eTypeError, "assigning non-exception to $!");
01421 }
01422 else {
01423 VALUE *ptr = errinfo_place(GET_THREAD());
01424 if (ptr) {
01425 *ptr = val;
01426 }
01427 else {
01428 rb_raise(rb_eRuntimeError, "errinfo_setter: not in rescue clause.");
01429 }
01430 }
01431 }
01432 #endif
01433
01434 VALUE
01435 rb_errinfo(void)
01436 {
01437 rb_thread_t *th = GET_THREAD();
01438 return th->errinfo;
01439 }
01440
01441 void
01442 rb_set_errinfo(VALUE err)
01443 {
01444 if (!NIL_P(err) && !rb_obj_is_kind_of(err, rb_eException)) {
01445 rb_raise(rb_eTypeError, "assigning non-exception to $!");
01446 }
01447 GET_THREAD()->errinfo = err;
01448 }
01449
01450 VALUE
01451 rb_rubylevel_errinfo(void)
01452 {
01453 return get_errinfo();
01454 }
01455
01456 static VALUE
01457 errat_getter(ID id)
01458 {
01459 VALUE err = get_errinfo();
01460 if (!NIL_P(err)) {
01461 return get_backtrace(err);
01462 }
01463 else {
01464 return Qnil;
01465 }
01466 }
01467
01468 static void
01469 errat_setter(VALUE val, ID id, VALUE *var)
01470 {
01471 VALUE err = get_errinfo();
01472 if (NIL_P(err)) {
01473 rb_raise(rb_eArgError, "$! not set");
01474 }
01475 set_backtrace(err, val);
01476 }
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488 static VALUE
01489 rb_f_method_name(void)
01490 {
01491 ID fname = rb_frame_caller();
01492
01493 if (fname) {
01494 return ID2SYM(fname);
01495 }
01496 else {
01497 return Qnil;
01498 }
01499 }
01500
01501 static VALUE
01502 rb_f_callee_name(void)
01503 {
01504 ID fname = rb_frame_callee();
01505
01506 if (fname) {
01507 return ID2SYM(fname);
01508 }
01509 else {
01510 return Qnil;
01511 }
01512 }
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524 static VALUE
01525 f_current_dirname(void)
01526 {
01527 VALUE base = rb_current_realfilepath();
01528 if (NIL_P(base)) {
01529 return Qnil;
01530 }
01531 base = rb_file_dirname(base);
01532 return base;
01533 }
01534
01535 void
01536 Init_eval(void)
01537 {
01538 rb_define_virtual_variable("$@", errat_getter, errat_setter);
01539 rb_define_virtual_variable("$!", errinfo_getter, 0);
01540
01541 rb_define_global_function("raise", rb_f_raise, -1);
01542 rb_define_global_function("fail", rb_f_raise, -1);
01543
01544 rb_define_global_function("global_variables", rb_f_global_variables, 0);
01545
01546 rb_define_global_function("__method__", rb_f_method_name, 0);
01547 rb_define_global_function("__callee__", rb_f_callee_name, 0);
01548 rb_define_global_function("__dir__", f_current_dirname, 0);
01549
01550 rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1);
01551 rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1);
01552 rb_define_private_method(rb_cModule, "include", rb_mod_include, -1);
01553 rb_define_private_method(rb_cModule, "prepend_features", rb_mod_prepend_features, 1);
01554 rb_define_private_method(rb_cModule, "prepend", rb_mod_prepend, -1);
01555 rb_define_private_method(rb_cModule, "refine", rb_mod_refine, 1);
01556 rb_undef_method(rb_cClass, "refine");
01557
01558 rb_undef_method(rb_cClass, "module_function");
01559
01560 Init_vm_eval();
01561 Init_eval_method();
01562
01563 rb_define_singleton_method(rb_cModule, "nesting", rb_mod_nesting, 0);
01564 rb_define_singleton_method(rb_cModule, "constants", rb_mod_s_constants, -1);
01565
01566 rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
01567 "include", top_include, -1);
01568 rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
01569 "using", top_using, 1);
01570
01571 rb_define_method(rb_mKernel, "extend", rb_obj_extend, -1);
01572
01573 rb_define_global_function("trace_var", rb_f_trace_var, -1);
01574 rb_define_global_function("untrace_var", rb_f_untrace_var, -1);
01575
01576 exception_error = rb_exc_new3(rb_eFatal,
01577 rb_obj_freeze(rb_str_new2("exception reentered")));
01578 OBJ_TAINT(exception_error);
01579 OBJ_FREEZE(exception_error);
01580 }
01581