summaryrefslogtreecommitdiff
path: root/vm_method.c
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-09-23 08:46:44 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-09-23 08:46:44 +0000
commit945f4df6a8c9eadd9b17558b2b374110b5ac3128 (patch)
tree3f7e648d4b11ac406adb8a6d5dc13b56b5b7bc4c /vm_method.c
parentbda0b012a8ced5b7db0fa5225b5da2a2ebb86aee (diff)
* 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
Diffstat (limited to 'vm_method.c')
-rw-r--r--vm_method.c37
1 files changed, 27 insertions, 10 deletions
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?");
}