diff options
author | Jemma Issroff <jemmaissroff@gmail.com> | 2023-12-04 10:55:11 -0500 |
---|---|---|
committer | Jemma Issroff <jemmaissroff@gmail.com> | 2023-12-04 17:02:04 -0500 |
commit | 81a700853d1d3bdf7973c7d7175711e7e8c508c7 (patch) | |
tree | fa69b4f4b4a2ebc761120168781fc267249b3837 /prism_compile.c | |
parent | 7d371ca25d8e8f6524894be4413484cc9b04cb72 (diff) | |
download | ruby-81a700853d1d3bdf7973c7d7175711e7e8c508c7.tar.gz |
[PRISM] Fixed redo node
Diffstat (limited to 'prism_compile.c')
-rw-r--r-- | prism_compile.c | 55 |
1 files changed, 54 insertions, 1 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: { |