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
This commit is contained in:
mame 2018-01-16 07:24:53 +00:00
Родитель 56524df980
Коммит 4b6f3bce25
6 изменённых файлов: 45 добавлений и 37 удалений

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

@ -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;

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

@ -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:

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

@ -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);

8
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]");

5
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)

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

@ -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);