ruby-changes:34881
From: nobu <ko1@a...>
Date: Sun, 27 Jul 2014 01:22:57 +0900 (JST)
Subject: [ruby-changes:34881] nobu:r46964 (trunk): proc.c: method_super_method
nobu 2014-07-27 01:22:41 +0900 (Sun, 27 Jul 2014) New Revision: 46964 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=46964 Log: 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] Modified files: trunk/ChangeLog trunk/NEWS trunk/proc.c trunk/test/ruby/test_method.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 46963) +++ ChangeLog (revision 46964) @@ -1,3 +1,10 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Sun Jul 27 01:22:39 2014 Nobuyoshi Nakada <nobu@r...> + + * 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] + Sat Jul 26 17:22:14 2014 URABE Shyouhei <shyouhei@r...> * ext/objspace/objspace_dump.c (dump_append): avoid fflush. Index: proc.c =================================================================== --- proc.c (revision 46963) +++ proc.c (revision 46964) @@ -1190,8 +1190,8 @@ rb_obj_is_method(VALUE m) https://github.com/ruby/ruby/blob/trunk/proc.c#L1190 } 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, VALU https://github.com/ruby/ruby/blob/trunk/proc.c#L1213 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, VALU https://github.com/ruby/ruby/blob/trunk/proc.c#L1274 } 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) https://github.com/ruby/ruby/blob/trunk/proc.c#L2422 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) https://github.com/ruby/ruby/blob/trunk/proc.c#L2787 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) https://github.com/ruby/ruby/blob/trunk/proc.c#L2809 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); Index: NEWS =================================================================== --- NEWS (revision 46963) +++ NEWS (revision 46964) @@ -63,6 +63,8 @@ with all sufficient information, see the https://github.com/ruby/ruby/blob/trunk/NEWS#L63 * Method * New methods: * Method#curry([arity]) returns a curried Proc. + * Method#super_method returns a Method of superclass, which would be called + when super is used. === Core classes compatibility issues (excluding feature bug fixes) Index: test/ruby/test_method.rb =================================================================== --- test/ruby/test_method.rb (revision 46963) +++ test/ruby/test_method.rb (revision 46964) @@ -806,4 +806,54 @@ class TestMethod < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_method.rb#L806 } assert_curry_var_args(c.new.method(:var_args)) end + + Feature9781 = '[ruby-core:62202] [Feature #9781]' + + def test_super_method + o = Derived.new + m = o.method(:foo).super_method + assert_equal(Base, m.owner, Feature9781) + assert_same(o, m.receiver, Feature9781) + assert_equal(:foo, m.name, Feature9781) + m = assert_nothing_raised(NameError, Feature9781) {break m.super_method} + assert_nil(m, Feature9781) + end + + def test_super_method_unbound + m = Derived.instance_method(:foo) + m = m.super_method + assert_equal(Base.instance_method(:foo), m, Feature9781) + m = assert_nothing_raised(NameError, Feature9781) {break m.super_method} + assert_nil(m, Feature9781) + end + + def test_super_method_module + m1 = Module.new {def foo; end} + c1 = Class.new(Derived) {include m1; def foo; end} + m = c1.instance_method(:foo) + assert_equal(c1, m.owner, Feature9781) + m = m.super_method + assert_equal(m1, m.owner, Feature9781) + m = m.super_method + assert_equal(Derived, m.owner, Feature9781) + m = m.super_method + assert_equal(Base, m.owner, Feature9781) + m2 = Module.new {def foo; end} + o = c1.new.extend(m2) + m = o.method(:foo) + assert_equal(m2, m.owner, Feature9781) + m = m.super_method + assert_equal(c1, m.owner, Feature9781) + assert_same(o, m.receiver, Feature9781) + end + + def test_super_method_removed + c1 = Class.new {private def foo; end} + c2 = Class.new(c1) {public :foo} + c3 = Class.new(c2) {def foo; end} + c1.class_eval {undef foo} + m = c3.instance_method(:foo) + m = assert_nothing_raised(NameError, Feature9781) {break m.super_method} + assert_nil(m, Feature9781) + end end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/