summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-08-13 10:31:33 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-08-13 10:31:33 +0000
commitc791dc1345ad8ebe7b707e8922b42a7a43c53b89 (patch)
tree020162add6282afc465081d6675dec75e4c33443
parent855f1ff1323e7eca763b34cc9f7b850dddaa1c0c (diff)
* 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4379 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog7
-rw-r--r--eval.c13
-rw-r--r--sample/test.rb28
3 files changed, 44 insertions, 4 deletions
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 <matz@ruby-lang.org>
+
+ * 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 <eban@ruby-lang.org>
* 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