summaryrefslogtreecommitdiff
path: root/eval.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-07-04 02:11:37 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-07-04 02:11:37 +0000
commita7e1820a9f9c0b6c84c281c171c105a34aa16738 (patch)
tree5de8ea761af4e4ac30dc229518093bacc55d2ee2 /eval.c
parent07132e0675ecacd9215504e9f9631fa1f83b7670 (diff)
__callee__ fix
* eval.c (rb_frame_callee, rb_f_callee_name): fix to return the called id. * vm_insnhelper.c (vm_push_frame): set proper method entry. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36301 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c68
1 files changed, 60 insertions, 8 deletions
diff --git a/eval.c b/eval.c
index 37bb35a148..2c82d4f2b8 100644
--- a/eval.c
+++ b/eval.c
@@ -874,27 +874,66 @@ frame_func_id(rb_control_frame_t *cfp)
return 0;
}
-ID
-rb_frame_this_func(void)
+static ID
+frame_called_id(rb_control_frame_t *cfp)
{
- return frame_func_id(GET_THREAD()->cfp);
+ const rb_method_entry_t *me_local;
+ rb_iseq_t *iseq = cfp->iseq;
+ if (cfp->me) {
+ return cfp->me->called_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->called_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_callee(void)
+rb_frame_this_func(void)
{
return frame_func_id(GET_THREAD()->cfp);
}
-static ID
-rb_frame_caller(void)
+static rb_control_frame_t *
+previous_frame(rb_thread_t *th)
{
- 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 prev_cfp;
+}
+
+ID
+rb_frame_callee(void)
+{
+ rb_control_frame_t *prev_cfp = previous_frame(GET_THREAD());
+ if (!prev_cfp) return 0;
+ return frame_called_id(prev_cfp);
+}
+
+static ID
+rb_frame_caller(void)
+{
+ rb_control_frame_t *prev_cfp = previous_frame(GET_THREAD());
+ if (!prev_cfp) return 0;
return frame_func_id(prev_cfp);
}
@@ -1248,6 +1287,19 @@ rb_f_method_name(void)
}
}
+static VALUE
+rb_f_callee_name(void)
+{
+ ID fname = rb_frame_callee(); /* need *callee* ID */
+
+ if (fname) {
+ return ID2SYM(fname);
+ }
+ else {
+ return Qnil;
+ }
+}
+
void
Init_eval(void)
{
@@ -1260,7 +1312,7 @@ Init_eval(void)
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_global_function("__callee__", rb_f_callee_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);