From c9e4dc308f51122e0401756ac3aa4972d0b4ad32 Mon Sep 17 00:00:00 2001 From: ko1 Date: Mon, 16 Feb 2009 20:54:58 +0000 Subject: * compile.c: fix to add "ensure" codes across "while" clause before "return" expression. [ruby-dev:37967] * bootstraptest/test_flow.rb: add a test. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22363 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 7 +++++ bootstraptest/test_flow.rb | 17 +++++++++-- compile.c | 73 ++++++++++++++++++++++++++++------------------ 3 files changed, 66 insertions(+), 31 deletions(-) diff --git a/ChangeLog b/ChangeLog index 84b60e0e9f..54122a8e80 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Tue Feb 17 05:41:08 2009 Koichi Sasada + + * compile.c: fix to add "ensure" codes across "while" clause + before "return" expression. [ruby-dev:37967] + + * bootstraptest/test_flow.rb: add a test. + Tue Feb 17 01:53:35 2009 Tanaka Akira * ext/socket/mkconstants.rb: generate rb_define_const directly for diff --git a/bootstraptest/test_flow.rb b/bootstraptest/test_flow.rb index 9964dfb2ed..46ca1a0c6a 100644 --- a/bootstraptest/test_flow.rb +++ b/bootstraptest/test_flow.rb @@ -200,7 +200,9 @@ assert_equal %q{[1, 2, 3, 5, 8, 9]}, %q{$a = []; begin; ; $a << 1 end; $a << 8 ; $a << 9 ; rescue Exception; $a << 99; end; $a} -assert_equal %q{[1, 2, 3, 5, 99]}, %q{$a = []; begin; ; $a << 1 +assert_equal %q{[1, 2, 3, 5, 99]}, %q{ +$a = []; +begin; ; $a << 1 while true; $a << 2 begin; $a << 3 break; $a << 4 @@ -488,4 +490,15 @@ assert_equal %q{[:ok, :ok2, :last]}, %q{ a << :last end a - } +} +assert_equal %Q{ENSURE\n}, %q{ + def test + while true + return + end + ensure + puts("ENSURE") + end + test +}, '[ruby-dev:37967]' + diff --git a/compile.c b/compile.c index 24a63e1d68..2bf4167719 100644 --- a/compile.c +++ b/compile.c @@ -2749,6 +2749,17 @@ make_name_for_block(rb_iseq_t *iseq) } } +static void +push_ensure_entry(rb_iseq_t *iseq, + struct iseq_compile_data_ensure_node_stack *enl, + struct ensure_range *er, NODE *node) +{ + enl->ensure_node = node; + enl->prev = iseq->compile_data->ensure_node_stack; /* prev */ + enl->erange = er; + iseq->compile_data->ensure_node_stack = enl; +} + static void add_ensure_range(rb_iseq_t *iseq, struct ensure_range *erange, LABEL *lstart, LABEL *lend) @@ -2768,7 +2779,7 @@ add_ensure_range(rb_iseq_t *iseq, struct ensure_range *erange, } static void -add_ensure_iseq(LINK_ANCHOR *ret, rb_iseq_t *iseq) +add_ensure_iseq(LINK_ANCHOR *ret, rb_iseq_t *iseq, int is_return) { struct iseq_compile_data_ensure_node_stack *enlp = iseq->compile_data->ensure_node_stack; @@ -2777,19 +2788,25 @@ add_ensure_iseq(LINK_ANCHOR *ret, rb_iseq_t *iseq) INIT_ANCHOR(ensure); while (enlp) { - DECL_ANCHOR(ensure_part); - LABEL *lstart = NEW_LABEL(0); - LABEL *lend = NEW_LABEL(0); + if (enlp->erange != 0) { + DECL_ANCHOR(ensure_part); + LABEL *lstart = NEW_LABEL(0); + LABEL *lend = NEW_LABEL(0); + INIT_ANCHOR(ensure_part); - INIT_ANCHOR(ensure_part); - add_ensure_range(iseq, enlp->erange, lstart, lend); + add_ensure_range(iseq, enlp->erange, lstart, lend); - iseq->compile_data->ensure_node_stack = enlp->prev; - ADD_LABEL(ensure_part, lstart); - COMPILE_POPED(ensure_part, "ensure part", enlp->ensure_node); - ADD_LABEL(ensure_part, lend); - - ADD_SEQ(ensure, ensure_part); + iseq->compile_data->ensure_node_stack = enlp->prev; + ADD_LABEL(ensure_part, lstart); + COMPILE_POPED(ensure_part, "ensure part", enlp->ensure_node); + ADD_LABEL(ensure_part, lend); + ADD_SEQ(ensure, ensure_part); + } + else { + if (!is_return) { + break; + } + } enlp = enlp->prev; } iseq->compile_data->ensure_node_stack = prev_enlp; @@ -3123,8 +3140,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) LABEL *prev_redo_label = iseq->compile_data->redo_label; VALUE prev_loopval_popped = iseq->compile_data->loopval_popped; - struct iseq_compile_data_ensure_node_stack *enlp = - iseq->compile_data->ensure_node_stack; + struct iseq_compile_data_ensure_node_stack enl; LABEL *next_label = iseq->compile_data->start_label = NEW_LABEL(nd_line(node)); /* next */ LABEL *redo_label = iseq->compile_data->redo_label = NEW_LABEL(nd_line(node)); /* redo */ @@ -3135,7 +3151,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) LABEL *tmp_label = NULL; iseq->compile_data->loopval_popped = 0; - iseq->compile_data->ensure_node_stack = 0; + push_ensure_entry(iseq, &enl, 0, 0); if (type == NODE_OPT_N || node->nd_state == 1) { ADD_INSNL(ret, nd_line(node), jump, next_label); @@ -3197,7 +3213,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) iseq->compile_data->end_label = prev_end_label; iseq->compile_data->redo_label = prev_redo_label; iseq->compile_data->loopval_popped = prev_loopval_popped; - iseq->compile_data->ensure_node_stack = enlp; + iseq->compile_data->ensure_node_stack = iseq->compile_data->ensure_node_stack->prev; break; } case NODE_ITER: @@ -3246,7 +3262,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) ADD_LABEL(ret, splabel); ADD_ADJUST(ret, nd_line(node), iseq->compile_data->redo_label); COMPILE_(ret, "break val (while/until)", node->nd_stts, iseq->compile_data->loopval_popped); - add_ensure_iseq(ret, iseq); + add_ensure_iseq(ret, iseq, 0); ADD_INSNL(ret, nd_line(node), jump, iseq->compile_data->end_label); ADD_ADJUST_RESTORE(ret, splabel); @@ -3306,7 +3322,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) debugs("next in while loop\n"); ADD_LABEL(ret, splabel); COMPILE(ret, "next val/valid syntax?", node->nd_stts); - add_ensure_iseq(ret, iseq); + add_ensure_iseq(ret, iseq, 0); ADD_ADJUST(ret, nd_line(node), iseq->compile_data->redo_label); ADD_INSNL(ret, nd_line(node), jump, iseq->compile_data->start_label); ADD_ADJUST_RESTORE(ret, splabel); @@ -3317,7 +3333,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) ADD_LABEL(ret, splabel); ADD_ADJUST(ret, nd_line(node), iseq->compile_data->start_label); COMPILE(ret, "next val", node->nd_stts); - add_ensure_iseq(ret, iseq); + add_ensure_iseq(ret, iseq, 0); ADD_INSNL(ret, nd_line(node), jump, iseq->compile_data->end_label); ADD_ADJUST_RESTORE(ret, splabel); @@ -3372,7 +3388,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) debugs("redo in while"); ADD_LABEL(ret, splabel); ADD_ADJUST(ret, nd_line(node), iseq->compile_data->redo_label); - add_ensure_iseq(ret, iseq); + add_ensure_iseq(ret, iseq, 0); ADD_INSNL(ret, nd_line(node), jump, iseq->compile_data->redo_label); ADD_ADJUST_RESTORE(ret, splabel); } @@ -3385,7 +3401,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) debugs("redo in block"); ADD_LABEL(ret, splabel); - add_ensure_iseq(ret, iseq); + add_ensure_iseq(ret, iseq, 0); ADD_ADJUST(ret, nd_line(node), iseq->compile_data->start_label); ADD_INSNL(ret, nd_line(node), jump, iseq->compile_data->start_label); ADD_ADJUST_RESTORE(ret, splabel); @@ -3542,19 +3558,17 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) LABEL *lstart = NEW_LABEL(nd_line(node)); LABEL *lend = NEW_LABEL(nd_line(node)); LABEL *lcont = NEW_LABEL(nd_line(node)); - struct ensure_range er = { 0 }; + struct ensure_range er; struct iseq_compile_data_ensure_node_stack enl; struct ensure_range *erange; INIT_ANCHOR(ensr); - er.begin = lstart; - er.end = lend; - enl.ensure_node = node->nd_ensr; - enl.prev = iseq->compile_data->ensure_node_stack; /* prev */ - enl.erange = &er; COMPILE_POPED(ensr, "ensure ensr", node->nd_ensr); - iseq->compile_data->ensure_node_stack = &enl; + er.begin = lstart; + er.end = lend; + er.next = 0; + push_ensure_entry(iseq, &enl, &er, node->nd_ensr); ADD_LABEL(ret, lstart); COMPILE_(ret, "ensure head", node->nd_head, poped); @@ -3573,6 +3587,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) ensure, lcont); erange = erange->next; } + iseq->compile_data->ensure_node_stack = enl.prev; break; } @@ -4171,7 +4186,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) COMPILE(ret, "return nd_stts (return val)", node->nd_stts); if (is->type == ISEQ_TYPE_METHOD) { - add_ensure_iseq(ret, iseq); + add_ensure_iseq(ret, iseq, 1); ADD_INSN(ret, nd_line(node), leave); ADD_ADJUST_RESTORE(ret, splabel); -- cgit v1.2.3