summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-08-20 18:58:32 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-08-20 18:58:32 +0000
commitad56f8c6110bd8233a4f2224ccdd1cc7ef645dc1 (patch)
tree274ff252edc7e4aba38c03752ebba1e3000bfebe
parent009debfd02f5024b85b5c325f42533b40f4028e9 (diff)
* enumerator.c (next_i): fix to return with Fiber#yield at
the end of each block. [ruby-dev:31470] * enumerator.c (enumerator_next_p): call init_next if not initialized. [ruby-dev:31514] * test/ruby/test_enumerator.rb: add tests for Enumerator. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13120 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog10
-rw-r--r--enumerator.c19
-rw-r--r--test/ruby/test_enumerator.rb48
-rw-r--r--version.h6
4 files changed, 73 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index d6c6e4b819..267c74224a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+Tue Aug 21 03:55:20 2007 Koichi Sasada <ko1@atdot.net>
+
+ * enumerator.c (next_i): fix to return with Fiber#yield at
+ the end of each block. [ruby-dev:31470]
+
+ * enumerator.c (enumerator_next_p): call init_next if not
+ initialized. [ruby-dev:31514]
+
+ * test/ruby/test_enumerator.rb: add tests for Enumerator.
+
Mon Aug 20 23:28:39 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
* string.c (Init_String): remove Symbol.intern and Symbol#dump.
diff --git a/enumerator.c b/enumerator.c
index 766d13758c..e2be0e2e85 100644
--- a/enumerator.c
+++ b/enumerator.c
@@ -13,6 +13,7 @@
************************************************/
#include "ruby/ruby.h"
+#include "debug.h"
/*
* Document-class: Enumerable::Enumerator
@@ -42,6 +43,7 @@ struct enumerator {
VALUE fib;
VALUE next;
VALUE dst;
+ VALUE has_next;
};
static void
@@ -237,6 +239,7 @@ enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, VALUE *argv)
if (argc) ptr->args = rb_ary_new4(argc, argv);
ptr->fib = 0;
ptr->next = ptr->dst = Qnil;
+ ptr->has_next = Qnil;
return enum_obj;
}
@@ -381,19 +384,20 @@ static VALUE
next_i(VALUE curr, VALUE obj)
{
struct enumerator *e = enumerator_ptr(obj);
-
e->dst = curr;
+
rb_block_call(obj, rb_intern("each"), 0, 0, next_ii, obj);
- return e->next;
+ e->has_next = Qfalse;
+ rb_fiber_yield(e->dst, 1, &e->next);
}
static void
next_init(VALUE obj, struct enumerator *e)
{
VALUE curr = rb_fiber_current();
-
e->dst = curr;
e->fib = rb_block_call(rb_cFiber, rb_intern("new"), 0, 0, next_i, obj);
+ e->has_next = Qtrue;
rb_fiber_yield(e->fib, 1, &curr);
}
@@ -416,16 +420,18 @@ enumerator_next(VALUE obj)
{
struct enumerator *e = enumerator_ptr(obj);
VALUE curr, v;
-
curr = rb_fiber_current();
+
if (!e->fib) {
next_init(obj, e);
}
- if (!rb_fiber_alive_p(e->fib)) {
+
+ if (!e->has_next) {
e->fib = 0;
e->next = e->dst = Qnil;
rb_raise(rb_eStopIteration, "Enumerator#each reached at end");
}
+
v = rb_fiber_yield(e->fib, 1, &curr);
return v;
}
@@ -441,11 +447,10 @@ static VALUE
enumerator_next_p(VALUE obj)
{
struct enumerator *e = enumerator_ptr(obj);
-
if (!e->fib) {
next_init(obj, e);
}
- return rb_fiber_alive_p(e->fib);
+ return e->has_next;
}
/*
diff --git a/test/ruby/test_enumerator.rb b/test/ruby/test_enumerator.rb
new file mode 100644
index 0000000000..6ff8f82019
--- /dev/null
+++ b/test/ruby/test_enumerator.rb
@@ -0,0 +1,48 @@
+require 'test/unit'
+
+class TestEnumerator < Test::Unit::TestCase
+ def enum_test obj
+ i = 0
+ obj.map{|e|
+ [i+=1, e]
+ }
+ end
+
+ def test_iterators
+ assert_equal [[1, 0], [2, 1], [3, 2]], enum_test(3.times)
+ assert_equal [[1, :x], [2, :y], [3, :z]], enum_test([:x, :y, :z].each)
+ assert_equal [[1, [:x, 1]], [2, [:y, 2]]], enum_test({:x=>1, :y=>2})
+ end
+
+ ## Enumerator as Iterator
+
+ def test_next
+ e = 3.times
+ 3.times{|i|
+ assert_equal i, e.next
+ }
+ assert_raise(StopIteration){e.next}
+ end
+
+ def test_next?
+ e = 3.times
+ assert_equal true, e.next?
+ 3.times{|i|
+ assert_equal true, e.next?
+ assert_equal i, e.next
+ }
+ assert_equal false, e.next?
+ end
+
+ def test_nested_itaration
+ def (o = Object.new).each
+ yield :ok1
+ yield [:ok2, :x].each.next
+ end
+ e = o.to_enum
+ assert_equal :ok1, e.next
+ assert_equal :ok2, e.next
+ assert_raise(StopIteration){e.next}
+ end
+end
+
diff --git a/version.h b/version.h
index b1b9795b5a..dcbfe5dee7 100644
--- a/version.h
+++ b/version.h
@@ -1,7 +1,7 @@
#define RUBY_VERSION "1.9.0"
-#define RUBY_RELEASE_DATE "2007-08-20"
+#define RUBY_RELEASE_DATE "2007-08-21"
#define RUBY_VERSION_CODE 190
-#define RUBY_RELEASE_CODE 20070820
+#define RUBY_RELEASE_CODE 20070821
#define RUBY_PATCHLEVEL 0
#define RUBY_VERSION_MAJOR 1
@@ -9,7 +9,7 @@
#define RUBY_VERSION_TEENY 0
#define RUBY_RELEASE_YEAR 2007
#define RUBY_RELEASE_MONTH 8
-#define RUBY_RELEASE_DAY 20
+#define RUBY_RELEASE_DAY 21
#ifdef RUBY_EXTERN
RUBY_EXTERN const char ruby_version[];