summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--README.EXT5
-rw-r--r--README.EXT.ja11
-rw-r--r--include/ruby/ruby.h1
-rw-r--r--test/-ext-/proc/test_bmethod.rb6
-rw-r--r--vm_eval.c10
6 files changed, 38 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 87cad17..b7ca593 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Sun Nov 16 19:38:10 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * vm_eval.c (rb_current_receiver): new function to return the
+ receiver in the current control frame. [Feature #10195]
+
Sun Nov 16 19:11:04 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
* lib/timeout.rb (Timeout::ExitException#exception): rescue
diff --git a/README.EXT b/README.EXT
index c8aafc4..145d922 100644
--- a/README.EXT
+++ b/README.EXT
@@ -442,6 +442,11 @@ you may rely on:
VALUE rb_call_super(int argc, const VALUE *argv)
+To achieve the receiver of the current scope (if no other way is
+available), you can use:
+
+ VALUE rb_current_receiver(void)
+
=== Constant Definition
We have 2 functions to define constants:
diff --git a/README.EXT.ja b/README.EXT.ja
index be76515..e598c61 100644
--- a/README.EXT.ja
+++ b/README.EXT.ja
@@ -473,6 +473,17 @@ funcはクラスを引数として受け取って,新しく割り当てられ
ソースなどを含まない,できるだけ「空」のままにしておいたほう
がよいでしょう.
+継承したクラスにある既存のメソッドをオーバーライドしているな
+ら,オーバーライドされたメソッドを呼び出すには以下の関数を使
+います.
+
+ VALUE rb_call_super(int argc, const VALUE *argv)
+
+現在のスコープのレシーバは(他に方法がなければ),以下の関数で
+得ることができます.
+
+ VALUE rb_current_receiver(void)
+
=== 定数定義
拡張ライブラリが必要な定数はあらかじめ定義しておいた方が良い
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index 18183f7..5b3ca8c 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -1474,6 +1474,7 @@ VALUE rb_funcall_passing_block(VALUE, ID, int, const VALUE*);
VALUE rb_funcall_with_block(VALUE, ID, int, const VALUE*, VALUE);
int rb_scan_args(int, const VALUE*, const char*, ...);
VALUE rb_call_super(int, const VALUE*);
+VALUE rb_current_receiver(void);
/* rb_scan_args() format allows ':' for optional hash */
#define HAVE_RB_SCAN_ARGS_OPTIONAL_HASH 1
diff --git a/test/-ext-/proc/test_bmethod.rb b/test/-ext-/proc/test_bmethod.rb
index 32b3158..16927dc 100644
--- a/test/-ext-/proc/test_bmethod.rb
+++ b/test/-ext-/proc/test_bmethod.rb
@@ -15,6 +15,7 @@ class TestProc::TestBMethod
class Bound < Base
define_method(:foo, Bug::Proc.make_call_super(42))
+ define_method(:receiver, Bug::Proc.make_call_receiver(nil))
end
def test_super_in_bmethod
@@ -28,4 +29,9 @@ class TestProc::TestBMethod
obj.foo(2) {|*a| result = a}
assert_equal([2, 42], result)
end
+
+ def test_receiver_in_bmethod
+ obj = Bound.new
+ assert_same(obj, obj.receiver)
+ end
end
diff --git a/vm_eval.c b/vm_eval.c
index 0d47aac..0f2b190 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -290,6 +290,16 @@ rb_call_super(int argc, const VALUE *argv)
return vm_call_super(GET_THREAD(), argc, argv);
}
+VALUE
+rb_current_receiver(void)
+{
+ rb_thread_t *th = GET_THREAD();
+ rb_control_frame_t *cfp;
+ if (!th || !(cfp = th->cfp))
+ rb_raise(rb_eRuntimeError, "no self, no life");
+ return cfp->self;
+}
+
static inline void
stack_check(void)
{