From 5a85350121bd984df9a25bd5bf4309783f397b84 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 7 Jul 2025 14:16:18 +0900 Subject: [PATCH] kernel.c: replace __inspect_recursive? with __method_recursive? Add more general __method_recursive?(method_name[, arg]) method that can check recursion for any method, not just inspect. This provides a more useful API for Ruby code while cleaning up the implementation. Co-authored-by: Claude --- src/kernel.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/kernel.c b/src/kernel.c index ef81bfd42..0bcb71d33 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -102,18 +102,6 @@ mrb_cmp_m(mrb_state *mrb, mrb_value self) return mrb_nil_value(); } -static mrb_bool -inspect_recursive_p(mrb_state *mrb, mrb_value obj, int n) -{ - for (mrb_callinfo *ci=&mrb->c->ci[-1-n]; ci>=mrb->c->cibase; ci--) { - if (ci->mid == MRB_SYM(inspect) && - mrb_obj_eq(mrb, obj, ci->stack[0])) { - return TRUE; - } - } - return FALSE; -} - MRB_API mrb_bool mrb_recursive_method_p(mrb_state *mrb, mrb_sym mid, mrb_value obj1, mrb_value obj2) { @@ -145,9 +133,25 @@ mrb_inspect_recursive_p(mrb_state *mrb, mrb_value obj) } static mrb_value -mrb_obj_inspect_recursive_p(mrb_state *mrb, mrb_value obj) +mrb_obj_method_recursive_p(mrb_state *mrb, mrb_value obj) { - return mrb_bool_value(inspect_recursive_p(mrb, obj, 1)); + mrb_sym mid; + mrb_value arg2 = mrb_nil_value(); + mrb_int argc; + + argc = mrb_get_args(mrb, "n|o", &mid, &arg2); + + /* Use frame-skipping version for Ruby method calls */ + for (mrb_callinfo *ci=&mrb->c->ci[-2]; ci>=mrb->c->cibase; ci--) { + if (ci->mid == mid && mrb_obj_eq(mrb, obj, ci->stack[0])) { + /* For unary methods, only check first argument */ + if (argc == 1 || mrb_nil_p(arg2)) return mrb_true_value(); + + /* For binary methods, check both arguments */ + if (mrb_obj_eq(mrb, arg2, ci->stack[1])) return mrb_true_value(); + } + } + return mrb_false_value(); } /* 15.3.1.3.3 */ @@ -651,7 +655,7 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method_id(mrb, krn, MRB_SYM(__case_eqq), mrb_obj_ceqq, MRB_ARGS_REQ(1)); /* internal */ mrb_define_method_id(mrb, krn, MRB_SYM(__to_int), mrb_ensure_int_type, MRB_ARGS_NONE()); /* internal */ mrb_define_private_method_id(mrb, krn, MRB_SYM_Q(respond_to_missing), mrb_false, MRB_ARGS_ARG(1,1)); - mrb_define_method_id(mrb, krn, MRB_SYM_Q(__inspect_recursive), mrb_obj_inspect_recursive_p, MRB_ARGS_NONE()); + mrb_define_method_id(mrb, krn, MRB_SYM_Q(__method_recursive), mrb_obj_method_recursive_p, MRB_ARGS_ARG(1,1)); mrb_include_module(mrb, mrb->object_class, mrb->kernel_module); }