diff options
| author | Takashi Kokubun <takashikkbn@gmail.com> | 2024-05-29 16:34:43 -0700 |
|---|---|---|
| committer | Takashi Kokubun <takashikkbn@gmail.com> | 2024-05-29 16:35:18 -0700 |
| commit | 0044b6aefc656874adb9266829f19870dcd3d75e (patch) | |
| tree | 10b43b917753e1d5df15c4d642431b24cbad6dbd | |
| parent | b3f2ccea5efb060e99d289b2272ddfe413e4f051 (diff) | |
merge revision(s) bc002971b6ad483dbf69b8a275c44412bb6ab954: [Backport #20094]
[Bug #20094] Distinguish `begin` and parentheses
| -rw-r--r-- | compile.c | 1 | ||||
| -rw-r--r-- | parse.y | 66 | ||||
| -rw-r--r-- | test/ruby/test_whileuntil.rb | 18 | ||||
| -rw-r--r-- | version.h | 2 |
4 files changed, 55 insertions, 32 deletions
@@ -7097,6 +7097,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c case NODE_COLON2: case NODE_COLON3: case NODE_BEGIN: + case NODE_BLOCK: CHECK(COMPILE(ret, "case in literal", node)); // (1) if (in_single_pattern) { ADD_INSN1(ret, line_node, dupn, INT2FIX(2)); @@ -1186,7 +1186,6 @@ static void fixpos(NODE*,NODE*); static int value_expr_gen(struct parser_params*,NODE*); static void void_expr(struct parser_params*,NODE*); static NODE *remove_begin(NODE*); -static NODE *remove_begin_all(NODE*); #define value_expr(node) value_expr_gen(p, (node)) static NODE *void_stmts(struct parser_params*,NODE*); static void reduce_nodes(struct parser_params*,NODE**); @@ -2387,7 +2386,7 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem static const char mesg[] = "can't make alias for the number variables"; /*%%%*/ yyerror1(&@3, mesg); - $$ = NEW_BEGIN(0, &@$); + $$ = NEW_ERROR(&@$); /*% %*/ /*% ripper[error]: alias_error!(ERR_MESG(), $3) %*/ } @@ -2593,7 +2592,7 @@ command_asgn : lhs '=' lex_ctxt command_rhs { /*%%%*/ rb_backref_error(p, $1); - $$ = NEW_BEGIN(0, &@$); + $$ = NEW_ERROR(&@$); /*% %*/ /*% ripper[error]: backref_error(p, RNODE($1), assign!(var_field(p, $1), $4)) %*/ } @@ -3072,7 +3071,7 @@ mlhs_node : user_variable { /*%%%*/ rb_backref_error(p, $1); - $$ = NEW_BEGIN(0, &@$); + $$ = NEW_ERROR(&@$); /*% %*/ /*% ripper[error]: backref_error(p, RNODE($1), var_field(p, $1)) %*/ } @@ -3138,7 +3137,7 @@ lhs : user_variable { /*%%%*/ rb_backref_error(p, $1); - $$ = NEW_BEGIN(0, &@$); + $$ = NEW_ERROR(&@$); /*% %*/ /*% ripper[error]: backref_error(p, RNODE($1), var_field(p, $1)) %*/ } @@ -3324,7 +3323,7 @@ arg : lhs '=' lex_ctxt arg_rhs { /*%%%*/ rb_backref_error(p, $1); - $$ = NEW_BEGIN(0, &@$); + $$ = NEW_ERROR(&@$); /*% %*/ /*% ripper[error]: backref_error(p, RNODE($1), opassign!(var_field(p, $1), $2, $4)) %*/ } @@ -3894,7 +3893,7 @@ primary : literal { /*%%%*/ if (nd_type_p($2, NODE_SELF)) RNODE_SELF($2)->nd_state = 0; - $$ = NEW_BEGIN($2, &@$); + $$ = NEW_BLOCK($2, &@$); /*% %*/ /*% ripper: paren!($2) %*/ } @@ -5505,7 +5504,7 @@ p_primitive : literal | keyword_variable { /*%%%*/ - if (!($$ = gettable(p, $1, &@$))) $$ = NEW_BEGIN(0, &@$); + if (!($$ = gettable(p, $1, &@$))) $$ = NEW_ERROR(&@$); /*% %*/ /*% ripper: var_ref!($1) %*/ } @@ -5545,7 +5544,7 @@ p_var_ref : '^' tIDENTIFIER p_expr_ref : '^' tLPAREN expr_value rparen { /*%%%*/ - $$ = NEW_BEGIN($3, &@$); + $$ = NEW_BLOCK($3, &@$); /*% %*/ /*% ripper: begin!($3) %*/ } @@ -5965,7 +5964,7 @@ string_dend : tSTRING_DEND string_dvar : nonlocal_var { /*%%%*/ - if (!($$ = gettable(p, $1, &@$))) $$ = NEW_BEGIN(0, &@$); + if (!($$ = gettable(p, $1, &@$))) $$ = NEW_ERROR(&@$); /*% %*/ /*% ripper: var_ref!($1) %*/ } @@ -6052,7 +6051,7 @@ var_ref : user_variable | keyword_variable { /*%%%*/ - if (!($$ = gettable(p, $1, &@$))) $$ = NEW_BEGIN(0, &@$); + if (!($$ = gettable(p, $1, &@$))) $$ = NEW_ERROR(&@$); /*% %*/ /*% ripper: var_ref!($1) %*/ } @@ -6653,7 +6652,7 @@ assoc : arg_value tASSOC arg_value { /*%%%*/ NODE *val = gettable(p, $1, &@$); - if (!val) val = NEW_BEGIN(0, &@$); + if (!val) val = NEW_ERROR(&@$); $$ = list_append(p, NEW_LIST(NEW_LIT(ID2SYM($1), &@1), &@$), val); /*% %*/ /*% ripper: assoc_new!($1, Qnil) %*/ @@ -11236,7 +11235,7 @@ rb_node_block_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc) { rb_node_block_t *n = NODE_NEWNODE(NODE_BLOCK, rb_node_block_t, loc); n->nd_head = nd_head; - n->nd_end = 0; + n->nd_end = (NODE *)n; n->nd_next = 0; return n; @@ -12327,7 +12326,6 @@ block_append(struct parser_params *p, NODE *head, NODE *tail) switch (nd_type(h)) { default: h = end = NEW_BLOCK(head, &head->nd_loc); - RNODE_BLOCK(end)->nd_end = end; head = end; break; case NODE_BLOCK: @@ -12353,7 +12351,6 @@ block_append(struct parser_params *p, NODE *head, NODE *tail) if (!nd_type_p(tail, NODE_BLOCK)) { tail = NEW_BLOCK(tail, &tail->nd_loc); - RNODE_BLOCK(tail)->nd_end = tail; } RNODE_BLOCK(end)->nd_next = tail; RNODE_BLOCK(h)->nd_end = RNODE_BLOCK(tail)->nd_end; @@ -12830,7 +12827,19 @@ 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) { - return NEW_DEFINED(remove_begin_all(expr), loc); + NODE *n = expr; + while (n) { + if (nd_type_p(n, NODE_BEGIN)) { + n = RNODE_BEGIN(n)->nd_body; + } + else if (nd_type_p(n, NODE_BLOCK) && RNODE_BLOCK(n)->nd_end == n) { + n = RNODE_BLOCK(n)->nd_head; + } + else { + break; + } + } + return NEW_DEFINED(n, loc); } static NODE* @@ -13282,7 +13291,7 @@ assignable(struct parser_params *p, ID id, NODE *val, const YYLTYPE *loc) case NODE_CVASGN: return NEW_CVASGN(id, val, loc); } if (err) yyerror1(loc, err); - return NEW_BEGIN(0, loc); + return NEW_ERROR(loc); } #else static VALUE @@ -13970,16 +13979,6 @@ remove_begin(NODE *node) return node; } -static NODE * -remove_begin_all(NODE *node) -{ - NODE **n = &node, *n1 = node; - while (n1 && nd_type_p(n1, NODE_BEGIN)) { - *n = n1 = RNODE_BEGIN(n1)->nd_body; - } - return node; -} - static void reduce_nodes(struct parser_params *p, NODE **body) { @@ -14149,7 +14148,12 @@ cond0(struct parser_params *p, NODE *node, enum cond_type type, const YYLTYPE *l return NEW_MATCH2(node, NEW_GVAR(idLASTLINE, loc), loc); case NODE_BLOCK: - RNODE_BLOCK(RNODE_BLOCK(node)->nd_end)->nd_head = cond0(p, RNODE_BLOCK(RNODE_BLOCK(node)->nd_end)->nd_head, type, loc, false); + { + NODE *end = RNODE_BLOCK(node)->nd_end; + NODE **expr = &RNODE_BLOCK(end)->nd_head; + if (top) top = node == end; + *expr = cond0(p, *expr, type, loc, top); + } break; case NODE_AND: @@ -14710,7 +14714,7 @@ new_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, struct lex_c } } else { - asgn = NEW_BEGIN(0, loc); + asgn = NEW_ERROR(loc); } return asgn; } @@ -14748,7 +14752,7 @@ new_const_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, struct asgn = NEW_OP_CDECL(lhs, op, rhs, loc); } else { - asgn = NEW_BEGIN(0, loc); + asgn = NEW_ERROR(loc); } fixpos(asgn, lhs); return asgn; @@ -15324,7 +15328,7 @@ rb_reg_named_capture_assign_iter_impl(struct parser_params *p, const char *s, lo } node = node_assign(p, assignable(p, var, 0, loc), NEW_LIT(ID2SYM(var), loc), NO_LEX_CTXT, loc); succ = *succ_block; - if (!succ) succ = NEW_BEGIN(0, loc); + if (!succ) succ = NEW_ERROR(loc); succ = block_append(p, succ, node); *succ_block = succ; return ST_CONTINUE; diff --git a/test/ruby/test_whileuntil.rb b/test/ruby/test_whileuntil.rb index 121c44817d..ff6d29ac4a 100644 --- a/test/ruby/test_whileuntil.rb +++ b/test/ruby/test_whileuntil.rb @@ -73,6 +73,24 @@ class TestWhileuntil < Test::Unit::TestCase } end + def test_begin_while + i = 0 + sum = 0 + begin + i += 1 + sum += i + end while i < 10 + assert_equal([10, 55], [i, sum]) + + i = 0 + sum = 0 + ( + i += 1 + sum += i + ) while false + assert_equal([0, 0], [i, sum]) + end + def test_until i = 0 until i>4 @@ -11,7 +11,7 @@ # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR #define RUBY_VERSION_TEENY 1 #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR -#define RUBY_PATCHLEVEL 73 +#define RUBY_PATCHLEVEL 74 #include "ruby/version.h" #include "ruby/internal/abi.h" |
