summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-11-16 10:38:15 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-11-16 10:38:15 +0000
commitde870875f773f5a680b12e5306bc316d35465fe5 (patch)
tree3e7e6687bcf49cc892b6d2fed53c6f5fcd48ae7e
parentb1acfbc121ad5eecaf315b6126f960894da1d83b (diff)
vm_eval.c: rb_current_receiver
* vm_eval.c (rb_current_receiver): new function to return the receiver in the current control frame. [Feature #10195] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@48462 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-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 87cad170aa..b7ca593680 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 c8aafc4d55..145d922b10 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 be76515cdc..e598c61979 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 18183f787c..5b3ca8c0a8 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 32b31580d6..16927dcf7d 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 0d47aacf30..0f2b19053d 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)
{