From 4b6f3bce2502e6bbe0a600aef61c8c129fa2af3e Mon Sep 17 00:00:00 2001 From: mame Date: Tue, 16 Jan 2018 07:24:53 +0000 Subject: [PATCH] node.c: Stop double meaning of NODE_FOR by introducing NODE_FOR_MASGN NODE_FOR was used both for "for"-statement itself and for multi-assignment of for-statement (for x, y, in...end). This change separates the two purposes, NODE_FOR for the former, and newly introduced NODE_FOR_MASGN for the latter. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61871 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- compile.c | 60 +++++++++++++++++++---------------------- ext/-test-/ast/ast.c | 4 +-- ext/objspace/objspace.c | 1 + node.c | 8 ++++++ node.h | 5 +++- parse.y | 4 +-- 6 files changed, 45 insertions(+), 37 deletions(-) diff --git a/compile.c b/compile.c index 27e6647f61..1dfbef52e3 100644 --- a/compile.c +++ b/compile.c @@ -5019,38 +5019,33 @@ compile_iter(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in } static int -compile_for(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) +compile_for_masgn(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) { + /* massign to var in "for" + * args.length == 1 && Array === (tmp = args[0]) ? tmp : args + */ const int line = nd_line(node); - if (node->nd_var) { - /* massign to var in "for" - * args.length == 1 && Array === (tmp = args[0]) ? tmp : args - */ - const NODE *var = node->nd_var; - LABEL *not_single = NEW_LABEL(nd_line(var)); - LABEL *not_ary = NEW_LABEL(nd_line(var)); - CHECK(COMPILE(ret, "for var", var)); - ADD_INSN(ret, line, dup); - ADD_CALL(ret, line, idLength, INT2FIX(0)); - ADD_INSN1(ret, line, putobject, INT2FIX(1)); - ADD_CALL(ret, line, idEq, INT2FIX(1)); - ADD_INSNL(ret, line, branchunless, not_single); - ADD_INSN(ret, line, dup); - ADD_INSN1(ret, line, putobject, INT2FIX(0)); - ADD_CALL(ret, line, idAREF, INT2FIX(1)); - ADD_INSN1(ret, line, putobject, rb_cArray); - ADD_INSN1(ret, line, topn, INT2FIX(1)); - ADD_CALL(ret, line, idEqq, INT2FIX(1)); - ADD_INSNL(ret, line, branchunless, not_ary); - ADD_INSN(ret, line, swap); - ADD_LABEL(ret, not_ary); - ADD_INSN(ret, line, pop); - ADD_LABEL(ret, not_single); - return COMPILE_OK; - } - else { - return compile_iter(iseq, ret, node, popped); - } + const NODE *var = node->nd_var; + LABEL *not_single = NEW_LABEL(nd_line(var)); + LABEL *not_ary = NEW_LABEL(nd_line(var)); + CHECK(COMPILE(ret, "for var", var)); + ADD_INSN(ret, line, dup); + ADD_CALL(ret, line, idLength, INT2FIX(0)); + ADD_INSN1(ret, line, putobject, INT2FIX(1)); + ADD_CALL(ret, line, idEq, INT2FIX(1)); + ADD_INSNL(ret, line, branchunless, not_single); + ADD_INSN(ret, line, dup); + ADD_INSN1(ret, line, putobject, INT2FIX(0)); + ADD_CALL(ret, line, idAREF, INT2FIX(1)); + ADD_INSN1(ret, line, putobject, rb_cArray); + ADD_INSN1(ret, line, topn, INT2FIX(1)); + ADD_CALL(ret, line, idEqq, INT2FIX(1)); + ADD_INSNL(ret, line, branchunless, not_ary); + ADD_INSN(ret, line, swap); + ADD_LABEL(ret, not_ary); + ADD_INSN(ret, line, pop); + ADD_LABEL(ret, not_single); + return COMPILE_OK; } static int @@ -5560,11 +5555,12 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in CHECK(compile_loop(iseq, ret, node, popped, type)); break; case NODE_FOR: - CHECK(compile_for(iseq, ret, node, popped)); - break; case NODE_ITER: CHECK(compile_iter(iseq, ret, node, popped)); break; + case NODE_FOR_MASGN: + CHECK(compile_for_masgn(iseq, ret, node, popped)); + break; case NODE_BREAK: CHECK(compile_break(iseq, ret, node, popped)); break; diff --git a/ext/-test-/ast/ast.c b/ext/-test-/ast/ast.c index ead7400786..eab1cfb99a 100644 --- a/ext/-test-/ast/ast.c +++ b/ext/-test-/ast/ast.c @@ -198,10 +198,10 @@ node_children(rb_ast_t *ast, NODE *node) loop: return rb_ary_new_from_node_args(ast, 2, node->nd_cond, node->nd_body); case NODE_ITER: - goto iter; case NODE_FOR: - iter: return rb_ary_new_from_node_args(ast, 2, node->nd_iter, node->nd_body); + case NODE_FOR_MASGN: + return rb_ary_new_from_node_args(ast, 1, node->nd_var); case NODE_BREAK: goto jump; case NODE_NEXT: diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c index e410941c7d..c791f3a7f7 100644 --- a/ext/objspace/objspace.c +++ b/ext/objspace/objspace.c @@ -382,6 +382,7 @@ count_nodes(int argc, VALUE *argv, VALUE os) COUNT_NODE(NODE_UNTIL); COUNT_NODE(NODE_ITER); COUNT_NODE(NODE_FOR); + COUNT_NODE(NODE_FOR_MASGN); COUNT_NODE(NODE_BREAK); COUNT_NODE(NODE_NEXT); COUNT_NODE(NODE_REDO); diff --git a/node.c b/node.c index 4770f7cfd2..1ea6cade20 100644 --- a/node.c +++ b/node.c @@ -240,6 +240,14 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node) F_NODE(nd_body, "body"); return; + case NODE_FOR_MASGN: + ANN("vars of for statement with masgn"); + ANN("format: for [nd_var] in ... do ... end"); + ANN("example: for x, y in 1..3 do foo end"); + LAST_NODE; + F_NODE(nd_var, "var"); + return; + case NODE_BREAK: ANN("break statement"); ANN("format: break [nd_stts]"); diff --git a/node.h b/node.h index 21ec7485cf..9cd66da5a8 100644 --- a/node.h +++ b/node.h @@ -42,6 +42,8 @@ enum node_type { #define NODE_ITER NODE_ITER NODE_FOR, #define NODE_FOR NODE_FOR + NODE_FOR_MASGN, +#define NODE_FOR_MASGN NODE_FOR_MASGN NODE_BREAK, #define NODE_BREAK NODE_BREAK NODE_NEXT, @@ -382,7 +384,8 @@ typedef struct RNode { #define NEW_WHEN(c,t,e,loc) NEW_NODE(NODE_WHEN,c,t,e,loc) #define NEW_WHILE(c,b,n,loc) NEW_NODE(NODE_WHILE,c,b,n,loc) #define NEW_UNTIL(c,b,n,loc) NEW_NODE(NODE_UNTIL,c,b,n,loc) -#define NEW_FOR(v,i,b,loc) NEW_NODE(NODE_FOR,v,b,i,loc) +#define NEW_FOR(i,b,loc) NEW_NODE(NODE_FOR,0,b,i,loc) +#define NEW_FOR_MASGN(v,loc) NEW_NODE(NODE_FOR_MASGN,v,0,0,loc) #define NEW_ITER(a,b,loc) NEW_NODE(NODE_ITER,0,NEW_SCOPE(a,b,loc),0,loc) #define NEW_LAMBDA(a,b,loc) NEW_NODE(NODE_LAMBDA,0,NEW_SCOPE(a,b,loc),0,loc) #define NEW_BREAK(s,loc) NEW_NODE(NODE_BREAK,s,0,0,loc) diff --git a/parse.y b/parse.y index 739746ca22..55b4e96184 100644 --- a/parse.y +++ b/parse.y @@ -2580,7 +2580,7 @@ primary : literal switch (nd_type($2)) { case NODE_MASGN: - m->nd_next = node_assign(p, $2, NEW_FOR(NEW_DVAR(id, &@2), 0, 0, &@2), &@2); + m->nd_next = node_assign(p, $2, NEW_FOR_MASGN(NEW_DVAR(id, &@2), &@2), &@2); args = new_args(p, m, 0, id, 0, new_args_tail(p, 0, 0, 0, &@2), &@2); break; case NODE_LASGN: @@ -2602,7 +2602,7 @@ primary : literal add_mark_object(p, (VALUE)rb_imemo_alloc_new((VALUE)tbl, 0, 0, 0)); scope = NEW_NODE(NODE_SCOPE, tbl, $5, args, &@$); tbl[0] = 1; tbl[1] = id; - $$ = NEW_FOR(0, $4, scope, &@$); + $$ = NEW_FOR($4, scope, &@$); fixpos($$, $2); /*% $$ = dispatch3(for, $2, $4, $5);