diff --git a/compile.c b/compile.c index afc2061b1273d3..306272455a1bf1 100644 --- a/compile.c +++ b/compile.c @@ -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)); diff --git a/parse.y b/parse.y index 5d1db1d1140e92..c3aac517d593a9 100644 --- a/parse.y +++ b/parse.y @@ -1188,7 +1188,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**); @@ -3898,7 +3897,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) %*/ } @@ -5561,7 +5560,7 @@ p_var_ref : '^' tIDENTIFIER p_expr_ref : '^' tLPAREN expr_value rparen { /*%%%*/ - $$ = NEW_BEGIN($3, &@$); + $$ = NEW_BLOCK($3, &@$); /*% %*/ /*% ripper: begin!($3) %*/ } @@ -12881,7 +12880,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* @@ -14021,16 +14032,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) { @@ -14200,7 +14201,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: diff --git a/test/ruby/test_whileuntil.rb b/test/ruby/test_whileuntil.rb index 121c44817df4a2..ff6d29ac4a9f89 100644 --- a/test/ruby/test_whileuntil.rb +++ b/test/ruby/test_whileuntil.rb @@ -73,6 +73,24 @@ def test_while } 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