summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Kokubun <takashikkbn@gmail.com>2024-05-29 16:34:43 -0700
committerTakashi Kokubun <takashikkbn@gmail.com>2024-05-29 16:35:18 -0700
commit0044b6aefc656874adb9266829f19870dcd3d75e (patch)
tree10b43b917753e1d5df15c4d642431b24cbad6dbd
parentb3f2ccea5efb060e99d289b2272ddfe413e4f051 (diff)
merge revision(s) bc002971b6ad483dbf69b8a275c44412bb6ab954: [Backport #20094]
[Bug #20094] Distinguish `begin` and parentheses
-rw-r--r--compile.c1
-rw-r--r--parse.y66
-rw-r--r--test/ruby/test_whileuntil.rb18
-rw-r--r--version.h2
4 files changed, 55 insertions, 32 deletions
diff --git a/compile.c b/compile.c
index 4fd562a678..3c92729760 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 0bb9709097..8755904b9a 100644
--- a/parse.y
+++ b/parse.y
@@ -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
diff --git a/version.h b/version.h
index 9777a89d3b..cf22947103 100644
--- a/version.h
+++ b/version.h
@@ -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"