[PRISM] Fix loop in rescue blocks
Fixes ruby/prism#2250. Co-Authored-By: Kevin Newton <kddnewton@gmail.com>
This commit is contained in:
parent
59bb78ebd0
commit
a120529020
@ -2761,7 +2761,10 @@ pm_compile_call(rb_iseq_t *iseq, const pm_call_node_t *call_node, LINK_ANCHOR *c
|
|||||||
ADD_INSNL(ret, &dummy_line_node, jump, end_label);
|
ADD_INSNL(ret, &dummy_line_node, jump, end_label);
|
||||||
ADD_LABEL(ret, else_label);
|
ADD_LABEL(ret, else_label);
|
||||||
}
|
}
|
||||||
ADD_LABEL(ret, end_label);
|
|
||||||
|
if ((block_iseq && ISEQ_BODY(block_iseq)->catch_table) || (call_node->base.flags & PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) {
|
||||||
|
ADD_LABEL(ret, end_label);
|
||||||
|
}
|
||||||
|
|
||||||
PM_POP_IF_POPPED;
|
PM_POP_IF_POPPED;
|
||||||
}
|
}
|
||||||
@ -6073,7 +6076,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
|
|||||||
// this compilation block.
|
// this compilation block.
|
||||||
LABEL *exception_match_label = NEW_LABEL(lineno);
|
LABEL *exception_match_label = NEW_LABEL(lineno);
|
||||||
LABEL *rescue_end_label = NEW_LABEL(lineno);
|
LABEL *rescue_end_label = NEW_LABEL(lineno);
|
||||||
ISEQ_COMPILE_DATA(iseq)->end_label = rescue_end_label;
|
|
||||||
|
|
||||||
// Next, compile each of the exceptions that we're going to be
|
// Next, compile each of the exceptions that we're going to be
|
||||||
// handling. For each one, we'll add instructions to check if the
|
// handling. For each one, we'll add instructions to check if the
|
||||||
@ -6098,12 +6100,12 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
|
|||||||
ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0);
|
ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0);
|
||||||
ADD_INSN1(ret, &dummy_line_node, putobject, rb_eStandardError);
|
ADD_INSN1(ret, &dummy_line_node, putobject, rb_eStandardError);
|
||||||
ADD_INSN1(ret, &dummy_line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
|
ADD_INSN1(ret, &dummy_line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
|
||||||
ADD_INSN1(ret, &dummy_line_node, branchif, exception_match_label);
|
ADD_INSNL(ret, &dummy_line_node, branchif, exception_match_label);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If none of the exceptions that we are matching against matched, then
|
// If none of the exceptions that we are matching against matched, then
|
||||||
// we'll jump straight to the rescue_end_label label.
|
// we'll jump straight to the rescue_end_label label.
|
||||||
ADD_INSN1(ret, &dummy_line_node, jump, rescue_end_label);
|
ADD_INSNL(ret, &dummy_line_node, jump, rescue_end_label);
|
||||||
|
|
||||||
// Here we have the exception_match_label, which is where the
|
// Here we have the exception_match_label, which is where the
|
||||||
// control-flow goes in the case that one of the exceptions matched.
|
// control-flow goes in the case that one of the exceptions matched.
|
||||||
@ -7081,8 +7083,8 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
|
|||||||
ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0);
|
ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0);
|
||||||
ADD_INSN1(ret, &dummy_line_node, putobject, rb_eStandardError);
|
ADD_INSN1(ret, &dummy_line_node, putobject, rb_eStandardError);
|
||||||
ADD_INSN1(ret, &dummy_line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
|
ADD_INSN1(ret, &dummy_line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
|
||||||
ADD_INSN1(ret, &dummy_line_node, branchif, lab);
|
ADD_INSNL(ret, &dummy_line_node, branchif, lab);
|
||||||
ADD_INSN1(ret, &dummy_line_node, jump, rescue_end);
|
ADD_INSNL(ret, &dummy_line_node, jump, rescue_end);
|
||||||
ADD_LABEL(ret, lab);
|
ADD_LABEL(ret, lab);
|
||||||
PM_COMPILE((pm_node_t *)scope_node->body);
|
PM_COMPILE((pm_node_t *)scope_node->body);
|
||||||
ADD_INSN(ret, &dummy_line_node, leave);
|
ADD_INSN(ret, &dummy_line_node, leave);
|
||||||
|
@ -987,10 +987,38 @@ module Prism
|
|||||||
|
|
||||||
def test_UntilNode
|
def test_UntilNode
|
||||||
assert_prism_eval("a = 0; until a == 1; a = a + 1; end")
|
assert_prism_eval("a = 0; until a == 1; a = a + 1; end")
|
||||||
|
|
||||||
|
# Test UntilNode in rescue
|
||||||
|
assert_prism_eval(<<~RUBY)
|
||||||
|
o = Object.new
|
||||||
|
o.instance_variable_set(:@ret, [])
|
||||||
|
def o.foo = @ret << @ret.length
|
||||||
|
def o.bar = @ret.length > 3
|
||||||
|
begin
|
||||||
|
raise
|
||||||
|
rescue
|
||||||
|
o.foo until o.bar
|
||||||
|
end
|
||||||
|
o.instance_variable_get(:@ret)
|
||||||
|
RUBY
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_WhileNode
|
def test_WhileNode
|
||||||
assert_prism_eval("a = 0; while a != 1; a = a + 1; end")
|
assert_prism_eval("a = 0; while a != 1; a = a + 1; end")
|
||||||
|
|
||||||
|
# Test WhileNode in rescue
|
||||||
|
assert_prism_eval(<<~RUBY)
|
||||||
|
o = Object.new
|
||||||
|
o.instance_variable_set(:@ret, [])
|
||||||
|
def o.foo = @ret << @ret.length
|
||||||
|
def o.bar = @ret.length < 3
|
||||||
|
begin
|
||||||
|
raise
|
||||||
|
rescue
|
||||||
|
o.foo while o.bar
|
||||||
|
end
|
||||||
|
o.instance_variable_get(:@ret)
|
||||||
|
RUBY
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_ForNode
|
def test_ForNode
|
||||||
|
Loading…
x
Reference in New Issue
Block a user