Ruby 1.9.3p327(2012-11-10revision37606)
eval.c
Go to the documentation of this file.
00001 /**********************************************************************
00002 
00003   eval.c -
00004 
00005   $Author: marcandre $
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 
00022 #define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
00023 
00024 NORETURN(void rb_raise_jump(VALUE));
00025 
00026 VALUE rb_eLocalJumpError;
00027 VALUE rb_eSysStackError;
00028 
00029 #define exception_error GET_VM()->special_exceptions[ruby_error_reenter]
00030 
00031 #include "eval_error.c"
00032 #include "eval_jump.c"
00033 
00034 /* initialize ruby */
00035 
00036 void
00037 ruby_init(void)
00038 {
00039     static int initialized = 0;
00040     int state;
00041 
00042     if (initialized)
00043         return;
00044     initialized = 1;
00045 
00046     ruby_init_stack((void *)&state);
00047     Init_BareVM();
00048     Init_heap();
00049 
00050     PUSH_TAG();
00051     if ((state = EXEC_TAG()) == 0) {
00052         rb_call_inits();
00053         ruby_prog_init();
00054     }
00055     POP_TAG();
00056 
00057     if (state) {
00058         error_print();
00059         exit(EXIT_FAILURE);
00060     }
00061     GET_VM()->running = 1;
00062 }
00063 
00064 void *
00065 ruby_options(int argc, char **argv)
00066 {
00067     int state;
00068     void *volatile iseq = 0;
00069 
00070     ruby_init_stack((void *)&iseq);
00071     PUSH_TAG();
00072     if ((state = EXEC_TAG()) == 0) {
00073         SAVE_ROOT_JMPBUF(GET_THREAD(), iseq = ruby_process_options(argc, argv));
00074     }
00075     else {
00076         rb_clear_trace_func();
00077         state = error_handle(state);
00078         iseq = (void *)INT2FIX(state);
00079     }
00080     POP_TAG();
00081     return iseq;
00082 }
00083 
00084 static void
00085 ruby_finalize_0(void)
00086 {
00087     PUSH_TAG();
00088     if (EXEC_TAG() == 0) {
00089         rb_trap_exit();
00090     }
00091     POP_TAG();
00092     rb_exec_end_proc();
00093     rb_clear_trace_func();
00094 }
00095 
00096 static void
00097 ruby_finalize_1(void)
00098 {
00099     ruby_sig_finalize();
00100     GET_THREAD()->errinfo = Qnil;
00101     rb_gc_call_finalizer_at_exit();
00102 }
00103 
00104 void
00105 ruby_finalize(void)
00106 {
00107     ruby_finalize_0();
00108     ruby_finalize_1();
00109 }
00110 
00111 int
00112 ruby_cleanup(volatile int ex)
00113 {
00114     int state;
00115     volatile VALUE errs[2];
00116     rb_thread_t *th = GET_THREAD();
00117     int nerr;
00118 
00119     rb_threadptr_interrupt(th);
00120     rb_threadptr_check_signal(th);
00121     PUSH_TAG();
00122     if ((state = EXEC_TAG()) == 0) {
00123         SAVE_ROOT_JMPBUF(th, { RUBY_VM_CHECK_INTS(); });
00124     }
00125     POP_TAG();
00126 
00127     errs[1] = th->errinfo;
00128     th->safe_level = 0;
00129     ruby_init_stack(&errs[STACK_UPPER(errs, 0, 1)]);
00130 
00131     PUSH_TAG();
00132     if ((state = EXEC_TAG()) == 0) {
00133         SAVE_ROOT_JMPBUF(th, ruby_finalize_0());
00134     }
00135     POP_TAG();
00136 
00137     errs[0] = th->errinfo;
00138     PUSH_TAG();
00139     if ((state = EXEC_TAG()) == 0) {
00140         SAVE_ROOT_JMPBUF(th, rb_thread_terminate_all());
00141     }
00142     else if (ex == 0) {
00143         ex = state;
00144     }
00145     th->errinfo = errs[1];
00146     ex = error_handle(ex);
00147     ruby_finalize_1();
00148 
00149     /* unlock again if finalizer took mutexes. */
00150     rb_threadptr_unlock_all_locking_mutexes(GET_THREAD());
00151     POP_TAG();
00152     rb_thread_stop_timer_thread(1);
00153 
00154 #if EXIT_SUCCESS != 0 || EXIT_FAILURE != 1
00155     switch (ex) {
00156 #if EXIT_SUCCESS != 0
00157       case 0: ex = EXIT_SUCCESS; break;
00158 #endif
00159 #if EXIT_FAILURE != 1
00160       case 1: ex = EXIT_FAILURE; break;
00161 #endif
00162     }
00163 #endif
00164 
00165     state = 0;
00166     for (nerr = 0; nerr < numberof(errs); ++nerr) {
00167         VALUE err = errs[nerr];
00168 
00169         if (!RTEST(err)) continue;
00170 
00171         /* th->errinfo contains a NODE while break'ing */
00172         if (TYPE(err) == T_NODE) continue;
00173 
00174         if (rb_obj_is_kind_of(err, rb_eSystemExit)) {
00175             ex = sysexit_status(err);
00176             break;
00177         }
00178         else if (rb_obj_is_kind_of(err, rb_eSignal)) {
00179             VALUE sig = rb_iv_get(err, "signo");
00180             state = NUM2INT(sig);
00181             break;
00182         }
00183         else if (ex == EXIT_SUCCESS) {
00184             ex = EXIT_FAILURE;
00185         }
00186     }
00187     ruby_vm_destruct(GET_VM());
00188     if (state) ruby_default_signal(state);
00189 
00190     return ex;
00191 }
00192 
00193 static int
00194 ruby_exec_internal(void *n)
00195 {
00196     volatile int state;
00197     VALUE iseq = (VALUE)n;
00198     rb_thread_t *th = GET_THREAD();
00199 
00200     if (!n) return 0;
00201 
00202     PUSH_TAG();
00203     if ((state = EXEC_TAG()) == 0) {
00204         SAVE_ROOT_JMPBUF(th, {
00205             th->base_block = 0;
00206             rb_iseq_eval_main(iseq);
00207         });
00208     }
00209     POP_TAG();
00210     return state;
00211 }
00212 
00213 void
00214 ruby_stop(int ex)
00215 {
00216     exit(ruby_cleanup(ex));
00217 }
00218 
00219 int
00220 ruby_executable_node(void *n, int *status)
00221 {
00222     VALUE v = (VALUE)n;
00223     int s;
00224 
00225     switch (v) {
00226       case Qtrue:  s = EXIT_SUCCESS; break;
00227       case Qfalse: s = EXIT_FAILURE; break;
00228       default:
00229         if (!FIXNUM_P(v)) return TRUE;
00230         s = FIX2INT(v);
00231     }
00232     if (status) *status = s;
00233     return FALSE;
00234 }
00235 
00236 int
00237 ruby_run_node(void *n)
00238 {
00239     int status;
00240     if (!ruby_executable_node(n, &status)) {
00241         ruby_cleanup(0);
00242         return status;
00243     }
00244     return ruby_cleanup(ruby_exec_node(n));
00245 }
00246 
00247 int
00248 ruby_exec_node(void *n)
00249 {
00250     ruby_init_stack((void *)&n);
00251     return ruby_exec_internal(n);
00252 }
00253 
00254 /*
00255  *  call-seq:
00256  *     Module.nesting    -> array
00257  *
00258  *  Returns the list of +Modules+ nested at the point of call.
00259  *
00260  *     module M1
00261  *       module M2
00262  *         $a = Module.nesting
00263  *       end
00264  *     end
00265  *     $a           #=> [M1::M2, M1]
00266  *     $a[0].name   #=> "M1::M2"
00267  */
00268 
00269 static VALUE
00270 rb_mod_nesting(void)
00271 {
00272     VALUE ary = rb_ary_new();
00273     const NODE *cref = rb_vm_cref();
00274 
00275     while (cref && cref->nd_next) {
00276         VALUE klass = cref->nd_clss;
00277         if (!(cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) &&
00278             !NIL_P(klass)) {
00279             rb_ary_push(ary, klass);
00280         }
00281         cref = cref->nd_next;
00282     }
00283     return ary;
00284 }
00285 
00286 /*
00287  *  call-seq:
00288  *     Module.constants   -> array
00289  *     Module.constants(inherited)   -> array
00290  *
00291  *  In the first form, returns an array of the names of all
00292  *  constants accessible from the point of call.
00293  *  This list includes the names of all modules and classes
00294  *  defined in the global scope.
00295  *
00296  *     Module.constants.first(4)
00297  *        # => [:ARGF, :ARGV, :ArgumentError, :Array]
00298  *
00299  *     Module.constants.include?(:SEEK_SET)   # => false
00300  *
00301  *     class IO
00302  *       Module.constants.include?(:SEEK_SET) # => true
00303  *     end
00304  *
00305  *  The second form calls the instance method +constants+.
00306  */
00307 
00308 static VALUE
00309 rb_mod_s_constants(int argc, VALUE *argv, VALUE mod)
00310 {
00311     const NODE *cref = rb_vm_cref();
00312     VALUE klass;
00313     VALUE cbase = 0;
00314     void *data = 0;
00315 
00316     if (argc > 0) {
00317         return rb_mod_constants(argc, argv, rb_cModule);
00318     }
00319 
00320     while (cref) {
00321         klass = cref->nd_clss;
00322         if (!(cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) &&
00323             !NIL_P(klass)) {
00324             data = rb_mod_const_at(cref->nd_clss, data);
00325             if (!cbase) {
00326                 cbase = klass;
00327             }
00328         }
00329         cref = cref->nd_next;
00330     }
00331 
00332     if (cbase) {
00333         data = rb_mod_const_of(cbase, data);
00334     }
00335     return rb_const_list(data);
00336 }
00337 
00338 void
00339 rb_frozen_class_p(VALUE klass)
00340 {
00341     const char *desc = "something(?!)";
00342 
00343     if (OBJ_FROZEN(klass)) {
00344         if (FL_TEST(klass, FL_SINGLETON))
00345             desc = "object";
00346         else {
00347             switch (TYPE(klass)) {
00348               case T_MODULE:
00349               case T_ICLASS:
00350                 desc = "module";
00351                 break;
00352               case T_CLASS:
00353                 desc = "class";
00354                 break;
00355             }
00356         }
00357         rb_error_frozen(desc);
00358     }
00359 }
00360 
00361 NORETURN(static void rb_longjmp(int, volatile VALUE));
00362 
00363 static void
00364 setup_exception(rb_thread_t *th, int tag, volatile VALUE mesg)
00365 {
00366     VALUE at;
00367     VALUE e;
00368     const char *file;
00369     volatile int line = 0;
00370 
00371     if (NIL_P(mesg)) {
00372         mesg = th->errinfo;
00373         if (INTERNAL_EXCEPTION_P(mesg)) JUMP_TAG(TAG_FATAL);
00374     }
00375     if (NIL_P(mesg)) {
00376         mesg = rb_exc_new(rb_eRuntimeError, 0, 0);
00377     }
00378 
00379     file = rb_sourcefile();
00380     if (file) line = rb_sourceline();
00381     if (file && !NIL_P(mesg)) {
00382         if (mesg == sysstack_error) {
00383             at = rb_enc_sprintf(rb_usascii_encoding(), "%s:%d", file, line);
00384             at = rb_ary_new3(1, at);
00385             rb_iv_set(mesg, "bt", at);
00386         }
00387         else {
00388             at = get_backtrace(mesg);
00389             if (NIL_P(at)) {
00390                 at = rb_make_backtrace();
00391                 if (OBJ_FROZEN(mesg)) {
00392                     mesg = rb_obj_dup(mesg);
00393                 }
00394                 set_backtrace(mesg, at);
00395             }
00396         }
00397     }
00398     if (!NIL_P(mesg)) {
00399         th->errinfo = mesg;
00400     }
00401 
00402     if (RTEST(ruby_debug) && !NIL_P(e = th->errinfo) &&
00403         !rb_obj_is_kind_of(e, rb_eSystemExit)) {
00404         int status;
00405 
00406         PUSH_TAG();
00407         if ((status = EXEC_TAG()) == 0) {
00408             RB_GC_GUARD(e) = rb_obj_as_string(e);
00409             if (file && line) {
00410                 warn_printf("Exception `%s' at %s:%d - %s\n",
00411                             rb_obj_classname(th->errinfo),
00412                             file, line, RSTRING_PTR(e));
00413             }
00414             else if (file) {
00415                 warn_printf("Exception `%s' at %s - %s\n",
00416                             rb_obj_classname(th->errinfo),
00417                             file, RSTRING_PTR(e));
00418             }
00419             else {
00420                 warn_printf("Exception `%s' - %s\n",
00421                             rb_obj_classname(th->errinfo),
00422                             RSTRING_PTR(e));
00423             }
00424         }
00425         POP_TAG();
00426         if (status == TAG_FATAL && th->errinfo == exception_error) {
00427             th->errinfo = mesg;
00428         }
00429         else if (status) {
00430             rb_threadptr_reset_raised(th);
00431             JUMP_TAG(status);
00432         }
00433     }
00434 
00435     if (rb_threadptr_set_raised(th)) {
00436         th->errinfo = exception_error;
00437         rb_threadptr_reset_raised(th);
00438         JUMP_TAG(TAG_FATAL);
00439     }
00440 
00441     rb_trap_restore_mask();
00442 
00443     if (tag != TAG_FATAL) {
00444         EXEC_EVENT_HOOK(th, RUBY_EVENT_RAISE, th->cfp->self, 0, 0);
00445     }
00446 }
00447 
00448 static void
00449 rb_longjmp(int tag, volatile VALUE mesg)
00450 {
00451     rb_thread_t *th = GET_THREAD();
00452     setup_exception(th, tag, mesg);
00453     rb_thread_raised_clear(th);
00454     JUMP_TAG(tag);
00455 }
00456 
00457 static VALUE make_exception(int argc, VALUE *argv, int isstr);
00458 
00459 void
00460 rb_exc_raise(VALUE mesg)
00461 {
00462     if (!NIL_P(mesg)) {
00463         mesg = make_exception(1, &mesg, FALSE);
00464     }
00465     rb_longjmp(TAG_RAISE, mesg);
00466 }
00467 
00468 void
00469 rb_exc_fatal(VALUE mesg)
00470 {
00471     if (!NIL_P(mesg)) {
00472         mesg = make_exception(1, &mesg, FALSE);
00473     }
00474     rb_longjmp(TAG_FATAL, mesg);
00475 }
00476 
00477 void
00478 rb_interrupt(void)
00479 {
00480     rb_raise(rb_eInterrupt, "%s", "");
00481 }
00482 
00483 static VALUE get_errinfo(void);
00484 
00485 /*
00486  *  call-seq:
00487  *     raise
00488  *     raise(string)
00489  *     raise(exception [, string [, array]])
00490  *     fail
00491  *     fail(string)
00492  *     fail(exception [, string [, array]])
00493  *
00494  *  With no arguments, raises the exception in <code>$!</code> or raises
00495  *  a <code>RuntimeError</code> if <code>$!</code> is +nil+.
00496  *  With a single +String+ argument, raises a
00497  *  +RuntimeError+ with the string as a message. Otherwise,
00498  *  the first parameter should be the name of an +Exception+
00499  *  class (or an object that returns an +Exception+ object when sent
00500  *  an +exception+ message). The optional second parameter sets the
00501  *  message associated with the exception, and the third parameter is an
00502  *  array of callback information. Exceptions are caught by the
00503  *  +rescue+ clause of <code>begin...end</code> blocks.
00504  *
00505  *     raise "Failed to create socket"
00506  *     raise ArgumentError, "No parameters", caller
00507  */
00508 
00509 static VALUE
00510 rb_f_raise(int argc, VALUE *argv)
00511 {
00512     VALUE err;
00513     if (argc == 0) {
00514         err = get_errinfo();
00515         if (!NIL_P(err)) {
00516             argc = 1;
00517             argv = &err;
00518         }
00519     }
00520     rb_raise_jump(rb_make_exception(argc, argv));
00521     return Qnil;                /* not reached */
00522 }
00523 
00524 static VALUE
00525 make_exception(int argc, VALUE *argv, int isstr)
00526 {
00527     VALUE mesg;
00528     ID exception;
00529     int n;
00530 
00531     mesg = Qnil;
00532     switch (argc) {
00533       case 0:
00534         break;
00535       case 1:
00536         if (NIL_P(argv[0]))
00537             break;
00538         if (isstr) {
00539             mesg = rb_check_string_type(argv[0]);
00540             if (!NIL_P(mesg)) {
00541                 mesg = rb_exc_new3(rb_eRuntimeError, mesg);
00542                 break;
00543             }
00544         }
00545         n = 0;
00546         goto exception_call;
00547 
00548       case 2:
00549       case 3:
00550         n = 1;
00551       exception_call:
00552         if (argv[0] == sysstack_error) return argv[0];
00553         CONST_ID(exception, "exception");
00554         mesg = rb_check_funcall(argv[0], exception, n, argv+1);
00555         if (mesg == Qundef) {
00556             rb_raise(rb_eTypeError, "exception class/object expected");
00557         }
00558         break;
00559       default:
00560         rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..3)", argc);
00561         break;
00562     }
00563     if (argc > 0) {
00564         if (!rb_obj_is_kind_of(mesg, rb_eException))
00565             rb_raise(rb_eTypeError, "exception object expected");
00566         if (argc > 2)
00567             set_backtrace(mesg, argv[2]);
00568     }
00569 
00570     return mesg;
00571 }
00572 
00573 VALUE
00574 rb_make_exception(int argc, VALUE *argv)
00575 {
00576     return make_exception(argc, argv, TRUE);
00577 }
00578 
00579 void
00580 rb_raise_jump(VALUE mesg)
00581 {
00582     rb_thread_t *th = GET_THREAD();
00583     rb_control_frame_t *cfp = th->cfp;
00584     VALUE klass = cfp->me->klass;
00585     VALUE self = cfp->self;
00586     ID mid = cfp->me->called_id;
00587 
00588     th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
00589 
00590     setup_exception(th, TAG_RAISE, mesg);
00591 
00592     EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, self, mid, klass);
00593     rb_thread_raised_clear(th);
00594     JUMP_TAG(TAG_RAISE);
00595 }
00596 
00597 void
00598 rb_jump_tag(int tag)
00599 {
00600     JUMP_TAG(tag);
00601 }
00602 
00603 int
00604 rb_block_given_p(void)
00605 {
00606     rb_thread_t *th = GET_THREAD();
00607 
00608     if ((th->cfp->lfp[0] & 0x02) == 0 &&
00609         GC_GUARDED_PTR_REF(th->cfp->lfp[0])) {
00610         return TRUE;
00611     }
00612     else {
00613         return FALSE;
00614     }
00615 }
00616 
00617 int
00618 rb_iterator_p(void)
00619 {
00620     return rb_block_given_p();
00621 }
00622 
00623 VALUE rb_eThreadError;
00624 
00625 void
00626 rb_need_block(void)
00627 {
00628     if (!rb_block_given_p()) {
00629         rb_vm_localjump_error("no block given", Qnil, 0);
00630     }
00631 }
00632 
00633 VALUE
00634 rb_rescue2(VALUE (* b_proc) (ANYARGS), VALUE data1,
00635            VALUE (* r_proc) (ANYARGS), VALUE data2, ...)
00636 {
00637     int state;
00638     rb_thread_t *th = GET_THREAD();
00639     rb_control_frame_t *cfp = th->cfp;
00640     volatile VALUE result;
00641     volatile VALUE e_info = th->errinfo;
00642     va_list args;
00643 
00644     PUSH_TAG();
00645     if ((state = EXEC_TAG()) == 0) {
00646       retry_entry:
00647         result = (*b_proc) (data1);
00648     }
00649     else {
00650         th->cfp = cfp; /* restore */
00651 
00652         if (state == TAG_RAISE) {
00653             int handle = FALSE;
00654             VALUE eclass;
00655 
00656             va_init_list(args, data2);
00657             while ((eclass = va_arg(args, VALUE)) != 0) {
00658                 if (rb_obj_is_kind_of(th->errinfo, eclass)) {
00659                     handle = TRUE;
00660                     break;
00661                 }
00662             }
00663             va_end(args);
00664 
00665             if (handle) {
00666                 if (r_proc) {
00667                     PUSH_TAG();
00668                     if ((state = EXEC_TAG()) == 0) {
00669                         result = (*r_proc) (data2, th->errinfo);
00670                     }
00671                     POP_TAG();
00672                     if (state == TAG_RETRY) {
00673                         state = 0;
00674                         th->errinfo = Qnil;
00675                         goto retry_entry;
00676                     }
00677                 }
00678                 else {
00679                     result = Qnil;
00680                     state = 0;
00681                 }
00682                 if (state == 0) {
00683                     th->errinfo = e_info;
00684                 }
00685             }
00686         }
00687     }
00688     POP_TAG();
00689     if (state)
00690         JUMP_TAG(state);
00691 
00692     return result;
00693 }
00694 
00695 VALUE
00696 rb_rescue(VALUE (* b_proc)(ANYARGS), VALUE data1,
00697           VALUE (* r_proc)(ANYARGS), VALUE data2)
00698 {
00699     return rb_rescue2(b_proc, data1, r_proc, data2, rb_eStandardError,
00700                       (VALUE)0);
00701 }
00702 
00703 VALUE
00704 rb_protect(VALUE (* proc) (VALUE), VALUE data, int * state)
00705 {
00706     volatile VALUE result = Qnil;
00707     int status;
00708     rb_thread_t *th = GET_THREAD();
00709     rb_control_frame_t *cfp = th->cfp;
00710     struct rb_vm_protect_tag protect_tag;
00711     rb_jmpbuf_t org_jmpbuf;
00712 
00713     protect_tag.prev = th->protect_tag;
00714 
00715     PUSH_TAG();
00716     th->protect_tag = &protect_tag;
00717     MEMCPY(&org_jmpbuf, &(th)->root_jmpbuf, rb_jmpbuf_t, 1);
00718     if ((status = EXEC_TAG()) == 0) {
00719         SAVE_ROOT_JMPBUF(th, result = (*proc) (data));
00720     }
00721     MEMCPY(&(th)->root_jmpbuf, &org_jmpbuf, rb_jmpbuf_t, 1);
00722     th->protect_tag = protect_tag.prev;
00723     POP_TAG();
00724 
00725     if (state) {
00726         *state = status;
00727     }
00728     if (status != 0) {
00729         th->cfp = cfp;
00730         return Qnil;
00731     }
00732 
00733     return result;
00734 }
00735 
00736 VALUE
00737 rb_ensure(VALUE (*b_proc)(ANYARGS), VALUE data1, VALUE (*e_proc)(ANYARGS), VALUE data2)
00738 {
00739     int state;
00740     volatile VALUE result = Qnil;
00741 
00742     PUSH_TAG();
00743     if ((state = EXEC_TAG()) == 0) {
00744         result = (*b_proc) (data1);
00745     }
00746     POP_TAG();
00747     /* TODO: fix me */
00748     /* retval = prot_tag ? prot_tag->retval : Qnil; */     /* save retval */
00749     (*e_proc) (data2);
00750     if (state)
00751         JUMP_TAG(state);
00752     return result;
00753 }
00754 
00755 static const rb_method_entry_t *
00756 method_entry_of_iseq(rb_control_frame_t *cfp, rb_iseq_t *iseq)
00757 {
00758     rb_thread_t *th = GET_THREAD();
00759     rb_control_frame_t *cfp_limit;
00760 
00761     cfp_limit = (rb_control_frame_t *)(th->stack + th->stack_size);
00762     while (cfp_limit > cfp) {
00763         if (cfp->iseq == iseq)
00764             return cfp->me;
00765         cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
00766     }
00767     return 0;
00768 }
00769 
00770 static ID
00771 frame_func_id(rb_control_frame_t *cfp)
00772 {
00773     const rb_method_entry_t *me_local;
00774     rb_iseq_t *iseq = cfp->iseq;
00775     if (cfp->me) {
00776         return cfp->me->def->original_id;
00777     }
00778     while (iseq) {
00779         if (RUBY_VM_IFUNC_P(iseq)) {
00780             NODE *ifunc = (NODE *)iseq;
00781             if (ifunc->nd_aid) return ifunc->nd_aid;
00782             return rb_intern("<ifunc>");
00783         }
00784         me_local = method_entry_of_iseq(cfp, iseq);
00785         if (me_local) {
00786             cfp->me = me_local;
00787             return me_local->def->original_id;
00788         }
00789         if (iseq->defined_method_id) {
00790             return iseq->defined_method_id;
00791         }
00792         if (iseq->local_iseq == iseq) {
00793             break;
00794         }
00795         iseq = iseq->parent_iseq;
00796     }
00797     return 0;
00798 }
00799 
00800 ID
00801 rb_frame_this_func(void)
00802 {
00803     return frame_func_id(GET_THREAD()->cfp);
00804 }
00805 
00806 ID
00807 rb_frame_callee(void)
00808 {
00809     return frame_func_id(GET_THREAD()->cfp);
00810 }
00811 
00812 static ID
00813 rb_frame_caller(void)
00814 {
00815     rb_thread_t *th = GET_THREAD();
00816     rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
00817     /* check if prev_cfp can be accessible */
00818     if ((void *)(th->stack + th->stack_size) == (void *)(prev_cfp)) {
00819         return 0;
00820     }
00821     return frame_func_id(prev_cfp);
00822 }
00823 
00824 void
00825 rb_frame_pop(void)
00826 {
00827     rb_thread_t *th = GET_THREAD();
00828     th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
00829 }
00830 
00831 /*
00832  *  call-seq:
00833  *     append_features(mod)   -> mod
00834  *
00835  *  When this module is included in another, Ruby calls
00836  *  <code>append_features</code> in this module, passing it the
00837  *  receiving module in _mod_. Ruby's default implementation is
00838  *  to add the constants, methods, and module variables of this module
00839  *  to _mod_ if this module has not already been added to
00840  *  _mod_ or one of its ancestors. See also <code>Module#include</code>.
00841  */
00842 
00843 static VALUE
00844 rb_mod_append_features(VALUE module, VALUE include)
00845 {
00846     switch (TYPE(include)) {
00847       case T_CLASS:
00848       case T_MODULE:
00849         break;
00850       default:
00851         Check_Type(include, T_CLASS);
00852         break;
00853     }
00854     rb_include_module(include, module);
00855 
00856     return module;
00857 }
00858 
00859 /*
00860  *  call-seq:
00861  *     include(module, ...)    -> self
00862  *
00863  *  Invokes <code>Module.append_features</code> on each parameter in reverse order.
00864  */
00865 
00866 static VALUE
00867 rb_mod_include(int argc, VALUE *argv, VALUE module)
00868 {
00869     int i;
00870 
00871     for (i = 0; i < argc; i++)
00872         Check_Type(argv[i], T_MODULE);
00873     while (argc--) {
00874         rb_funcall(argv[argc], rb_intern("append_features"), 1, module);
00875         rb_funcall(argv[argc], rb_intern("included"), 1, module);
00876     }
00877     return module;
00878 }
00879 
00880 void
00881 rb_obj_call_init(VALUE obj, int argc, VALUE *argv)
00882 {
00883     PASS_PASSED_BLOCK();
00884     rb_funcall2(obj, idInitialize, argc, argv);
00885 }
00886 
00887 void
00888 rb_extend_object(VALUE obj, VALUE module)
00889 {
00890     rb_include_module(rb_singleton_class(obj), module);
00891 }
00892 
00893 /*
00894  *  call-seq:
00895  *     extend_object(obj)    -> obj
00896  *
00897  *  Extends the specified object by adding this module's constants and
00898  *  methods (which are added as singleton methods). This is the callback
00899  *  method used by <code>Object#extend</code>.
00900  *
00901  *     module Picky
00902  *       def Picky.extend_object(o)
00903  *         if String === o
00904  *           puts "Can't add Picky to a String"
00905  *         else
00906  *           puts "Picky added to #{o.class}"
00907  *           super
00908  *         end
00909  *       end
00910  *     end
00911  *     (s = Array.new).extend Picky  # Call Object.extend
00912  *     (s = "quick brown fox").extend Picky
00913  *
00914  *  <em>produces:</em>
00915  *
00916  *     Picky added to Array
00917  *     Can't add Picky to a String
00918  */
00919 
00920 static VALUE
00921 rb_mod_extend_object(VALUE mod, VALUE obj)
00922 {
00923     rb_extend_object(obj, mod);
00924     return obj;
00925 }
00926 
00927 /*
00928  *  call-seq:
00929  *     obj.extend(module, ...)    -> obj
00930  *
00931  *  Adds to _obj_ the instance methods from each module given as a
00932  *  parameter.
00933  *
00934  *     module Mod
00935  *       def hello
00936  *         "Hello from Mod.\n"
00937  *       end
00938  *     end
00939  *
00940  *     class Klass
00941  *       def hello
00942  *         "Hello from Klass.\n"
00943  *       end
00944  *     end
00945  *
00946  *     k = Klass.new
00947  *     k.hello         #=> "Hello from Klass.\n"
00948  *     k.extend(Mod)   #=> #<Klass:0x401b3bc8>
00949  *     k.hello         #=> "Hello from Mod.\n"
00950  */
00951 
00952 static VALUE
00953 rb_obj_extend(int argc, VALUE *argv, VALUE obj)
00954 {
00955     int i;
00956 
00957     if (argc == 0) {
00958         rb_raise(rb_eArgError, "wrong number of arguments (at least 1)");
00959     }
00960     for (i = 0; i < argc; i++)
00961         Check_Type(argv[i], T_MODULE);
00962     while (argc--) {
00963         rb_funcall(argv[argc], rb_intern("extend_object"), 1, obj);
00964         rb_funcall(argv[argc], rb_intern("extended"), 1, obj);
00965     }
00966     return obj;
00967 }
00968 
00969 /*
00970  *  call-seq:
00971  *     include(module, ...)   -> self
00972  *
00973  *  Invokes <code>Module.append_features</code>
00974  *  on each parameter in turn. Effectively adds the methods and constants
00975  *  in each module to the receiver.
00976  */
00977 
00978 static VALUE
00979 top_include(int argc, VALUE *argv, VALUE self)
00980 {
00981     rb_thread_t *th = GET_THREAD();
00982 
00983     rb_secure(4);
00984     if (th->top_wrapper) {
00985         rb_warning
00986             ("main#include in the wrapped load is effective only in wrapper module");
00987         return rb_mod_include(argc, argv, th->top_wrapper);
00988     }
00989     return rb_mod_include(argc, argv, rb_cObject);
00990 }
00991 
00992 static VALUE *
00993 errinfo_place(rb_thread_t *th)
00994 {
00995     rb_control_frame_t *cfp = th->cfp;
00996     rb_control_frame_t *end_cfp = RUBY_VM_END_CONTROL_FRAME(th);
00997 
00998     while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, end_cfp)) {
00999         if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
01000             if (cfp->iseq->type == ISEQ_TYPE_RESCUE) {
01001                 return &cfp->dfp[-2];
01002             }
01003             else if (cfp->iseq->type == ISEQ_TYPE_ENSURE &&
01004                      TYPE(cfp->dfp[-2]) != T_NODE &&
01005                      !FIXNUM_P(cfp->dfp[-2])) {
01006                 return &cfp->dfp[-2];
01007             }
01008         }
01009         cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
01010     }
01011     return 0;
01012 }
01013 
01014 static VALUE
01015 get_thread_errinfo(rb_thread_t *th)
01016 {
01017     VALUE *ptr = errinfo_place(th);
01018     if (ptr) {
01019         return *ptr;
01020     }
01021     else {
01022         return th->errinfo;
01023     }
01024 }
01025 
01026 static VALUE
01027 get_errinfo(void)
01028 {
01029     return get_thread_errinfo(GET_THREAD());
01030 }
01031 
01032 static VALUE
01033 errinfo_getter(ID id)
01034 {
01035     return get_errinfo();
01036 }
01037 
01038 #if 0
01039 static void
01040 errinfo_setter(VALUE val, ID id, VALUE *var)
01041 {
01042     if (!NIL_P(val) && !rb_obj_is_kind_of(val, rb_eException)) {
01043         rb_raise(rb_eTypeError, "assigning non-exception to $!");
01044     }
01045     else {
01046         VALUE *ptr = errinfo_place(GET_THREAD());
01047         if (ptr) {
01048             *ptr = val;
01049         }
01050         else {
01051             rb_raise(rb_eRuntimeError, "errinfo_setter: not in rescue clause.");
01052         }
01053     }
01054 }
01055 #endif
01056 
01057 VALUE
01058 rb_errinfo(void)
01059 {
01060     rb_thread_t *th = GET_THREAD();
01061     return th->errinfo;
01062 }
01063 
01064 void
01065 rb_set_errinfo(VALUE err)
01066 {
01067     if (!NIL_P(err) && !rb_obj_is_kind_of(err, rb_eException)) {
01068         rb_raise(rb_eTypeError, "assigning non-exception to $!");
01069     }
01070     GET_THREAD()->errinfo = err;
01071 }
01072 
01073 VALUE
01074 rb_rubylevel_errinfo(void)
01075 {
01076     return get_errinfo();
01077 }
01078 
01079 static VALUE
01080 errat_getter(ID id)
01081 {
01082     VALUE err = get_errinfo();
01083     if (!NIL_P(err)) {
01084         return get_backtrace(err);
01085     }
01086     else {
01087         return Qnil;
01088     }
01089 }
01090 
01091 static void
01092 errat_setter(VALUE val, ID id, VALUE *var)
01093 {
01094     VALUE err = get_errinfo();
01095     if (NIL_P(err)) {
01096         rb_raise(rb_eArgError, "$! not set");
01097     }
01098     set_backtrace(err, val);
01099 }
01100 
01101 /*
01102  *  call-seq:
01103  *     __method__         -> symbol
01104  *     __callee__         -> symbol
01105  *
01106  *  Returns the name of the current method as a Symbol.
01107  *  If called outside of a method, it returns <code>nil</code>.
01108  *
01109  */
01110 
01111 static VALUE
01112 rb_f_method_name(void)
01113 {
01114     ID fname = rb_frame_caller(); /* need *caller* ID */
01115 
01116     if (fname) {
01117         return ID2SYM(fname);
01118     }
01119     else {
01120         return Qnil;
01121     }
01122 }
01123 
01124 void
01125 Init_eval(void)
01126 {
01127     rb_define_virtual_variable("$@", errat_getter, errat_setter);
01128     rb_define_virtual_variable("$!", errinfo_getter, 0);
01129 
01130     rb_define_global_function("raise", rb_f_raise, -1);
01131     rb_define_global_function("fail", rb_f_raise, -1);
01132 
01133     rb_define_global_function("global_variables", rb_f_global_variables, 0);    /* in variable.c */
01134 
01135     rb_define_global_function("__method__", rb_f_method_name, 0);
01136     rb_define_global_function("__callee__", rb_f_method_name, 0);
01137 
01138     rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1);
01139     rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1);
01140     rb_define_private_method(rb_cModule, "include", rb_mod_include, -1);
01141 
01142     rb_undef_method(rb_cClass, "module_function");
01143 
01144     Init_vm_eval();
01145     Init_eval_method();
01146 
01147     rb_define_singleton_method(rb_cModule, "nesting", rb_mod_nesting, 0);
01148     rb_define_singleton_method(rb_cModule, "constants", rb_mod_s_constants, -1);
01149 
01150     rb_define_singleton_method(rb_vm_top_self(), "include", top_include, -1);
01151 
01152     rb_define_method(rb_mKernel, "extend", rb_obj_extend, -1);
01153 
01154     rb_define_global_function("trace_var", rb_f_trace_var, -1); /* in variable.c */
01155     rb_define_global_function("untrace_var", rb_f_untrace_var, -1);     /* in variable.c */
01156 
01157     exception_error = rb_exc_new3(rb_eFatal,
01158                                   rb_obj_freeze(rb_str_new2("exception reentered")));
01159     OBJ_TAINT(exception_error);
01160     OBJ_FREEZE(exception_error);
01161 }
01162