diff options
| author | S-H-GAMELINKS <gamelinks007@gmail.com> | 2025-07-08 23:14:37 +0900 |
|---|---|---|
| committer | Nobuyoshi Nakada <nobu.nakada@gmail.com> | 2025-07-16 16:17:10 +0900 |
| commit | f0649ab46a5235904ea6f9b95aa07cb9375fd463 (patch) | |
| tree | f58ccc2dcf3f9b1dd8678c9890f6fcc64dfd6593 /parse.y | |
| parent | 54ec48249192325d108355bb8c7d735cd5081617 (diff) | |
Make `defined? (x;)` return `expression` when using parse.y parser
Follow up [Bug #21029].
Currently, `defined? (x;)` returns `expression` when using Prism parser.
See:
- https://github.com/ruby/ruby/pull/12949
- https://bugs.ruby-lang.org/issues/21029
However, `defined? (x;)` returns nil when using parse.y, as reported in bug ticket comment and test-all (when using parse.y parser) test result.
This change adds a context flag to track trailing semicolons in defined? scope.
When a trailing semicolon is detected within a defined? scope, the generated AST node is wrapped with NODE_BLOCK.
This change ensures consistent behavior with `defined? (;x)` .
Diffstat (limited to 'parse.y')
| -rw-r--r-- | parse.y | 21 |
1 files changed, 20 insertions, 1 deletions
@@ -314,6 +314,7 @@ struct lex_context { unsigned int in_argdef: 1; unsigned int in_def: 1; unsigned int in_class: 1; + unsigned int has_trailing_semicolon: 1; BITFIELD(enum rb_parser_shareability, shareable_constant_value, 2); BITFIELD(enum rescue_context, in_rescue, 2); unsigned int cant_return: 1; @@ -4041,6 +4042,7 @@ arg : asgn(arg_rhs) { p->ctxt.in_defined = $3.in_defined; $$ = new_defined(p, $4, &@$); + p->ctxt.has_trailing_semicolon = $3.has_trailing_semicolon; /*% ripper: defined!($:4) %*/ } | def_endless_method(endless_arg) @@ -4428,6 +4430,7 @@ primary : inline_primary { p->ctxt.in_defined = $4.in_defined; $$ = new_defined(p, $5, &@$); + p->ctxt.has_trailing_semicolon = $4.has_trailing_semicolon; /*% ripper: defined!($:5) %*/ } | keyword_not '(' expr rparen @@ -6706,7 +6709,14 @@ trailer : '\n'? | ',' ; -term : ';' {yyerrok;token_flush(p);} +term : ';' + { + yyerrok; + token_flush(p); + if (p->ctxt.in_defined) { + p->ctxt.has_trailing_semicolon = 1; + } + } | '\n' { @$.end_pos = @$.beg_pos; @@ -13013,6 +13023,9 @@ kwd_append(rb_node_kw_arg_t *kwlist, rb_node_kw_arg_t *kw) static NODE * new_defined(struct parser_params *p, NODE *expr, const YYLTYPE *loc) { + int had_trailing_semicolon = p->ctxt.has_trailing_semicolon; + p->ctxt.has_trailing_semicolon = 0; + NODE *n = expr; while (n) { if (nd_type_p(n, NODE_BEGIN)) { @@ -13025,6 +13038,12 @@ new_defined(struct parser_params *p, NODE *expr, const YYLTYPE *loc) break; } } + + if (had_trailing_semicolon && !nd_type_p(expr, NODE_BLOCK)) { + NODE *block = NEW_BLOCK(expr, loc); + return NEW_DEFINED(block, loc); + } + return NEW_DEFINED(n, loc); } |
