From fbb3a2426f66a4ea794e4fea66af357b8d06ce09 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 27 Mar 2023 19:14:21 +0900 Subject: [PATCH] proc.c (mrb_proc_eql): define `==` and `eql?` for Proc class --- include/mruby/internal.h | 1 + src/proc.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/include/mruby/internal.h b/include/mruby/internal.h index 9a7d33ac7..a5bf81e76 100644 --- a/include/mruby/internal.h +++ b/include/mruby/internal.h @@ -118,6 +118,7 @@ void mrb_proc_merge_lvar(mrb_state *mrb, mrb_irep *irep, struct REnv *env, int n mrb_value mrb_proc_local_variables(mrb_state *mrb, const struct RProc *proc); const struct RProc *mrb_proc_get_caller(mrb_state *mrb, struct REnv **env); mrb_value mrb_proc_get_self(mrb_state *mrb, struct RProc *p, struct RClass **target_class_p); +mrb_bool mrb_proc_eql(mrb_state *mrb, mrb_value self, mrb_value other); #endif /* range */ diff --git a/src/proc.c b/src/proc.c index f8139a8a7..ac601a4b8 100644 --- a/src/proc.c +++ b/src/proc.c @@ -277,6 +277,36 @@ proc_arity(mrb_state *mrb, mrb_value self) return mrb_int_value(mrb, mrb_proc_arity(mrb_proc_ptr(self))); } +mrb_bool +mrb_proc_eql(mrb_state *mrb, mrb_value self, mrb_value other) +{ + if (mrb_type(self) != MRB_TT_PROC) return FALSE; + if (mrb_type(other) != MRB_TT_PROC) return FALSE; + + struct RProc *p1 = mrb_proc_ptr(self); + struct RProc *p2 = mrb_proc_ptr(other); + if (MRB_PROC_CFUNC_P(p1)) { + if (!MRB_PROC_CFUNC_P(p1)) return FALSE; + if (p1->body.func != p2->body.func) return FALSE; + } + else if (MRB_PROC_CFUNC_P(p2)) return FALSE; + else if (p1->body.irep != p2->body.irep) return FALSE; + return TRUE; +} + +static mrb_value +proc_eql(mrb_state *mrb, mrb_value self) +{ + return mrb_bool_value(mrb_proc_eql(mrb, self, mrb_get_arg1(mrb))); +} + +static mrb_value +proc_hash(mrb_state *mrb, mrb_value self) +{ + struct RProc *p = mrb_proc_ptr(self); + return mrb_int_value(mrb, (mrb_int)(((intptr_t)p->body.irep)^MRB_TT_PROC)); +} + /* 15.3.1.2.6 */ /* 15.3.1.3.27 */ /* @@ -464,6 +494,9 @@ mrb_init_proc(mrb_state *mrb) mrb_define_class_method(mrb, mrb->proc_class, "new", mrb_proc_s_new, MRB_ARGS_NONE()|MRB_ARGS_BLOCK()); mrb_define_method(mrb, mrb->proc_class, "initialize_copy", mrb_proc_init_copy, MRB_ARGS_REQ(1)); mrb_define_method(mrb, mrb->proc_class, "arity", proc_arity, MRB_ARGS_NONE()); /* 15.2.17.4.2 */ + mrb_define_method(mrb, mrb->proc_class, "==", proc_eql, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, mrb->proc_class, "eql?", proc_eql, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, mrb->proc_class, "hash", proc_hash, MRB_ARGS_NONE()); /* 15.2.17.4.2 */ MRB_METHOD_FROM_PROC(m, &call_proc); mrb_define_method_raw(mrb, mrb->proc_class, MRB_SYM(call), m); /* 15.2.17.4.3 */