summaryrefslogtreecommitdiff
path: root/ruby_1_9_3/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'ruby_1_9_3/eval.c')
-rw-r--r--ruby_1_9_3/eval.c1161
1 files changed, 0 insertions, 1161 deletions
diff --git a/ruby_1_9_3/eval.c b/ruby_1_9_3/eval.c
deleted file mode 100644
index 9ceb833d37..0000000000
--- a/ruby_1_9_3/eval.c
+++ /dev/null
@@ -1,1161 +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"
-#include "iseq.h"
-#include "gc.h"
-#include "ruby/vm.h"
-#include "ruby/encoding.h"
-#include "internal.h"
-#include "vm_core.h"
-
-#define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
-
-NORETURN(void rb_raise_jump(VALUE));
-
-VALUE rb_eLocalJumpError;
-VALUE rb_eSysStackError;
-
-#define exception_error GET_VM()->special_exceptions[ruby_error_reenter]
-
-#include "eval_error.c"
-#include "eval_jump.c"
-
-/* initialize ruby */
-
-void
-ruby_init(void)
-{
- static int initialized = 0;
- int state;
-
- if (initialized)
- return;
- initialized = 1;
-
- ruby_init_stack((void *)&state);
- Init_BareVM();
- Init_heap();
-
- PUSH_TAG();
- if ((state = EXEC_TAG()) == 0) {
- rb_call_inits();
- ruby_prog_init();
- }
- POP_TAG();
-
- if (state) {
- error_print();
- exit(EXIT_FAILURE);
- }
- GET_VM()->running = 1;
-}
-
-void *
-ruby_options(int argc, char **argv)
-{
- int state;
- void *volatile iseq = 0;
-
- ruby_init_stack((void *)&iseq);
- PUSH_TAG();
- if ((state = EXEC_TAG()) == 0) {
- SAVE_ROOT_JMPBUF(GET_THREAD(), iseq = ruby_process_options(argc, argv));
- }
- else {
- rb_clear_trace_func();
- state = error_handle(state);
- iseq = (void *)INT2FIX(state);
- }
- POP_TAG();
- return iseq;
-}
-
-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();
-}
-
-int
-ruby_cleanup(volatile int ex)
-{
- int state;
- volatile VALUE errs[2];
- rb_thread_t *th = GET_THREAD();
- int nerr;
-
- rb_threadptr_interrupt(th);
- rb_threadptr_check_signal(th);
- PUSH_TAG();
- if ((state = EXEC_TAG()) == 0) {
- SAVE_ROOT_JMPBUF(th, { RUBY_VM_CHECK_INTS(); });
- }
- POP_TAG();
-
- errs[1] = th->errinfo;
- th->safe_level = 0;
- ruby_init_stack(&errs[STACK_UPPER(errs, 0, 1)]);
-
- 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();
-
- /* unlock again if finalizer took mutexes. */
- rb_threadptr_unlock_all_locking_mutexes(GET_THREAD());
- POP_TAG();
- rb_thread_stop_timer_thread(1);
-
-#if EXIT_SUCCESS != 0 || EXIT_FAILURE != 1
- switch (ex) {
-#if EXIT_SUCCESS != 0
- case 0: ex = EXIT_SUCCESS; break;
-#endif
-#if EXIT_FAILURE != 1
- case 1: ex = EXIT_FAILURE; break;
-#endif
- }
-#endif
-
- state = 0;
- for (nerr = 0; nerr < numberof(errs); ++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)) {
- ex = sysexit_status(err);
- break;
- }
- else if (rb_obj_is_kind_of(err, rb_eSignal)) {
- VALUE sig = rb_iv_get(err, "signo");
- state = NUM2INT(sig);
- break;
- }
- else if (ex == EXIT_SUCCESS) {
- ex = EXIT_FAILURE;
- }
- }
- ruby_vm_destruct(GET_VM());
- if (state) ruby_default_signal(state);
-
- return ex;
-}
-
-static int
-ruby_exec_internal(void *n)
-{
- volatile 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_main(iseq);
- });
- }
- POP_TAG();
- return state;
-}
-
-void
-ruby_stop(int ex)
-{
- exit(ruby_cleanup(ex));
-}
-
-int
-ruby_executable_node(void *n, int *status)
-{
- VALUE v = (VALUE)n;
- int s;
-
- switch (v) {
- case Qtrue: s = EXIT_SUCCESS; break;
- case Qfalse: s = EXIT_FAILURE; break;
- default:
- if (!FIXNUM_P(v)) return TRUE;
- s = FIX2INT(v);
- }
- if (status) *status = s;
- return FALSE;
-}
-
-int
-ruby_run_node(void *n)
-{
- int status;
- if (!ruby_executable_node(n, &status)) {
- ruby_cleanup(0);
- return status;
- }
- return ruby_cleanup(ruby_exec_node(n));
-}
-
-int
-ruby_exec_node(void *n)
-{
- ruby_init_stack((void *)&n);
- return ruby_exec_internal(n);
-}
-
-/*
- * 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 = rb_vm_cref();
-
- while (cref && cref->nd_next) {
- VALUE klass = cref->nd_clss;
- if (!(cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) &&
- !NIL_P(klass)) {
- rb_ary_push(ary, klass);
- }
- cref = cref->nd_next;
- }
- return ary;
-}
-
-/*
- * call-seq:
- * Module.constants -> array
- * Module.constants(inherited) -> array
- *
- * In the first form, returns an array of the names of all
- * constants accessible from the point of call.
- * This list includes the names of all modules and classes
- * defined in the global scope.
- *
- * Module.constants.first(4)
- * # => [:ARGF, :ARGV, :ArgumentError, :Array]
- *
- * Module.constants.include?(:SEEK_SET) # => false
- *
- * class IO
- * Module.constants.include?(:SEEK_SET) # => true
- * end
- *
- * The second form calls the instance method +constants+.
- */
-
-static VALUE
-rb_mod_s_constants(int argc, VALUE *argv, VALUE mod)
-{
- const NODE *cref = rb_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 (!(cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) &&
- !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, volatile VALUE));
-
-static void
-setup_exception(rb_thread_t *th, int tag, volatile VALUE mesg)
-{
- VALUE at;
- VALUE e;
- const char *file;
- volatile int line = 0;
-
- if (NIL_P(mesg)) {
- mesg = th->errinfo;
- if (INTERNAL_EXCEPTION_P(mesg)) JUMP_TAG(TAG_FATAL);
- }
- 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)) {
- if (mesg == sysstack_error) {
- at = rb_enc_sprintf(rb_usascii_encoding(), "%s:%d", file, line);
- at = rb_ary_new3(1, at);
- rb_iv_set(mesg, "bt", at);
- }
- else {
- 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 && line) {
- warn_printf("Exception `%s' at %s:%d - %s\n",
- rb_obj_classname(th->errinfo),
- file, line, RSTRING_PTR(e));
- }
- else if (file) {
- warn_printf("Exception `%s' at %s - %s\n",
- rb_obj_classname(th->errinfo),
- file, 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_threadptr_reset_raised(th);
- JUMP_TAG(status);
- }
- }
-
- if (rb_threadptr_set_raised(th)) {
- th->errinfo = exception_error;
- rb_threadptr_reset_raised(th);
- JUMP_TAG(TAG_FATAL);
- }
-
- rb_trap_restore_mask();
-
- if (tag != TAG_FATAL) {
- EXEC_EVENT_HOOK(th, RUBY_EVENT_RAISE, th->cfp->self, 0, 0);
- }
-}
-
-static void
-rb_longjmp(int tag, volatile VALUE mesg)
-{
- rb_thread_t *th = GET_THREAD();
- setup_exception(th, tag, mesg);
- rb_thread_raised_clear(th);
- JUMP_TAG(tag);
-}
-
-static VALUE make_exception(int argc, VALUE *argv, int isstr);
-
-void
-rb_exc_raise(VALUE mesg)
-{
- if (!NIL_P(mesg)) {
- mesg = make_exception(1, &mesg, FALSE);
- }
- rb_longjmp(TAG_RAISE, mesg);
-}
-
-void
-rb_exc_fatal(VALUE mesg)
-{
- if (!NIL_P(mesg)) {
- mesg = make_exception(1, &mesg, FALSE);
- }
- 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 */
-}
-
-static VALUE
-make_exception(int argc, VALUE *argv, int isstr)
-{
- VALUE mesg;
- ID exception;
- int n;
-
- mesg = Qnil;
- switch (argc) {
- case 0:
- break;
- case 1:
- if (NIL_P(argv[0]))
- break;
- if (isstr) {
- mesg = rb_check_string_type(argv[0]);
- if (!NIL_P(mesg)) {
- mesg = rb_exc_new3(rb_eRuntimeError, mesg);
- break;
- }
- }
- n = 0;
- goto exception_call;
-
- case 2:
- case 3:
- n = 1;
- exception_call:
- if (argv[0] == sysstack_error) return argv[0];
- CONST_ID(exception, "exception");
- mesg = rb_check_funcall(argv[0], exception, n, argv+1);
- if (mesg == Qundef) {
- rb_raise(rb_eTypeError, "exception class/object expected");
- }
- break;
- default:
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..3)", argc);
- 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;
-}
-
-VALUE
-rb_make_exception(int argc, VALUE *argv)
-{
- return make_exception(argc, argv, TRUE);
-}
-
-void
-rb_raise_jump(VALUE mesg)
-{
- rb_thread_t *th = GET_THREAD();
- rb_control_frame_t *cfp = th->cfp;
- VALUE klass = cfp->me->klass;
- VALUE self = cfp->self;
- ID mid = cfp->me->called_id;
-
- th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
-
- setup_exception(th, TAG_RAISE, mesg);
-
- EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, self, mid, klass);
- rb_thread_raised_clear(th);
- JUMP_TAG(TAG_RAISE);
-}
-
-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 TRUE;
- }
- else {
- return FALSE;
- }
-}
-
-int
-rb_iterator_p(void)
-{
- return rb_block_given_p();
-}
-
-VALUE rb_eThreadError;
-
-void
-rb_need_block(void)
-{
- if (!rb_block_given_p()) {
- rb_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 = FALSE;
- VALUE eclass;
-
- va_init_list(args, data2);
- while ((eclass = va_arg(args, VALUE)) != 0) {
- if (rb_obj_is_kind_of(th->errinfo, eclass)) {
- handle = TRUE;
- 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)
-{
- volatile VALUE result = Qnil;
- int status;
- rb_thread_t *th = GET_THREAD();
- rb_control_frame_t *cfp = th->cfp;
- struct rb_vm_protect_tag protect_tag;
- rb_jmpbuf_t org_jmpbuf;
-
- protect_tag.prev = th->protect_tag;
-
- PUSH_TAG();
- th->protect_tag = &protect_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->protect_tag = protect_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;
-}
-
-static const rb_method_entry_t *
-method_entry_of_iseq(rb_control_frame_t *cfp, rb_iseq_t *iseq)
-{
- rb_thread_t *th = GET_THREAD();
- rb_control_frame_t *cfp_limit;
-
- cfp_limit = (rb_control_frame_t *)(th->stack + th->stack_size);
- while (cfp_limit > cfp) {
- if (cfp->iseq == iseq)
- return cfp->me;
- cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
- }
- return 0;
-}
-
-static ID
-frame_func_id(rb_control_frame_t *cfp)
-{
- const rb_method_entry_t *me_local;
- rb_iseq_t *iseq = cfp->iseq;
- if (cfp->me) {
- return cfp->me->def->original_id;
- }
- while (iseq) {
- if (RUBY_VM_IFUNC_P(iseq)) {
- NODE *ifunc = (NODE *)iseq;
- if (ifunc->nd_aid) return ifunc->nd_aid;
- return rb_intern("<ifunc>");
- }
- me_local = method_entry_of_iseq(cfp, iseq);
- if (me_local) {
- cfp->me = me_local;
- return me_local->def->original_id;
- }
- 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)
-{
- return frame_func_id(GET_THREAD()->cfp);
-}
-
-static ID
-rb_frame_caller(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 reverse order.
- */
-
-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 (at least 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);
-}
-
-static VALUE *
-errinfo_place(rb_thread_t *th)
-{
- 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_thread_errinfo(rb_thread_t *th)
-{
- VALUE *ptr = errinfo_place(th);
- if (ptr) {
- return *ptr;
- }
- else {
- return th->errinfo;
- }
-}
-
-static VALUE
-get_errinfo(void)
-{
- return get_thread_errinfo(GET_THREAD());
-}
-
-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(GET_THREAD());
- 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);
-}
-
-/*
- * 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_caller(); /* need *caller* ID */
-
- if (fname) {
- return ID2SYM(fname);
- }
- else {
- return Qnil;
- }
-}
-
-void
-Init_eval(void)
-{
- rb_define_virtual_variable("$@", errat_getter, errat_setter);
- rb_define_virtual_variable("$!", errinfo_getter, 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("__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_undef_method(rb_cClass, "module_function");
-
- 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 */
-
- exception_error = rb_exc_new3(rb_eFatal,
- rb_obj_freeze(rb_str_new2("exception reentered")));
- OBJ_TAINT(exception_error);
- OBJ_FREEZE(exception_error);
-}