diff options
author | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2007-08-20 18:58:32 +0000 |
---|---|---|
committer | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2007-08-20 18:58:32 +0000 |
commit | ad56f8c6110bd8233a4f2224ccdd1cc7ef645dc1 (patch) | |
tree | 274ff252edc7e4aba38c03752ebba1e3000bfebe | |
parent | 009debfd02f5024b85b5c325f42533b40f4028e9 (diff) | |
download | ruby-ad56f8c6110bd8233a4f2224ccdd1cc7ef645dc1.tar.gz |
* 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-- | ChangeLog | 10 | ||||
-rw-r--r-- | enumerator.c | 19 | ||||
-rw-r--r-- | test/ruby/test_enumerator.rb | 48 | ||||
-rw-r--r-- | version.h | 6 |
4 files changed, 73 insertions, 10 deletions
@@ -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
+
@@ -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[]; |