summaryrefslogtreecommitdiff
path: root/proc.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-07-26 16:22:41 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-07-26 16:22:41 +0000
commitb4981594dd8ac975d76ad1654a419bd6263c3c69 (patch)
treea5addb7c35ce34625a76898f3fb0b17219b5207c /proc.c
parent042a162af14b2d1f31130271530c7d66be5fd741 (diff)
proc.c: method_super_method
* proc.c (method_super_method): new method Method#super_method, which returns a method object of the method to be called by `super` in the receiver method object. [ruby-core:62202] [Feature #9781] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46964 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'proc.c')
-rw-r--r--proc.c34
1 files changed, 32 insertions, 2 deletions
diff --git a/proc.c b/proc.c
index e9cffbf5a2..5e5705214e 100644
--- a/proc.c
+++ b/proc.c
@@ -1190,8 +1190,8 @@ rb_obj_is_method(VALUE m)
}
static VALUE
-mnew_from_me(rb_method_entry_t *me, VALUE defined_class, VALUE klass,
- VALUE obj, ID id, VALUE mclass, int scope)
+mnew_internal(rb_method_entry_t *me, VALUE defined_class, VALUE klass,
+ VALUE obj, ID id, VALUE mclass, int scope, int error)
{
VALUE method;
VALUE rclass = klass;
@@ -1213,12 +1213,14 @@ mnew_from_me(rb_method_entry_t *me, VALUE defined_class, VALUE klass,
goto gen_method;
}
}
+ if (!error) return Qnil;
rb_print_undef(klass, id, 0);
}
def = me->def;
if (flag == NOEX_UNDEF) {
flag = me->flag;
if (scope && (flag & NOEX_MASK) != NOEX_PUBLIC) {
+ if (!error) return Qnil;
rb_print_inaccessible(klass, id, flag & NOEX_MASK);
}
}
@@ -1272,6 +1274,13 @@ mnew_from_me(rb_method_entry_t *me, VALUE defined_class, VALUE klass,
}
static VALUE
+mnew_from_me(rb_method_entry_t *me, VALUE defined_class, VALUE klass,
+ VALUE obj, ID id, VALUE mclass, int scope)
+{
+ return mnew_internal(me, defined_class, klass, obj, id, mclass, scope, TRUE);
+}
+
+static VALUE
mnew(VALUE klass, VALUE obj, ID id, VALUE mclass, int scope)
{
VALUE defined_class;
@@ -2413,6 +2422,25 @@ method_proc(VALUE method)
return procval;
}
+static VALUE
+method_super_method(VALUE method)
+{
+ struct METHOD *data;
+ VALUE defined_class, super_class;
+ rb_method_entry_t *me;
+
+ TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
+ defined_class = data->defined_class;
+ if (BUILTIN_TYPE(defined_class) == T_MODULE) defined_class = data->rclass;
+ super_class = RCLASS_SUPER(defined_class);
+ if (!super_class) return Qnil;
+ me = rb_method_entry_without_refinements(super_class, data->id, &defined_class);
+ if (!me) return Qnil;
+ return mnew_internal(me, defined_class,
+ super_class, data->recv, data->id,
+ rb_obj_class(method), FALSE, FALSE);
+}
+
/*
* call-seq:
* local_jump_error.exit_value -> obj
@@ -2759,6 +2787,7 @@ Init_Proc(void)
rb_define_method(rb_cMethod, "unbind", method_unbind, 0);
rb_define_method(rb_cMethod, "source_location", rb_method_location, 0);
rb_define_method(rb_cMethod, "parameters", rb_method_parameters, 0);
+ rb_define_method(rb_cMethod, "super_method", method_super_method, 0);
rb_define_method(rb_mKernel, "method", rb_obj_method, 1);
rb_define_method(rb_mKernel, "public_method", rb_obj_public_method, 1);
rb_define_method(rb_mKernel, "singleton_method", rb_obj_singleton_method, 1);
@@ -2780,6 +2809,7 @@ Init_Proc(void)
rb_define_method(rb_cUnboundMethod, "bind", umethod_bind, 1);
rb_define_method(rb_cUnboundMethod, "source_location", rb_method_location, 0);
rb_define_method(rb_cUnboundMethod, "parameters", rb_method_parameters, 0);
+ rb_define_method(rb_cUnboundMethod, "super_method", method_super_method, 0);
/* Module#*_method */
rb_define_method(rb_cModule, "instance_method", rb_mod_instance_method, 1);