Ruby 1.9.3p327(2012-11-10revision37606)
enumerator.c
Go to the documentation of this file.
00001 /************************************************
00002 
00003   enumerator.c - provides Enumerator class
00004 
00005   $Author: marcandre $
00006 
00007   Copyright (C) 2001-2003 Akinori MUSHA
00008 
00009   $Idaemons: /home/cvs/rb/enumerator/enumerator.c,v 1.1.1.1 2001/07/15 10:12:48 knu Exp $
00010   $RoughId: enumerator.c,v 1.6 2003/07/27 11:03:24 nobu Exp $
00011   $Id: enumerator.c 34713 2012-02-20 23:55:19Z marcandre $
00012 
00013 ************************************************/
00014 
00015 #include "ruby/ruby.h"
00016 
00017 /*
00018  * Document-class: Enumerator
00019  *
00020  * A class which allows both internal and external iteration.
00021  *
00022  * An Enumerator can be created by the following methods.
00023  * - Kernel#to_enum
00024  * - Kernel#enum_for
00025  * - Enumerator.new
00026  *
00027  * Most methods have two forms: a block form where the contents
00028  * are evaluated for each item in the enumeration, and a non-block form
00029  * which returns a new Enumerator wrapping the iteration.
00030  *
00031  *   enumerator = %w(one two three).each
00032  *   puts enumerator.class # => Enumerator
00033  *   enumerator.each_with_object("foo") do |item,obj|
00034  *     puts "#{obj}: #{item}"
00035  *   end
00036  *   # foo: one
00037  *   # foo: two
00038  *   # foo: three
00039  *   enum_with_obj = enumerator.each_with_object("foo")
00040  *   puts enum_with_obj.class # => Enumerator
00041  *   enum_with_obj.each do |item,obj|
00042  *     puts "#{obj: #{item}"
00043  *   end
00044  *   # foo: one
00045  *   # foo: two
00046  *   # foo: three
00047  *
00048  * This allows you to chain Enumerators together.  For example, you
00049  * can map a list's elements to strings containing the index
00050  * and the element as a string via:
00051  *
00052  *   puts %w[foo bar baz].map.with_index {|w,i| "#{i}:#{w}" }
00053  *   # => ["0:foo", "1:bar", "2:baz"]
00054  *
00055  * An Enumerator can also be used as an external iterator.
00056  * For example, Enumerator#next returns the next value of the iterator
00057  * or raises StopIteration if the Enumerator is at the end.
00058  *
00059  *   e = [1,2,3].each   # returns an enumerator object.
00060  *   puts e.next   # => 1
00061  *   puts e.next   # => 2
00062  *   puts e.next   # => 3
00063  *   puts e.next   # raises StopIteration
00064  *
00065  * You can use this to implement an internal iterator as follows:
00066  *
00067  *   def ext_each(e)
00068  *     while true
00069  *       begin
00070  *         vs = e.next_values
00071  *       rescue StopIteration
00072  *         return $!.result
00073  *       end
00074  *       y = yield(*vs)
00075  *       e.feed y
00076  *     end
00077  *   end
00078  *
00079  *   o = Object.new
00080  *
00081  *   def o.each
00082  *     puts yield
00083  *     puts yield(1)
00084  *     puts yield(1, 2)
00085  *     3
00086  *   end
00087  *
00088  *   # use o.each as an internal iterator directly.
00089  *   puts o.each {|*x| puts x; [:b, *x] }
00090  *   # => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3
00091  *
00092  *   # convert o.each to an external iterator for
00093  *   # implementing an internal iterator.
00094  *   puts ext_each(o.to_enum) {|*x| puts x; [:b, *x] }
00095  *   # => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3
00096  *
00097  */
00098 VALUE rb_cEnumerator;
00099 static ID id_rewind, id_each;
00100 static VALUE sym_each;
00101 
00102 VALUE rb_eStopIteration;
00103 
00104 struct enumerator {
00105     VALUE obj;
00106     ID    meth;
00107     VALUE args;
00108     VALUE fib;
00109     VALUE dst;
00110     VALUE lookahead;
00111     VALUE feedvalue;
00112     VALUE stop_exc;
00113 };
00114 
00115 static VALUE rb_cGenerator, rb_cYielder;
00116 
00117 struct generator {
00118     VALUE proc;
00119 };
00120 
00121 struct yielder {
00122     VALUE proc;
00123 };
00124 
00125 static VALUE generator_allocate(VALUE klass);
00126 static VALUE generator_init(VALUE obj, VALUE proc);
00127 
00128 /*
00129  * Enumerator
00130  */
00131 static void
00132 enumerator_mark(void *p)
00133 {
00134     struct enumerator *ptr = p;
00135     rb_gc_mark(ptr->obj);
00136     rb_gc_mark(ptr->args);
00137     rb_gc_mark(ptr->fib);
00138     rb_gc_mark(ptr->dst);
00139     rb_gc_mark(ptr->lookahead);
00140     rb_gc_mark(ptr->feedvalue);
00141     rb_gc_mark(ptr->stop_exc);
00142 }
00143 
00144 #define enumerator_free RUBY_TYPED_DEFAULT_FREE
00145 
00146 static size_t
00147 enumerator_memsize(const void *p)
00148 {
00149     return p ? sizeof(struct enumerator) : 0;
00150 }
00151 
00152 static const rb_data_type_t enumerator_data_type = {
00153     "enumerator",
00154     {
00155         enumerator_mark,
00156         enumerator_free,
00157         enumerator_memsize,
00158     },
00159 };
00160 
00161 static struct enumerator *
00162 enumerator_ptr(VALUE obj)
00163 {
00164     struct enumerator *ptr;
00165 
00166     TypedData_Get_Struct(obj, struct enumerator, &enumerator_data_type, ptr);
00167     if (!ptr || ptr->obj == Qundef) {
00168         rb_raise(rb_eArgError, "uninitialized enumerator");
00169     }
00170     return ptr;
00171 }
00172 
00173 /*
00174  * call-seq:
00175  *   obj.to_enum(method = :each, *args)
00176  *   obj.enum_for(method = :each, *args)
00177  *
00178  * Creates a new Enumerator which will enumerate by on calling +method+ on
00179  * +obj+.
00180  *
00181  * +method+:: the method to call on +obj+ to generate the enumeration
00182  * +args+:: arguments that will be passed in +method+ <i>in addition</i>
00183  *          to the item itself.  Note that the number of args
00184  *          must not exceed the number expected by +method+
00185  *
00186  * === Example
00187  *
00188  *   str = "xyz"
00189  *
00190  *   enum = str.enum_for(:each_byte)
00191  *   enum.each { |b| puts b }
00192  *   # => 120
00193  *   # => 121
00194  *   # => 122
00195  *
00196  *   # protect an array from being modified by some_method
00197  *   a = [1, 2, 3]
00198  *   some_method(a.to_enum)
00199  *
00200  */
00201 static VALUE
00202 obj_to_enum(int argc, VALUE *argv, VALUE obj)
00203 {
00204     VALUE meth = sym_each;
00205 
00206     if (argc > 0) {
00207         --argc;
00208         meth = *argv++;
00209     }
00210     return rb_enumeratorize(obj, meth, argc, argv);
00211 }
00212 
00213 static VALUE
00214 enumerator_allocate(VALUE klass)
00215 {
00216     struct enumerator *ptr;
00217     VALUE enum_obj;
00218 
00219     enum_obj = TypedData_Make_Struct(klass, struct enumerator, &enumerator_data_type, ptr);
00220     ptr->obj = Qundef;
00221 
00222     return enum_obj;
00223 }
00224 
00225 static VALUE
00226 enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, VALUE *argv)
00227 {
00228     struct enumerator *ptr;
00229 
00230     TypedData_Get_Struct(enum_obj, struct enumerator, &enumerator_data_type, ptr);
00231 
00232     if (!ptr) {
00233         rb_raise(rb_eArgError, "unallocated enumerator");
00234     }
00235 
00236     ptr->obj  = obj;
00237     ptr->meth = rb_to_id(meth);
00238     if (argc) ptr->args = rb_ary_new4(argc, argv);
00239     ptr->fib = 0;
00240     ptr->dst = Qnil;
00241     ptr->lookahead = Qundef;
00242     ptr->feedvalue = Qundef;
00243     ptr->stop_exc = Qfalse;
00244 
00245     return enum_obj;
00246 }
00247 
00248 /*
00249  * call-seq:
00250  *   Enumerator.new { |yielder| ... }
00251  *   Enumerator.new(obj, method = :each, *args)
00252  *
00253  * Creates a new Enumerator object, which can be used as an
00254  * Enumerable.
00255  *
00256  * In the first form, iteration is defined by the given block, in
00257  * which a "yielder" object, given as block parameter, can be used to
00258  * yield a value by calling the +yield+ method (aliased as +<<+):
00259  *
00260  *   fib = Enumerator.new do |y|
00261  *     a = b = 1
00262  *     loop do
00263  *       y << a
00264  *       a, b = b, a + b
00265  *     end
00266  *   end
00267  *
00268  *   p fib.take(10) # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
00269  *
00270  * In the second, deprecated, form, a generated Enumerator iterates over the
00271  * given object using the given method with the given arguments passed.
00272  *
00273  * Use of this form is discouraged.  Use Kernel#enum_for or Kernel#to_enum
00274  * instead.
00275  *
00276  *   e = Enumerator.new(ObjectSpace, :each_object)
00277  *       #-> ObjectSpace.enum_for(:each_object)
00278  *
00279  *   e.select { |obj| obj.is_a?(Class) }  #=> array of all classes
00280  *
00281  */
00282 static VALUE
00283 enumerator_initialize(int argc, VALUE *argv, VALUE obj)
00284 {
00285     VALUE recv, meth = sym_each;
00286 
00287     if (argc == 0) {
00288         if (!rb_block_given_p())
00289             rb_raise(rb_eArgError, "wrong number of argument (0 for 1+)");
00290 
00291         recv = generator_init(generator_allocate(rb_cGenerator), rb_block_proc());
00292     }
00293     else {
00294         recv = *argv++;
00295         if (--argc) {
00296             meth = *argv++;
00297             --argc;
00298         }
00299     }
00300 
00301     return enumerator_init(obj, recv, meth, argc, argv);
00302 }
00303 
00304 /* :nodoc: */
00305 static VALUE
00306 enumerator_init_copy(VALUE obj, VALUE orig)
00307 {
00308     struct enumerator *ptr0, *ptr1;
00309 
00310     ptr0 = enumerator_ptr(orig);
00311     if (ptr0->fib) {
00312         /* Fibers cannot be copied */
00313         rb_raise(rb_eTypeError, "can't copy execution context");
00314     }
00315 
00316     TypedData_Get_Struct(obj, struct enumerator, &enumerator_data_type, ptr1);
00317 
00318     if (!ptr1) {
00319         rb_raise(rb_eArgError, "unallocated enumerator");
00320     }
00321 
00322     ptr1->obj  = ptr0->obj;
00323     ptr1->meth = ptr0->meth;
00324     ptr1->args = ptr0->args;
00325     ptr1->fib  = 0;
00326     ptr1->lookahead  = Qundef;
00327     ptr1->feedvalue  = Qundef;
00328 
00329     return obj;
00330 }
00331 
00332 VALUE
00333 rb_enumeratorize(VALUE obj, VALUE meth, int argc, VALUE *argv)
00334 {
00335     return enumerator_init(enumerator_allocate(rb_cEnumerator), obj, meth, argc, argv);
00336 }
00337 
00338 static VALUE
00339 enumerator_block_call(VALUE obj, rb_block_call_func *func, VALUE arg)
00340 {
00341     int argc = 0;
00342     VALUE *argv = 0;
00343     const struct enumerator *e = enumerator_ptr(obj);
00344     ID meth = e->meth;
00345 
00346     if (e->args) {
00347         argc = RARRAY_LENINT(e->args);
00348         argv = RARRAY_PTR(e->args);
00349     }
00350     return rb_block_call(e->obj, meth, argc, argv, func, arg);
00351 }
00352 
00353 /*
00354  * call-seq:
00355  *   enum.each {...}
00356  *
00357  * Iterates over the block according to how this Enumerable was constructed.
00358  * If no block is given, returns self.
00359  *
00360  */
00361 static VALUE
00362 enumerator_each(VALUE obj)
00363 {
00364     if (!rb_block_given_p()) return obj;
00365     return enumerator_block_call(obj, 0, obj);
00366 }
00367 
00368 static VALUE
00369 enumerator_with_index_i(VALUE val, VALUE m, int argc, VALUE *argv)
00370 {
00371     VALUE idx;
00372     VALUE *memo = (VALUE *)m;
00373 
00374     idx = INT2FIX(*memo);
00375     ++*memo;
00376 
00377     if (argc <= 1)
00378         return rb_yield_values(2, val, idx);
00379 
00380     return rb_yield_values(2, rb_ary_new4(argc, argv), idx);
00381 }
00382 
00383 /*
00384  * call-seq:
00385  *   e.with_index(offset = 0) {|(*args), idx| ... }
00386  *   e.with_index(offset = 0)
00387  *
00388  * Iterates the given block for each element with an index, which
00389  * starts from +offset+.  If no block is given, returns a new Enumerator
00390  * that includes the index, starting from +offset+
00391  *
00392  * +offset+:: the starting index to use
00393  *
00394  */
00395 static VALUE
00396 enumerator_with_index(int argc, VALUE *argv, VALUE obj)
00397 {
00398     VALUE memo;
00399 
00400     rb_scan_args(argc, argv, "01", &memo);
00401     RETURN_ENUMERATOR(obj, argc, argv);
00402     memo = NIL_P(memo) ? 0 : (VALUE)NUM2LONG(memo);
00403     return enumerator_block_call(obj, enumerator_with_index_i, (VALUE)&memo);
00404 }
00405 
00406 /*
00407  * call-seq:
00408  *   e.each_with_index {|(*args), idx| ... }
00409  *   e.each_with_index
00410  *
00411  * Same as Enumerator#with_index(0), i.e. there is no starting offset.
00412  *
00413  * If no block is given, a new Enumerator is returned that includes the index.
00414  *
00415  */
00416 static VALUE
00417 enumerator_each_with_index(VALUE obj)
00418 {
00419     return enumerator_with_index(0, NULL, obj);
00420 }
00421 
00422 static VALUE
00423 enumerator_with_object_i(VALUE val, VALUE memo, int argc, VALUE *argv)
00424 {
00425     if (argc <= 1)
00426         return rb_yield_values(2, val, memo);
00427 
00428     return rb_yield_values(2, rb_ary_new4(argc, argv), memo);
00429 }
00430 
00431 /*
00432  * call-seq:
00433  *   e.with_object(obj) {|(*args), obj| ... }
00434  *   e.with_object(obj)
00435  *
00436  * Iterates the given block for each element with an arbitrary object, +obj+,
00437  * and returns +obj+
00438  *
00439  * If no block is given, returns a new Enumerator.
00440  *
00441  * === Example
00442  *
00443  *   to_three = Enumerator.new do |y|
00444  *     3.times do |x|
00445  *       y << x
00446  *     end
00447  *   end
00448  *
00449  *   to_three_with_string = to_three.with_object("foo")
00450  *   to_three_with_string.each do |x,string|
00451  *     puts "#{string}: #{x}"
00452  *   end
00453  *
00454  *   # => foo:0
00455  *   # => foo:1
00456  *   # => foo:2
00457  */
00458 static VALUE
00459 enumerator_with_object(VALUE obj, VALUE memo)
00460 {
00461     RETURN_ENUMERATOR(obj, 1, &memo);
00462     enumerator_block_call(obj, enumerator_with_object_i, memo);
00463 
00464     return memo;
00465 }
00466 
00467 static VALUE
00468 next_ii(VALUE i, VALUE obj, int argc, VALUE *argv)
00469 {
00470     struct enumerator *e = enumerator_ptr(obj);
00471     VALUE feedvalue = Qnil;
00472     VALUE args = rb_ary_new4(argc, argv);
00473     rb_fiber_yield(1, &args);
00474     if (e->feedvalue != Qundef) {
00475         feedvalue = e->feedvalue;
00476         e->feedvalue = Qundef;
00477     }
00478     return feedvalue;
00479 }
00480 
00481 static VALUE
00482 next_i(VALUE curr, VALUE obj)
00483 {
00484     struct enumerator *e = enumerator_ptr(obj);
00485     VALUE nil = Qnil;
00486     VALUE result;
00487 
00488     result = rb_block_call(obj, id_each, 0, 0, next_ii, obj);
00489     e->stop_exc = rb_exc_new2(rb_eStopIteration, "iteration reached an end");
00490     rb_ivar_set(e->stop_exc, rb_intern("result"), result);
00491     return rb_fiber_yield(1, &nil);
00492 }
00493 
00494 static void
00495 next_init(VALUE obj, struct enumerator *e)
00496 {
00497     VALUE curr = rb_fiber_current();
00498     e->dst = curr;
00499     e->fib = rb_fiber_new(next_i, obj);
00500     e->lookahead = Qundef;
00501 }
00502 
00503 static VALUE
00504 get_next_values(VALUE obj, struct enumerator *e)
00505 {
00506     VALUE curr, vs;
00507 
00508     if (e->stop_exc)
00509         rb_exc_raise(e->stop_exc);
00510 
00511     curr = rb_fiber_current();
00512 
00513     if (!e->fib || !rb_fiber_alive_p(e->fib)) {
00514         next_init(obj, e);
00515     }
00516 
00517     vs = rb_fiber_resume(e->fib, 1, &curr);
00518     if (e->stop_exc) {
00519         e->fib = 0;
00520         e->dst = Qnil;
00521         e->lookahead = Qundef;
00522         e->feedvalue = Qundef;
00523         rb_exc_raise(e->stop_exc);
00524     }
00525     return vs;
00526 }
00527 
00528 /*
00529  * call-seq:
00530  *   e.next_values   -> array
00531  *
00532  * Returns the next object as an array in the enumerator, and move the
00533  * internal position forward.  When the position reached at the end,
00534  * StopIteration is raised.
00535  *
00536  * This method can be used to distinguish <code>yield</code> and <code>yield
00537  * nil</code>.
00538  *
00539  * === Example
00540  *
00541  *   o = Object.new
00542  *   def o.each
00543  *     yield
00544  *     yield 1
00545  *     yield 1, 2
00546  *     yield nil
00547  *     yield [1, 2]
00548  *   end
00549  *   e = o.to_enum
00550  *   p e.next_values
00551  *   p e.next_values
00552  *   p e.next_values
00553  *   p e.next_values
00554  *   p e.next_values
00555  *   e = o.to_enum
00556  *   p e.next
00557  *   p e.next
00558  *   p e.next
00559  *   p e.next
00560  *   p e.next
00561  *
00562  *   ## yield args       next_values      next
00563  *   #  yield            []               nil
00564  *   #  yield 1          [1]              1
00565  *   #  yield 1, 2       [1, 2]           [1, 2]
00566  *   #  yield nil        [nil]            nil
00567  *   #  yield [1, 2]     [[1, 2]]         [1, 2]
00568  *
00569  * Note that +next_values+ does not affect other non-external enumeration
00570  * methods unless underlying iteration method itself has side-effect, e.g.
00571  * IO#each_line.
00572  *
00573  */
00574 
00575 static VALUE
00576 enumerator_next_values(VALUE obj)
00577 {
00578     struct enumerator *e = enumerator_ptr(obj);
00579     VALUE vs;
00580 
00581     if (e->lookahead != Qundef) {
00582         vs = e->lookahead;
00583         e->lookahead = Qundef;
00584         return vs;
00585     }
00586 
00587     return get_next_values(obj, e);
00588 }
00589 
00590 static VALUE
00591 ary2sv(VALUE args, int dup)
00592 {
00593     if (TYPE(args) != T_ARRAY)
00594         return args;
00595 
00596     switch (RARRAY_LEN(args)) {
00597       case 0:
00598         return Qnil;
00599 
00600       case 1:
00601         return RARRAY_PTR(args)[0];
00602 
00603       default:
00604         if (dup)
00605             return rb_ary_dup(args);
00606         return args;
00607     }
00608 }
00609 
00610 /*
00611  * call-seq:
00612  *   e.next   -> object
00613  *
00614  * Returns the next object in the enumerator, and move the internal position
00615  * forward.  When the position reached at the end, StopIteration is raised.
00616  *
00617  * === Example
00618  *
00619  *   a = [1,2,3]
00620  *   e = a.to_enum
00621  *   p e.next   #=> 1
00622  *   p e.next   #=> 2
00623  *   p e.next   #=> 3
00624  *   p e.next   #raises StopIteration
00625  *
00626  * Note that enumeration sequence by +next+ does not affect other non-external
00627  * enumeration methods, unless the underlying iteration methods itself has
00628  * side-effect, e.g. IO#each_line.
00629  *
00630  */
00631 
00632 static VALUE
00633 enumerator_next(VALUE obj)
00634 {
00635     VALUE vs = enumerator_next_values(obj);
00636     return ary2sv(vs, 0);
00637 }
00638 
00639 static VALUE
00640 enumerator_peek_values(VALUE obj)
00641 {
00642     struct enumerator *e = enumerator_ptr(obj);
00643 
00644     if (e->lookahead == Qundef) {
00645         e->lookahead = get_next_values(obj, e);
00646     }
00647     return e->lookahead;
00648 }
00649 
00650 /*
00651  * call-seq:
00652  *   e.peek_values   -> array
00653  *
00654  * Returns the next object as an array, similar to Enumerator#next_values, but
00655  * doesn't move the internal position forward.  If the position is already at
00656  * the end, StopIteration is raised.
00657  *
00658  * === Example
00659  *
00660  *   o = Object.new
00661  *   def o.each
00662  *     yield
00663  *     yield 1
00664  *     yield 1, 2
00665  *   end
00666  *   e = o.to_enum
00667  *   p e.peek_values    #=> []
00668  *   e.next
00669  *   p e.peek_values    #=> [1]
00670  *   p e.peek_values    #=> [1]
00671  *   e.next
00672  *   p e.peek_values    #=> [1, 2]
00673  *   e.next
00674  *   p e.peek_values    # raises StopIteration
00675  *
00676  */
00677 
00678 static VALUE
00679 enumerator_peek_values_m(VALUE obj)
00680 {
00681     return rb_ary_dup(enumerator_peek_values(obj));
00682 }
00683 
00684 /*
00685  * call-seq:
00686  *   e.peek   -> object
00687  *
00688  * Returns the next object in the enumerator, but doesn't move the internal
00689  * position forward.  If the position is already at the end, StopIteration
00690  * is raised.
00691  *
00692  * === Example
00693  *
00694  *   a = [1,2,3]
00695  *   e = a.to_enum
00696  *   p e.next   #=> 1
00697  *   p e.peek   #=> 2
00698  *   p e.peek   #=> 2
00699  *   p e.peek   #=> 2
00700  *   p e.next   #=> 2
00701  *   p e.next   #=> 3
00702  *   p e.next   #raises StopIteration
00703  *
00704  */
00705 
00706 static VALUE
00707 enumerator_peek(VALUE obj)
00708 {
00709     VALUE vs = enumerator_peek_values(obj);
00710     return ary2sv(vs, 1);
00711 }
00712 
00713 /*
00714  * call-seq:
00715  *   e.feed obj   -> nil
00716  *
00717  * Sets the value to be returned by the next yield inside +e+.
00718  *
00719  * If the value is not set, the yield returns nil.
00720  *
00721  * This value is cleared after being yielded.
00722  *
00723  *   o = Object.new
00724  *   def o.each
00725  *     x = yield         # (2) blocks
00726  *     p x               # (5) => "foo"
00727  *     x = yield         # (6) blocks
00728  *     p x               # (8) => nil
00729  *     x = yield         # (9) blocks
00730  *     p x               # not reached w/o another e.next
00731  *   end
00732  *
00733  *   e = o.to_enum
00734  *   e.next              # (1)
00735  *   e.feed "foo"        # (3)
00736  *   e.next              # (4)
00737  *   e.next              # (7)
00738  *                       # (10)
00739  */
00740 
00741 static VALUE
00742 enumerator_feed(VALUE obj, VALUE v)
00743 {
00744     struct enumerator *e = enumerator_ptr(obj);
00745 
00746     if (e->feedvalue != Qundef) {
00747         rb_raise(rb_eTypeError, "feed value already set");
00748     }
00749     e->feedvalue = v;
00750 
00751     return Qnil;
00752 }
00753 
00754 /*
00755  * call-seq:
00756  *   e.rewind   -> e
00757  *
00758  * Rewinds the enumeration sequence to the beginning.
00759  *
00760  * If the enclosed object responds to a "rewind" method, it is called.
00761  */
00762 
00763 static VALUE
00764 enumerator_rewind(VALUE obj)
00765 {
00766     struct enumerator *e = enumerator_ptr(obj);
00767 
00768     rb_check_funcall(e->obj, id_rewind, 0, 0);
00769 
00770     e->fib = 0;
00771     e->dst = Qnil;
00772     e->lookahead = Qundef;
00773     e->feedvalue = Qundef;
00774     e->stop_exc = Qfalse;
00775     return obj;
00776 }
00777 
00778 static VALUE
00779 inspect_enumerator(VALUE obj, VALUE dummy, int recur)
00780 {
00781     struct enumerator *e;
00782     const char *cname;
00783     VALUE eobj, str;
00784     int tainted, untrusted;
00785 
00786     TypedData_Get_Struct(obj, struct enumerator, &enumerator_data_type, e);
00787 
00788     cname = rb_obj_classname(obj);
00789 
00790     if (!e || e->obj == Qundef) {
00791         return rb_sprintf("#<%s: uninitialized>", cname);
00792     }
00793 
00794     if (recur) {
00795         str = rb_sprintf("#<%s: ...>", cname);
00796         OBJ_TAINT(str);
00797         return str;
00798     }
00799 
00800     eobj = e->obj;
00801 
00802     tainted   = OBJ_TAINTED(eobj);
00803     untrusted = OBJ_UNTRUSTED(eobj);
00804 
00805     /* (1..100).each_cons(2) => "#<Enumerator: 1..100:each_cons(2)>" */
00806     str = rb_sprintf("#<%s: ", cname);
00807     rb_str_concat(str, rb_inspect(eobj));
00808     rb_str_buf_cat2(str, ":");
00809     rb_str_buf_cat2(str, rb_id2name(e->meth));
00810 
00811     if (e->args) {
00812         long   argc = RARRAY_LEN(e->args);
00813         VALUE *argv = RARRAY_PTR(e->args);
00814 
00815         rb_str_buf_cat2(str, "(");
00816 
00817         while (argc--) {
00818             VALUE arg = *argv++;
00819 
00820             rb_str_concat(str, rb_inspect(arg));
00821             rb_str_buf_cat2(str, argc > 0 ? ", " : ")");
00822 
00823             if (OBJ_TAINTED(arg)) tainted = TRUE;
00824             if (OBJ_UNTRUSTED(arg)) untrusted = TRUE;
00825         }
00826     }
00827 
00828     rb_str_buf_cat2(str, ">");
00829 
00830     if (tainted) OBJ_TAINT(str);
00831     if (untrusted) OBJ_UNTRUST(str);
00832     return str;
00833 }
00834 
00835 /*
00836  * call-seq:
00837  *   e.inspect  -> string
00838  *
00839  * Creates a printable version of <i>e</i>.
00840  */
00841 
00842 static VALUE
00843 enumerator_inspect(VALUE obj)
00844 {
00845     return rb_exec_recursive(inspect_enumerator, obj, 0);
00846 }
00847 
00848 /*
00849  * Yielder
00850  */
00851 static void
00852 yielder_mark(void *p)
00853 {
00854     struct yielder *ptr = p;
00855     rb_gc_mark(ptr->proc);
00856 }
00857 
00858 #define yielder_free RUBY_TYPED_DEFAULT_FREE
00859 
00860 static size_t
00861 yielder_memsize(const void *p)
00862 {
00863     return p ? sizeof(struct yielder) : 0;
00864 }
00865 
00866 static const rb_data_type_t yielder_data_type = {
00867     "yielder",
00868     {
00869         yielder_mark,
00870         yielder_free,
00871         yielder_memsize,
00872     },
00873 };
00874 
00875 static struct yielder *
00876 yielder_ptr(VALUE obj)
00877 {
00878     struct yielder *ptr;
00879 
00880     TypedData_Get_Struct(obj, struct yielder, &yielder_data_type, ptr);
00881     if (!ptr || ptr->proc == Qundef) {
00882         rb_raise(rb_eArgError, "uninitialized yielder");
00883     }
00884     return ptr;
00885 }
00886 
00887 /* :nodoc: */
00888 static VALUE
00889 yielder_allocate(VALUE klass)
00890 {
00891     struct yielder *ptr;
00892     VALUE obj;
00893 
00894     obj = TypedData_Make_Struct(klass, struct yielder, &yielder_data_type, ptr);
00895     ptr->proc = Qundef;
00896 
00897     return obj;
00898 }
00899 
00900 static VALUE
00901 yielder_init(VALUE obj, VALUE proc)
00902 {
00903     struct yielder *ptr;
00904 
00905     TypedData_Get_Struct(obj, struct yielder, &yielder_data_type, ptr);
00906 
00907     if (!ptr) {
00908         rb_raise(rb_eArgError, "unallocated yielder");
00909     }
00910 
00911     ptr->proc = proc;
00912 
00913     return obj;
00914 }
00915 
00916 /* :nodoc: */
00917 static VALUE
00918 yielder_initialize(VALUE obj)
00919 {
00920     rb_need_block();
00921 
00922     return yielder_init(obj, rb_block_proc());
00923 }
00924 
00925 /* :nodoc: */
00926 static VALUE
00927 yielder_yield(VALUE obj, VALUE args)
00928 {
00929     struct yielder *ptr = yielder_ptr(obj);
00930 
00931     return rb_proc_call(ptr->proc, args);
00932 }
00933 
00934 /* :nodoc: */
00935 static VALUE yielder_yield_push(VALUE obj, VALUE args)
00936 {
00937     yielder_yield(obj, args);
00938     return obj;
00939 }
00940 
00941 static VALUE
00942 yielder_yield_i(VALUE obj, VALUE memo, int argc, VALUE *argv)
00943 {
00944     return rb_yield_values2(argc, argv);
00945 }
00946 
00947 static VALUE
00948 yielder_new(void)
00949 {
00950     return yielder_init(yielder_allocate(rb_cYielder), rb_proc_new(yielder_yield_i, 0));
00951 }
00952 
00953 /*
00954  * Generator
00955  */
00956 static void
00957 generator_mark(void *p)
00958 {
00959     struct generator *ptr = p;
00960     rb_gc_mark(ptr->proc);
00961 }
00962 
00963 #define generator_free RUBY_TYPED_DEFAULT_FREE
00964 
00965 static size_t
00966 generator_memsize(const void *p)
00967 {
00968     return p ? sizeof(struct generator) : 0;
00969 }
00970 
00971 static const rb_data_type_t generator_data_type = {
00972     "generator",
00973     {
00974         generator_mark,
00975         generator_free,
00976         generator_memsize,
00977     },
00978 };
00979 
00980 static struct generator *
00981 generator_ptr(VALUE obj)
00982 {
00983     struct generator *ptr;
00984 
00985     TypedData_Get_Struct(obj, struct generator, &generator_data_type, ptr);
00986     if (!ptr || ptr->proc == Qundef) {
00987         rb_raise(rb_eArgError, "uninitialized generator");
00988     }
00989     return ptr;
00990 }
00991 
00992 /* :nodoc: */
00993 static VALUE
00994 generator_allocate(VALUE klass)
00995 {
00996     struct generator *ptr;
00997     VALUE obj;
00998 
00999     obj = TypedData_Make_Struct(klass, struct generator, &generator_data_type, ptr);
01000     ptr->proc = Qundef;
01001 
01002     return obj;
01003 }
01004 
01005 static VALUE
01006 generator_init(VALUE obj, VALUE proc)
01007 {
01008     struct generator *ptr;
01009 
01010     TypedData_Get_Struct(obj, struct generator, &generator_data_type, ptr);
01011 
01012     if (!ptr) {
01013         rb_raise(rb_eArgError, "unallocated generator");
01014     }
01015 
01016     ptr->proc = proc;
01017 
01018     return obj;
01019 }
01020 
01021 /* :nodoc: */
01022 static VALUE
01023 generator_initialize(int argc, VALUE *argv, VALUE obj)
01024 {
01025     VALUE proc;
01026 
01027     if (argc == 0) {
01028         rb_need_block();
01029 
01030         proc = rb_block_proc();
01031     } else {
01032         rb_scan_args(argc, argv, "1", &proc);
01033 
01034         if (!rb_obj_is_proc(proc))
01035             rb_raise(rb_eTypeError,
01036                      "wrong argument type %s (expected Proc)",
01037                      rb_obj_classname(proc));
01038 
01039         if (rb_block_given_p()) {
01040             rb_warn("given block not used");
01041         }
01042     }
01043 
01044     return generator_init(obj, proc);
01045 }
01046 
01047 /* :nodoc: */
01048 static VALUE
01049 generator_init_copy(VALUE obj, VALUE orig)
01050 {
01051     struct generator *ptr0, *ptr1;
01052 
01053     ptr0 = generator_ptr(orig);
01054 
01055     TypedData_Get_Struct(obj, struct generator, &generator_data_type, ptr1);
01056 
01057     if (!ptr1) {
01058         rb_raise(rb_eArgError, "unallocated generator");
01059     }
01060 
01061     ptr1->proc = ptr0->proc;
01062 
01063     return obj;
01064 }
01065 
01066 /* :nodoc: */
01067 static VALUE
01068 generator_each(VALUE obj)
01069 {
01070     struct generator *ptr = generator_ptr(obj);
01071     VALUE yielder;
01072 
01073     yielder = yielder_new();
01074 
01075     return rb_proc_call(ptr->proc, rb_ary_new3(1, yielder));
01076 }
01077 
01078 /*
01079  * Document-class: StopIteration
01080  *
01081  * Raised to stop the iteration, in particular by Enumerator#next. It is
01082  * rescued by Kernel#loop.
01083  *
01084  *   loop do
01085  *     puts "Hello"
01086  *     raise StopIteration
01087  *     puts "World"
01088  *   end
01089  *   puts "Done!"
01090  *
01091  * <em>produces:</em>
01092  *
01093  *   Hello
01094  *   Done!
01095  */
01096 
01097 /*
01098  * call-seq:
01099  *   result       -> value
01100  *
01101  * Returns the return value of the iterator.
01102  *
01103  *   o = Object.new
01104  *   def o.each
01105  *     yield 1
01106  *     yield 2
01107  *     yield 3
01108  *     100
01109  *   end
01110  *
01111  *   e = o.to_enum
01112  *
01113  *   puts e.next                   #=> 1
01114  *   puts e.next                   #=> 2
01115  *   puts e.next                   #=> 3
01116  *
01117  *   begin
01118  *     e.next
01119  *   rescue StopIteration => ex
01120  *     puts ex.result              #=> 100
01121  *   end
01122  *
01123  */
01124 static VALUE
01125 stop_result(VALUE self)
01126 {
01127     return rb_attr_get(self, rb_intern("result"));
01128 }
01129 
01130 void
01131 Init_Enumerator(void)
01132 {
01133     rb_define_method(rb_mKernel, "to_enum", obj_to_enum, -1);
01134     rb_define_method(rb_mKernel, "enum_for", obj_to_enum, -1);
01135 
01136     rb_cEnumerator = rb_define_class("Enumerator", rb_cObject);
01137     rb_include_module(rb_cEnumerator, rb_mEnumerable);
01138 
01139     rb_define_alloc_func(rb_cEnumerator, enumerator_allocate);
01140     rb_define_method(rb_cEnumerator, "initialize", enumerator_initialize, -1);
01141     rb_define_method(rb_cEnumerator, "initialize_copy", enumerator_init_copy, 1);
01142     rb_define_method(rb_cEnumerator, "each", enumerator_each, 0);
01143     rb_define_method(rb_cEnumerator, "each_with_index", enumerator_each_with_index, 0);
01144     rb_define_method(rb_cEnumerator, "each_with_object", enumerator_with_object, 1);
01145     rb_define_method(rb_cEnumerator, "with_index", enumerator_with_index, -1);
01146     rb_define_method(rb_cEnumerator, "with_object", enumerator_with_object, 1);
01147     rb_define_method(rb_cEnumerator, "next_values", enumerator_next_values, 0);
01148     rb_define_method(rb_cEnumerator, "peek_values", enumerator_peek_values_m, 0);
01149     rb_define_method(rb_cEnumerator, "next", enumerator_next, 0);
01150     rb_define_method(rb_cEnumerator, "peek", enumerator_peek, 0);
01151     rb_define_method(rb_cEnumerator, "feed", enumerator_feed, 1);
01152     rb_define_method(rb_cEnumerator, "rewind", enumerator_rewind, 0);
01153     rb_define_method(rb_cEnumerator, "inspect", enumerator_inspect, 0);
01154 
01155     rb_eStopIteration = rb_define_class("StopIteration", rb_eIndexError);
01156     rb_define_method(rb_eStopIteration, "result", stop_result, 0);
01157 
01158     /* Generator */
01159     rb_cGenerator = rb_define_class_under(rb_cEnumerator, "Generator", rb_cObject);
01160     rb_include_module(rb_cGenerator, rb_mEnumerable);
01161     rb_define_alloc_func(rb_cGenerator, generator_allocate);
01162     rb_define_method(rb_cGenerator, "initialize", generator_initialize, -1);
01163     rb_define_method(rb_cGenerator, "initialize_copy", generator_init_copy, 1);
01164     rb_define_method(rb_cGenerator, "each", generator_each, 0);
01165 
01166     /* Yielder */
01167     rb_cYielder = rb_define_class_under(rb_cEnumerator, "Yielder", rb_cObject);
01168     rb_define_alloc_func(rb_cYielder, yielder_allocate);
01169     rb_define_method(rb_cYielder, "initialize", yielder_initialize, 0);
01170     rb_define_method(rb_cYielder, "yield", yielder_yield, -2);
01171     rb_define_method(rb_cYielder, "<<", yielder_yield_push, -2);
01172 
01173     id_rewind = rb_intern("rewind");
01174     id_each = rb_intern("each");
01175     sym_each = ID2SYM(id_each);
01176 
01177     rb_provide("enumerator.so");        /* for backward compatibility */
01178 }
01179