diff options
Diffstat (limited to 'trunk/eval.c')
-rw-r--r-- | trunk/eval.c | 1262 |
1 files changed, 0 insertions, 1262 deletions
diff --git a/trunk/eval.c b/trunk/eval.c deleted file mode 100644 index 142433ac93..0000000000 --- a/trunk/eval.c +++ /dev/null @@ -1,1262 +0,0 @@ -/********************************************************************** - - eval.c - - - $Author$ - created at: Thu Jun 10 14:22:17 JST 1993 - - Copyright (C) 1993-2007 Yukihiro Matsumoto - Copyright (C) 2000 Network Applied Communication Laboratory, Inc. - Copyright (C) 2000 Information-technology Promotion Agency, Japan - -**********************************************************************/ - -#include "eval_intern.h" - -VALUE proc_invoke(VALUE, VALUE, VALUE, VALUE); -VALUE rb_binding_new(void); -NORETURN(void rb_raise_jump(VALUE)); - -ID rb_frame_callee(void); -VALUE rb_eLocalJumpError; -VALUE rb_eSysStackError; - -#define exception_error GET_VM()->special_exceptions[ruby_error_reenter] - -#include "eval_error.c" -#include "eval_safe.c" -#include "eval_jump.c" - -/* initialize ruby */ - -#if defined(__APPLE__) -#define environ (*_NSGetEnviron()) -#elif !defined(_WIN32) && !defined(__MACOS__) || defined(_WIN32_WCE) -extern char **environ; -#endif -char **rb_origenviron; - -void rb_clear_trace_func(void); -void rb_thread_stop_timer_thread(void); - -void rb_call_inits(void); -void Init_heap(void); -void Init_ext(void); -void Init_BareVM(void); - -void -ruby_init(void) -{ - static int initialized = 0; - int state; - - if (initialized) - return; - initialized = 1; - -#ifdef __MACOS__ - rb_origenviron = 0; -#else - rb_origenviron = environ; -#endif - - Init_stack((void *)&state); - Init_BareVM(); - Init_heap(); - - PUSH_TAG(); - if ((state = EXEC_TAG()) == 0) { - rb_call_inits(); - -#ifdef __MACOS__ - _macruby_init(); -#elif defined(__VMS) - _vmsruby_init(); -#endif - - ruby_prog_init(); - ALLOW_INTS; - } - POP_TAG(); - - if (state) { - error_print(); - exit(EXIT_FAILURE); - } - GET_VM()->running = 1; -} - -extern void rb_clear_trace_func(void); - -void * -ruby_options(int argc, char **argv) -{ - int state; - void *tree = 0; - - Init_stack((void *)&state); - PUSH_TAG(); - if ((state = EXEC_TAG()) == 0) { - SAVE_ROOT_JMPBUF(GET_THREAD(), tree = ruby_process_options(argc, argv)); - } - else { - rb_clear_trace_func(); - state = error_handle(state); - tree = (void *)INT2FIX(state); - } - POP_TAG(); - return tree; -} - -static void -ruby_finalize_0(void) -{ - PUSH_TAG(); - if (EXEC_TAG() == 0) { - rb_trap_exit(); - } - POP_TAG(); - rb_exec_end_proc(); - rb_clear_trace_func(); -} - -static void -ruby_finalize_1(void) -{ - ruby_sig_finalize(); - GET_THREAD()->errinfo = Qnil; - rb_gc_call_finalizer_at_exit(); -} - -void -ruby_finalize(void) -{ - ruby_finalize_0(); - ruby_finalize_1(); -} - -void rb_thread_stop_timer_thread(void); - -int -ruby_cleanup(int ex) -{ - int state; - volatile VALUE errs[2]; - rb_thread_t *th = GET_THREAD(); - int nerr; - - errs[1] = th->errinfo; - th->safe_level = 0; - Init_stack((void *)&state); - - PUSH_TAG(); - if ((state = EXEC_TAG()) == 0) { - SAVE_ROOT_JMPBUF(th, ruby_finalize_0()); - } - POP_TAG(); - - errs[0] = th->errinfo; - PUSH_TAG(); - if ((state = EXEC_TAG()) == 0) { - SAVE_ROOT_JMPBUF(th, rb_thread_terminate_all()); - } - else if (ex == 0) { - ex = state; - } - th->errinfo = errs[1]; - ex = error_handle(ex); - ruby_finalize_1(); - POP_TAG(); - rb_thread_stop_timer_thread(); - - for (nerr = 0; nerr < sizeof(errs) / sizeof(errs[0]); ++nerr) { - VALUE err = errs[nerr]; - - if (!RTEST(err)) continue; - - /* th->errinfo contains a NODE while break'ing */ - if (TYPE(err) == T_NODE) continue; - - if (rb_obj_is_kind_of(err, rb_eSystemExit)) { - return sysexit_status(err); - } - else if (rb_obj_is_kind_of(err, rb_eSignal)) { - VALUE sig = rb_iv_get(err, "signo"); - ruby_default_signal(NUM2INT(sig)); - } - else if (ex == 0) { - ex = 1; - } - } - -#if EXIT_SUCCESS != 0 || EXIT_FAILURE != 1 - switch (ex) { -#if EXIT_SUCCESS != 0 - case 0: return EXIT_SUCCESS; -#endif -#if EXIT_FAILURE != 1 - case 1: return EXIT_FAILURE; -#endif - } -#endif - - return ex; -} - -int -ruby_exec_node(void *n, const char *file) -{ - int state; - VALUE iseq = (VALUE)n; - rb_thread_t *th = GET_THREAD(); - - if (!n) return 0; - - PUSH_TAG(); - if ((state = EXEC_TAG()) == 0) { - SAVE_ROOT_JMPBUF(th, { - th->base_block = 0; - rb_iseq_eval(iseq); - }); - } - POP_TAG(); - return state; -} - -void -ruby_stop(int ex) -{ - exit(ruby_cleanup(ex)); -} - -int -ruby_run_node(void *n) -{ - VALUE v = (VALUE)n; - - switch (v) { - case Qtrue: return EXIT_SUCCESS; - case Qfalse: return EXIT_FAILURE; - } - if (FIXNUM_P(v)) { - return FIX2INT(v); - } - Init_stack((void *)&n); - return ruby_cleanup(ruby_exec_node(n, 0)); -} - -/* - * call-seq: - * Module.nesting => array - * - * Returns the list of +Modules+ nested at the point of call. - * - * module M1 - * module M2 - * $a = Module.nesting - * end - * end - * $a #=> [M1::M2, M1] - * $a[0].name #=> "M1::M2" - */ - -static VALUE -rb_mod_nesting(void) -{ - VALUE ary = rb_ary_new(); - const NODE *cref = vm_cref(); - - while (cref && cref->nd_next) { - VALUE klass = cref->nd_clss; - if (!NIL_P(klass)) { - rb_ary_push(ary, klass); - } - cref = cref->nd_next; - } - return ary; -} - -/* - * call-seq: - * Module.constants => array - * - * Returns an array of the names of all constants defined in the - * system. This list includes the names of all modules and classes. - * - * p Module.constants.sort[1..5] - * - * <em>produces:</em> - * - * ["ARGV", "ArgumentError", "Array", "Bignum", "Binding"] - */ - -static VALUE -rb_mod_s_constants(int argc, VALUE *argv, VALUE mod) -{ - const NODE *cref = vm_cref(); - VALUE klass; - VALUE cbase = 0; - void *data = 0; - - if (argc > 0) { - return rb_mod_constants(argc, argv, rb_cModule); - } - - while (cref) { - klass = cref->nd_clss; - if (!NIL_P(klass)) { - data = rb_mod_const_at(cref->nd_clss, data); - if (!cbase) { - cbase = klass; - } - } - cref = cref->nd_next; - } - - if (cbase) { - data = rb_mod_const_of(cbase, data); - } - return rb_const_list(data); -} - -void -rb_frozen_class_p(VALUE klass) -{ - const char *desc = "something(?!)"; - - if (OBJ_FROZEN(klass)) { - if (FL_TEST(klass, FL_SINGLETON)) - desc = "object"; - else { - switch (TYPE(klass)) { - case T_MODULE: - case T_ICLASS: - desc = "module"; - break; - case T_CLASS: - desc = "class"; - break; - } - } - rb_error_frozen(desc); - } -} - -NORETURN(static void rb_longjmp(int, VALUE)); -VALUE rb_make_backtrace(void); - -static void -rb_longjmp(int tag, VALUE mesg) -{ - VALUE at; - VALUE e; - rb_thread_t *th = GET_THREAD(); - const char *file; - int line = 0; - - if (rb_thread_set_raised(th)) { - th->errinfo = exception_error; - JUMP_TAG(TAG_FATAL); - } - - if (NIL_P(mesg)) - mesg = th->errinfo; - if (NIL_P(mesg)) { - mesg = rb_exc_new(rb_eRuntimeError, 0, 0); - } - - file = rb_sourcefile(); - if (file) line = rb_sourceline(); - if (file && !NIL_P(mesg)) { - at = get_backtrace(mesg); - if (NIL_P(at)) { - at = rb_make_backtrace(); - if (OBJ_FROZEN(mesg)) { - mesg = rb_obj_dup(mesg); - } - set_backtrace(mesg, at); - } - } - if (!NIL_P(mesg)) { - th->errinfo = mesg; - } - - if (RTEST(ruby_debug) && !NIL_P(e = th->errinfo) && - !rb_obj_is_kind_of(e, rb_eSystemExit)) { - int status; - - PUSH_TAG(); - if ((status = EXEC_TAG()) == 0) { - RB_GC_GUARD(e) = rb_obj_as_string(e); - if (file) { - warn_printf("Exception `%s' at %s:%d - %s\n", - rb_obj_classname(th->errinfo), - file, line, RSTRING_PTR(e)); - } - else { - warn_printf("Exception `%s' - %s\n", - rb_obj_classname(th->errinfo), - RSTRING_PTR(e)); - } - } - POP_TAG(); - if (status == TAG_FATAL && th->errinfo == exception_error) { - th->errinfo = mesg; - } - else if (status) { - rb_thread_reset_raised(th); - JUMP_TAG(status); - } - } - - rb_trap_restore_mask(); - - if (tag != TAG_FATAL) { - EXEC_EVENT_HOOK(th, RUBY_EVENT_RAISE, th->cfp->self, - 0 /* TODO: id */, 0 /* TODO: klass */); - } - - rb_thread_raised_clear(th); - JUMP_TAG(tag); -} - -void -rb_exc_raise(VALUE mesg) -{ - rb_longjmp(TAG_RAISE, mesg); -} - -void -rb_exc_fatal(VALUE mesg) -{ - rb_longjmp(TAG_FATAL, mesg); -} - -void -rb_interrupt(void) -{ - rb_raise(rb_eInterrupt, "%s", ""); -} - -static VALUE get_errinfo(void); - -/* - * call-seq: - * raise - * raise(string) - * raise(exception [, string [, array]]) - * fail - * fail(string) - * fail(exception [, string [, array]]) - * - * With no arguments, raises the exception in <code>$!</code> or raises - * a <code>RuntimeError</code> if <code>$!</code> is +nil+. - * With a single +String+ argument, raises a - * +RuntimeError+ with the string as a message. Otherwise, - * the first parameter should be the name of an +Exception+ - * class (or an object that returns an +Exception+ object when sent - * an +exception+ message). The optional second parameter sets the - * message associated with the exception, and the third parameter is an - * array of callback information. Exceptions are caught by the - * +rescue+ clause of <code>begin...end</code> blocks. - * - * raise "Failed to create socket" - * raise ArgumentError, "No parameters", caller - */ - -static VALUE -rb_f_raise(int argc, VALUE *argv) -{ - VALUE err; - if (argc == 0) { - err = get_errinfo(); - if (!NIL_P(err)) { - argc = 1; - argv = &err; - } - } - rb_raise_jump(rb_make_exception(argc, argv)); - return Qnil; /* not reached */ -} - -VALUE -rb_make_exception(int argc, VALUE *argv) -{ - VALUE mesg; - ID exception; - int n; - - mesg = Qnil; - switch (argc) { - case 0: - mesg = Qnil; - break; - case 1: - if (NIL_P(argv[0])) - break; - if (TYPE(argv[0]) == T_STRING) { - mesg = rb_exc_new3(rb_eRuntimeError, argv[0]); - break; - } - n = 0; - goto exception_call; - - case 2: - case 3: - n = 1; - exception_call: - CONST_ID(exception, "exception"); - if (!rb_respond_to(argv[0], exception)) { - rb_raise(rb_eTypeError, "exception class/object expected"); - } - mesg = rb_funcall(argv[0], exception, n, argv[1]); - break; - default: - rb_raise(rb_eArgError, "wrong number of arguments"); - break; - } - if (argc > 0) { - if (!rb_obj_is_kind_of(mesg, rb_eException)) - rb_raise(rb_eTypeError, "exception object expected"); - if (argc > 2) - set_backtrace(mesg, argv[2]); - } - - return mesg; -} - -void -rb_raise_jump(VALUE mesg) -{ - rb_thread_t *th = GET_THREAD(); - th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp); - /* TODO: fix me */ - rb_longjmp(TAG_RAISE, mesg); -} - -void -rb_jump_tag(int tag) -{ - JUMP_TAG(tag); -} - -int -rb_block_given_p(void) -{ - rb_thread_t *th = GET_THREAD(); - - if ((th->cfp->lfp[0] & 0x02) == 0 && - GC_GUARDED_PTR_REF(th->cfp->lfp[0])) { - return Qtrue; - } - else { - return Qfalse; - } -} - -int -rb_iterator_p() -{ - return rb_block_given_p(); -} - -/* - * call-seq: - * block_given? => true or false - * iterator? => true or false - * - * Returns <code>true</code> if <code>yield</code> would execute a - * block in the current context. The <code>iterator?</code> form - * is mildly deprecated. - * - * def try - * if block_given? - * yield - * else - * "no block" - * end - * end - * try #=> "no block" - * try { "hello" } #=> "hello" - * try do "hello" end #=> "hello" - */ - - -VALUE -rb_f_block_given_p(void) -{ - rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *cfp = th->cfp; - cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)); - - if (cfp != 0 && - (cfp->lfp[0] & 0x02) == 0 && - GC_GUARDED_PTR_REF(cfp->lfp[0])) { - return Qtrue; - } - else { - return Qfalse; - } -} - -VALUE rb_eThreadError; - -void -rb_need_block() -{ - if (!rb_block_given_p()) { - vm_localjump_error("no block given", Qnil, 0); - } -} - -VALUE -rb_rescue2(VALUE (* b_proc) (ANYARGS), VALUE data1, - VALUE (* r_proc) (ANYARGS), VALUE data2, ...) -{ - int state; - rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *cfp = th->cfp; - volatile VALUE result; - volatile VALUE e_info = th->errinfo; - va_list args; - - PUSH_TAG(); - if ((state = EXEC_TAG()) == 0) { - retry_entry: - result = (*b_proc) (data1); - } - else { - th->cfp = cfp; /* restore */ - - if (state == TAG_RAISE) { - int handle = Qfalse; - VALUE eclass; - - va_init_list(args, data2); - while ((eclass = va_arg(args, VALUE)) != 0) { - if (rb_obj_is_kind_of(th->errinfo, eclass)) { - handle = Qtrue; - break; - } - } - va_end(args); - - if (handle) { - if (r_proc) { - PUSH_TAG(); - if ((state = EXEC_TAG()) == 0) { - result = (*r_proc) (data2, th->errinfo); - } - POP_TAG(); - if (state == TAG_RETRY) { - state = 0; - th->errinfo = Qnil; - goto retry_entry; - } - } - else { - result = Qnil; - state = 0; - } - if (state == 0) { - th->errinfo = e_info; - } - } - } - } - POP_TAG(); - if (state) - JUMP_TAG(state); - - return result; -} - -VALUE -rb_rescue(VALUE (* b_proc)(ANYARGS), VALUE data1, - VALUE (* r_proc)(ANYARGS), VALUE data2) -{ - return rb_rescue2(b_proc, data1, r_proc, data2, rb_eStandardError, - (VALUE)0); -} - -VALUE -rb_protect(VALUE (* proc) (VALUE), VALUE data, int * state) -{ - VALUE result = Qnil; /* OK */ - int status; - rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *cfp = th->cfp; - struct rb_vm_trap_tag trap_tag; - rb_jmpbuf_t org_jmpbuf; - - trap_tag.prev = th->trap_tag; - - PUSH_TAG(); - th->trap_tag = &trap_tag; - MEMCPY(&org_jmpbuf, &(th)->root_jmpbuf, rb_jmpbuf_t, 1); - if ((status = EXEC_TAG()) == 0) { - SAVE_ROOT_JMPBUF(th, result = (*proc) (data)); - } - MEMCPY(&(th)->root_jmpbuf, &org_jmpbuf, rb_jmpbuf_t, 1); - th->trap_tag = trap_tag.prev; - POP_TAG(); - - if (state) { - *state = status; - } - if (status != 0) { - th->cfp = cfp; - return Qnil; - } - - return result; -} - -VALUE -rb_ensure(VALUE (*b_proc)(ANYARGS), VALUE data1, VALUE (*e_proc)(ANYARGS), VALUE data2) -{ - int state; - volatile VALUE result = Qnil; - - PUSH_TAG(); - if ((state = EXEC_TAG()) == 0) { - result = (*b_proc) (data1); - } - POP_TAG(); - /* TODO: fix me */ - /* retval = prot_tag ? prot_tag->retval : Qnil; */ /* save retval */ - (*e_proc) (data2); - if (state) - JUMP_TAG(state); - return result; -} - -VALUE -rb_with_disable_interrupt(VALUE (*proc)(ANYARGS), VALUE data) -{ - VALUE result = Qnil; /* OK */ - int status; - - DEFER_INTS; - { - int thr_critical = rb_thread_critical; - - rb_thread_critical = Qtrue; - PUSH_TAG(); - if ((status = EXEC_TAG()) == 0) { - result = (*proc) (data); - } - POP_TAG(); - rb_thread_critical = thr_critical; - } - ENABLE_INTS; - if (status) - JUMP_TAG(status); - - return result; -} - -static ID -frame_func_id(rb_control_frame_t *cfp) -{ - rb_iseq_t *iseq = cfp->iseq; - if (!iseq) { - return cfp->method_id; - } - while (iseq) { - if (RUBY_VM_IFUNC_P(iseq)) { - return rb_intern("<ifunc>"); - } - if (iseq->defined_method_id) { - return iseq->defined_method_id; - } - if (iseq->local_iseq == iseq) { - break; - } - iseq = iseq->parent_iseq; - } - return 0; -} - -ID -rb_frame_this_func(void) -{ - return frame_func_id(GET_THREAD()->cfp); -} - -ID -rb_frame_callee(void) -{ - rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp); - /* check if prev_cfp can be accessible */ - if ((void *)(th->stack + th->stack_size) == (void *)(prev_cfp)) { - return 0; - } - return frame_func_id(prev_cfp); -} - -void -rb_frame_pop(void) -{ - rb_thread_t *th = GET_THREAD(); - th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp); -} - -/* - * call-seq: - * append_features(mod) => mod - * - * When this module is included in another, Ruby calls - * <code>append_features</code> in this module, passing it the - * receiving module in _mod_. Ruby's default implementation is - * to add the constants, methods, and module variables of this module - * to _mod_ if this module has not already been added to - * _mod_ or one of its ancestors. See also <code>Module#include</code>. - */ - -static VALUE -rb_mod_append_features(VALUE module, VALUE include) -{ - switch (TYPE(include)) { - case T_CLASS: - case T_MODULE: - break; - default: - Check_Type(include, T_CLASS); - break; - } - rb_include_module(include, module); - - return module; -} - -/* - * call-seq: - * include(module, ...) => self - * - * Invokes <code>Module.append_features</code> on each parameter in turn. - */ - -static VALUE -rb_mod_include(int argc, VALUE *argv, VALUE module) -{ - int i; - - for (i = 0; i < argc; i++) - Check_Type(argv[i], T_MODULE); - while (argc--) { - rb_funcall(argv[argc], rb_intern("append_features"), 1, module); - rb_funcall(argv[argc], rb_intern("included"), 1, module); - } - return module; -} - -void -rb_obj_call_init(VALUE obj, int argc, VALUE *argv) -{ - PASS_PASSED_BLOCK(); - rb_funcall2(obj, idInitialize, argc, argv); -} - -void -rb_extend_object(VALUE obj, VALUE module) -{ - rb_include_module(rb_singleton_class(obj), module); -} - -/* - * call-seq: - * extend_object(obj) => obj - * - * Extends the specified object by adding this module's constants and - * methods (which are added as singleton methods). This is the callback - * method used by <code>Object#extend</code>. - * - * module Picky - * def Picky.extend_object(o) - * if String === o - * puts "Can't add Picky to a String" - * else - * puts "Picky added to #{o.class}" - * super - * end - * end - * end - * (s = Array.new).extend Picky # Call Object.extend - * (s = "quick brown fox").extend Picky - * - * <em>produces:</em> - * - * Picky added to Array - * Can't add Picky to a String - */ - -static VALUE -rb_mod_extend_object(VALUE mod, VALUE obj) -{ - rb_extend_object(obj, mod); - return obj; -} - -/* - * call-seq: - * obj.extend(module, ...) => obj - * - * Adds to _obj_ the instance methods from each module given as a - * parameter. - * - * module Mod - * def hello - * "Hello from Mod.\n" - * end - * end - * - * class Klass - * def hello - * "Hello from Klass.\n" - * end - * end - * - * k = Klass.new - * k.hello #=> "Hello from Klass.\n" - * k.extend(Mod) #=> #<Klass:0x401b3bc8> - * k.hello #=> "Hello from Mod.\n" - */ - -static VALUE -rb_obj_extend(int argc, VALUE *argv, VALUE obj) -{ - int i; - - if (argc == 0) { - rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)"); - } - for (i = 0; i < argc; i++) - Check_Type(argv[i], T_MODULE); - while (argc--) { - rb_funcall(argv[argc], rb_intern("extend_object"), 1, obj); - rb_funcall(argv[argc], rb_intern("extended"), 1, obj); - } - return obj; -} - -/* - * call-seq: - * include(module, ...) => self - * - * Invokes <code>Module.append_features</code> - * on each parameter in turn. Effectively adds the methods and constants - * in each module to the receiver. - */ - -static VALUE -top_include(int argc, VALUE *argv, VALUE self) -{ - rb_thread_t *th = GET_THREAD(); - - rb_secure(4); - if (th->top_wrapper) { - rb_warning - ("main#include in the wrapped load is effective only in wrapper module"); - return rb_mod_include(argc, argv, th->top_wrapper); - } - return rb_mod_include(argc, argv, rb_cObject); -} - -VALUE rb_f_trace_var(); -VALUE rb_f_untrace_var(); - -static VALUE * -errinfo_place(void) -{ - rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *cfp = th->cfp; - rb_control_frame_t *end_cfp = RUBY_VM_END_CONTROL_FRAME(th); - - while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, end_cfp)) { - if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) { - if (cfp->iseq->type == ISEQ_TYPE_RESCUE) { - return &cfp->dfp[-2]; - } - else if (cfp->iseq->type == ISEQ_TYPE_ENSURE && - TYPE(cfp->dfp[-2]) != T_NODE && - !FIXNUM_P(cfp->dfp[-2])) { - return &cfp->dfp[-2]; - } - } - cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); - } - return 0; -} - -static VALUE -get_errinfo(void) -{ - VALUE *ptr = errinfo_place(); - if (ptr) { - return *ptr; - } - else { - return Qnil; - } -} - -static VALUE -errinfo_getter(ID id) -{ - return get_errinfo(); -} - -#if 0 -static void -errinfo_setter(VALUE val, ID id, VALUE *var) -{ - if (!NIL_P(val) && !rb_obj_is_kind_of(val, rb_eException)) { - rb_raise(rb_eTypeError, "assigning non-exception to $!"); - } - else { - VALUE *ptr = errinfo_place(); - if (ptr) { - *ptr = val; - } - else { - rb_raise(rb_eRuntimeError, "errinfo_setter: not in rescue clause."); - } - } -} -#endif - -VALUE -rb_errinfo(void) -{ - rb_thread_t *th = GET_THREAD(); - return th->errinfo; -} - -void -rb_set_errinfo(VALUE err) -{ - if (!NIL_P(err) && !rb_obj_is_kind_of(err, rb_eException)) { - rb_raise(rb_eTypeError, "assigning non-exception to $!"); - } - GET_THREAD()->errinfo = err; -} - -VALUE -rb_rubylevel_errinfo(void) -{ - return get_errinfo(); -} - -static VALUE -errat_getter(ID id) -{ - VALUE err = get_errinfo(); - if (!NIL_P(err)) { - return get_backtrace(err); - } - else { - return Qnil; - } -} - -static void -errat_setter(VALUE val, ID id, VALUE *var) -{ - VALUE err = get_errinfo(); - if (NIL_P(err)) { - rb_raise(rb_eArgError, "$! not set"); - } - set_backtrace(err, val); -} - -int vm_collect_local_variables_in_heap(rb_thread_t *th, VALUE *dfp, VALUE ary); - -/* - * call-seq: - * local_variables => array - * - * Returns the names of the current local variables. - * - * fred = 1 - * for i in 1..10 - * # ... - * end - * local_variables #=> ["fred", "i"] - */ - -static VALUE -rb_f_local_variables(void) -{ - VALUE ary = rb_ary_new(); - rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *cfp = - vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp)); - int i; - - while (cfp) { - if (cfp->iseq) { - for (i = 0; i < cfp->iseq->local_table_size; i++) { - ID lid = cfp->iseq->local_table[i]; - if (lid) { - const char *vname = rb_id2name(lid); - /* should skip temporary variable */ - if (vname) { - rb_ary_push(ary, ID2SYM(lid)); - } - } - } - } - if (cfp->lfp != cfp->dfp) { - /* block */ - VALUE *dfp = GC_GUARDED_PTR_REF(cfp->dfp[0]); - - if (vm_collect_local_variables_in_heap(th, dfp, ary)) { - break; - } - else { - while (cfp->dfp != dfp) { - cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); - } - } - } - else { - break; - } - } - return ary; -} - - -/* - * call-seq: - * __method__ => symbol - * __callee__ => symbol - * - * Returns the name of the current method as a Symbol. - * If called outside of a method, it returns <code>nil</code>. - * - */ - -static VALUE -rb_f_method_name(void) -{ - ID fname = rb_frame_callee(); - - if (fname) { - return ID2SYM(fname); - } - else { - return Qnil; - } -} - -void -Init_eval(void) -{ - /* TODO: fix position */ - GET_THREAD()->vm->mark_object_ary = rb_ary_new(); - - rb_define_virtual_variable("$@", errat_getter, errat_setter); - rb_define_virtual_variable("$!", errinfo_getter, 0); - - rb_define_global_function("eval", rb_f_eval, -1); - rb_define_global_function("iterator?", rb_f_block_given_p, 0); - rb_define_global_function("block_given?", rb_f_block_given_p, 0); - - rb_define_global_function("raise", rb_f_raise, -1); - rb_define_global_function("fail", rb_f_raise, -1); - - rb_define_global_function("global_variables", rb_f_global_variables, 0); /* in variable.c */ - rb_define_global_function("local_variables", rb_f_local_variables, 0); - - rb_define_global_function("__method__", rb_f_method_name, 0); - rb_define_global_function("__callee__", rb_f_method_name, 0); - - rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1); - rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1); - rb_define_private_method(rb_cModule, "include", rb_mod_include, -1); - rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1); - rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1); - - rb_undef_method(rb_cClass, "module_function"); - - { - extern void Init_vm_eval(void); - extern void Init_eval_method(void); - Init_vm_eval(); - Init_eval_method(); - } - - rb_define_singleton_method(rb_cModule, "nesting", rb_mod_nesting, 0); - rb_define_singleton_method(rb_cModule, "constants", rb_mod_s_constants, -1); - - rb_define_singleton_method(rb_vm_top_self(), "include", top_include, -1); - - rb_define_method(rb_mKernel, "extend", rb_obj_extend, -1); - - rb_define_global_function("trace_var", rb_f_trace_var, -1); /* in variable.c */ - rb_define_global_function("untrace_var", rb_f_untrace_var, -1); /* in variable.c */ - - rb_define_virtual_variable("$SAFE", safe_getter, safe_setter); - - exception_error = rb_exc_new3(rb_eFatal, - rb_obj_freeze(rb_str_new2("exception reentered"))); - rb_ivar_set(exception_error, idThrowState, INT2FIX(TAG_FATAL)); - OBJ_TAINT(exception_error); - OBJ_FREEZE(exception_error); -} - - -/* for parser */ - -int -rb_dvar_defined(ID id) -{ - rb_thread_t *th = GET_THREAD(); - rb_iseq_t *iseq; - if (th->base_block && (iseq = th->base_block->iseq)) { - while (iseq->type == ISEQ_TYPE_BLOCK || - iseq->type == ISEQ_TYPE_RESCUE || - iseq->type == ISEQ_TYPE_ENSURE || - iseq->type == ISEQ_TYPE_EVAL) { - int i; - - for (i = 0; i < iseq->local_table_size; i++) { - if (iseq->local_table[i] == id) { - return 1; - } - } - iseq = iseq->parent_iseq; - } - } - return 0; -} - -int -rb_local_defined(ID id) -{ - rb_thread_t *th = GET_THREAD(); - rb_iseq_t *iseq; - - if (th->base_block && th->base_block->iseq) { - int i; - iseq = th->base_block->iseq->local_iseq; - - for (i=0; i<iseq->local_table_size; i++) { - if (iseq->local_table[i] == id) { - return 1; - } - } - } - return 0; -} - -int -rb_parse_in_eval(void) -{ - return GET_THREAD()->parse_in_eval != 0; -} - - |