mirror of
https://github.com/ruby/ruby.git
synced 2025-09-15 16:44:01 +02:00
compile.c: compile_break
* compile.c (compile_break): extract from iseq_compile_each. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59593 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
12693e245f
commit
582b7057dc
1 changed files with 70 additions and 62 deletions
132
compile.c
132
compile.c
|
@ -4362,6 +4362,71 @@ compile_loop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped, co
|
||||||
return COMPILE_OK;
|
return COMPILE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
compile_break(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) {
|
||||||
|
/* while/until */
|
||||||
|
LABEL *splabel = NEW_LABEL(0);
|
||||||
|
ADD_LABEL(ret, splabel);
|
||||||
|
ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->redo_label);
|
||||||
|
CHECK(COMPILE_(ret, "break val (while/until)", node->nd_stts,
|
||||||
|
ISEQ_COMPILE_DATA(iseq)->loopval_popped));
|
||||||
|
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_BLOCK) {
|
||||||
|
break_by_insn:
|
||||||
|
/* escape from block */
|
||||||
|
CHECK(COMPILE(ret, "break val (block)", node->nd_stts));
|
||||||
|
ADD_INSN1(ret, line, throw, INT2FIX(level | TAG_BREAK));
|
||||||
|
if (popped) {
|
||||||
|
ADD_INSN(ret, line, pop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (iseq->body->type == ISEQ_TYPE_EVAL) {
|
||||||
|
break_in_eval:
|
||||||
|
COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with break");
|
||||||
|
return COMPILE_NG;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const rb_iseq_t *ip = iseq->body->parent_iseq;
|
||||||
|
|
||||||
|
while (ip) {
|
||||||
|
if (!ISEQ_COMPILE_DATA(ip)) {
|
||||||
|
ip = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
level++;
|
||||||
|
if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
|
||||||
|
level = VM_THROW_NO_ESCAPE_FLAG;
|
||||||
|
goto break_by_insn;
|
||||||
|
}
|
||||||
|
else if (ip->body->type == ISEQ_TYPE_BLOCK) {
|
||||||
|
level <<= VM_THROW_LEVEL_SHIFT;
|
||||||
|
goto break_by_insn;
|
||||||
|
}
|
||||||
|
else if (ip->body->type == ISEQ_TYPE_EVAL) {
|
||||||
|
goto break_in_eval;
|
||||||
|
}
|
||||||
|
|
||||||
|
ip = ip->body->parent_iseq;
|
||||||
|
}
|
||||||
|
COMPILE_ERROR(ERROR_ARGS "Invalid break");
|
||||||
|
return COMPILE_NG;
|
||||||
|
}
|
||||||
|
return COMPILE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static int iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped);
|
static int iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped);
|
||||||
/**
|
/**
|
||||||
compile each node
|
compile each node
|
||||||
|
@ -4527,69 +4592,9 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popp
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NODE_BREAK:{
|
case NODE_BREAK:
|
||||||
unsigned long level = 0;
|
CHECK(compile_break(iseq, ret, node, popped));
|
||||||
|
|
||||||
if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0) {
|
|
||||||
/* while/until */
|
|
||||||
LABEL *splabel = NEW_LABEL(0);
|
|
||||||
ADD_LABEL(ret, splabel);
|
|
||||||
ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->redo_label);
|
|
||||||
CHECK(COMPILE_(ret, "break val (while/until)", node->nd_stts,
|
|
||||||
ISEQ_COMPILE_DATA(iseq)->loopval_popped));
|
|
||||||
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_BLOCK) {
|
|
||||||
break_by_insn:
|
|
||||||
/* escape from block */
|
|
||||||
CHECK(COMPILE(ret, "break val (block)", node->nd_stts));
|
|
||||||
ADD_INSN1(ret, line, throw, INT2FIX(level | TAG_BREAK));
|
|
||||||
if (popped) {
|
|
||||||
ADD_INSN(ret, line, pop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (iseq->body->type == ISEQ_TYPE_EVAL) {
|
|
||||||
break_in_eval:
|
|
||||||
COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with break");
|
|
||||||
ng:
|
|
||||||
debug_node_end();
|
|
||||||
return COMPILE_NG;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const rb_iseq_t *ip = iseq->body->parent_iseq;
|
|
||||||
|
|
||||||
while (ip) {
|
|
||||||
if (!ISEQ_COMPILE_DATA(ip)) {
|
|
||||||
ip = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
level++;
|
|
||||||
if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
|
|
||||||
level = VM_THROW_NO_ESCAPE_FLAG;
|
|
||||||
goto break_by_insn;
|
|
||||||
}
|
|
||||||
else if (ip->body->type == ISEQ_TYPE_BLOCK) {
|
|
||||||
level <<= VM_THROW_LEVEL_SHIFT;
|
|
||||||
goto break_by_insn;
|
|
||||||
}
|
|
||||||
else if (ip->body->type == ISEQ_TYPE_EVAL) {
|
|
||||||
goto break_in_eval;
|
|
||||||
}
|
|
||||||
|
|
||||||
ip = ip->body->parent_iseq;
|
|
||||||
}
|
|
||||||
COMPILE_ERROR(ERROR_ARGS "Invalid break");
|
|
||||||
goto ng;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case NODE_NEXT:{
|
case NODE_NEXT:{
|
||||||
unsigned long level = 0;
|
unsigned long level = 0;
|
||||||
|
|
||||||
|
@ -6501,6 +6506,9 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popp
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
UNKNOWN_NODE("iseq_compile_each", node, COMPILE_NG);
|
UNKNOWN_NODE("iseq_compile_each", node, COMPILE_NG);
|
||||||
|
ng:
|
||||||
|
debug_node_end();
|
||||||
|
return COMPILE_NG;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check & remove redundant trace(line) */
|
/* check & remove redundant trace(line) */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue