mirror of
https://github.com/ruby/ruby.git
synced 2025-08-23 13:04:13 +02:00
[PRISM] Fix compilation for NextNode
This code was almost enitrely the same as the existing compiler's code for its NextNode.
This commit is contained in:
parent
71babe5536
commit
e3ca50b02f
2 changed files with 104 additions and 8 deletions
|
@ -3460,15 +3460,81 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
|
|||
}
|
||||
case PM_NEXT_NODE: {
|
||||
pm_next_node_t *next_node = (pm_next_node_t *) node;
|
||||
if (next_node->arguments) {
|
||||
PM_COMPILE_NOT_POPPED((pm_node_t *)next_node->arguments);
|
||||
|
||||
if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0 && can_add_ensure_iseq(iseq)) {
|
||||
LABEL *splabel = NEW_LABEL(0);
|
||||
|
||||
ADD_LABEL(ret, splabel);
|
||||
|
||||
add_ensure_iseq(ret, iseq, 0);
|
||||
|
||||
ADD_ADJUST(ret, &dummy_line_node, ISEQ_COMPILE_DATA(iseq)->redo_label);
|
||||
ADD_INSNL(ret, &dummy_line_node, jump, ISEQ_COMPILE_DATA(iseq)->start_label);
|
||||
|
||||
ADD_ADJUST_RESTORE(ret, splabel);
|
||||
PM_PUTNIL_UNLESS_POPPED;
|
||||
}
|
||||
else if (ISEQ_COMPILE_DATA(iseq)->end_label && can_add_ensure_iseq(iseq)) {
|
||||
LABEL *splabel = NEW_LABEL(0);
|
||||
|
||||
ADD_LABEL(ret, splabel);
|
||||
ADD_ADJUST(ret, &dummy_line_node, ISEQ_COMPILE_DATA(iseq)->start_label);
|
||||
|
||||
if (next_node->arguments) {
|
||||
PM_COMPILE((pm_node_t *)next_node->arguments);
|
||||
}
|
||||
else {
|
||||
PM_PUTNIL;
|
||||
}
|
||||
|
||||
add_ensure_iseq(ret, iseq, 0);
|
||||
ADD_INSNL(ret, &dummy_line_node, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
|
||||
ADD_ADJUST_RESTORE(ret, splabel);
|
||||
splabel->unremovable = FALSE;
|
||||
|
||||
PM_PUTNIL_UNLESS_POPPED;
|
||||
}
|
||||
else {
|
||||
PM_PUTNIL;
|
||||
}
|
||||
const rb_iseq_t *ip = iseq;
|
||||
|
||||
PM_POP;
|
||||
ADD_INSNL(ret, &dummy_line_node, jump, ISEQ_COMPILE_DATA(iseq)->start_label);
|
||||
unsigned long throw_flag = 0;
|
||||
while (ip) {
|
||||
if (!ISEQ_COMPILE_DATA(ip)) {
|
||||
ip = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
throw_flag = VM_THROW_NO_ESCAPE_FLAG;
|
||||
if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
|
||||
/* while loop */
|
||||
break;
|
||||
}
|
||||
else if (ISEQ_BODY(ip)->type == ISEQ_TYPE_BLOCK) {
|
||||
break;
|
||||
}
|
||||
else if (ISEQ_BODY(ip)->type == ISEQ_TYPE_EVAL) {
|
||||
rb_raise(rb_eArgError, "Can't escape from eval with next");
|
||||
return;
|
||||
}
|
||||
|
||||
ip = ISEQ_BODY(ip)->parent_iseq;
|
||||
}
|
||||
if (ip != 0) {
|
||||
if (next_node->arguments) {
|
||||
PM_COMPILE((pm_node_t *)next_node->arguments);
|
||||
}
|
||||
else {
|
||||
PM_PUTNIL;
|
||||
}
|
||||
ADD_INSN1(ret, &dummy_line_node, throw, INT2FIX(throw_flag | TAG_NEXT));
|
||||
|
||||
PM_POP_IF_POPPED;
|
||||
}
|
||||
else {
|
||||
rb_raise(rb_eArgError, "Invalid next");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -760,8 +760,38 @@ module Prism
|
|||
end
|
||||
|
||||
def test_NextNode
|
||||
# TODO:
|
||||
# assert_prism_eval("2.times do |i|; next if i == 1; end")
|
||||
assert_prism_eval("2.times do |i|; next if i == 1; end")
|
||||
|
||||
assert_prism_eval(<<-CODE)
|
||||
res = []
|
||||
i = 0
|
||||
while i < 5
|
||||
i += 1
|
||||
next if i == 3
|
||||
res << i
|
||||
end
|
||||
res
|
||||
CODE
|
||||
|
||||
assert_prism_eval(<<-CODE)
|
||||
res = []
|
||||
(1..5).each do |i|
|
||||
next if i.even?
|
||||
res << i
|
||||
end
|
||||
res
|
||||
CODE
|
||||
|
||||
assert_prism_eval(<<-CODE)
|
||||
res = []
|
||||
i = 0
|
||||
begin
|
||||
i += 1
|
||||
next if i == 3
|
||||
res << i
|
||||
end while i < 5
|
||||
res
|
||||
CODE
|
||||
end
|
||||
|
||||
def test_RedoNode
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue