From 945f4df6a8c9eadd9b17558b2b374110b5ac3128 Mon Sep 17 00:00:00 2001 From: matz Date: Wed, 23 Sep 2009 08:46:44 +0000 Subject: * vm_method.c (basic_obj_respond_to): new function to fundamental behavior for #respond_to? * vm_method.c (basic_obj_respond_to): calls #respond_to_missing method if overridden, to check responsiveness of methods implemented by #method_missing. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25054 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 9 +++++++++ vm_method.c | 37 +++++++++++++++++++++++++++---------- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8dfe995234..94ffa631ee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -23,6 +23,15 @@ Wed Sep 23 05:03:36 2009 Marc-Andre Lafortune Module#define_method, even when that singleton class was of the right kind_of. A patch by Shane O'Brien [ruby-core:25632] +Tue Sep 22 22:56:48 2009 Yukihiro Matsumoto + + * vm_method.c (basic_obj_respond_to): new function to fundamental + behavior for #respond_to? + + * vm_method.c (basic_obj_respond_to): calls #respond_to_missing + method if overridden, to check responsiveness of methods + implemented by #method_missing. + Tue Sep 22 16:34:33 2009 Nobuyoshi Nakada * st.c (st_table_entry, st_get_key): use st_index_t. diff --git a/vm_method.c b/vm_method.c index b64dbcc683..2be0a9603f 100644 --- a/vm_method.c +++ b/vm_method.c @@ -8,7 +8,7 @@ static void rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me); -static ID object_id; +static ID object_id, respond_to_missing; static ID removed, singleton_removed, undefined, singleton_undefined; static ID added, singleton_added, attached; @@ -1114,21 +1114,30 @@ rb_method_basic_definition_p(VALUE klass, ID id) return 0; } +static inline int +basic_obj_respond_to(VALUE obj, ID id, int pub) +{ + VALUE klass = CLASS_OF(obj); + + if (!rb_method_boundp(klass, id, pub)) { + if (!rb_method_basic_definition_p(klass, respond_to_missing)) { + return RTEST(rb_funcall(obj, respond_to_missing, pub ? 1 : 2, ID2SYM(id), Qtrue)); + } + return Qfalse; + } + return Qtrue; +} + int rb_obj_respond_to(VALUE obj, ID id, int priv) { VALUE klass = CLASS_OF(obj); if (rb_method_basic_definition_p(klass, idRespond_to)) { - return rb_method_boundp(klass, id, !priv); + return basic_obj_respond_to(obj, id, !RTEST(priv)); } else { - VALUE args[2]; - int n = 0; - args[n++] = ID2SYM(id); - if (priv) - args[n++] = Qtrue; - return RTEST(rb_funcall2(obj, idRespond_to, n, args)); + return RTEST(rb_funcall(obj, idRespond_to, priv ? 2 : 1, ID2SYM(id), Qtrue)); } } @@ -1138,6 +1147,7 @@ rb_respond_to(VALUE obj, ID id) return rb_obj_respond_to(obj, id, FALSE); } + /* * call-seq: * obj.respond_to?(symbol, include_private=false) => true or false @@ -1159,9 +1169,14 @@ obj_respond_to(int argc, VALUE *argv, VALUE obj) rb_scan_args(argc, argv, "11", &mid, &priv); id = rb_to_id(mid); - if (rb_method_boundp(CLASS_OF(obj), id, !RTEST(priv))) { + if (basic_obj_respond_to(obj, id, !RTEST(priv))) return Qtrue; - } + return Qfalse; +} + +static VALUE +obj_respond_to_missing(int argc, VALUE *argv, VALUE obj) +{ return Qfalse; } @@ -1172,6 +1187,7 @@ Init_eval_method(void) #define rb_intern(str) rb_intern_const(str) rb_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1); + rb_define_method(rb_mKernel, "respond_to_missing?", obj_respond_to_missing, -1); rb_define_private_method(rb_cModule, "remove_method", rb_mod_remove_method, -1); rb_define_private_method(rb_cModule, "undef_method", rb_mod_undef_method, -1); @@ -1199,5 +1215,6 @@ Init_eval_method(void) undefined = rb_intern("method_undefined"); singleton_undefined = rb_intern("singleton_method_undefined"); attached = rb_intern("__attached__"); + respond_to_missing = rb_intern("respond_to_missing?"); } -- cgit v1.2.3