diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-05-13 05:52:03 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-05-13 05:52:03 +0000 |
commit | 0824f9f224117ce26973df3ebc6216d03723dd0e (patch) | |
tree | ae0cfcf9bcbf5bad8fd00620b84c734d30f94d2a /proc.c | |
parent | 304850801475722c686e31c93f82e18ede93ba05 (diff) | |
download | ruby-0824f9f224117ce26973df3ebc6216d03723dd0e.tar.gz |
proc.c: Kernel#singleton_method
* proc.c (rb_obj_singleton_method): new method Kernel#singleton_method
which returns a Method object of the singleton method.
non-singleton method causes NameError, but not aliased or zsuper
method, right now.
[ruby-core:54914] [Feature #8391]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40684 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'proc.c')
-rw-r--r-- | proc.c | 61 |
1 files changed, 57 insertions, 4 deletions
@@ -933,18 +933,18 @@ rb_obj_is_method(VALUE m) } static VALUE -mnew(VALUE klass, VALUE obj, ID id, VALUE mclass, int scope) +mnew_from_me(rb_method_entry_t *me, VALUE defined_class, VALUE klass, + VALUE obj, ID id, VALUE mclass, int scope) { VALUE method; - VALUE rclass = klass, defined_class; + VALUE rclass = klass; ID rid = id; struct METHOD *data; - rb_method_entry_t *me, meb; + rb_method_entry_t meb; rb_method_definition_t *def = 0; rb_method_flag_t flag = NOEX_UNDEF; again: - me = rb_method_entry_without_refinements(klass, id, &defined_class); if (UNDEFINED_METHOD_ENTRY_P(me)) { ID rmiss = idRespond_to_missing; VALUE sym = ID2SYM(id); @@ -988,6 +988,7 @@ mnew(VALUE klass, VALUE obj, ID id, VALUE mclass, int scope) if (def && def->type == VM_METHOD_TYPE_ZSUPER) { klass = RCLASS_SUPER(defined_class); id = def->original_id; + me = rb_method_entry_without_refinements(klass, id, &defined_class); goto again; } @@ -1019,6 +1020,15 @@ mnew(VALUE klass, VALUE obj, ID id, VALUE mclass, int scope) return method; } +static VALUE +mnew(VALUE klass, VALUE obj, ID id, VALUE mclass, int scope) +{ + VALUE defined_class; + rb_method_entry_t *me = + rb_method_entry_without_refinements(klass, id, &defined_class); + return mnew_from_me(me, defined_class, klass, obj, id, mclass, scope); +} + /********************************************************************** * @@ -1274,6 +1284,48 @@ rb_obj_public_method(VALUE obj, VALUE vid) /* * call-seq: + * obj.singleton_method(sym) -> method + * + * Similar to _method_, searches singleton method only. + * + * class Demo + * def initialize(n) + * @iv = n + * end + * def hello() + * "Hello, @iv = #{@iv}" + * end + * end + * + * k = Demo.new(99) + * def k.hi + * "Hi, @iv = #{@iv}" + * end + * m = k.singleton_method(:hi) + * m.call #=> "Hi, @iv = 99" + * m = k.singleton_method(:hello) #=> NameError + */ + +VALUE +rb_obj_singleton_method(VALUE obj, VALUE vid) +{ + rb_method_entry_t *me; + VALUE klass; + ID id = rb_check_id(&vid); + if (!id) { + rb_name_error_str(vid, "undefined singleton method `%"PRIsVALUE"' for `%"PRIsVALUE"'", + QUOTE(vid), obj); + } + if (NIL_P(klass = rb_singleton_class_get(obj)) || + !(me = rb_method_entry_at(klass, id))) { + rb_name_error(id, "undefined singleton method `%"PRIsVALUE"' for `%"PRIsVALUE"'", + QUOTE_ID(id), obj); + } + return mnew_from_me(me, klass, klass, obj, id, rb_cMethod, FALSE); +} + +/* + * call-seq: * mod.instance_method(symbol) -> unbound_method * * Returns an +UnboundMethod+ representing the given @@ -2372,6 +2424,7 @@ Init_Proc(void) rb_define_method(rb_cMethod, "parameters", rb_method_parameters, 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); /* UnboundMethod */ rb_cUnboundMethod = rb_define_class("UnboundMethod", rb_cObject); |