diff --git a/ChangeLog b/ChangeLog index 4a5d5ae60e..2ecd320314 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Wed Aug 13 18:13:49 2003 Yukihiro Matsumoto + + * eval.c (POP_BLOCK): turn on BLOCK_LEFT flag when leaving block. + + * eval.c (proc_invoke): unpack return/break destination when block + is already left. + Wed Aug 13 15:58:31 2003 WATANABE Hirofumi * object.c (rb_class_s_alloc): add function prototype to avoid VC++ diff --git a/eval.c b/eval.c index 2317c8bf95..a03c676068 100644 --- a/eval.c +++ b/eval.c @@ -632,6 +632,7 @@ struct BLOCK { #define BLOCK_DYNAMIC 2 #define BLOCK_ORPHAN 4 #define BLOCK_LAMBDA 8 +#define BLOCK_LEFT 16 static struct BLOCK *ruby_block; @@ -666,12 +667,13 @@ new_blktag() _block.block_obj = 0; \ ruby_block = &_block -#define POP_BLOCK() \ +#define POP_BLOCK() \ if (_block.tag->flags & (BLOCK_DYNAMIC)) \ _block.tag->flags |= BLOCK_ORPHAN; \ else if (!(_block.scope->flags & SCOPE_DONT_RECYCLE)) \ rb_gc_force_recycle((VALUE)_block.tag); \ - ruby_block = _block.prev; \ + ruby_block = _block.prev; \ + _block.tag->flags |= BLOCK_LEFT; \ } while (0) struct RVarmap *ruby_dyna_vars; @@ -7023,6 +7025,7 @@ proc_invoke(proc, args, self, klass) if (klass) _block.frame.last_class = klass; ruby_block = &_block; + again: PUSH_ITER(ITER_CUR); ruby_frame->iter = ITER_CUR; PUSH_TAG(PROT_NONE); @@ -7035,7 +7038,9 @@ proc_invoke(proc, args, self, klass) POP_ITER(); incoming_state = state; - if (orphan || ruby_block->tag->dst == state) { + if (orphan || pcall || + ((ruby_block->tag->flags & BLOCK_LEFT) && + ruby_block->tag->dst == state)) { state &= TAG_MASK; } ruby_block = old_block; @@ -8499,7 +8504,7 @@ intersect_fds(src, dst, max) if (FD_ISSET(i, src)) { /* Wake up only one thread per fd. */ FD_CLR(i, src); - ++n; + n++; } else { FD_CLR(i, dst); diff --git a/sample/test.rb b/sample/test.rb index 6d2a6cde95..8b8354ad5c 100644 --- a/sample/test.rb +++ b/sample/test.rb @@ -1033,6 +1033,34 @@ test_ok(get_block(&lambda).class == Proc) test_ok(Proc.new{|a,| a}.call(1,2,3) == 1) argument_test(true, Proc.new{|a,|}, 1,2) +def test_return1 + Proc.new { + return 55 + }.call + 5 +end +test_ok(test_return1() == 55) +def test_return2 + lambda { + return 55 + }.call + 5 +end +test_ok(test_return2() == 60) + +def proc_call(&b) + b.call +end +def proc_yield() + yield +end +def proc_return1 + proc_call{return 42}+1 +end +test_ok(proc_return1() == 42) +def proc_return2 + proc_yield{return 42}+1 +end +test_ok(proc_return2() == 42) + def ljump_test(state, proc, *args) x = state begin