summaryrefslogtreecommitdiff
path: root/compile.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-08-15 00:18:47 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-08-15 00:18:47 +0000
commit7e958b890e663edd7985e347f677b5851e3c5d9c (patch)
tree68db724c6d5e65c0809fd1f502447ae2ca40b6b4 /compile.c
parent582b7057dc92fcf23b01a4fb699ebe008fd92240 (diff)
compile.c: compile_next
* compile.c (compile_next): extract from iseq_compile_each. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59594 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'compile.c')
-rw-r--r--compile.c151
1 files changed, 79 insertions, 72 deletions
diff --git a/compile.c b/compile.c
index b8f04584f4..f7ba263fa3 100644
--- a/compile.c
+++ b/compile.c
@@ -4427,6 +4427,83 @@ compile_break(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped)
return COMPILE_OK;
}
+static int
+compile_next(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped)
+{
+ const int line = nd_line(node);
+ unsigned long level = 0;
+
+ if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0) {
+ LABEL *splabel = NEW_LABEL(0);
+ debugs("next in while loop\n");
+ ADD_LABEL(ret, splabel);
+ CHECK(COMPILE(ret, "next val/valid syntax?", node->nd_stts));
+ add_ensure_iseq(ret, iseq, 0);
+ ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->redo_label);
+ ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(iseq)->start_label);
+ ADD_ADJUST_RESTORE(ret, splabel);
+ if (!popped) {
+ ADD_INSN(ret, line, putnil);
+ }
+ }
+ else if (ISEQ_COMPILE_DATA(iseq)->end_label) {
+ LABEL *splabel = NEW_LABEL(0);
+ debugs("next in block\n");
+ ADD_LABEL(ret, splabel);
+ ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->start_label);
+ CHECK(COMPILE(ret, "next val", node->nd_stts));
+ add_ensure_iseq(ret, iseq, 0);
+ ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
+ ADD_ADJUST_RESTORE(ret, splabel);
+
+ if (!popped) {
+ ADD_INSN(ret, line, putnil);
+ }
+ }
+ else if (iseq->body->type == ISEQ_TYPE_EVAL) {
+ next_in_eval:
+ COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with next");
+ return COMPILE_NG;
+ }
+ else {
+ const rb_iseq_t *ip = iseq;
+
+ while (ip) {
+ if (!ISEQ_COMPILE_DATA(ip)) {
+ ip = 0;
+ break;
+ }
+
+ level = VM_THROW_NO_ESCAPE_FLAG;
+ if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
+ /* while loop */
+ break;
+ }
+ else if (ip->body->type == ISEQ_TYPE_BLOCK) {
+ break;
+ }
+ else if (ip->body->type == ISEQ_TYPE_EVAL) {
+ goto next_in_eval;
+ }
+
+ ip = ip->body->parent_iseq;
+ }
+ if (ip != 0) {
+ CHECK(COMPILE(ret, "next val", node->nd_stts));
+ ADD_INSN1(ret, line, throw, INT2FIX(level | TAG_NEXT));
+
+ if (popped) {
+ ADD_INSN(ret, line, pop);
+ }
+ }
+ else {
+ COMPILE_ERROR(ERROR_ARGS "Invalid next");
+ return COMPILE_NG;
+ }
+ }
+ return COMPILE_OK;
+}
+
static int iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped);
/**
compile each node
@@ -4595,79 +4672,9 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popp
case NODE_BREAK:
CHECK(compile_break(iseq, ret, node, popped));
break;
- case NODE_NEXT:{
- unsigned long level = 0;
-
- if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0) {
- LABEL *splabel = NEW_LABEL(0);
- debugs("next in while loop\n");
- ADD_LABEL(ret, splabel);
- CHECK(COMPILE(ret, "next val/valid syntax?", node->nd_stts));
- add_ensure_iseq(ret, iseq, 0);
- ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->redo_label);
- ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(iseq)->start_label);
- ADD_ADJUST_RESTORE(ret, splabel);
- if (!popped) {
- ADD_INSN(ret, line, putnil);
- }
- }
- else if (ISEQ_COMPILE_DATA(iseq)->end_label) {
- LABEL *splabel = NEW_LABEL(0);
- debugs("next in block\n");
- ADD_LABEL(ret, splabel);
- ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->start_label);
- CHECK(COMPILE(ret, "next val", node->nd_stts));
- add_ensure_iseq(ret, iseq, 0);
- ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
- ADD_ADJUST_RESTORE(ret, splabel);
-
- if (!popped) {
- ADD_INSN(ret, line, putnil);
- }
- }
- else if (iseq->body->type == ISEQ_TYPE_EVAL) {
- next_in_eval:
- COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with next");
- goto ng;
- }
- else {
- const rb_iseq_t *ip = iseq;
-
- while (ip) {
- if (!ISEQ_COMPILE_DATA(ip)) {
- ip = 0;
- break;
- }
-
- level = VM_THROW_NO_ESCAPE_FLAG;
- if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
- /* while loop */
- break;
- }
- else if (ip->body->type == ISEQ_TYPE_BLOCK) {
- break;
- }
- else if (ip->body->type == ISEQ_TYPE_EVAL) {
- goto next_in_eval;
- }
-
- ip = ip->body->parent_iseq;
- }
- if (ip != 0) {
- CHECK(COMPILE(ret, "next val", node->nd_stts));
- ADD_INSN1(ret, line, throw, INT2FIX(level | TAG_NEXT));
-
- if (popped) {
- ADD_INSN(ret, line, pop);
- }
- }
- else {
- COMPILE_ERROR(ERROR_ARGS "Invalid next");
- goto ng;
- }
- }
+ case NODE_NEXT:
+ CHECK(compile_next(iseq, ret, node, popped));
break;
- }
case NODE_REDO:{
if (ISEQ_COMPILE_DATA(iseq)->redo_label) {
LABEL *splabel = NEW_LABEL(0);