mirror of
https://github.com/ruby/ruby.git
synced 2026-01-26 20:19:19 +00:00
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
This commit is contained in:
parent
582b7057dc
commit
7e958b890e
151
compile.c
151
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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user