summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compile.c60
-rw-r--r--ext/-test-/ast/ast.c4
-rw-r--r--ext/objspace/objspace.c1
-rw-r--r--node.c8
-rw-r--r--node.h5
-rw-r--r--parse.y4
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);