aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--prism_compile.c55
-rw-r--r--test/ruby/test_compile_prism.rb39
2 files changed, 81 insertions, 13 deletions
diff --git a/prism_compile.c b/prism_compile.c
index 6526718d70..d2999a9d10 100644
--- a/prism_compile.c
+++ b/prism_compile.c
@@ -3722,7 +3722,60 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
return;
}
case PM_REDO_NODE: {
- ADD_INSNL(ret, &dummy_line_node, jump, ISEQ_COMPILE_DATA(iseq)->redo_label);
+ if (ISEQ_COMPILE_DATA(iseq)->redo_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)->redo_label);
+
+ add_ensure_iseq(ret, iseq, 0);
+ ADD_INSNL(ret, &dummy_line_node, jump, ISEQ_COMPILE_DATA(iseq)->redo_label);
+ ADD_ADJUST_RESTORE(ret, splabel);
+ PM_PUTNIL_UNLESS_POPPED;
+ }
+ else if (ISEQ_BODY(iseq)->type != ISEQ_TYPE_EVAL && ISEQ_COMPILE_DATA(iseq)->start_label && 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)->start_label);
+ ADD_INSNL(ret, &dummy_line_node, jump, ISEQ_COMPILE_DATA(iseq)->start_label);
+ ADD_ADJUST_RESTORE(ret, splabel);
+
+ PM_PUTNIL_UNLESS_POPPED;
+ }
+ else {
+ const rb_iseq_t *ip = iseq;
+
+ while (ip) {
+ if (!ISEQ_COMPILE_DATA(ip)) {
+ ip = 0;
+ break;
+ }
+
+ if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
+ break;
+ }
+ else if (ISEQ_BODY(ip)->type == ISEQ_TYPE_BLOCK) {
+ break;
+ }
+ else if (ISEQ_BODY(ip)->type == ISEQ_TYPE_EVAL) {
+ rb_bug("Invalid redo\n");
+ }
+
+ ip = ISEQ_BODY(ip)->parent_iseq;
+ }
+ if (ip != 0) {
+ PM_PUTNIL;
+ ADD_INSN1(ret, &dummy_line_node, throw, INT2FIX(VM_THROW_NO_ESCAPE_FLAG | TAG_REDO));
+
+ PM_POP_IF_POPPED;
+ }
+ else {
+ rb_bug("Invalid redo\n");
+ }
+ }
return;
}
case PM_REGULAR_EXPRESSION_NODE: {
diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb
index b4e24c6c67..22e4f6b7bf 100644
--- a/test/ruby/test_compile_prism.rb
+++ b/test/ruby/test_compile_prism.rb
@@ -815,18 +815,33 @@ module Prism
end
def test_RedoNode
- # TODO:
- # assert_prism_eval(<<-CODE
- # counter = 0
-
- # 5.times do |i|
- # counter += 1
- # if i == 2 && counter < 3
- # redo
- # end
- # end
- # CODE
- # )
+ assert_prism_eval(<<-CODE)
+ counter = 0
+
+ 5.times do |i|
+ counter += 1
+ if i == 2 && counter < 3
+ redo
+ end
+ end
+ CODE
+
+ assert_prism_eval(<<-CODE)
+ for i in 1..5
+ if i == 3
+ i = 0
+ redo
+ end
+ end
+ CODE
+
+ assert_prism_eval(<<-CODE)
+ i = 0
+ begin
+ i += 1
+ redo if i == 3
+ end while i < 5
+ CODE
end
def test_RescueNode