eval.c

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

Generated on 19 Jul 2016 for Ruby by  doxygen 1.4.7