• Main Page
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

eval.c

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

Generated on Thu Sep 8 2011 03:50:27 for Ruby by  doxygen 1.7.1