From 36a0f83db328f33047c3e2c1c62c25abddffdf02 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 21 Mar 2026 14:33:49 +0900 Subject: [PATCH] mruby-regexp: accept Regexp argument in Regexp.new Regexp.new(regexp) copies the source and flags from the given Regexp object, matching CRuby behavior. Co-authored-by: Claude --- mrbgems/mruby-regexp/src/regexp.c | 19 +++++++++++++++++-- mrbgems/mruby-regexp/test/regexp.rb | 10 +++++++++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/mrbgems/mruby-regexp/src/regexp.c b/mrbgems/mruby-regexp/src/regexp.c index d580880f8..85e361c6a 100644 --- a/mrbgems/mruby-regexp/src/regexp.c +++ b/mrbgems/mruby-regexp/src/regexp.c @@ -72,6 +72,7 @@ parse_flags(mrb_state *mrb, mrb_value flags_val) /* * Regexp.new(pattern, flags=nil) + * Regexp.new(regexp) * Regexp.compile(pattern, flags=nil) */ static mrb_value @@ -81,9 +82,23 @@ regexp_init(mrb_state *mrb, mrb_value self) mrb_value flags_val = mrb_nil_value(); mrb_regexp_pattern *pat; - mrb_get_args(mrb, "S|o", &pattern, &flags_val); + mrb_get_args(mrb, "o|o", &pattern, &flags_val); + + uint32_t flags; + + /* If pattern is a Regexp, copy its source and flags */ + if (mrb_obj_is_kind_of(mrb, pattern, mrb_class_get(mrb, "Regexp"))) { + mrb_value iflags = mrb_iv_get(mrb, pattern, mrb_intern_lit(mrb, "@flags")); + flags = mrb_nil_p(iflags) ? 0 : (uint32_t)mrb_integer(iflags); + pattern = mrb_iv_get(mrb, pattern, mrb_intern_lit(mrb, "@source")); + } + else { + if (!mrb_string_p(pattern)) { + mrb_raise(mrb, E_TYPE_ERROR, "wrong argument type (expected String or Regexp)"); + } + flags = parse_flags(mrb, flags_val); + } - uint32_t flags = parse_flags(mrb, flags_val); pat = re_compile(mrb, RSTRING_PTR(pattern), RSTRING_LEN(pattern), flags); DATA_TYPE(self) = ®exp_type; diff --git a/mrbgems/mruby-regexp/test/regexp.rb b/mrbgems/mruby-regexp/test/regexp.rb index 4cabb883d..3dc5373b3 100644 --- a/mrbgems/mruby-regexp/test/regexp.rb +++ b/mrbgems/mruby-regexp/test/regexp.rb @@ -1,8 +1,16 @@ -assert("Regexp.new") do +assert("Regexp.new with string") do re = Regexp.new("abc") assert_kind_of Regexp, re end +assert("Regexp.new with regexp") do + r1 = Regexp.new("abc", Regexp::IGNORECASE) + r2 = Regexp.new(r1) + assert_equal r1.source, r2.source + assert_equal r1.options, r2.options + assert_true r2.match?("ABC") +end + assert("Regexp#match - simple") do re = Regexp.new("abc") md = re.match("xabcy")