Ruby
2.0.0p247(2013-06-27revision41674)
|
00001 /************************************************ 00002 00003 enumerator.c - provides Enumerator class 00004 00005 $Author: nagachika $ 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 39587 2013-03-04 15:50:02Z nagachika $ 00012 00013 ************************************************/ 00014 00015 #include "ruby/ruby.h" 00016 #include "node.h" 00017 #include "internal.h" 00018 00019 /* 00020 * Document-class: Enumerator 00021 * 00022 * A class which allows both internal and external iteration. 00023 * 00024 * An Enumerator can be created by the following methods. 00025 * - Kernel#to_enum 00026 * - Kernel#enum_for 00027 * - Enumerator.new 00028 * 00029 * Most methods have two forms: a block form where the contents 00030 * are evaluated for each item in the enumeration, and a non-block form 00031 * which returns a new Enumerator wrapping the iteration. 00032 * 00033 * enumerator = %w(one two three).each 00034 * puts enumerator.class # => Enumerator 00035 * 00036 * enumerator.each_with_object("foo") do |item, obj| 00037 * puts "#{obj}: #{item}" 00038 * end 00039 * 00040 * # foo: one 00041 * # foo: two 00042 * # foo: three 00043 * 00044 * enum_with_obj = enumerator.each_with_object("foo") 00045 * puts enum_with_obj.class # => Enumerator 00046 * 00047 * enum_with_obj.each do |item, obj| 00048 * puts "#{obj}: #{item}" 00049 * end 00050 * 00051 * # foo: one 00052 * # foo: two 00053 * # foo: three 00054 * 00055 * This allows you to chain Enumerators together. For example, you 00056 * can map a list's elements to strings containing the index 00057 * and the element as a string via: 00058 * 00059 * puts %w[foo bar baz].map.with_index { |w, i| "#{i}:#{w}" } 00060 * # => ["0:foo", "1:bar", "2:baz"] 00061 * 00062 * An Enumerator can also be used as an external iterator. 00063 * For example, Enumerator#next returns the next value of the iterator 00064 * or raises StopIteration if the Enumerator is at the end. 00065 * 00066 * e = [1,2,3].each # returns an enumerator object. 00067 * puts e.next # => 1 00068 * puts e.next # => 2 00069 * puts e.next # => 3 00070 * puts e.next # raises StopIteration 00071 * 00072 * You can use this to implement an internal iterator as follows: 00073 * 00074 * def ext_each(e) 00075 * while true 00076 * begin 00077 * vs = e.next_values 00078 * rescue StopIteration 00079 * return $!.result 00080 * end 00081 * y = yield(*vs) 00082 * e.feed y 00083 * end 00084 * end 00085 * 00086 * o = Object.new 00087 * 00088 * def o.each 00089 * puts yield 00090 * puts yield(1) 00091 * puts yield(1, 2) 00092 * 3 00093 * end 00094 * 00095 * # use o.each as an internal iterator directly. 00096 * puts o.each {|*x| puts x; [:b, *x] } 00097 * # => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3 00098 * 00099 * # convert o.each to an external iterator for 00100 * # implementing an internal iterator. 00101 * puts ext_each(o.to_enum) {|*x| puts x; [:b, *x] } 00102 * # => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3 00103 * 00104 */ 00105 VALUE rb_cEnumerator; 00106 VALUE rb_cLazy; 00107 static ID id_rewind, id_each, id_new, id_initialize, id_yield, id_call, id_size, id_to_enum; 00108 static ID id_eqq, id_next, id_result, id_lazy, id_receiver, id_arguments, id_memo, id_method, id_force; 00109 static VALUE sym_each, sym_cycle; 00110 00111 VALUE rb_eStopIteration; 00112 00113 struct enumerator { 00114 VALUE obj; 00115 ID meth; 00116 VALUE args; 00117 VALUE fib; 00118 VALUE dst; 00119 VALUE lookahead; 00120 VALUE feedvalue; 00121 VALUE stop_exc; 00122 VALUE size; 00123 VALUE (*size_fn)(ANYARGS); 00124 }; 00125 00126 static VALUE rb_cGenerator, rb_cYielder; 00127 00128 struct generator { 00129 VALUE proc; 00130 }; 00131 00132 struct yielder { 00133 VALUE proc; 00134 }; 00135 00136 static VALUE generator_allocate(VALUE klass); 00137 static VALUE generator_init(VALUE obj, VALUE proc); 00138 00139 /* 00140 * Enumerator 00141 */ 00142 static void 00143 enumerator_mark(void *p) 00144 { 00145 struct enumerator *ptr = p; 00146 rb_gc_mark(ptr->obj); 00147 rb_gc_mark(ptr->args); 00148 rb_gc_mark(ptr->fib); 00149 rb_gc_mark(ptr->dst); 00150 rb_gc_mark(ptr->lookahead); 00151 rb_gc_mark(ptr->feedvalue); 00152 rb_gc_mark(ptr->stop_exc); 00153 rb_gc_mark(ptr->size); 00154 } 00155 00156 #define enumerator_free RUBY_TYPED_DEFAULT_FREE 00157 00158 static size_t 00159 enumerator_memsize(const void *p) 00160 { 00161 return p ? sizeof(struct enumerator) : 0; 00162 } 00163 00164 static const rb_data_type_t enumerator_data_type = { 00165 "enumerator", 00166 { 00167 enumerator_mark, 00168 enumerator_free, 00169 enumerator_memsize, 00170 }, 00171 }; 00172 00173 static struct enumerator * 00174 enumerator_ptr(VALUE obj) 00175 { 00176 struct enumerator *ptr; 00177 00178 TypedData_Get_Struct(obj, struct enumerator, &enumerator_data_type, ptr); 00179 if (!ptr || ptr->obj == Qundef) { 00180 rb_raise(rb_eArgError, "uninitialized enumerator"); 00181 } 00182 return ptr; 00183 } 00184 00185 /* 00186 * call-seq: 00187 * obj.to_enum(method = :each, *args) -> enum 00188 * obj.enum_for(method = :each, *args) -> enum 00189 * obj.to_enum(method = :each, *args) {|*args| block} -> enum 00190 * obj.enum_for(method = :each, *args){|*args| block} -> enum 00191 * 00192 * Creates a new Enumerator which will enumerate by calling +method+ on 00193 * +obj+, passing +args+ if any. 00194 * 00195 * If a block is given, it will be used to calculate the size of 00196 * the enumerator without the need to iterate it (see Enumerator#size). 00197 * 00198 * === Examples 00199 * 00200 * str = "xyz" 00201 * 00202 * enum = str.enum_for(:each_byte) 00203 * enum.each { |b| puts b } 00204 * # => 120 00205 * # => 121 00206 * # => 122 00207 * 00208 * # protect an array from being modified by some_method 00209 * a = [1, 2, 3] 00210 * some_method(a.to_enum) 00211 * 00212 * It is typical to call to_enum when defining methods for 00213 * a generic Enumerable, in case no block is passed. 00214 * 00215 * Here is such an example, with parameter passing and a sizing block: 00216 * 00217 * module Enumerable 00218 * # a generic method to repeat the values of any enumerable 00219 * def repeat(n) 00220 * raise ArgumentError, "#{n} is negative!" if n < 0 00221 * unless block_given? 00222 * return to_enum(__method__, n) do # __method__ is :repeat here 00223 * sz = size # Call size and multiply by n... 00224 * sz * n if sz # but return nil if size itself is nil 00225 * end 00226 * end 00227 * each do |*val| 00228 * n.times { yield *val } 00229 * end 00230 * end 00231 * end 00232 * 00233 * %i[hello world].repeat(2) { |w| puts w } 00234 * # => Prints 'hello', 'hello', 'world', 'world' 00235 * enum = (1..14).repeat(3) 00236 * # => returns an Enumerator when called without a block 00237 * enum.first(4) # => [1, 1, 1, 2] 00238 * enum.size # => 42 00239 */ 00240 static VALUE 00241 obj_to_enum(int argc, VALUE *argv, VALUE obj) 00242 { 00243 VALUE enumerator, meth = sym_each; 00244 00245 if (argc > 0) { 00246 --argc; 00247 meth = *argv++; 00248 } 00249 enumerator = rb_enumeratorize_with_size(obj, meth, argc, argv, 0); 00250 if (rb_block_given_p()) { 00251 enumerator_ptr(enumerator)->size = rb_block_proc(); 00252 } 00253 return enumerator; 00254 } 00255 00256 static VALUE 00257 enumerator_allocate(VALUE klass) 00258 { 00259 struct enumerator *ptr; 00260 VALUE enum_obj; 00261 00262 enum_obj = TypedData_Make_Struct(klass, struct enumerator, &enumerator_data_type, ptr); 00263 ptr->obj = Qundef; 00264 00265 return enum_obj; 00266 } 00267 00268 static VALUE 00269 enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, VALUE *argv, VALUE (*size_fn)(ANYARGS), VALUE size) 00270 { 00271 struct enumerator *ptr; 00272 00273 TypedData_Get_Struct(enum_obj, struct enumerator, &enumerator_data_type, ptr); 00274 00275 if (!ptr) { 00276 rb_raise(rb_eArgError, "unallocated enumerator"); 00277 } 00278 00279 ptr->obj = obj; 00280 ptr->meth = rb_to_id(meth); 00281 if (argc) ptr->args = rb_ary_new4(argc, argv); 00282 ptr->fib = 0; 00283 ptr->dst = Qnil; 00284 ptr->lookahead = Qundef; 00285 ptr->feedvalue = Qundef; 00286 ptr->stop_exc = Qfalse; 00287 ptr->size = size; 00288 ptr->size_fn = size_fn; 00289 00290 return enum_obj; 00291 } 00292 00293 /* 00294 * call-seq: 00295 * Enumerator.new(size = nil) { |yielder| ... } 00296 * Enumerator.new(obj, method = :each, *args) 00297 * 00298 * Creates a new Enumerator object, which can be used as an 00299 * Enumerable. 00300 * 00301 * In the first form, iteration is defined by the given block, in 00302 * which a "yielder" object, given as block parameter, can be used to 00303 * yield a value by calling the +yield+ method (aliased as +<<+): 00304 * 00305 * fib = Enumerator.new do |y| 00306 * a = b = 1 00307 * loop do 00308 * y << a 00309 * a, b = b, a + b 00310 * end 00311 * end 00312 * 00313 * p fib.take(10) # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] 00314 * 00315 * The optional parameter can be used to specify how to calculate the size 00316 * in a lazy fashion (see Enumerator#size). It can either be a value or 00317 * a callable object. 00318 * 00319 * In the second, deprecated, form, a generated Enumerator iterates over the 00320 * given object using the given method with the given arguments passed. 00321 * 00322 * Use of this form is discouraged. Use Kernel#enum_for or Kernel#to_enum 00323 * instead. 00324 * 00325 * e = Enumerator.new(ObjectSpace, :each_object) 00326 * #-> ObjectSpace.enum_for(:each_object) 00327 * 00328 * e.select { |obj| obj.is_a?(Class) } #=> array of all classes 00329 * 00330 */ 00331 static VALUE 00332 enumerator_initialize(int argc, VALUE *argv, VALUE obj) 00333 { 00334 VALUE recv, meth = sym_each; 00335 VALUE size = Qnil; 00336 00337 if (rb_block_given_p()) { 00338 rb_check_arity(argc, 0, 1); 00339 recv = generator_init(generator_allocate(rb_cGenerator), rb_block_proc()); 00340 if (argc) { 00341 if (NIL_P(argv[0]) || rb_obj_is_proc(argv[0]) || 00342 (RB_TYPE_P(argv[0], T_FLOAT) && RFLOAT_VALUE(argv[0]) == INFINITY)) { 00343 size = argv[0]; 00344 } else { 00345 size = rb_to_int(argv[0]); 00346 } 00347 argc = 0; 00348 } 00349 } 00350 else { 00351 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS); 00352 rb_warn("Enumerator.new without a block is deprecated; use Object#to_enum"); 00353 recv = *argv++; 00354 if (--argc) { 00355 meth = *argv++; 00356 --argc; 00357 } 00358 } 00359 00360 return enumerator_init(obj, recv, meth, argc, argv, 0, size); 00361 } 00362 00363 /* :nodoc: */ 00364 static VALUE 00365 enumerator_init_copy(VALUE obj, VALUE orig) 00366 { 00367 struct enumerator *ptr0, *ptr1; 00368 00369 if (!OBJ_INIT_COPY(obj, orig)) return obj; 00370 ptr0 = enumerator_ptr(orig); 00371 if (ptr0->fib) { 00372 /* Fibers cannot be copied */ 00373 rb_raise(rb_eTypeError, "can't copy execution context"); 00374 } 00375 00376 TypedData_Get_Struct(obj, struct enumerator, &enumerator_data_type, ptr1); 00377 00378 if (!ptr1) { 00379 rb_raise(rb_eArgError, "unallocated enumerator"); 00380 } 00381 00382 ptr1->obj = ptr0->obj; 00383 ptr1->meth = ptr0->meth; 00384 ptr1->args = ptr0->args; 00385 ptr1->fib = 0; 00386 ptr1->lookahead = Qundef; 00387 ptr1->feedvalue = Qundef; 00388 ptr1->size = ptr0->size; 00389 ptr1->size_fn = ptr0->size_fn; 00390 00391 return obj; 00392 } 00393 00394 /* 00395 * For backwards compatibility; use rb_enumeratorize_with_size 00396 */ 00397 VALUE 00398 rb_enumeratorize(VALUE obj, VALUE meth, int argc, VALUE *argv) 00399 { 00400 return rb_enumeratorize_with_size(obj, meth, argc, argv, 0); 00401 } 00402 00403 static VALUE 00404 lazy_to_enum_i(VALUE self, VALUE meth, int argc, VALUE *argv, VALUE (*size_fn)(ANYARGS)); 00405 00406 VALUE 00407 rb_enumeratorize_with_size(VALUE obj, VALUE meth, int argc, VALUE *argv, VALUE (*size_fn)(ANYARGS)) 00408 { 00409 /* Similar effect as calling obj.to_enum, i.e. dispatching to either 00410 Kernel#to_enum vs Lazy#to_enum */ 00411 if (RTEST(rb_obj_is_kind_of(obj, rb_cLazy))) 00412 return lazy_to_enum_i(obj, meth, argc, argv, size_fn); 00413 else 00414 return enumerator_init(enumerator_allocate(rb_cEnumerator), 00415 obj, meth, argc, argv, size_fn, Qnil); 00416 } 00417 00418 static VALUE 00419 enumerator_block_call(VALUE obj, rb_block_call_func *func, VALUE arg) 00420 { 00421 int argc = 0; 00422 VALUE *argv = 0; 00423 const struct enumerator *e = enumerator_ptr(obj); 00424 ID meth = e->meth; 00425 00426 if (e->args) { 00427 argc = RARRAY_LENINT(e->args); 00428 argv = RARRAY_PTR(e->args); 00429 } 00430 return rb_block_call(e->obj, meth, argc, argv, func, arg); 00431 } 00432 00433 /* 00434 * call-seq: 00435 * enum.each {...} 00436 * 00437 * Iterates over the block according to how this Enumerable was constructed. 00438 * If no block is given, returns self. 00439 * 00440 */ 00441 static VALUE 00442 enumerator_each(int argc, VALUE *argv, VALUE obj) 00443 { 00444 if (argc > 0) { 00445 struct enumerator *e = enumerator_ptr(obj = rb_obj_dup(obj)); 00446 VALUE args = e->args; 00447 if (args) { 00448 args = rb_ary_dup(args); 00449 rb_ary_cat(args, argv, argc); 00450 } 00451 else { 00452 args = rb_ary_new4(argc, argv); 00453 } 00454 e->args = args; 00455 } 00456 if (!rb_block_given_p()) return obj; 00457 return enumerator_block_call(obj, 0, obj); 00458 } 00459 00460 static VALUE 00461 enumerator_with_index_i(VALUE val, VALUE m, int argc, VALUE *argv) 00462 { 00463 VALUE idx; 00464 VALUE *memo = (VALUE *)m; 00465 00466 idx = INT2FIX(*memo); 00467 ++*memo; 00468 00469 if (argc <= 1) 00470 return rb_yield_values(2, val, idx); 00471 00472 return rb_yield_values(2, rb_ary_new4(argc, argv), idx); 00473 } 00474 00475 static VALUE 00476 enumerator_size(VALUE obj); 00477 00478 /* 00479 * call-seq: 00480 * e.with_index(offset = 0) {|(*args), idx| ... } 00481 * e.with_index(offset = 0) 00482 * 00483 * Iterates the given block for each element with an index, which 00484 * starts from +offset+. If no block is given, returns a new Enumerator 00485 * that includes the index, starting from +offset+ 00486 * 00487 * +offset+:: the starting index to use 00488 * 00489 */ 00490 static VALUE 00491 enumerator_with_index(int argc, VALUE *argv, VALUE obj) 00492 { 00493 VALUE memo; 00494 00495 rb_scan_args(argc, argv, "01", &memo); 00496 RETURN_SIZED_ENUMERATOR(obj, argc, argv, enumerator_size); 00497 memo = NIL_P(memo) ? 0 : (VALUE)NUM2LONG(memo); 00498 return enumerator_block_call(obj, enumerator_with_index_i, (VALUE)&memo); 00499 } 00500 00501 /* 00502 * call-seq: 00503 * e.each_with_index {|(*args), idx| ... } 00504 * e.each_with_index 00505 * 00506 * Same as Enumerator#with_index(0), i.e. there is no starting offset. 00507 * 00508 * If no block is given, a new Enumerator is returned that includes the index. 00509 * 00510 */ 00511 static VALUE 00512 enumerator_each_with_index(VALUE obj) 00513 { 00514 return enumerator_with_index(0, NULL, obj); 00515 } 00516 00517 static VALUE 00518 enumerator_with_object_i(VALUE val, VALUE memo, int argc, VALUE *argv) 00519 { 00520 if (argc <= 1) 00521 return rb_yield_values(2, val, memo); 00522 00523 return rb_yield_values(2, rb_ary_new4(argc, argv), memo); 00524 } 00525 00526 /* 00527 * call-seq: 00528 * e.with_object(obj) {|(*args), obj| ... } 00529 * e.with_object(obj) 00530 * 00531 * Iterates the given block for each element with an arbitrary object, +obj+, 00532 * and returns +obj+ 00533 * 00534 * If no block is given, returns a new Enumerator. 00535 * 00536 * === Example 00537 * 00538 * to_three = Enumerator.new do |y| 00539 * 3.times do |x| 00540 * y << x 00541 * end 00542 * end 00543 * 00544 * to_three_with_string = to_three.with_object("foo") 00545 * to_three_with_string.each do |x,string| 00546 * puts "#{string}: #{x}" 00547 * end 00548 * 00549 * # => foo:0 00550 * # => foo:1 00551 * # => foo:2 00552 */ 00553 static VALUE 00554 enumerator_with_object(VALUE obj, VALUE memo) 00555 { 00556 RETURN_SIZED_ENUMERATOR(obj, 1, &memo, enumerator_size); 00557 enumerator_block_call(obj, enumerator_with_object_i, memo); 00558 00559 return memo; 00560 } 00561 00562 static VALUE 00563 next_ii(VALUE i, VALUE obj, int argc, VALUE *argv) 00564 { 00565 struct enumerator *e = enumerator_ptr(obj); 00566 VALUE feedvalue = Qnil; 00567 VALUE args = rb_ary_new4(argc, argv); 00568 rb_fiber_yield(1, &args); 00569 if (e->feedvalue != Qundef) { 00570 feedvalue = e->feedvalue; 00571 e->feedvalue = Qundef; 00572 } 00573 return feedvalue; 00574 } 00575 00576 static VALUE 00577 next_i(VALUE curr, VALUE obj) 00578 { 00579 struct enumerator *e = enumerator_ptr(obj); 00580 VALUE nil = Qnil; 00581 VALUE result; 00582 00583 result = rb_block_call(obj, id_each, 0, 0, next_ii, obj); 00584 e->stop_exc = rb_exc_new2(rb_eStopIteration, "iteration reached an end"); 00585 rb_ivar_set(e->stop_exc, id_result, result); 00586 return rb_fiber_yield(1, &nil); 00587 } 00588 00589 static void 00590 next_init(VALUE obj, struct enumerator *e) 00591 { 00592 VALUE curr = rb_fiber_current(); 00593 e->dst = curr; 00594 e->fib = rb_fiber_new(next_i, obj); 00595 e->lookahead = Qundef; 00596 } 00597 00598 static VALUE 00599 get_next_values(VALUE obj, struct enumerator *e) 00600 { 00601 VALUE curr, vs; 00602 00603 if (e->stop_exc) 00604 rb_exc_raise(e->stop_exc); 00605 00606 curr = rb_fiber_current(); 00607 00608 if (!e->fib || !rb_fiber_alive_p(e->fib)) { 00609 next_init(obj, e); 00610 } 00611 00612 vs = rb_fiber_resume(e->fib, 1, &curr); 00613 if (e->stop_exc) { 00614 e->fib = 0; 00615 e->dst = Qnil; 00616 e->lookahead = Qundef; 00617 e->feedvalue = Qundef; 00618 rb_exc_raise(e->stop_exc); 00619 } 00620 return vs; 00621 } 00622 00623 /* 00624 * call-seq: 00625 * e.next_values -> array 00626 * 00627 * Returns the next object as an array in the enumerator, and move the 00628 * internal position forward. When the position reached at the end, 00629 * StopIteration is raised. 00630 * 00631 * This method can be used to distinguish <code>yield</code> and <code>yield 00632 * nil</code>. 00633 * 00634 * === Example 00635 * 00636 * o = Object.new 00637 * def o.each 00638 * yield 00639 * yield 1 00640 * yield 1, 2 00641 * yield nil 00642 * yield [1, 2] 00643 * end 00644 * e = o.to_enum 00645 * p e.next_values 00646 * p e.next_values 00647 * p e.next_values 00648 * p e.next_values 00649 * p e.next_values 00650 * e = o.to_enum 00651 * p e.next 00652 * p e.next 00653 * p e.next 00654 * p e.next 00655 * p e.next 00656 * 00657 * ## yield args next_values next 00658 * # yield [] nil 00659 * # yield 1 [1] 1 00660 * # yield 1, 2 [1, 2] [1, 2] 00661 * # yield nil [nil] nil 00662 * # yield [1, 2] [[1, 2]] [1, 2] 00663 * 00664 * Note that +next_values+ does not affect other non-external enumeration 00665 * methods unless underlying iteration method itself has side-effect, e.g. 00666 * IO#each_line. 00667 * 00668 */ 00669 00670 static VALUE 00671 enumerator_next_values(VALUE obj) 00672 { 00673 struct enumerator *e = enumerator_ptr(obj); 00674 VALUE vs; 00675 00676 if (e->lookahead != Qundef) { 00677 vs = e->lookahead; 00678 e->lookahead = Qundef; 00679 return vs; 00680 } 00681 00682 return get_next_values(obj, e); 00683 } 00684 00685 static VALUE 00686 ary2sv(VALUE args, int dup) 00687 { 00688 if (!RB_TYPE_P(args, T_ARRAY)) 00689 return args; 00690 00691 switch (RARRAY_LEN(args)) { 00692 case 0: 00693 return Qnil; 00694 00695 case 1: 00696 return RARRAY_PTR(args)[0]; 00697 00698 default: 00699 if (dup) 00700 return rb_ary_dup(args); 00701 return args; 00702 } 00703 } 00704 00705 /* 00706 * call-seq: 00707 * e.next -> object 00708 * 00709 * Returns the next object in the enumerator, and move the internal position 00710 * forward. When the position reached at the end, StopIteration is raised. 00711 * 00712 * === Example 00713 * 00714 * a = [1,2,3] 00715 * e = a.to_enum 00716 * p e.next #=> 1 00717 * p e.next #=> 2 00718 * p e.next #=> 3 00719 * p e.next #raises StopIteration 00720 * 00721 * Note that enumeration sequence by +next+ does not affect other non-external 00722 * enumeration methods, unless the underlying iteration methods itself has 00723 * side-effect, e.g. IO#each_line. 00724 * 00725 */ 00726 00727 static VALUE 00728 enumerator_next(VALUE obj) 00729 { 00730 VALUE vs = enumerator_next_values(obj); 00731 return ary2sv(vs, 0); 00732 } 00733 00734 static VALUE 00735 enumerator_peek_values(VALUE obj) 00736 { 00737 struct enumerator *e = enumerator_ptr(obj); 00738 00739 if (e->lookahead == Qundef) { 00740 e->lookahead = get_next_values(obj, e); 00741 } 00742 return e->lookahead; 00743 } 00744 00745 /* 00746 * call-seq: 00747 * e.peek_values -> array 00748 * 00749 * Returns the next object as an array, similar to Enumerator#next_values, but 00750 * doesn't move the internal position forward. If the position is already at 00751 * the end, StopIteration is raised. 00752 * 00753 * === Example 00754 * 00755 * o = Object.new 00756 * def o.each 00757 * yield 00758 * yield 1 00759 * yield 1, 2 00760 * end 00761 * e = o.to_enum 00762 * p e.peek_values #=> [] 00763 * e.next 00764 * p e.peek_values #=> [1] 00765 * p e.peek_values #=> [1] 00766 * e.next 00767 * p e.peek_values #=> [1, 2] 00768 * e.next 00769 * p e.peek_values # raises StopIteration 00770 * 00771 */ 00772 00773 static VALUE 00774 enumerator_peek_values_m(VALUE obj) 00775 { 00776 return rb_ary_dup(enumerator_peek_values(obj)); 00777 } 00778 00779 /* 00780 * call-seq: 00781 * e.peek -> object 00782 * 00783 * Returns the next object in the enumerator, but doesn't move the internal 00784 * position forward. If the position is already at the end, StopIteration 00785 * is raised. 00786 * 00787 * === Example 00788 * 00789 * a = [1,2,3] 00790 * e = a.to_enum 00791 * p e.next #=> 1 00792 * p e.peek #=> 2 00793 * p e.peek #=> 2 00794 * p e.peek #=> 2 00795 * p e.next #=> 2 00796 * p e.next #=> 3 00797 * p e.next #raises StopIteration 00798 * 00799 */ 00800 00801 static VALUE 00802 enumerator_peek(VALUE obj) 00803 { 00804 VALUE vs = enumerator_peek_values(obj); 00805 return ary2sv(vs, 1); 00806 } 00807 00808 /* 00809 * call-seq: 00810 * e.feed obj -> nil 00811 * 00812 * Sets the value to be returned by the next yield inside +e+. 00813 * 00814 * If the value is not set, the yield returns nil. 00815 * 00816 * This value is cleared after being yielded. 00817 * 00818 * o = Object.new 00819 * def o.each 00820 * x = yield # (2) blocks 00821 * p x # (5) => "foo" 00822 * x = yield # (6) blocks 00823 * p x # (8) => nil 00824 * x = yield # (9) blocks 00825 * p x # not reached w/o another e.next 00826 * end 00827 * 00828 * e = o.to_enum 00829 * e.next # (1) 00830 * e.feed "foo" # (3) 00831 * e.next # (4) 00832 * e.next # (7) 00833 * # (10) 00834 */ 00835 00836 static VALUE 00837 enumerator_feed(VALUE obj, VALUE v) 00838 { 00839 struct enumerator *e = enumerator_ptr(obj); 00840 00841 if (e->feedvalue != Qundef) { 00842 rb_raise(rb_eTypeError, "feed value already set"); 00843 } 00844 e->feedvalue = v; 00845 00846 return Qnil; 00847 } 00848 00849 /* 00850 * call-seq: 00851 * e.rewind -> e 00852 * 00853 * Rewinds the enumeration sequence to the beginning. 00854 * 00855 * If the enclosed object responds to a "rewind" method, it is called. 00856 */ 00857 00858 static VALUE 00859 enumerator_rewind(VALUE obj) 00860 { 00861 struct enumerator *e = enumerator_ptr(obj); 00862 00863 rb_check_funcall(e->obj, id_rewind, 0, 0); 00864 00865 e->fib = 0; 00866 e->dst = Qnil; 00867 e->lookahead = Qundef; 00868 e->feedvalue = Qundef; 00869 e->stop_exc = Qfalse; 00870 return obj; 00871 } 00872 00873 static VALUE 00874 inspect_enumerator(VALUE obj, VALUE dummy, int recur) 00875 { 00876 struct enumerator *e; 00877 const char *cname; 00878 VALUE eobj, eargs, str, method; 00879 int tainted, untrusted; 00880 00881 TypedData_Get_Struct(obj, struct enumerator, &enumerator_data_type, e); 00882 00883 cname = rb_obj_classname(obj); 00884 00885 if (!e || e->obj == Qundef) { 00886 return rb_sprintf("#<%s: uninitialized>", cname); 00887 } 00888 00889 if (recur) { 00890 str = rb_sprintf("#<%s: ...>", cname); 00891 OBJ_TAINT(str); 00892 return str; 00893 } 00894 00895 eobj = rb_attr_get(obj, id_receiver); 00896 if (NIL_P(eobj)) { 00897 eobj = e->obj; 00898 } 00899 00900 tainted = OBJ_TAINTED(eobj); 00901 untrusted = OBJ_UNTRUSTED(eobj); 00902 00903 /* (1..100).each_cons(2) => "#<Enumerator: 1..100:each_cons(2)>" */ 00904 str = rb_sprintf("#<%s: ", cname); 00905 rb_str_concat(str, rb_inspect(eobj)); 00906 method = rb_attr_get(obj, id_method); 00907 if (NIL_P(method)) { 00908 rb_str_buf_cat2(str, ":"); 00909 rb_str_buf_cat2(str, rb_id2name(e->meth)); 00910 } 00911 else if (method != Qfalse) { 00912 Check_Type(method, T_SYMBOL); 00913 rb_str_buf_cat2(str, ":"); 00914 rb_str_buf_cat2(str, rb_id2name(SYM2ID(method))); 00915 } 00916 00917 eargs = rb_attr_get(obj, id_arguments); 00918 if (NIL_P(eargs)) { 00919 eargs = e->args; 00920 } 00921 if (eargs != Qfalse) { 00922 long argc = RARRAY_LEN(eargs); 00923 VALUE *argv = RARRAY_PTR(eargs); 00924 00925 if (argc > 0) { 00926 rb_str_buf_cat2(str, "("); 00927 00928 while (argc--) { 00929 VALUE arg = *argv++; 00930 00931 rb_str_concat(str, rb_inspect(arg)); 00932 rb_str_buf_cat2(str, argc > 0 ? ", " : ")"); 00933 00934 if (OBJ_TAINTED(arg)) tainted = TRUE; 00935 if (OBJ_UNTRUSTED(arg)) untrusted = TRUE; 00936 } 00937 } 00938 } 00939 00940 rb_str_buf_cat2(str, ">"); 00941 00942 if (tainted) OBJ_TAINT(str); 00943 if (untrusted) OBJ_UNTRUST(str); 00944 return str; 00945 } 00946 00947 /* 00948 * call-seq: 00949 * e.inspect -> string 00950 * 00951 * Creates a printable version of <i>e</i>. 00952 */ 00953 00954 static VALUE 00955 enumerator_inspect(VALUE obj) 00956 { 00957 return rb_exec_recursive(inspect_enumerator, obj, 0); 00958 } 00959 00960 /* 00961 * call-seq: 00962 * e.size -> int, Float::INFINITY or nil 00963 * 00964 * Returns the size of the enumerator, or +nil+ if it can't be calculated lazily. 00965 * 00966 * (1..100).to_a.permutation(4).size # => 94109400 00967 * loop.size # => Float::INFINITY 00968 * (1..100).drop_while.size # => nil 00969 */ 00970 00971 static VALUE 00972 enumerator_size(VALUE obj) 00973 { 00974 struct enumerator *e = enumerator_ptr(obj); 00975 00976 if (e->size_fn) { 00977 return (*e->size_fn)(e->obj, e->args, obj); 00978 } 00979 if (rb_obj_is_proc(e->size)) { 00980 if (e->args) 00981 return rb_proc_call(e->size, e->args); 00982 else 00983 return rb_proc_call_with_block(e->size, 0, 0, Qnil); 00984 } 00985 return e->size; 00986 } 00987 00988 /* 00989 * Yielder 00990 */ 00991 static void 00992 yielder_mark(void *p) 00993 { 00994 struct yielder *ptr = p; 00995 rb_gc_mark(ptr->proc); 00996 } 00997 00998 #define yielder_free RUBY_TYPED_DEFAULT_FREE 00999 01000 static size_t 01001 yielder_memsize(const void *p) 01002 { 01003 return p ? sizeof(struct yielder) : 0; 01004 } 01005 01006 static const rb_data_type_t yielder_data_type = { 01007 "yielder", 01008 { 01009 yielder_mark, 01010 yielder_free, 01011 yielder_memsize, 01012 }, 01013 }; 01014 01015 static struct yielder * 01016 yielder_ptr(VALUE obj) 01017 { 01018 struct yielder *ptr; 01019 01020 TypedData_Get_Struct(obj, struct yielder, &yielder_data_type, ptr); 01021 if (!ptr || ptr->proc == Qundef) { 01022 rb_raise(rb_eArgError, "uninitialized yielder"); 01023 } 01024 return ptr; 01025 } 01026 01027 /* :nodoc: */ 01028 static VALUE 01029 yielder_allocate(VALUE klass) 01030 { 01031 struct yielder *ptr; 01032 VALUE obj; 01033 01034 obj = TypedData_Make_Struct(klass, struct yielder, &yielder_data_type, ptr); 01035 ptr->proc = Qundef; 01036 01037 return obj; 01038 } 01039 01040 static VALUE 01041 yielder_init(VALUE obj, VALUE proc) 01042 { 01043 struct yielder *ptr; 01044 01045 TypedData_Get_Struct(obj, struct yielder, &yielder_data_type, ptr); 01046 01047 if (!ptr) { 01048 rb_raise(rb_eArgError, "unallocated yielder"); 01049 } 01050 01051 ptr->proc = proc; 01052 01053 return obj; 01054 } 01055 01056 /* :nodoc: */ 01057 static VALUE 01058 yielder_initialize(VALUE obj) 01059 { 01060 rb_need_block(); 01061 01062 return yielder_init(obj, rb_block_proc()); 01063 } 01064 01065 /* :nodoc: */ 01066 static VALUE 01067 yielder_yield(VALUE obj, VALUE args) 01068 { 01069 struct yielder *ptr = yielder_ptr(obj); 01070 01071 return rb_proc_call(ptr->proc, args); 01072 } 01073 01074 /* :nodoc: */ 01075 static VALUE yielder_yield_push(VALUE obj, VALUE args) 01076 { 01077 yielder_yield(obj, args); 01078 return obj; 01079 } 01080 01081 static VALUE 01082 yielder_yield_i(VALUE obj, VALUE memo, int argc, VALUE *argv) 01083 { 01084 return rb_yield_values2(argc, argv); 01085 } 01086 01087 static VALUE 01088 yielder_new(void) 01089 { 01090 return yielder_init(yielder_allocate(rb_cYielder), rb_proc_new(yielder_yield_i, 0)); 01091 } 01092 01093 /* 01094 * Generator 01095 */ 01096 static void 01097 generator_mark(void *p) 01098 { 01099 struct generator *ptr = p; 01100 rb_gc_mark(ptr->proc); 01101 } 01102 01103 #define generator_free RUBY_TYPED_DEFAULT_FREE 01104 01105 static size_t 01106 generator_memsize(const void *p) 01107 { 01108 return p ? sizeof(struct generator) : 0; 01109 } 01110 01111 static const rb_data_type_t generator_data_type = { 01112 "generator", 01113 { 01114 generator_mark, 01115 generator_free, 01116 generator_memsize, 01117 }, 01118 }; 01119 01120 static struct generator * 01121 generator_ptr(VALUE obj) 01122 { 01123 struct generator *ptr; 01124 01125 TypedData_Get_Struct(obj, struct generator, &generator_data_type, ptr); 01126 if (!ptr || ptr->proc == Qundef) { 01127 rb_raise(rb_eArgError, "uninitialized generator"); 01128 } 01129 return ptr; 01130 } 01131 01132 /* :nodoc: */ 01133 static VALUE 01134 generator_allocate(VALUE klass) 01135 { 01136 struct generator *ptr; 01137 VALUE obj; 01138 01139 obj = TypedData_Make_Struct(klass, struct generator, &generator_data_type, ptr); 01140 ptr->proc = Qundef; 01141 01142 return obj; 01143 } 01144 01145 static VALUE 01146 generator_init(VALUE obj, VALUE proc) 01147 { 01148 struct generator *ptr; 01149 01150 TypedData_Get_Struct(obj, struct generator, &generator_data_type, ptr); 01151 01152 if (!ptr) { 01153 rb_raise(rb_eArgError, "unallocated generator"); 01154 } 01155 01156 ptr->proc = proc; 01157 01158 return obj; 01159 } 01160 01161 /* :nodoc: */ 01162 static VALUE 01163 generator_initialize(int argc, VALUE *argv, VALUE obj) 01164 { 01165 VALUE proc; 01166 01167 if (argc == 0) { 01168 rb_need_block(); 01169 01170 proc = rb_block_proc(); 01171 } 01172 else { 01173 rb_scan_args(argc, argv, "1", &proc); 01174 01175 if (!rb_obj_is_proc(proc)) 01176 rb_raise(rb_eTypeError, 01177 "wrong argument type %s (expected Proc)", 01178 rb_obj_classname(proc)); 01179 01180 if (rb_block_given_p()) { 01181 rb_warn("given block not used"); 01182 } 01183 } 01184 01185 return generator_init(obj, proc); 01186 } 01187 01188 /* :nodoc: */ 01189 static VALUE 01190 generator_init_copy(VALUE obj, VALUE orig) 01191 { 01192 struct generator *ptr0, *ptr1; 01193 01194 if (!OBJ_INIT_COPY(obj, orig)) return obj; 01195 01196 ptr0 = generator_ptr(orig); 01197 01198 TypedData_Get_Struct(obj, struct generator, &generator_data_type, ptr1); 01199 01200 if (!ptr1) { 01201 rb_raise(rb_eArgError, "unallocated generator"); 01202 } 01203 01204 ptr1->proc = ptr0->proc; 01205 01206 return obj; 01207 } 01208 01209 /* :nodoc: */ 01210 static VALUE 01211 generator_each(int argc, VALUE *argv, VALUE obj) 01212 { 01213 struct generator *ptr = generator_ptr(obj); 01214 VALUE args = rb_ary_new2(argc + 1); 01215 01216 rb_ary_push(args, yielder_new()); 01217 if (argc > 0) { 01218 rb_ary_cat(args, argv, argc); 01219 } 01220 01221 return rb_proc_call(ptr->proc, args); 01222 } 01223 01224 /* Lazy Enumerator methods */ 01225 static VALUE 01226 enum_size(VALUE self) 01227 { 01228 VALUE r = rb_check_funcall(self, id_size, 0, 0); 01229 return (r == Qundef) ? Qnil : r; 01230 } 01231 01232 static VALUE 01233 lazy_size(VALUE self) 01234 { 01235 return enum_size(rb_ivar_get(self, id_receiver)); 01236 } 01237 01238 static VALUE 01239 lazy_receiver_size(VALUE generator, VALUE args, VALUE lazy) 01240 { 01241 return lazy_size(lazy); 01242 } 01243 01244 static VALUE 01245 lazy_init_iterator(VALUE val, VALUE m, int argc, VALUE *argv) 01246 { 01247 VALUE result; 01248 if (argc == 1) { 01249 VALUE args[2]; 01250 args[0] = m; 01251 args[1] = val; 01252 result = rb_yield_values2(2, args); 01253 } 01254 else { 01255 VALUE args; 01256 int len = rb_long2int((long)argc + 1); 01257 01258 args = rb_ary_tmp_new(len); 01259 rb_ary_push(args, m); 01260 if (argc > 0) { 01261 rb_ary_cat(args, argv, argc); 01262 } 01263 result = rb_yield_values2(len, RARRAY_PTR(args)); 01264 RB_GC_GUARD(args); 01265 } 01266 if (result == Qundef) rb_iter_break(); 01267 return Qnil; 01268 } 01269 01270 static VALUE 01271 lazy_init_block_i(VALUE val, VALUE m, int argc, VALUE *argv) 01272 { 01273 rb_block_call(m, id_each, argc-1, argv+1, lazy_init_iterator, val); 01274 return Qnil; 01275 } 01276 01277 /* 01278 * call-seq: 01279 * Lazy.new(obj, size=nil) { |yielder, *values| ... } 01280 * 01281 * Creates a new Lazy enumerator. When the enumerator is actually enumerated 01282 * (e.g. by calling #force), +obj+ will be enumerated and each value passed 01283 * to the given block. The block can yield values back using +yielder+. 01284 * For example, to create a method +filter_map+ in both lazy and 01285 * non-lazy fashions: 01286 * 01287 * module Enumerable 01288 * def filter_map(&block) 01289 * map(&block).compact 01290 * end 01291 * end 01292 * 01293 * class Enumerator::Lazy 01294 * def filter_map 01295 * Lazy.new(self) do |yielder, *values| 01296 * result = yield *values 01297 * yielder << result if result 01298 * end 01299 * end 01300 * end 01301 * 01302 * (1..Float::INFINITY).lazy.filter_map{|i| i*i if i.even?}.first(5) 01303 * # => [4, 16, 36, 64, 100] 01304 */ 01305 static VALUE 01306 lazy_initialize(int argc, VALUE *argv, VALUE self) 01307 { 01308 VALUE obj, size = Qnil; 01309 VALUE generator; 01310 01311 rb_check_arity(argc, 1, 2); 01312 if (!rb_block_given_p()) { 01313 rb_raise(rb_eArgError, "tried to call lazy new without a block"); 01314 } 01315 obj = argv[0]; 01316 if (argc > 1) { 01317 size = argv[1]; 01318 } 01319 generator = generator_allocate(rb_cGenerator); 01320 rb_block_call(generator, id_initialize, 0, 0, lazy_init_block_i, obj); 01321 enumerator_init(self, generator, sym_each, 0, 0, 0, size); 01322 rb_ivar_set(self, id_receiver, obj); 01323 01324 return self; 01325 } 01326 01327 static VALUE 01328 lazy_set_method(VALUE lazy, VALUE args, VALUE (*size_fn)(ANYARGS)) 01329 { 01330 ID id = rb_frame_this_func(); 01331 struct enumerator *e = enumerator_ptr(lazy); 01332 rb_ivar_set(lazy, id_method, ID2SYM(id)); 01333 if (NIL_P(args)) { 01334 /* Qfalse indicates that the arguments are empty */ 01335 rb_ivar_set(lazy, id_arguments, Qfalse); 01336 } 01337 else { 01338 rb_ivar_set(lazy, id_arguments, args); 01339 } 01340 e->size_fn = size_fn; 01341 return lazy; 01342 } 01343 01344 /* 01345 * call-seq: 01346 * e.lazy -> lazy_enumerator 01347 * 01348 * Returns a lazy enumerator, whose methods map/collect, 01349 * flat_map/collect_concat, select/find_all, reject, grep, zip, take, 01350 * take_while, drop, drop_while, and cycle enumerate values only on an 01351 * as-needed basis. However, if a block is given to zip or cycle, values 01352 * are enumerated immediately. 01353 * 01354 * === Example 01355 * 01356 * The following program finds pythagorean triples: 01357 * 01358 * def pythagorean_triples 01359 * (1..Float::INFINITY).lazy.flat_map {|z| 01360 * (1..z).flat_map {|x| 01361 * (x..z).select {|y| 01362 * x**2 + y**2 == z**2 01363 * }.map {|y| 01364 * [x, y, z] 01365 * } 01366 * } 01367 * } 01368 * end 01369 * # show first ten pythagorean triples 01370 * p pythagorean_triples.take(10).force # take is lazy, so force is needed 01371 * p pythagorean_triples.first(10) # first is eager 01372 * # show pythagorean triples less than 100 01373 * p pythagorean_triples.take_while { |*, z| z < 100 }.force 01374 */ 01375 static VALUE 01376 enumerable_lazy(VALUE obj) 01377 { 01378 VALUE result = lazy_to_enum_i(obj, sym_each, 0, 0, enum_size); 01379 /* Qfalse indicates that the Enumerator::Lazy has no method name */ 01380 rb_ivar_set(result, id_method, Qfalse); 01381 return result; 01382 } 01383 01384 static VALUE 01385 lazy_to_enum_i(VALUE obj, VALUE meth, int argc, VALUE *argv, VALUE (*size_fn)(ANYARGS)) 01386 { 01387 return enumerator_init(enumerator_allocate(rb_cLazy), 01388 obj, meth, argc, argv, size_fn, Qnil); 01389 } 01390 01391 /* 01392 * call-seq: 01393 * lzy.to_enum(method = :each, *args) -> lazy_enum 01394 * lzy.enum_for(method = :each, *args) -> lazy_enum 01395 * lzy.to_enum(method = :each, *args) {|*args| block} -> lazy_enum 01396 * lzy.enum_for(method = :each, *args){|*args| block} -> lazy_enum 01397 * 01398 * Similar to Kernel#to_enum, except it returns a lazy enumerator. 01399 * This makes it easy to define Enumerable methods that will 01400 * naturally remain lazy if called from a lazy enumerator. 01401 * 01402 * For example, continuing from the example in Kernel#to_enum: 01403 * 01404 * # See Kernel#to_enum for the definition of repeat 01405 * r = 1..Float::INFINITY 01406 * r.repeat(2).first(5) # => [1, 1, 2, 2, 3] 01407 * r.repeat(2).class # => Enumerator 01408 * r.repeat(2).map{|n| n ** 2}.first(5) # => endless loop! 01409 * # works naturally on lazy enumerator: 01410 * r.lazy.repeat(2).class # => Enumerator::Lazy 01411 * r.lazy.repeat(2).map{|n| n ** 2}.first(5) # => [1, 1, 4, 4, 9] 01412 */ 01413 01414 static VALUE 01415 lazy_to_enum(int argc, VALUE *argv, VALUE self) 01416 { 01417 VALUE lazy, meth = sym_each; 01418 01419 if (argc > 0) { 01420 --argc; 01421 meth = *argv++; 01422 } 01423 lazy = lazy_to_enum_i(self, meth, argc, argv, 0); 01424 if (rb_block_given_p()) { 01425 enumerator_ptr(lazy)->size = rb_block_proc(); 01426 } 01427 return lazy; 01428 } 01429 01430 static VALUE 01431 lazy_map_func(VALUE val, VALUE m, int argc, VALUE *argv) 01432 { 01433 VALUE result = rb_yield_values2(argc - 1, &argv[1]); 01434 01435 rb_funcall(argv[0], id_yield, 1, result); 01436 return Qnil; 01437 } 01438 01439 static VALUE 01440 lazy_map(VALUE obj) 01441 { 01442 if (!rb_block_given_p()) { 01443 rb_raise(rb_eArgError, "tried to call lazy map without a block"); 01444 } 01445 01446 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj, 01447 lazy_map_func, 0), 01448 Qnil, lazy_receiver_size); 01449 } 01450 01451 static VALUE 01452 lazy_flat_map_i(VALUE i, VALUE yielder, int argc, VALUE *argv) 01453 { 01454 return rb_funcall2(yielder, id_yield, argc, argv); 01455 } 01456 01457 static VALUE 01458 lazy_flat_map_each(VALUE obj, VALUE yielder) 01459 { 01460 rb_block_call(obj, id_each, 0, 0, lazy_flat_map_i, yielder); 01461 return Qnil; 01462 } 01463 01464 static VALUE 01465 lazy_flat_map_to_ary(VALUE obj, VALUE yielder) 01466 { 01467 VALUE ary = rb_check_array_type(obj); 01468 if (NIL_P(ary)) { 01469 rb_funcall(yielder, id_yield, 1, obj); 01470 } 01471 else { 01472 long i; 01473 for (i = 0; i < RARRAY_LEN(ary); i++) { 01474 rb_funcall(yielder, id_yield, 1, RARRAY_PTR(ary)[i]); 01475 } 01476 } 01477 return Qnil; 01478 } 01479 01480 static VALUE 01481 lazy_flat_map_func(VALUE val, VALUE m, int argc, VALUE *argv) 01482 { 01483 VALUE result = rb_yield_values2(argc - 1, &argv[1]); 01484 if (RB_TYPE_P(result, T_ARRAY)) { 01485 long i; 01486 for (i = 0; i < RARRAY_LEN(result); i++) { 01487 rb_funcall(argv[0], id_yield, 1, RARRAY_PTR(result)[i]); 01488 } 01489 } 01490 else { 01491 if (rb_respond_to(result, id_force) && rb_respond_to(result, id_each)) { 01492 lazy_flat_map_each(result, argv[0]); 01493 } 01494 else { 01495 lazy_flat_map_to_ary(result, argv[0]); 01496 } 01497 } 01498 return Qnil; 01499 } 01500 01501 /* 01502 * call-seq: 01503 * lazy.flat_map { |obj| block } -> a_lazy_enumerator 01504 * 01505 * Returns a new lazy enumerator with the concatenated results of running 01506 * <i>block</i> once for every element in <i>lazy</i>. 01507 * 01508 * ["foo", "bar"].lazy.flat_map {|i| i.each_char.lazy}.force 01509 * #=> ["f", "o", "o", "b", "a", "r"] 01510 * 01511 * A value <i>x</i> returned by <i>block</i> is decomposed if either of 01512 * the following conditions is true: 01513 * 01514 * a) <i>x</i> responds to both each and force, which means that 01515 * <i>x</i> is a lazy enumerator. 01516 * b) <i>x</i> is an array or responds to to_ary. 01517 * 01518 * Otherwise, <i>x</i> is contained as-is in the return value. 01519 * 01520 * [{a:1}, {b:2}].lazy.flat_map {|i| i}.force 01521 * #=> [{:a=>1}, {:b=>2}] 01522 */ 01523 static VALUE 01524 lazy_flat_map(VALUE obj) 01525 { 01526 if (!rb_block_given_p()) { 01527 rb_raise(rb_eArgError, "tried to call lazy flat_map without a block"); 01528 } 01529 01530 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj, 01531 lazy_flat_map_func, 0), 01532 Qnil, 0); 01533 } 01534 01535 static VALUE 01536 lazy_select_func(VALUE val, VALUE m, int argc, VALUE *argv) 01537 { 01538 VALUE element = rb_enum_values_pack(argc - 1, argv + 1); 01539 01540 if (RTEST(rb_yield(element))) { 01541 return rb_funcall(argv[0], id_yield, 1, element); 01542 } 01543 return Qnil; 01544 } 01545 01546 static VALUE 01547 lazy_select(VALUE obj) 01548 { 01549 if (!rb_block_given_p()) { 01550 rb_raise(rb_eArgError, "tried to call lazy select without a block"); 01551 } 01552 01553 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj, 01554 lazy_select_func, 0), 01555 Qnil, 0); 01556 } 01557 01558 static VALUE 01559 lazy_reject_func(VALUE val, VALUE m, int argc, VALUE *argv) 01560 { 01561 VALUE element = rb_enum_values_pack(argc - 1, argv + 1); 01562 01563 if (!RTEST(rb_yield(element))) { 01564 return rb_funcall(argv[0], id_yield, 1, element); 01565 } 01566 return Qnil; 01567 } 01568 01569 static VALUE 01570 lazy_reject(VALUE obj) 01571 { 01572 if (!rb_block_given_p()) { 01573 rb_raise(rb_eArgError, "tried to call lazy reject without a block"); 01574 } 01575 01576 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj, 01577 lazy_reject_func, 0), 01578 Qnil, 0); 01579 } 01580 01581 static VALUE 01582 lazy_grep_func(VALUE val, VALUE m, int argc, VALUE *argv) 01583 { 01584 VALUE i = rb_enum_values_pack(argc - 1, argv + 1); 01585 VALUE result = rb_funcall(m, id_eqq, 1, i); 01586 01587 if (RTEST(result)) { 01588 rb_funcall(argv[0], id_yield, 1, i); 01589 } 01590 return Qnil; 01591 } 01592 01593 static VALUE 01594 lazy_grep_iter(VALUE val, VALUE m, int argc, VALUE *argv) 01595 { 01596 VALUE i = rb_enum_values_pack(argc - 1, argv + 1); 01597 VALUE result = rb_funcall(m, id_eqq, 1, i); 01598 01599 if (RTEST(result)) { 01600 rb_funcall(argv[0], id_yield, 1, rb_yield(i)); 01601 } 01602 return Qnil; 01603 } 01604 01605 static VALUE 01606 lazy_grep(VALUE obj, VALUE pattern) 01607 { 01608 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj, 01609 rb_block_given_p() ? 01610 lazy_grep_iter : lazy_grep_func, 01611 pattern), 01612 rb_ary_new3(1, pattern), 0); 01613 } 01614 01615 static VALUE 01616 call_next(VALUE obj) 01617 { 01618 return rb_funcall(obj, id_next, 0); 01619 } 01620 01621 static VALUE 01622 next_stopped(VALUE obj) 01623 { 01624 return Qnil; 01625 } 01626 01627 static VALUE 01628 lazy_zip_arrays_func(VALUE val, VALUE arrays, int argc, VALUE *argv) 01629 { 01630 VALUE yielder, ary, memo; 01631 long i, count; 01632 01633 yielder = argv[0]; 01634 memo = rb_attr_get(yielder, id_memo); 01635 count = NIL_P(memo) ? 0 : NUM2LONG(memo); 01636 01637 ary = rb_ary_new2(RARRAY_LEN(arrays) + 1); 01638 rb_ary_push(ary, argv[1]); 01639 for (i = 0; i < RARRAY_LEN(arrays); i++) { 01640 rb_ary_push(ary, rb_ary_entry(RARRAY_PTR(arrays)[i], count)); 01641 } 01642 rb_funcall(yielder, id_yield, 1, ary); 01643 rb_ivar_set(yielder, id_memo, LONG2NUM(++count)); 01644 return Qnil; 01645 } 01646 01647 static VALUE 01648 lazy_zip_func(VALUE val, VALUE zip_args, int argc, VALUE *argv) 01649 { 01650 VALUE yielder, ary, arg, v; 01651 long i; 01652 01653 yielder = argv[0]; 01654 arg = rb_attr_get(yielder, id_memo); 01655 if (NIL_P(arg)) { 01656 arg = rb_ary_new2(RARRAY_LEN(zip_args)); 01657 for (i = 0; i < RARRAY_LEN(zip_args); i++) { 01658 rb_ary_push(arg, rb_funcall(RARRAY_PTR(zip_args)[i], id_to_enum, 0)); 01659 } 01660 rb_ivar_set(yielder, id_memo, arg); 01661 } 01662 01663 ary = rb_ary_new2(RARRAY_LEN(arg) + 1); 01664 rb_ary_push(ary, argv[1]); 01665 for (i = 0; i < RARRAY_LEN(arg); i++) { 01666 v = rb_rescue2(call_next, RARRAY_PTR(arg)[i], next_stopped, 0, 01667 rb_eStopIteration, (VALUE)0); 01668 rb_ary_push(ary, v); 01669 } 01670 rb_funcall(yielder, id_yield, 1, ary); 01671 return Qnil; 01672 } 01673 01674 static VALUE 01675 lazy_zip(int argc, VALUE *argv, VALUE obj) 01676 { 01677 VALUE ary, v; 01678 long i; 01679 rb_block_call_func *func = lazy_zip_arrays_func; 01680 01681 if (rb_block_given_p()) { 01682 return rb_call_super(argc, argv); 01683 } 01684 01685 ary = rb_ary_new2(argc); 01686 for (i = 0; i < argc; i++) { 01687 v = rb_check_array_type(argv[i]); 01688 if (NIL_P(v)) { 01689 for (; i < argc; i++) { 01690 if (!rb_respond_to(argv[i], id_each)) { 01691 rb_raise(rb_eTypeError, "wrong argument type %s (must respond to :each)", 01692 rb_obj_classname(argv[i])); 01693 } 01694 } 01695 ary = rb_ary_new4(argc, argv); 01696 func = lazy_zip_func; 01697 break; 01698 } 01699 rb_ary_push(ary, v); 01700 } 01701 01702 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj, 01703 func, ary), 01704 ary, lazy_receiver_size); 01705 } 01706 01707 static VALUE 01708 lazy_take_func(VALUE val, VALUE args, int argc, VALUE *argv) 01709 { 01710 long remain; 01711 VALUE memo = rb_attr_get(argv[0], id_memo); 01712 if (NIL_P(memo)) { 01713 memo = args; 01714 } 01715 01716 rb_funcall2(argv[0], id_yield, argc - 1, argv + 1); 01717 if ((remain = NUM2LONG(memo)-1) == 0) { 01718 return Qundef; 01719 } 01720 else { 01721 rb_ivar_set(argv[0], id_memo, LONG2NUM(remain)); 01722 return Qnil; 01723 } 01724 } 01725 01726 static VALUE 01727 lazy_take_size(VALUE generator, VALUE args, VALUE lazy) 01728 { 01729 VALUE receiver = lazy_size(lazy); 01730 long len = NUM2LONG(RARRAY_PTR(rb_ivar_get(lazy, id_arguments))[0]); 01731 if (NIL_P(receiver) || (FIXNUM_P(receiver) && FIX2LONG(receiver) < len)) 01732 return receiver; 01733 return LONG2NUM(len); 01734 } 01735 01736 static VALUE 01737 lazy_take(VALUE obj, VALUE n) 01738 { 01739 long len = NUM2LONG(n); 01740 VALUE lazy; 01741 01742 if (len < 0) { 01743 rb_raise(rb_eArgError, "attempt to take negative size"); 01744 } 01745 if (len == 0) { 01746 VALUE len = INT2NUM(0); 01747 lazy = lazy_to_enum_i(obj, sym_cycle, 1, &len, 0); 01748 } 01749 else { 01750 lazy = rb_block_call(rb_cLazy, id_new, 1, &obj, 01751 lazy_take_func, n); 01752 } 01753 return lazy_set_method(lazy, rb_ary_new3(1, n), lazy_take_size); 01754 } 01755 01756 static VALUE 01757 lazy_take_while_func(VALUE val, VALUE args, int argc, VALUE *argv) 01758 { 01759 VALUE result = rb_yield_values2(argc - 1, &argv[1]); 01760 if (!RTEST(result)) return Qundef; 01761 rb_funcall2(argv[0], id_yield, argc - 1, argv + 1); 01762 return Qnil; 01763 } 01764 01765 static VALUE 01766 lazy_take_while(VALUE obj) 01767 { 01768 if (!rb_block_given_p()) { 01769 rb_raise(rb_eArgError, "tried to call lazy take_while without a block"); 01770 } 01771 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj, 01772 lazy_take_while_func, 0), 01773 Qnil, 0); 01774 } 01775 01776 static VALUE 01777 lazy_drop_size(VALUE generator, VALUE args, VALUE lazy) 01778 { 01779 long len = NUM2LONG(RARRAY_PTR(rb_ivar_get(lazy, id_arguments))[0]); 01780 VALUE receiver = lazy_size(lazy); 01781 if (NIL_P(receiver)) 01782 return receiver; 01783 if (FIXNUM_P(receiver)) { 01784 len = FIX2LONG(receiver) - len; 01785 return LONG2FIX(len < 0 ? 0 : len); 01786 } 01787 return rb_funcall(receiver, '-', 1, LONG2NUM(len)); 01788 } 01789 01790 static VALUE 01791 lazy_drop_func(VALUE val, VALUE args, int argc, VALUE *argv) 01792 { 01793 long remain; 01794 VALUE memo = rb_attr_get(argv[0], id_memo); 01795 if (NIL_P(memo)) { 01796 memo = args; 01797 } 01798 if ((remain = NUM2LONG(memo)) == 0) { 01799 rb_funcall2(argv[0], id_yield, argc - 1, argv + 1); 01800 } 01801 else { 01802 rb_ivar_set(argv[0], id_memo, LONG2NUM(--remain)); 01803 } 01804 return Qnil; 01805 } 01806 01807 static VALUE 01808 lazy_drop(VALUE obj, VALUE n) 01809 { 01810 long len = NUM2LONG(n); 01811 01812 if (len < 0) { 01813 rb_raise(rb_eArgError, "attempt to drop negative size"); 01814 } 01815 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj, 01816 lazy_drop_func, n), 01817 rb_ary_new3(1, n), lazy_drop_size); 01818 } 01819 01820 static VALUE 01821 lazy_drop_while_func(VALUE val, VALUE args, int argc, VALUE *argv) 01822 { 01823 VALUE memo = rb_attr_get(argv[0], id_memo); 01824 if (NIL_P(memo) && !RTEST(rb_yield_values2(argc - 1, &argv[1]))) { 01825 rb_ivar_set(argv[0], id_memo, memo = Qtrue); 01826 } 01827 if (memo == Qtrue) { 01828 rb_funcall2(argv[0], id_yield, argc - 1, argv + 1); 01829 } 01830 return Qnil; 01831 } 01832 01833 static VALUE 01834 lazy_drop_while(VALUE obj) 01835 { 01836 if (!rb_block_given_p()) { 01837 rb_raise(rb_eArgError, "tried to call lazy drop_while without a block"); 01838 } 01839 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj, 01840 lazy_drop_while_func, 0), 01841 Qnil, 0); 01842 } 01843 01844 static VALUE 01845 lazy_super(int argc, VALUE *argv, VALUE lazy) 01846 { 01847 return enumerable_lazy(rb_call_super(argc, argv)); 01848 } 01849 01850 static VALUE 01851 lazy_lazy(VALUE obj) 01852 { 01853 return obj; 01854 } 01855 01856 /* 01857 * Document-class: StopIteration 01858 * 01859 * Raised to stop the iteration, in particular by Enumerator#next. It is 01860 * rescued by Kernel#loop. 01861 * 01862 * loop do 01863 * puts "Hello" 01864 * raise StopIteration 01865 * puts "World" 01866 * end 01867 * puts "Done!" 01868 * 01869 * <em>produces:</em> 01870 * 01871 * Hello 01872 * Done! 01873 */ 01874 01875 /* 01876 * call-seq: 01877 * result -> value 01878 * 01879 * Returns the return value of the iterator. 01880 * 01881 * o = Object.new 01882 * def o.each 01883 * yield 1 01884 * yield 2 01885 * yield 3 01886 * 100 01887 * end 01888 * 01889 * e = o.to_enum 01890 * 01891 * puts e.next #=> 1 01892 * puts e.next #=> 2 01893 * puts e.next #=> 3 01894 * 01895 * begin 01896 * e.next 01897 * rescue StopIteration => ex 01898 * puts ex.result #=> 100 01899 * end 01900 * 01901 */ 01902 01903 static VALUE 01904 stop_result(VALUE self) 01905 { 01906 return rb_attr_get(self, id_result); 01907 } 01908 01909 void 01910 InitVM_Enumerator(void) 01911 { 01912 rb_define_method(rb_mKernel, "to_enum", obj_to_enum, -1); 01913 rb_define_method(rb_mKernel, "enum_for", obj_to_enum, -1); 01914 01915 rb_cEnumerator = rb_define_class("Enumerator", rb_cObject); 01916 rb_include_module(rb_cEnumerator, rb_mEnumerable); 01917 01918 rb_define_alloc_func(rb_cEnumerator, enumerator_allocate); 01919 rb_define_method(rb_cEnumerator, "initialize", enumerator_initialize, -1); 01920 rb_define_method(rb_cEnumerator, "initialize_copy", enumerator_init_copy, 1); 01921 rb_define_method(rb_cEnumerator, "each", enumerator_each, -1); 01922 rb_define_method(rb_cEnumerator, "each_with_index", enumerator_each_with_index, 0); 01923 rb_define_method(rb_cEnumerator, "each_with_object", enumerator_with_object, 1); 01924 rb_define_method(rb_cEnumerator, "with_index", enumerator_with_index, -1); 01925 rb_define_method(rb_cEnumerator, "with_object", enumerator_with_object, 1); 01926 rb_define_method(rb_cEnumerator, "next_values", enumerator_next_values, 0); 01927 rb_define_method(rb_cEnumerator, "peek_values", enumerator_peek_values_m, 0); 01928 rb_define_method(rb_cEnumerator, "next", enumerator_next, 0); 01929 rb_define_method(rb_cEnumerator, "peek", enumerator_peek, 0); 01930 rb_define_method(rb_cEnumerator, "feed", enumerator_feed, 1); 01931 rb_define_method(rb_cEnumerator, "rewind", enumerator_rewind, 0); 01932 rb_define_method(rb_cEnumerator, "inspect", enumerator_inspect, 0); 01933 rb_define_method(rb_cEnumerator, "size", enumerator_size, 0); 01934 01935 /* Lazy */ 01936 rb_cLazy = rb_define_class_under(rb_cEnumerator, "Lazy", rb_cEnumerator); 01937 rb_define_method(rb_mEnumerable, "lazy", enumerable_lazy, 0); 01938 rb_define_method(rb_cLazy, "initialize", lazy_initialize, -1); 01939 rb_define_method(rb_cLazy, "to_enum", lazy_to_enum, -1); 01940 rb_define_method(rb_cLazy, "enum_for", lazy_to_enum, -1); 01941 rb_define_method(rb_cLazy, "map", lazy_map, 0); 01942 rb_define_method(rb_cLazy, "collect", lazy_map, 0); 01943 rb_define_method(rb_cLazy, "flat_map", lazy_flat_map, 0); 01944 rb_define_method(rb_cLazy, "collect_concat", lazy_flat_map, 0); 01945 rb_define_method(rb_cLazy, "select", lazy_select, 0); 01946 rb_define_method(rb_cLazy, "find_all", lazy_select, 0); 01947 rb_define_method(rb_cLazy, "reject", lazy_reject, 0); 01948 rb_define_method(rb_cLazy, "grep", lazy_grep, 1); 01949 rb_define_method(rb_cLazy, "zip", lazy_zip, -1); 01950 rb_define_method(rb_cLazy, "take", lazy_take, 1); 01951 rb_define_method(rb_cLazy, "take_while", lazy_take_while, 0); 01952 rb_define_method(rb_cLazy, "drop", lazy_drop, 1); 01953 rb_define_method(rb_cLazy, "drop_while", lazy_drop_while, 0); 01954 rb_define_method(rb_cLazy, "lazy", lazy_lazy, 0); 01955 rb_define_method(rb_cLazy, "chunk", lazy_super, -1); 01956 rb_define_method(rb_cLazy, "slice_before", lazy_super, -1); 01957 01958 rb_define_alias(rb_cLazy, "force", "to_a"); 01959 01960 rb_eStopIteration = rb_define_class("StopIteration", rb_eIndexError); 01961 rb_define_method(rb_eStopIteration, "result", stop_result, 0); 01962 01963 /* Generator */ 01964 rb_cGenerator = rb_define_class_under(rb_cEnumerator, "Generator", rb_cObject); 01965 rb_include_module(rb_cGenerator, rb_mEnumerable); 01966 rb_define_alloc_func(rb_cGenerator, generator_allocate); 01967 rb_define_method(rb_cGenerator, "initialize", generator_initialize, -1); 01968 rb_define_method(rb_cGenerator, "initialize_copy", generator_init_copy, 1); 01969 rb_define_method(rb_cGenerator, "each", generator_each, -1); 01970 01971 /* Yielder */ 01972 rb_cYielder = rb_define_class_under(rb_cEnumerator, "Yielder", rb_cObject); 01973 rb_define_alloc_func(rb_cYielder, yielder_allocate); 01974 rb_define_method(rb_cYielder, "initialize", yielder_initialize, 0); 01975 rb_define_method(rb_cYielder, "yield", yielder_yield, -2); 01976 rb_define_method(rb_cYielder, "<<", yielder_yield_push, -2); 01977 01978 rb_provide("enumerator.so"); /* for backward compatibility */ 01979 } 01980 01981 void 01982 Init_Enumerator(void) 01983 { 01984 id_rewind = rb_intern("rewind"); 01985 id_each = rb_intern("each"); 01986 id_call = rb_intern("call"); 01987 id_size = rb_intern("size"); 01988 id_yield = rb_intern("yield"); 01989 id_new = rb_intern("new"); 01990 id_initialize = rb_intern("initialize"); 01991 id_next = rb_intern("next"); 01992 id_result = rb_intern("result"); 01993 id_lazy = rb_intern("lazy"); 01994 id_eqq = rb_intern("==="); 01995 id_receiver = rb_intern("receiver"); 01996 id_arguments = rb_intern("arguments"); 01997 id_memo = rb_intern("memo"); 01998 id_method = rb_intern("method"); 01999 id_force = rb_intern("force"); 02000 id_to_enum = rb_intern("to_enum"); 02001 sym_each = ID2SYM(id_each); 02002 sym_cycle = ID2SYM(rb_intern("cycle")); 02003 02004 InitVM(Enumerator); 02005 } 02006