[Bug #20969] Pass `assignable` from ripper
authorNobuyoshi Nakada <[email protected]>
Thu, 19 Dec 2024 14:20:09 +0000 (19 23:20 +0900)
committerNobuyoshi Nakada <[email protected]>
Thu, 19 Dec 2024 14:20:09 +0000 (19 23:20 +0900)
For the universal parser, `rb_reg_named_capture_assign_iter_impl`
function is shared between the parser and ripper.  However
`parser_params` struct is partially different, and `assignable`
function depends on that part indirectly.

internal/parse.h
parse.y
ruby_parser.c
rubyparser.h
test/ripper/test_ripper.rb

index de42acb..c4df4b9 100644 (file)
@@ -79,8 +79,9 @@ void rb_parser_string_free(rb_parser_t *p, rb_parser_string_t *str);
 int rb_parser_dvar_defined_ref(struct parser_params*, ID, ID**);
 ID rb_parser_internal_id(struct parser_params*);
 int rb_parser_reg_fragment_check(struct parser_params*, rb_parser_string_t*, int);
-int rb_reg_named_capture_assign_iter_impl(struct parser_params *p, const char *s, long len, rb_encoding *enc, NODE **succ_block, const rb_code_location_t *loc);
+int rb_reg_named_capture_assign_iter_impl(struct parser_params *p, const char *s, long len, rb_encoding *enc, NODE **succ_block, const rb_code_location_t *loc, rb_parser_assignable_func assignable);
 int rb_parser_local_defined(struct parser_params *p, ID id, const struct rb_iseq_struct *iseq);
+NODE *rb_parser_assignable(struct parser_params *p, ID id, NODE *val, const YYLTYPE *loc);
 
 RUBY_SYMBOL_EXPORT_END
 
diff --git a/parse.y b/parse.y
index 768492d..ee85f5f 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -76,7 +76,7 @@ syntax_error_new(void)
 }
 #endif
 
-static NODE *reg_named_capture_assign(struct parser_params* p, VALUE regexp, const YYLTYPE *loc);
+static NODE *reg_named_capture_assign(struct parser_params* p, VALUE regexp, const YYLTYPE *loc, rb_parser_assignable_func assignable);
 
 #define compile_callback rb_suppress_tracing
 #endif /* !UNIVERSAL_PARSER */
@@ -12916,7 +12916,7 @@ match_op(struct parser_params *p, NODE *node1, NODE *node2, const YYLTYPE *op_lo
                 const VALUE lit = rb_node_regx_string_val(n);
                 if (!NIL_P(lit)) {
                     NODE *match = NEW_MATCH2(node1, node2, loc);
-                    RNODE_MATCH2(match)->nd_args = reg_named_capture_assign(p, lit, loc);
+                    RNODE_MATCH2(match)->nd_args = reg_named_capture_assign(p, lit, loc, assignable);
                     nd_set_line(match, line);
                     return match;
                 }
@@ -15402,6 +15402,7 @@ typedef struct {
     rb_encoding *enc;
     NODE *succ_block;
     const YYLTYPE *loc;
+    rb_parser_assignable_func assignable;
 } reg_named_capture_assign_t;
 
 static int
@@ -15414,11 +15415,11 @@ reg_named_capture_assign_iter(const OnigUChar *name, const OnigUChar *name_end,
     long len = name_end - name;
     const char *s = (const char *)name;
 
-    return rb_reg_named_capture_assign_iter_impl(p, s, len, enc, &arg->succ_block, arg->loc);
+    return rb_reg_named_capture_assign_iter_impl(p, s, len, enc, &arg->succ_block, arg->loc, arg->assignable);
 }
 
 static NODE *
-reg_named_capture_assign(struct parser_params* p, VALUE regexp, const YYLTYPE *loc)
+reg_named_capture_assign(struct parser_params* p, VALUE regexp, const YYLTYPE *loc, rb_parser_assignable_func assignable)
 {
     reg_named_capture_assign_t arg;
 
@@ -15426,6 +15427,7 @@ reg_named_capture_assign(struct parser_params* p, VALUE regexp, const YYLTYPE *l
     arg.enc = rb_enc_get(regexp);
     arg.succ_block = 0;
     arg.loc = loc;
+    arg.assignable = assignable;
     onig_foreach_name(RREGEXP_PTR(regexp), reg_named_capture_assign_iter, &arg);
 
     if (!arg.succ_block) return 0;
@@ -15434,9 +15436,15 @@ reg_named_capture_assign(struct parser_params* p, VALUE regexp, const YYLTYPE *l
 #endif
 
 #ifndef RIPPER
+NODE *
+rb_parser_assignable(struct parser_params *p, ID id, NODE *val, const YYLTYPE *loc)
+{
+    return assignable(p, id, val, loc);
+}
+
 int
 rb_reg_named_capture_assign_iter_impl(struct parser_params *p, const char *s, long len,
-          rb_encoding *enc, NODE **succ_block, const rb_code_location_t *loc)
+                                      rb_encoding *enc, NODE **succ_block, const rb_code_location_t *loc, rb_parser_assignable_func assignable)
 {
     ID var;
     NODE *node, *succ;
index 2a371ff..a4c4689 100644 (file)
@@ -197,6 +197,7 @@ typedef struct {
     rb_encoding *enc;
     NODE *succ_block;
     const rb_code_location_t *loc;
+    rb_parser_assignable_func assignable;
 } reg_named_capture_assign_t;
 
 static int
@@ -210,11 +211,12 @@ reg_named_capture_assign_iter(const OnigUChar *name, const OnigUChar *name_end,
     long len = name_end - name;
     const char *s = (const char *)name;
 
-    return rb_reg_named_capture_assign_iter_impl(p, s, len, enc, &arg->succ_block, loc);
+    return rb_reg_named_capture_assign_iter_impl(p, s, len, enc, &arg->succ_block, loc, arg->assignable);
 }
 
 static NODE *
-reg_named_capture_assign(struct parser_params* p, VALUE regexp, const rb_code_location_t *loc)
+reg_named_capture_assign(struct parser_params* p, VALUE regexp, const rb_code_location_t *loc,
+                         rb_parser_assignable_func assignable)
 {
     reg_named_capture_assign_t arg;
 
@@ -222,6 +224,7 @@ reg_named_capture_assign(struct parser_params* p, VALUE regexp, const rb_code_lo
     arg.enc = rb_enc_get(regexp);
     arg.succ_block = 0;
     arg.loc = loc;
+    arg.assignable = assignable;
     onig_foreach_name(RREGEXP_PTR(regexp), reg_named_capture_assign_iter, &arg);
 
     if (!arg.succ_block) return 0;
index 0950a32..7fa71f1 100644 (file)
@@ -1171,6 +1171,8 @@ typedef struct parser_params rb_parser_t;
 typedef struct rb_imemo_tmpbuf_struct rb_imemo_tmpbuf_t;
 #endif
 
+typedef NODE *(*rb_parser_assignable_func)(struct parser_params *p, ID id, NODE *val, const rb_code_location_t *loc);
+
 #ifdef UNIVERSAL_PARSER
 typedef struct rb_parser_config_struct {
     /* Memory */
@@ -1188,7 +1190,7 @@ typedef struct rb_parser_config_struct {
 
     // VALUE rb_suppress_tracing(VALUE (*func)(VALUE), VALUE arg);
     VALUE (*compile_callback)(VALUE (*func)(VALUE), VALUE arg);
-    NODE *(*reg_named_capture_assign)(struct parser_params* p, VALUE regexp, const rb_code_location_t *loc);
+    NODE *(*reg_named_capture_assign)(struct parser_params* p, VALUE regexp, const rb_code_location_t *loc, rb_parser_assignable_func assignable);
 
     /* Variable */
     VALUE (*attr_get)(VALUE obj, ID id);
index f129a41..0d3e33d 100644 (file)
@@ -148,6 +148,13 @@ end
     assert_nothing_raised { Ripper.lex src }
   end
 
+  def test_assignable_in_regexp
+    assert_separately(%w(-rripper), "", "#{<<~"begin;"}\n#{<<~'end;'}")
+    begin;
+      assert_nil(Ripper.parse('/(?<_1>)/ =~ s'))
+    end;
+  end
+
   def test_no_memory_leak
     assert_no_memory_leak(%w(-rripper), "", "#{<<~'end;'}", rss: true)
       2_000_000.times do