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 ID
00755 frame_func_id(rb_control_frame_t *cfp)
00756 {
00757     rb_iseq_t *iseq = cfp->iseq;
00758     if (!iseq) {
00759         return cfp->me->def->original_id;
00760     }
00761     while (iseq) {
00762         if (RUBY_VM_IFUNC_P(iseq)) {
00763             return rb_intern("<ifunc>");
00764         }
00765         if (iseq->defined_method_id) {
00766             return iseq->defined_method_id;
00767         }
00768         if (iseq->local_iseq == iseq) {
00769             break;
00770         }
00771         iseq = iseq->parent_iseq;
00772     }
00773     return 0;
00774 }
00775 
00776 ID
00777 rb_frame_this_func(void)
00778 {
00779     return frame_func_id(GET_THREAD()->cfp);
00780 }
00781 
00782 ID
00783 rb_frame_callee(void)
00784 {
00785     return frame_func_id(GET_THREAD()->cfp);
00786 }
00787 
00788 static ID
00789 rb_frame_caller(void)
00790 {
00791     rb_thread_t *th = GET_THREAD();
00792     rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
00793     /* check if prev_cfp can be accessible */
00794     if ((void *)(th->stack + th->stack_size) == (void *)(prev_cfp)) {
00795         return 0;
00796     }
00797     return frame_func_id(prev_cfp);
00798 }
00799 
00800 void
00801 rb_frame_pop(void)
00802 {
00803     rb_thread_t *th = GET_THREAD();
00804     th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
00805 }
00806 
00807 /*
00808  *  call-seq:
00809  *     append_features(mod)   -> mod
00810  *
00811  *  When this module is included in another, Ruby calls
00812  *  <code>append_features</code> in this module, passing it the
00813  *  receiving module in _mod_. Ruby's default implementation is
00814  *  to add the constants, methods, and module variables of this module
00815  *  to _mod_ if this module has not already been added to
00816  *  _mod_ or one of its ancestors. See also <code>Module#include</code>.
00817  */
00818 
00819 static VALUE
00820 rb_mod_append_features(VALUE module, VALUE include)
00821 {
00822     switch (TYPE(include)) {
00823       case T_CLASS:
00824       case T_MODULE:
00825         break;
00826       default:
00827         Check_Type(include, T_CLASS);
00828         break;
00829     }
00830     rb_include_module(include, module);
00831 
00832     return module;
00833 }
00834 
00835 /*
00836  *  call-seq:
00837  *     include(module, ...)    -> self
00838  *
00839  *  Invokes <code>Module.append_features</code> on each parameter in reverse order.
00840  */
00841 
00842 static VALUE
00843 rb_mod_include(int argc, VALUE *argv, VALUE module)
00844 {
00845     int i;
00846 
00847     for (i = 0; i < argc; i++)
00848         Check_Type(argv[i], T_MODULE);
00849     while (argc--) {
00850         rb_funcall(argv[argc], rb_intern("append_features"), 1, module);
00851         rb_funcall(argv[argc], rb_intern("included"), 1, module);
00852     }
00853     return module;
00854 }
00855 
00856 void
00857 rb_obj_call_init(VALUE obj, int argc, VALUE *argv)
00858 {
00859     PASS_PASSED_BLOCK();
00860     rb_funcall2(obj, idInitialize, argc, argv);
00861 }
00862 
00863 void
00864 rb_extend_object(VALUE obj, VALUE module)
00865 {
00866     rb_include_module(rb_singleton_class(obj), module);
00867 }
00868 
00869 /*
00870  *  call-seq:
00871  *     extend_object(obj)    -> obj
00872  *
00873  *  Extends the specified object by adding this module's constants and
00874  *  methods (which are added as singleton methods). This is the callback
00875  *  method used by <code>Object#extend</code>.
00876  *
00877  *     module Picky
00878  *       def Picky.extend_object(o)
00879  *         if String === o
00880  *           puts "Can't add Picky to a String"
00881  *         else
00882  *           puts "Picky added to #{o.class}"
00883  *           super
00884  *         end
00885  *       end
00886  *     end
00887  *     (s = Array.new).extend Picky  # Call Object.extend
00888  *     (s = "quick brown fox").extend Picky
00889  *
00890  *  <em>produces:</em>
00891  *
00892  *     Picky added to Array
00893  *     Can't add Picky to a String
00894  */
00895 
00896 static VALUE
00897 rb_mod_extend_object(VALUE mod, VALUE obj)
00898 {
00899     rb_extend_object(obj, mod);
00900     return obj;
00901 }
00902 
00903 /*
00904  *  call-seq:
00905  *     obj.extend(module, ...)    -> obj
00906  *
00907  *  Adds to _obj_ the instance methods from each module given as a
00908  *  parameter.
00909  *
00910  *     module Mod
00911  *       def hello
00912  *         "Hello from Mod.\n"
00913  *       end
00914  *     end
00915  *
00916  *     class Klass
00917  *       def hello
00918  *         "Hello from Klass.\n"
00919  *       end
00920  *     end
00921  *
00922  *     k = Klass.new
00923  *     k.hello         #=> "Hello from Klass.\n"
00924  *     k.extend(Mod)   #=> #<Klass:0x401b3bc8>
00925  *     k.hello         #=> "Hello from Mod.\n"
00926  */
00927 
00928 static VALUE
00929 rb_obj_extend(int argc, VALUE *argv, VALUE obj)
00930 {
00931     int i;
00932 
00933     if (argc == 0) {
00934         rb_raise(rb_eArgError, "wrong number of arguments (at least 1)");
00935     }
00936     for (i = 0; i < argc; i++)
00937         Check_Type(argv[i], T_MODULE);
00938     while (argc--) {
00939         rb_funcall(argv[argc], rb_intern("extend_object"), 1, obj);
00940         rb_funcall(argv[argc], rb_intern("extended"), 1, obj);
00941     }
00942     return obj;
00943 }
00944 
00945 /*
00946  *  call-seq:
00947  *     include(module, ...)   -> self
00948  *
00949  *  Invokes <code>Module.append_features</code>
00950  *  on each parameter in turn. Effectively adds the methods and constants
00951  *  in each module to the receiver.
00952  */
00953 
00954 static VALUE
00955 top_include(int argc, VALUE *argv, VALUE self)
00956 {
00957     rb_thread_t *th = GET_THREAD();
00958 
00959     rb_secure(4);
00960     if (th->top_wrapper) {
00961         rb_warning
00962             ("main#include in the wrapped load is effective only in wrapper module");
00963         return rb_mod_include(argc, argv, th->top_wrapper);
00964     }
00965     return rb_mod_include(argc, argv, rb_cObject);
00966 }
00967 
00968 VALUE rb_f_trace_var();
00969 VALUE rb_f_untrace_var();
00970 
00971 static VALUE *
00972 errinfo_place(rb_thread_t *th)
00973 {
00974     rb_control_frame_t *cfp = th->cfp;
00975     rb_control_frame_t *end_cfp = RUBY_VM_END_CONTROL_FRAME(th);
00976 
00977     while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, end_cfp)) {
00978         if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
00979             if (cfp->iseq->type == ISEQ_TYPE_RESCUE) {
00980                 return &cfp->dfp[-2];
00981             }
00982             else if (cfp->iseq->type == ISEQ_TYPE_ENSURE &&
00983                      TYPE(cfp->dfp[-2]) != T_NODE &&
00984                      !FIXNUM_P(cfp->dfp[-2])) {
00985                 return &cfp->dfp[-2];
00986             }
00987         }
00988         cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
00989     }
00990     return 0;
00991 }
00992 
00993 static VALUE
00994 get_thread_errinfo(rb_thread_t *th)
00995 {
00996     VALUE *ptr = errinfo_place(th);
00997     if (ptr) {
00998         return *ptr;
00999     }
01000     else {
01001         return th->errinfo;
01002     }
01003 }
01004 
01005 static VALUE
01006 get_errinfo(void)
01007 {
01008     return get_thread_errinfo(GET_THREAD());
01009 }
01010 
01011 static VALUE
01012 errinfo_getter(ID id)
01013 {
01014     return get_errinfo();
01015 }
01016 
01017 #if 0
01018 static void
01019 errinfo_setter(VALUE val, ID id, VALUE *var)
01020 {
01021     if (!NIL_P(val) && !rb_obj_is_kind_of(val, rb_eException)) {
01022         rb_raise(rb_eTypeError, "assigning non-exception to $!");
01023     }
01024     else {
01025         VALUE *ptr = errinfo_place(GET_THREAD());
01026         if (ptr) {
01027             *ptr = val;
01028         }
01029         else {
01030             rb_raise(rb_eRuntimeError, "errinfo_setter: not in rescue clause.");
01031         }
01032     }
01033 }
01034 #endif
01035 
01036 VALUE
01037 rb_errinfo(void)
01038 {
01039     rb_thread_t *th = GET_THREAD();
01040     return th->errinfo;
01041 }
01042 
01043 void
01044 rb_set_errinfo(VALUE err)
01045 {
01046     if (!NIL_P(err) && !rb_obj_is_kind_of(err, rb_eException)) {
01047         rb_raise(rb_eTypeError, "assigning non-exception to $!");
01048     }
01049     GET_THREAD()->errinfo = err;
01050 }
01051 
01052 VALUE
01053 rb_rubylevel_errinfo(void)
01054 {
01055     return get_errinfo();
01056 }
01057 
01058 static VALUE
01059 errat_getter(ID id)
01060 {
01061     VALUE err = get_errinfo();
01062     if (!NIL_P(err)) {
01063         return get_backtrace(err);
01064     }
01065     else {
01066         return Qnil;
01067     }
01068 }
01069 
01070 static void
01071 errat_setter(VALUE val, ID id, VALUE *var)
01072 {
01073     VALUE err = get_errinfo();
01074     if (NIL_P(err)) {
01075         rb_raise(rb_eArgError, "$! not set");
01076     }
01077     set_backtrace(err, val);
01078 }
01079 
01080 /*
01081  *  call-seq:
01082  *     __method__         -> symbol
01083  *     __callee__         -> symbol
01084  *
01085  *  Returns the name of the current method as a Symbol.
01086  *  If called outside of a method, it returns <code>nil</code>.
01087  *
01088  */
01089 
01090 static VALUE
01091 rb_f_method_name(void)
01092 {
01093     ID fname = rb_frame_caller(); /* need *caller* ID */
01094 
01095     if (fname) {
01096         return ID2SYM(fname);
01097     }
01098     else {
01099         return Qnil;
01100     }
01101 }
01102 
01103 void
01104 Init_eval(void)
01105 {
01106     rb_define_virtual_variable("$@", errat_getter, errat_setter);
01107     rb_define_virtual_variable("$!", errinfo_getter, 0);
01108 
01109     rb_define_global_function("raise", rb_f_raise, -1);
01110     rb_define_global_function("fail", rb_f_raise, -1);
01111 
01112     rb_define_global_function("global_variables", rb_f_global_variables, 0);    /* in variable.c */
01113 
01114     rb_define_global_function("__method__", rb_f_method_name, 0);
01115     rb_define_global_function("__callee__", rb_f_method_name, 0);
01116 
01117     rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1);
01118     rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1);
01119     rb_define_private_method(rb_cModule, "include", rb_mod_include, -1);
01120 
01121     rb_undef_method(rb_cClass, "module_function");
01122 
01123     {
01124         extern void Init_vm_eval(void);
01125         extern void Init_eval_method(void);
01126         Init_vm_eval();
01127         Init_eval_method();
01128     }
01129 
01130     rb_define_singleton_method(rb_cModule, "nesting", rb_mod_nesting, 0);
01131     rb_define_singleton_method(rb_cModule, "constants", rb_mod_s_constants, -1);
01132 
01133     rb_define_singleton_method(rb_vm_top_self(), "include", top_include, -1);
01134 
01135     rb_define_method(rb_mKernel, "extend", rb_obj_extend, -1);
01136 
01137     rb_define_global_function("trace_var", rb_f_trace_var, -1); /* in variable.c */
01138     rb_define_global_function("untrace_var", rb_f_untrace_var, -1);     /* in variable.c */
01139 
01140     exception_error = rb_exc_new3(rb_eFatal,
01141                                   rb_obj_freeze(rb_str_new2("exception reentered")));
01142     OBJ_TAINT(exception_error);
01143     OBJ_FREEZE(exception_error);
01144 }
01145 

Generated on Wed Aug 10 09:16:55 2011 for Ruby by  doxygen 1.4.7