[Bug #20094] Distinguish `begin` and parentheses

This commit is contained in:
Nobuyoshi Nakada 2023-12-27 17:49:59 +09:00
Родитель 15c280639e
Коммит bc002971b6
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 3582D74E1FEE4465
3 изменённых файлов: 40 добавлений и 15 удалений

Просмотреть файл

@ -7097,6 +7097,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
case NODE_COLON2: case NODE_COLON2:
case NODE_COLON3: case NODE_COLON3:
case NODE_BEGIN: case NODE_BEGIN:
case NODE_BLOCK:
CHECK(COMPILE(ret, "case in literal", node)); // (1) CHECK(COMPILE(ret, "case in literal", node)); // (1)
if (in_single_pattern) { if (in_single_pattern) {
ADD_INSN1(ret, line_node, dupn, INT2FIX(2)); ADD_INSN1(ret, line_node, dupn, INT2FIX(2));

36
parse.y
Просмотреть файл

@ -1188,7 +1188,6 @@ static void fixpos(NODE*,NODE*);
static int value_expr_gen(struct parser_params*,NODE*); static int value_expr_gen(struct parser_params*,NODE*);
static void void_expr(struct parser_params*,NODE*); static void void_expr(struct parser_params*,NODE*);
static NODE *remove_begin(NODE*); static NODE *remove_begin(NODE*);
static NODE *remove_begin_all(NODE*);
#define value_expr(node) value_expr_gen(p, (node)) #define value_expr(node) value_expr_gen(p, (node))
static NODE *void_stmts(struct parser_params*,NODE*); static NODE *void_stmts(struct parser_params*,NODE*);
static void reduce_nodes(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; if (nd_type_p($2, NODE_SELF)) RNODE_SELF($2)->nd_state = 0;
$$ = NEW_BEGIN($2, &@$); $$ = NEW_BLOCK($2, &@$);
/*% %*/ /*% %*/
/*% ripper: paren!($2) %*/ /*% ripper: paren!($2) %*/
} }
@ -5561,7 +5560,7 @@ p_var_ref : '^' tIDENTIFIER
p_expr_ref : '^' tLPAREN expr_value rparen p_expr_ref : '^' tLPAREN expr_value rparen
{ {
/*%%%*/ /*%%%*/
$$ = NEW_BEGIN($3, &@$); $$ = NEW_BLOCK($3, &@$);
/*% %*/ /*% %*/
/*% ripper: begin!($3) %*/ /*% ripper: begin!($3) %*/
} }
@ -12881,7 +12880,19 @@ kwd_append(rb_node_kw_arg_t *kwlist, rb_node_kw_arg_t *kw)
static NODE * static NODE *
new_defined(struct parser_params *p, NODE *expr, const YYLTYPE *loc) 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* static NODE*
@ -14021,16 +14032,6 @@ remove_begin(NODE *node)
return 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 static void
reduce_nodes(struct parser_params *p, NODE **body) 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); return NEW_MATCH2(node, NEW_GVAR(idLASTLINE, loc), loc);
case NODE_BLOCK: 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; break;
case NODE_AND: case NODE_AND:

Просмотреть файл

@ -73,6 +73,24 @@ class TestWhileuntil < Test::Unit::TestCase
} }
end 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 def test_until
i = 0 i = 0
until i>4 until i>4