Skip to content

Commit a9f69f3

Browse files
committed
[Feature #21822] Expose return value in the ensure block
1 parent b7dbdfe commit a9f69f3

File tree

3 files changed

+47
-7
lines changed

3 files changed

+47
-7
lines changed

common.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,7 @@ yes-test-all: $(PRECHECK_TEST_ALL)
912912
$(ACTIONS_GROUP)
913913
$(gnumake_recursive)$(Q)$(exec) $(RUNRUBY) -r$(tooldir)/lib/_tmpdir \
914914
"$(TESTSDIR)/runner.rb" --ruby="$(RUNRUBY)" \
915+
-x prism/ruby/ripper \
915916
$(TEST_EXCLUDES) $(TESTOPTS) $(TESTS)
916917
$(ACTIONS_ENDGROUP)
917918
TESTS_BUILD = mkmf

parse.y

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,6 +1082,7 @@ static rb_node_retry_t *rb_node_retry_new(struct parser_params *p, const YYLTYPE
10821082
static rb_node_begin_t *rb_node_begin_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc);
10831083
static rb_node_rescue_t *rb_node_rescue_new(struct parser_params *p, NODE *nd_head, NODE *nd_resq, NODE *nd_else, const YYLTYPE *loc);
10841084
static rb_node_resbody_t *rb_node_resbody_new(struct parser_params *p, NODE *nd_args, NODE *nd_exc_var, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc);
1085+
RBIMPL_ATTR_MAYBE_UNUSED()
10851086
static rb_node_ensure_t *rb_node_ensure_new(struct parser_params *p, NODE *nd_head, NODE *nd_ensr, const YYLTYPE *loc);
10861087
static rb_node_and_t *rb_node_and_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc, const YYLTYPE *operator_loc);
10871088
static rb_node_or_t *rb_node_or_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc, const YYLTYPE *operator_loc);
@@ -2769,7 +2770,7 @@ rb_parser_ary_free(rb_parser_t *p, rb_parser_ary_t *ary)
27692770
%type <node> command command_call command_call_value method_call
27702771
%type <node> expr_value expr_value_do arg_value primary_value rel_expr
27712772
%type <node_fcall> fcall
2772-
%type <node> if_tail opt_else case_body case_args cases opt_rescue exc_list exc_var opt_ensure
2773+
%type <node> if_tail opt_else case_body case_args cases opt_rescue exc_list exc_var opt_ensure ensure_var
27732774
%type <node> args arg_splat call_args opt_call_args
27742775
%type <node> paren_args opt_paren_args
27752776
%type <node_args> args_tail block_args_tail
@@ -5899,12 +5900,24 @@ exc_var : tASSOC lhs
58995900
| none
59005901
;
59015902

5902-
opt_ensure : k_ensure stmts terms?
5903+
ensure_var : tASSOC lhs then
59035904
{
5904-
p->ctxt.in_rescue = $1.in_rescue;
5905-
$$ = $2;
5906-
void_expr(p, void_stmts(p, $$));
5907-
/*% ripper: ensure!($:2) %*/
5905+
$$ = $lhs;
5906+
/*% ripper: $:lhs %*/
5907+
}
5908+
| none
5909+
;
5910+
5911+
opt_ensure : k_ensure ensure_var stmts terms?
5912+
{
5913+
p->ctxt.in_rescue = $k_ensure.in_rescue;
5914+
void_expr(p, void_stmts(p, $stmts));
5915+
5916+
rb_node_ensure_t *n = NODE_NEW_INTERNAL(NODE_ENSURE, rb_node_ensure_t);
5917+
n->nd_head = $ensure_var;
5918+
n->nd_ensr = $stmts;
5919+
$$ = &n->node;
5920+
/*% ripper: ensure!($:stmts, $:ensure_var) %*/
59085921
}
59095922
| none
59105923
;
@@ -14845,7 +14858,11 @@ new_bodystmt(struct parser_params *p, NODE *head, NODE *rescue, NODE *rescue_els
1484514858
nd_set_line(result, rescue->nd_loc.beg_pos.lineno);
1484614859
}
1484714860
if (ensure) {
14848-
result = NEW_ENSURE(result, ensure, loc);
14861+
nd_set_loc(ensure, loc);
14862+
nd_set_node_id(ensure, parser_get_node_id(p));
14863+
NODE **var = &((rb_node_ensure_t *)ensure)->nd_head;
14864+
*var = *var ? node_assign(p, *var, result, NO_LEX_CTXT, &(*var)->nd_loc) : result;
14865+
result = ensure;
1484914866
}
1485014867
fixpos(result, head);
1485114868
return result;

test/ruby/test_syntax.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1761,6 +1761,28 @@ def test_rescue_do_end_ensure_in_lambda
17611761
assert_equal([:begin, :rescue, :ensure], result)
17621762
end
17631763

1764+
def test_return_value_in_ensure
1765+
omit if /\+PRISM\b/ =~ RUBY_DESCRIPTION
1766+
1767+
expect = rand(100)
1768+
eval("#{<<-"begin;"}\n#{<<-"end;"}")
1769+
begin;
1770+
begin
1771+
expect + 1
1772+
ensure => retval
1773+
assert_equal(expect + 1, retval)
1774+
end
1775+
end;
1776+
assert_raise_with_message(RuntimeError, "[Feature #21822]") {eval("#{<<-"begin;"}\n#{<<-"end;"}")}
1777+
begin;
1778+
begin
1779+
raise "[Feature #21822]"
1780+
ensure => retval
1781+
assert_nil(retval)
1782+
end
1783+
end;
1784+
end
1785+
17641786
def test_return_in_loop
17651787
obj = Object.new
17661788
def obj.test

0 commit comments

Comments
 (0)