1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* enumerator.c (enumerator_next, enumerator_rewind),

lib/generator.rb (Enumerator#rewind): If the enclosed object
  responds to a "rewind" method, call it.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@20645 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
knu 2008-12-11 12:14:10 +00:00
parent dd5a95a14c
commit 5d8659a195
4 changed files with 67 additions and 5 deletions

View file

@ -22,6 +22,7 @@
*/
VALUE rb_cEnumerator;
static VALUE sym_each;
static ID id_rewind;
VALUE rb_eStopIteration;
@ -497,6 +498,18 @@ enumerator_with_object(obj, memo)
return memo;
}
static int
require_generator()
{
static int done = 0;
if (done)
return 0; /* not the first time */
rb_require("generator");
done = 1;
return 1; /* the first time */
}
/*
* call-seq:
* e.next => object
@ -517,8 +530,15 @@ static VALUE
enumerator_next(obj)
VALUE obj;
{
rb_require("generator");
return rb_funcall(obj, rb_intern("next"), 0, 0);
if (require_generator()) {
/*
* Call the new rewind method that the generator library
* redefines.
*/
return rb_funcall(obj, rb_intern("next"), 0, 0);
} else {
rb_raise(rb_eRuntimeError, "unexpected call; the generator library must have failed in redefining this method");
}
}
/*
@ -526,14 +546,33 @@ enumerator_next(obj)
* e.rewind => e
*
* Rewinds the enumeration sequence by the next method.
*
* If the enclosed object responds to a "rewind" method, it is called.
*/
static VALUE
enumerator_rewind(obj)
VALUE obj;
{
rb_require("generator");
return rb_funcall(obj, rb_intern("rewind"), 0, 0);
if (require_generator()) {
/*
* Call the new rewind method that the generator library
* redefines.
*/
return rb_funcall(obj, rb_intern("rewind"), 0, 0);
} else {
/*
* Once the generator library is loaded and the rewind method
* is overridden, this method changes itself to a secret knob
* to rewind the internal object. (black magic!)
*/
struct enumerator *e;
e = enumerator_ptr(obj);
if (rb_respond_to(e->obj, id_rewind))
rb_funcall(e->obj, id_rewind, 0);
return obj;
}
}
/*
@ -815,7 +854,8 @@ Init_Enumerator()
rb_define_method(rb_cYielder, "yield", yielder_yield, -2);
rb_define_method(rb_cYielder, "<<", yielder_yield, -2);
sym_each = ID2SYM(rb_intern("each"));
sym_each = ID2SYM(rb_intern("each"));
id_rewind = rb_intern("rewind");
/* backward compatibility */
rb_provide("enumerator.so");