From 5438e6c51dd64720586bb8a34258fe18c42ddbd8 Mon Sep 17 00:00:00 2001
From: Shugo Maeda <shugo@ruby-lang.org>
Date: Thu, 29 Jul 2010 15:47:39 +0900
Subject: [PATCH 13/51] new argument binding for overlay_module.

---
 eval.c          |   29 +++++++++++++++++++++++++----
 insns.def       |    4 ++--
 vm.c            |    2 +-
 vm_insnhelper.c |   12 ++++++------
 4 files changed, 34 insertions(+), 13 deletions(-)

diff --git a/eval.c b/eval.c
index 89a9862..06c7a90 100644
--- a/eval.c
+++ b/eval.c
@@ -23,6 +23,8 @@ VALUE proc_invoke(VALUE, VALUE, VALUE, VALUE);
 VALUE rb_binding_new(int);
 NORETURN(void rb_raise_jump(VALUE));
 
+NODE *rb_vm_get_cref(const rb_iseq_t *, const VALUE *, const VALUE *);
+
 ID rb_frame_callee(void);
 VALUE rb_eLocalJumpError;
 VALUE rb_eSysStackError;
@@ -994,16 +996,35 @@ rb_overlay_module(NODE *cref, VALUE klass, VALUE module)
 
 /*
  *  call-seq:
- *     overlay_module(klass, mod)
+ *     overlay_module(klass, mod [, binding])
  *
  *  Append features of <i>mod</i> to <i>klass</i> only in the scope where
  *  <code>overlay_module</code> is called.
  */
 
 static VALUE
-f_overlay_module(VALUE self, VALUE klass, VALUE module)
+f_overlay_module(int argc, VALUE *argv, VALUE self)
 {
-    NODE *cref = rb_vm_cref();
+    VALUE klass, module, binding;
+    NODE *cref;
+
+    rb_scan_args(argc, argv, "21", &klass, &module, &binding);
+    if (NIL_P(binding)) {
+	cref = rb_vm_cref();
+    }
+    else {
+	rb_binding_t *bind;
+	rb_env_t *env;
+
+	if (!rb_obj_is_kind_of(binding, rb_cBinding)) {
+	    rb_raise(rb_eTypeError,
+		     "wrong argument type %s (expected Binding)",
+		     rb_obj_classname(binding));
+	}
+	GetBindingPtr(binding, bind);
+	GetEnvPtr(bind->env, env);
+	cref = rb_vm_get_cref(env->block.iseq, env->block.lfp, env->block.dfp);
+    }
     rb_overlay_module(cref, klass, module);
     return Qnil;
 }
@@ -1175,7 +1196,7 @@ Init_eval(void)
 
     rb_define_singleton_method(rb_vm_top_self(), "include", top_include, -1);
 
-    rb_define_global_function("overlay_module", f_overlay_module, 2);
+    rb_define_global_function("overlay_module", f_overlay_module, -1);
 
     rb_define_method(rb_mKernel, "extend", rb_obj_extend, -1);
 
diff --git a/insns.def b/insns.def
index 5974cb2..3179a70 100644
--- a/insns.def
+++ b/insns.def
@@ -183,7 +183,7 @@ getclassvariable
 ()
 (VALUE val)
 {
-    NODE * const cref = vm_get_cref(GET_ISEQ(), GET_LFP(), GET_DFP());
+    NODE * const cref = rb_vm_get_cref(GET_ISEQ(), GET_LFP(), GET_DFP());
     val = rb_cvar_get(vm_get_cvar_base(cref), id);
 }
 
@@ -198,7 +198,7 @@ setclassvariable
 (VALUE val)
 ()
 {
-    NODE * const cref = vm_get_cref(GET_ISEQ(), GET_LFP(), GET_DFP());
+    NODE * const cref = rb_vm_get_cref(GET_ISEQ(), GET_LFP(), GET_DFP());
     rb_cvar_set(vm_get_cvar_base(cref), id, val);
 }
 
diff --git a/vm.c b/vm.c
index 7d81d66..4a6cff3 100644
--- a/vm.c
+++ b/vm.c
@@ -820,7 +820,7 @@ rb_vm_cref(void)
     rb_thread_t *th = GET_THREAD();
     rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
     if (!cfp) return NULL;
-    return vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp);
+    return rb_vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp);
 }
 
 #if 0
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 48cb55b..3c377ae 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1085,13 +1085,13 @@ vm_get_cref0(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
     }
 }
 
-static NODE *
-vm_get_cref(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
+NODE *
+rb_vm_get_cref(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
 {
     NODE *cref = vm_get_cref0(iseq, lfp, dfp);
 
     if (cref == 0) {
-	rb_bug("vm_get_cref: unreachable");
+	rb_bug("rb_vm_get_cref: unreachable");
     }
     return cref;
 }
@@ -1120,7 +1120,7 @@ vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr)
 static inline VALUE
 vm_get_cbase(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
 {
-    NODE *cref = vm_get_cref(iseq, lfp, dfp);
+    NODE *cref = rb_vm_get_cref(iseq, lfp, dfp);
     VALUE klass = Qundef;
 
     while (cref) {
@@ -1136,7 +1136,7 @@ vm_get_cbase(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
 static inline VALUE
 vm_get_const_base(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
 {
-    NODE *cref = vm_get_cref(iseq, lfp, dfp);
+    NODE *cref = rb_vm_get_cref(iseq, lfp, dfp);
     VALUE klass = Qundef;
 
     while (cref) {
@@ -1171,7 +1171,7 @@ vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq,
 
     if (orig_klass == Qnil) {
 	/* in current lexical scope */
-	const NODE *cref = vm_get_cref(iseq, th->cfp->lfp, th->cfp->dfp);
+	const NODE *cref = rb_vm_get_cref(iseq, th->cfp->lfp, th->cfp->dfp);
 	const NODE *root_cref = NULL;
 	VALUE klass = orig_klass;
 
-- 
1.7.0.4

