Skip to content
Browse files

fixed break, next and redo with ensure block, fixed codes below.

1)
1.times { begin; break; ensure; p 42; end }

2)
i=0; while i<1; begin; break; ensure; p 42; end; end

3)
i=0; while true; begin; break if i>0; i=1; redo; ensure; p 42; end; end

4)
def f(&proc) p :ok; end; f(&nil)
  • Loading branch information...
1 parent ba7056c commit dcd258b4dfc63a4ba4b952e8c7633dec00484fa5 @takaokouji takaokouji committed
Showing with 50 additions and 9 deletions.
  1. +44 −5 compiler.cpp
  2. +2 −0 compiler.h
  3. +3 −3 test_vm/block.rb
  4. +1 −1 test_vm/dispatch.rb
View
49 compiler.cpp
@@ -1921,6 +1921,32 @@ RoxorCompiler::compile_break_val(Value *val)
}
void
+RoxorCompiler::compile_break_within_loop(Value *val)
+{
+ if (ensure_bb == NULL) {
+ BranchInst::Create(current_loop_end_bb, bb);
+ current_loop_exit_val->addIncoming(val, bb);
+ }
+ else {
+ BranchInst::Create(ensure_bb, bb);
+ ensure_pn->addIncoming(val, bb);
+ }
+}
+
+void
+RoxorCompiler::compile_break_within_block(Value *val)
+{
+ if (ensure_bb == NULL) {
+ compile_break_val(val);
+ ReturnInst::Create(context, val, bb);
+ }
+ else {
+ BranchInst::Create(ensure_bb, bb);
+ ensure_pn->addIncoming(val, bb);
+ }
+}
+
+void
RoxorCompiler::compile_return_from_block(Value *val, int id)
{
if (returnFromBlockFunc == NULL) {
@@ -2006,12 +2032,10 @@ RoxorCompiler::compile_jump(NODE *node)
compile_landing_pad_footer();
}
if (within_loop) {
- BranchInst::Create(current_loop_end_bb, bb);
- current_loop_exit_val->addIncoming(val, bb);
+ compile_break_within_loop(val);
}
else if (within_block) {
- compile_break_val(val);
- ReturnInst::Create(context, val, bb);
+ compile_break_within_block(val);
}
else {
rb_raise(rb_eLocalJumpError, "unexpected break");
@@ -2041,6 +2065,9 @@ RoxorCompiler::compile_jump(NODE *node)
compile_landing_pad_footer();
}
if (within_loop) {
+ if (ensure_node != NULL) {
+ compile_node(ensure_node);
+ }
BranchInst::Create(current_loop_body_bb, bb);
}
else if (within_block) {
@@ -4735,7 +4762,19 @@ RoxorCompiler::compile_node0(NODE *node)
compile_set_has_ensure(old_has_ensure);
compile_node(node->nd_ensr);
// the return value is the PHINode from all the return
- compile_simple_return(new_ensure_pn);
+ const bool within_loop = current_loop_begin_bb != NULL
+ && current_loop_body_bb != NULL
+ && current_loop_end_bb != NULL;
+ const bool within_block = block_declaration;
+ if (within_loop) {
+ compile_break_within_loop(new_ensure_pn);
+ }
+ else if (within_block) {
+ compile_break_within_block(new_ensure_pn);
+ }
+ else {
+ compile_simple_return(new_ensure_pn);
+ }
}
// we also have to compile the ensure
View
2 compiler.h
@@ -399,6 +399,8 @@ class RoxorCompiler {
Value *compile_dstr(NODE *node);
Value *compile_dvar_slot(ID name);
void compile_break_val(Value *val);
+ void compile_break_within_loop(Value *val);
+ void compile_break_within_block(Value *val);
void compile_simple_return(Value *val);
Value *compile_set_has_ensure(Value *val);
void compile_return_from_block(Value *val, int id);
View
6 test_vm/block.rb
@@ -183,10 +183,10 @@ def foo(x); yield x; end
assert "42", "begin p proc { break 24 }.call rescue LocalJumpError; p 42 end", :known_bug => true
assert "42", "def foo; yield; end; foo { break }; 1.times {p 42}"
-assert "42", "1.times { begin; break; ensure; p 42; end }", :known_bug => true
-assert "42", "i=0; while i<1; begin; break; ensure; p 42; end; end", :known_bug => true
+assert "42", "1.times { begin; break; ensure; p 42; end }"
+assert "42", "i=0; while i<1; begin; break; ensure; p 42; end; end"
-assert "42\n42", "i=0; while true; begin; break if i>0; i=1; redo; ensure; p 42; end; end", :known_bug => true
+assert "42\n42", "i=0; while true; begin; break if i>0; i=1; redo; ensure; p 42; end; end"
assert "42", "p [42].map { |x| x }.map { |y| y }[0]"
View
2 test_vm/dispatch.rb
@@ -141,7 +141,7 @@ def foo
assert ":ok", "def foo(&block); :ok; end; p foo"
assert ":ok", "def foo(*args, &block); :ok; end; p foo"
assert ":ok", "def foo(x, *args, &block); x; end; p foo(:ok)"
-assert ":ok", "def f(&proc) p :ok; end; f(&nil)", :known_bug => true
+assert ":ok", "def f(&proc) p :ok; end; f(&nil)"
assert ":ok", %{
def foo(&block) p(block ? :ko : :ok) end

0 comments on commit dcd258b

Please sign in to comment.
Something went wrong with that request. Please try again.