Ruby 2.1.5p273(2014-11-13revision48405)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

enumerator.c
Go to the documentation of this file.
1 /************************************************
2
3 enumerator.c - provides Enumerator class
4
5 $Author: nagachika $
6
7 Copyright (C) 2001-2003 Akinori MUSHA
8
9 $Idaemons: /home/cvs/rb/enumerator/enumerator.c,v 1.1.1.1 2001/07/15 10:12:48 knu Exp $
10 $RoughId: enumerator.c,v 1.6 2003/07/27 11:03:24 nobu Exp $
11 $Id: enumerator.c 46677 2014-07-03 15:46:17Z nagachika $
12
13 ************************************************/
14
15 #include "ruby/ruby.h"
16 #include "node.h"
17 #include "internal.h"
18
19 /*
20 * Document-class: Enumerator
21 *
22 * A class which allows both internal and external iteration.
23 *
24 * An Enumerator can be created by the following methods.
25 * - Kernel#to_enum
26 * - Kernel#enum_for
27 * - Enumerator.new
28 *
29 * Most methods have two forms: a block form where the contents
30 * are evaluated for each item in the enumeration, and a non-block form
31 * which returns a new Enumerator wrapping the iteration.
32 *
33 * enumerator = %w(one two three).each
34 * puts enumerator.class # => Enumerator
35 *
36 * enumerator.each_with_object("foo") do |item, obj|
37 * puts "#{obj}: #{item}"
38 * end
39 *
40 * # foo: one
41 * # foo: two
42 * # foo: three
43 *
44 * enum_with_obj = enumerator.each_with_object("foo")
45 * puts enum_with_obj.class # => Enumerator
46 *
47 * enum_with_obj.each do |item, obj|
48 * puts "#{obj}: #{item}"
49 * end
50 *
51 * # foo: one
52 * # foo: two
53 * # foo: three
54 *
55 * This allows you to chain Enumerators together. For example, you
56 * can map a list's elements to strings containing the index
57 * and the element as a string via:
58 *
59 * puts %w[foo bar baz].map.with_index { |w, i| "#{i}:#{w}" }
60 * # => ["0:foo", "1:bar", "2:baz"]
61 *
62 * An Enumerator can also be used as an external iterator.
63 * For example, Enumerator#next returns the next value of the iterator
64 * or raises StopIteration if the Enumerator is at the end.
65 *
66 * e = [1,2,3].each # returns an enumerator object.
67 * puts e.next # => 1
68 * puts e.next # => 2
69 * puts e.next # => 3
70 * puts e.next # raises StopIteration
71 *
72 * You can use this to implement an internal iterator as follows:
73 *
74 * def ext_each(e)
75 * while true
76 * begin
77 * vs = e.next_values
78 * rescue StopIteration
79 * return $!.result
80 * end
81 * y = yield(*vs)
82 * e.feed y
83 * end
84 * end
85 *
86 * o = Object.new
87 *
88 * def o.each
89 * puts yield
90 * puts yield(1)
91 * puts yield(1, 2)
92 * 3
93 * end
94 *
95 * # use o.each as an internal iterator directly.
96 * puts o.each {|*x| puts x; [:b, *x] }
97 * # => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3
98 *
99 * # convert o.each to an external iterator for
100 * # implementing an internal iterator.
101 * puts ext_each(o.to_enum) {|*x| puts x; [:b, *x] }
102 * # => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3
103 *
104 */
105 VALUE rb_cEnumerator;
106 VALUE rb_cLazy;
107 static ID id_rewind, id_each, id_new, id_initialize, id_yield, id_call, id_size, id_to_enum;
108 static ID id_eqq, id_next, id_result, id_lazy, id_receiver, id_arguments, id_memo, id_method, id_force;
109 static VALUE sym_each, sym_cycle;
110
111 VALUE rb_eStopIteration;
112
113 struct enumerator {
114 VALUE obj;
115 ID meth;
116 VALUE args;
117 VALUE fib;
118 VALUE dst;
119 VALUE lookahead;
120 VALUE feedvalue;
121 VALUE stop_exc;
122 VALUE size;
123 rb_enumerator_size_func *size_fn;
124 };
125
126 static VALUE rb_cGenerator, rb_cYielder;
127
128 struct generator {
129 VALUE proc;
130 };
131
132 struct yielder {
133 VALUE proc;
134 };
135
136 static VALUE generator_allocate(VALUE klass);
137 static VALUE generator_init(VALUE obj, VALUE proc);
138
139 /*
140 * Enumerator
141 */
142 static void
143 enumerator_mark(void *p)
144 {
145 struct enumerator *ptr = p;
146 rb_gc_mark(ptr->obj);
147 rb_gc_mark(ptr->args);
148 rb_gc_mark(ptr->fib);
149 rb_gc_mark(ptr->dst);
150 rb_gc_mark(ptr->lookahead);
151 rb_gc_mark(ptr->feedvalue);
152 rb_gc_mark(ptr->stop_exc);
153 rb_gc_mark(ptr->size);
154 }
155
156 #define enumerator_free RUBY_TYPED_DEFAULT_FREE
157
158 static size_t
159 enumerator_memsize(const void *p)
160 {
161 return p ? sizeof(struct enumerator) : 0;
162 }
163
164 static const rb_data_type_t enumerator_data_type = {
165 "enumerator",
166 {
167 enumerator_mark,
168 enumerator_free,
169 enumerator_memsize,
170 },
171 NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
172 };
173
174 static struct enumerator *
175 enumerator_ptr(VALUE obj)
176 {
177 struct enumerator *ptr;
178
179 TypedData_Get_Struct(obj, struct enumerator, &enumerator_data_type, ptr);
180 if (!ptr || ptr->obj == Qundef) {
181 rb_raise(rb_eArgError, "uninitialized enumerator");
182 }
183 return ptr;
184 }
185
186 /*
187 * call-seq:
188 * obj.to_enum(method = :each, *args) -> enum
189 * obj.enum_for(method = :each, *args) -> enum
190 * obj.to_enum(method = :each, *args) {|*args| block} -> enum
191 * obj.enum_for(method = :each, *args){|*args| block} -> enum
192 *
193 * Creates a new Enumerator which will enumerate by calling +method+ on
194 * +obj+, passing +args+ if any.
195 *
196 * If a block is given, it will be used to calculate the size of
197 * the enumerator without the need to iterate it (see Enumerator#size).
198 *
199 * === Examples
200 *
201 * str = "xyz"
202 *
203 * enum = str.enum_for(:each_byte)
204 * enum.each { |b| puts b }
205 * # => 120
206 * # => 121
207 * # => 122
208 *
209 * # protect an array from being modified by some_method
210 * a = [1, 2, 3]
211 * some_method(a.to_enum)
212 *
213 * It is typical to call to_enum when defining methods for
214 * a generic Enumerable, in case no block is passed.
215 *
216 * Here is such an example, with parameter passing and a sizing block:
217 *
218 * module Enumerable
219 * # a generic method to repeat the values of any enumerable
220 * def repeat(n)
221 * raise ArgumentError, "#{n} is negative!" if n < 0
222 * unless block_given?
223 * return to_enum(__method__, n) do # __method__ is :repeat here
224 * sz = size # Call size and multiply by n...
225 * sz * n if sz # but return nil if size itself is nil
226 * end
227 * end
228 * each do |*val|
229 * n.times { yield *val }
230 * end
231 * end
232 * end
233 *
234 * %i[hello world].repeat(2) { |w| puts w }
235 * # => Prints 'hello', 'hello', 'world', 'world'
236 * enum = (1..14).repeat(3)
237 * # => returns an Enumerator when called without a block
238 * enum.first(4) # => [1, 1, 1, 2]
239 * enum.size # => 42
240 */
241 static VALUE
242 obj_to_enum(int argc, VALUE *argv, VALUE obj)
243 {
244 VALUE enumerator, meth = sym_each;
245
246 if (argc > 0) {
247 --argc;
248 meth = *argv++;
249 }
250 enumerator = rb_enumeratorize_with_size(obj, meth, argc, argv, 0);
251 if (rb_block_given_p()) {
252 enumerator_ptr(enumerator)->size = rb_block_proc();
253 }
254 return enumerator;
255 }
256
257 static VALUE
258 enumerator_allocate(VALUE klass)
259 {
260 struct enumerator *ptr;
261 VALUE enum_obj;
262
263 enum_obj = TypedData_Make_Struct(klass, struct enumerator, &enumerator_data_type, ptr);
264 ptr->obj = Qundef;
265
266 return enum_obj;
267 }
268
269 static VALUE
270 enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, VALUE *argv, rb_enumerator_size_func *size_fn, VALUE size)
271 {
272 struct enumerator *ptr;
273
274 rb_check_frozen(enum_obj);
275 TypedData_Get_Struct(enum_obj, struct enumerator, &enumerator_data_type, ptr);
276
277 if (!ptr) {
278 rb_raise(rb_eArgError, "unallocated enumerator");
279 }
280
281 ptr->obj = obj;
282 ptr->meth = rb_to_id(meth);
283 if (argc) ptr->args = rb_ary_new4(argc, argv);
284 ptr->fib = 0;
285 ptr->dst = Qnil;
286 ptr->lookahead = Qundef;
287 ptr->feedvalue = Qundef;
288 ptr->stop_exc = Qfalse;
289 ptr->size = size;
290 ptr->size_fn = size_fn;
291
292 return enum_obj;
293 }
294
295 /*
296 * call-seq:
297 * Enumerator.new(size = nil) { |yielder| ... }
298 * Enumerator.new(obj, method = :each, *args)
299 *
300 * Creates a new Enumerator object, which can be used as an
301 * Enumerable.
302 *
303 * In the first form, iteration is defined by the given block, in
304 * which a "yielder" object, given as block parameter, can be used to
305 * yield a value by calling the +yield+ method (aliased as +<<+):
306 *
307 * fib = Enumerator.new do |y|
308 * a = b = 1
309 * loop do
310 * y << a
311 * a, b = b, a + b
312 * end
313 * end
314 *
315 * p fib.take(10) # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
316 *
317 * The optional parameter can be used to specify how to calculate the size
318 * in a lazy fashion (see Enumerator#size). It can either be a value or
319 * a callable object.
320 *
321 * In the second, deprecated, form, a generated Enumerator iterates over the
322 * given object using the given method with the given arguments passed.
323 *
324 * Use of this form is discouraged. Use Kernel#enum_for or Kernel#to_enum
325 * instead.
326 *
327 * e = Enumerator.new(ObjectSpace, :each_object)
328 * #-> ObjectSpace.enum_for(:each_object)
329 *
330 * e.select { |obj| obj.is_a?(Class) } #=> array of all classes
331 *
332 */
333 static VALUE
334 enumerator_initialize(int argc, VALUE *argv, VALUE obj)
335 {
336 VALUE recv, meth = sym_each;
337 VALUE size = Qnil;
338
339 if (rb_block_given_p()) {
340 rb_check_arity(argc, 0, 1);
341 recv = generator_init(generator_allocate(rb_cGenerator), rb_block_proc());
342 if (argc) {
343 if (NIL_P(argv[0]) || rb_respond_to(argv[0], id_call) ||
344 (RB_TYPE_P(argv[0], T_FLOAT) && RFLOAT_VALUE(argv[0]) == INFINITY)) {
345 size = argv[0];
346 }
347 else {
348 size = rb_to_int(argv[0]);
349 }
350 argc = 0;
351 }
352 }
353 else {
354 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
355 rb_warn("Enumerator.new without a block is deprecated; use Object#to_enum");
356 recv = *argv++;
357 if (--argc) {
358 meth = *argv++;
359 --argc;
360 }
361 }
362
363 return enumerator_init(obj, recv, meth, argc, argv, 0, size);
364 }
365
366 /* :nodoc: */
367 static VALUE
368 enumerator_init_copy(VALUE obj, VALUE orig)
369 {
370 struct enumerator *ptr0, *ptr1;
371
372 if (!OBJ_INIT_COPY(obj, orig)) return obj;
373 ptr0 = enumerator_ptr(orig);
374 if (ptr0->fib) {
375 /* Fibers cannot be copied */
376 rb_raise(rb_eTypeError, "can't copy execution context");
377 }
378
379 TypedData_Get_Struct(obj, struct enumerator, &enumerator_data_type, ptr1);
380
381 if (!ptr1) {
382 rb_raise(rb_eArgError, "unallocated enumerator");
383 }
384
385 ptr1->obj = ptr0->obj;
386 ptr1->meth = ptr0->meth;
387 ptr1->args = ptr0->args;
388 ptr1->fib = 0;
389 ptr1->lookahead = Qundef;
390 ptr1->feedvalue = Qundef;
391 ptr1->size = ptr0->size;
392 ptr1->size_fn = ptr0->size_fn;
393
394 return obj;
395 }
396
397 /*
398 * For backwards compatibility; use rb_enumeratorize_with_size
399 */
400 VALUE
401 rb_enumeratorize(VALUE obj, VALUE meth, int argc, VALUE *argv)
402 {
403 return rb_enumeratorize_with_size(obj, meth, argc, argv, 0);
404 }
405
406 static VALUE
407 lazy_to_enum_i(VALUE self, VALUE meth, int argc, VALUE *argv, rb_enumerator_size_func *size_fn);
408
409 VALUE
410 rb_enumeratorize_with_size(VALUE obj, VALUE meth, int argc, VALUE *argv, rb_enumerator_size_func *size_fn)
411 {
412 /* Similar effect as calling obj.to_enum, i.e. dispatching to either
413 Kernel#to_enum vs Lazy#to_enum */
414 if (RTEST(rb_obj_is_kind_of(obj, rb_cLazy)))
415 return lazy_to_enum_i(obj, meth, argc, argv, size_fn);
416 else
417 return enumerator_init(enumerator_allocate(rb_cEnumerator),
418 obj, meth, argc, argv, size_fn, Qnil);
419 }
420
421 static VALUE
422 enumerator_block_call(VALUE obj, rb_block_call_func *func, VALUE arg)
423 {
424 int argc = 0;
425 VALUE *argv = 0;
426 const struct enumerator *e = enumerator_ptr(obj);
427 ID meth = e->meth;
428
429 if (e->args) {
430 argc = RARRAY_LENINT(e->args);
431 argv = RARRAY_PTR(e->args);
432 }
433 return rb_block_call(e->obj, meth, argc, argv, func, arg);
434 }
435
436 /*
437 * call-seq:
438 * enum.each { |elm| block } -> obj
439 * enum.each -> enum
440 * enum.each(*appending_args) { |elm| block } -> obj
441 * enum.each(*appending_args) -> an_enumerator
442 *
443 * Iterates over the block according to how this Enumerator was constructed.
444 * If no block and no arguments are given, returns self.
445 *
446 * === Examples
447 *
448 * "Hello, world!".scan(/\w+/) #=> ["Hello", "world"]
449 * "Hello, world!".to_enum(:scan, /\w+/).to_a #=> ["Hello", "world"]
450 * "Hello, world!".to_enum(:scan).each(/\w+/).to_a #=> ["Hello", "world"]
451 *
452 * obj = Object.new
453 *
454 * def obj.each_arg(a, b=:b, *rest)
455 * yield a
456 * yield b
457 * yield rest
458 * :method_returned
459 * end
460 *
461 * enum = obj.to_enum :each_arg, :a, :x
462 *
463 * enum.each.to_a #=> [:a, :x, []]
464 * enum.each.equal?(enum) #=> true
465 * enum.each { |elm| elm } #=> :method_returned
466 *
467 * enum.each(:y, :z).to_a #=> [:a, :x, [:y, :z]]
468 * enum.each(:y, :z).equal?(enum) #=> false
469 * enum.each(:y, :z) { |elm| elm } #=> :method_returned
470 *
471 */
472 static VALUE
473 enumerator_each(int argc, VALUE *argv, VALUE obj)
474 {
475 if (argc > 0) {
476 struct enumerator *e = enumerator_ptr(obj = rb_obj_dup(obj));
477 VALUE args = e->args;
478 if (args) {
479 #if SIZEOF_INT < SIZEOF_LONG
480 /* check int range overflow */
481 rb_long2int(RARRAY_LEN(args) + argc);
482 #endif
483 args = rb_ary_dup(args);
484 rb_ary_cat(args, argv, argc);
485 }
486 else {
487 args = rb_ary_new4(argc, argv);
488 }
489 e->args = args;
490 }
491 if (!rb_block_given_p()) return obj;
492 return enumerator_block_call(obj, 0, obj);
493 }
494
495 static VALUE
496 enumerator_with_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
497 {
498 NODE *memo = (NODE *)m;
499 VALUE idx = memo->u1.value;
500 memo->u1.value = rb_int_succ(idx);
501
502 if (argc <= 1)
503 return rb_yield_values(2, val, idx);
504
505 return rb_yield_values(2, rb_ary_new4(argc, argv), idx);
506 }
507
508 static VALUE
509 enumerator_size(VALUE obj);
510
511 static VALUE
512 enumerator_enum_size(VALUE obj, VALUE args, VALUE eobj)
513 {
514 return enumerator_size(obj);
515 }
516
517 /*
518 * call-seq:
519 * e.with_index(offset = 0) {|(*args), idx| ... }
520 * e.with_index(offset = 0)
521 *
522 * Iterates the given block for each element with an index, which
523 * starts from +offset+. If no block is given, returns a new Enumerator
524 * that includes the index, starting from +offset+
525 *
526 * +offset+:: the starting index to use
527 *
528 */
529 static VALUE
530 enumerator_with_index(int argc, VALUE *argv, VALUE obj)
531 {
532 VALUE memo;
533
534 rb_scan_args(argc, argv, "01", &memo);
535 RETURN_SIZED_ENUMERATOR(obj, argc, argv, enumerator_enum_size);
536 if (NIL_P(memo))
537 memo = INT2FIX(0);
538 else
539 memo = rb_to_int(memo);
540 return enumerator_block_call(obj, enumerator_with_index_i, (VALUE)NEW_MEMO(memo, 0, 0));
541 }
542
543 /*
544 * call-seq:
545 * e.each_with_index {|(*args), idx| ... }
546 * e.each_with_index
547 *
548 * Same as Enumerator#with_index(0), i.e. there is no starting offset.
549 *
550 * If no block is given, a new Enumerator is returned that includes the index.
551 *
552 */
553 static VALUE
554 enumerator_each_with_index(VALUE obj)
555 {
556 return enumerator_with_index(0, NULL, obj);
557 }
558
559 static VALUE
560 enumerator_with_object_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, memo))
561 {
562 if (argc <= 1)
563 return rb_yield_values(2, val, memo);
564
565 return rb_yield_values(2, rb_ary_new4(argc, argv), memo);
566 }
567
568 /*
569 * call-seq:
570 * e.each_with_object(obj) {|(*args), obj| ... }
571 * e.each_with_object(obj)
572 * e.with_object(obj) {|(*args), obj| ... }
573 * e.with_object(obj)
574 *
575 * Iterates the given block for each element with an arbitrary object, +obj+,
576 * and returns +obj+
577 *
578 * If no block is given, returns a new Enumerator.
579 *
580 * === Example
581 *
582 * to_three = Enumerator.new do |y|
583 * 3.times do |x|
584 * y << x
585 * end
586 * end
587 *
588 * to_three_with_string = to_three.with_object("foo")
589 * to_three_with_string.each do |x,string|
590 * puts "#{string}: #{x}"
591 * end
592 *
593 * # => foo:0
594 * # => foo:1
595 * # => foo:2
596 */
597 static VALUE
598 enumerator_with_object(VALUE obj, VALUE memo)
599 {
600 RETURN_SIZED_ENUMERATOR(obj, 1, &memo, enumerator_enum_size);
601 enumerator_block_call(obj, enumerator_with_object_i, memo);
602
603 return memo;
604 }
605
606 static VALUE
607 next_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, obj))
608 {
609 struct enumerator *e = enumerator_ptr(obj);
610 VALUE feedvalue = Qnil;
611 VALUE args = rb_ary_new4(argc, argv);
612 rb_fiber_yield(1, &args);
613 if (e->feedvalue != Qundef) {
614 feedvalue = e->feedvalue;
615 e->feedvalue = Qundef;
616 }
617 return feedvalue;
618 }
619
620 static VALUE
621 next_i(VALUE curr, VALUE obj)
622 {
623 struct enumerator *e = enumerator_ptr(obj);
624 VALUE nil = Qnil;
625 VALUE result;
626
627 result = rb_block_call(obj, id_each, 0, 0, next_ii, obj);
628 e->stop_exc = rb_exc_new2(rb_eStopIteration, "iteration reached an end");
629 rb_ivar_set(e->stop_exc, id_result, result);
630 return rb_fiber_yield(1, &nil);
631 }
632
633 static void
634 next_init(VALUE obj, struct enumerator *e)
635 {
636 VALUE curr = rb_fiber_current();
637 e->dst = curr;
638 e->fib = rb_fiber_new(next_i, obj);
639 e->lookahead = Qundef;
640 }
641
642 static VALUE
643 get_next_values(VALUE obj, struct enumerator *e)
644 {
645 VALUE curr, vs;
646
647 if (e->stop_exc)
648 rb_exc_raise(e->stop_exc);
649
650 curr = rb_fiber_current();
651
652 if (!e->fib || !rb_fiber_alive_p(e->fib)) {
653 next_init(obj, e);
654 }
655
656 vs = rb_fiber_resume(e->fib, 1, &curr);
657 if (e->stop_exc) {
658 e->fib = 0;
659 e->dst = Qnil;
660 e->lookahead = Qundef;
661 e->feedvalue = Qundef;
662 rb_exc_raise(e->stop_exc);
663 }
664 return vs;
665 }
666
667 /*
668 * call-seq:
669 * e.next_values -> array
670 *
671 * Returns the next object as an array in the enumerator, and move the
672 * internal position forward. When the position reached at the end,
673 * StopIteration is raised.
674 *
675 * This method can be used to distinguish <code>yield</code> and <code>yield
676 * nil</code>.
677 *
678 * === Example
679 *
680 * o = Object.new
681 * def o.each
682 * yield
683 * yield 1
684 * yield 1, 2
685 * yield nil
686 * yield [1, 2]
687 * end
688 * e = o.to_enum
689 * p e.next_values
690 * p e.next_values
691 * p e.next_values
692 * p e.next_values
693 * p e.next_values
694 * e = o.to_enum
695 * p e.next
696 * p e.next
697 * p e.next
698 * p e.next
699 * p e.next
700 *
701 * ## yield args next_values next
702 * # yield [] nil
703 * # yield 1 [1] 1
704 * # yield 1, 2 [1, 2] [1, 2]
705 * # yield nil [nil] nil
706 * # yield [1, 2] [[1, 2]] [1, 2]
707 *
708 * Note that +next_values+ does not affect other non-external enumeration
709 * methods unless underlying iteration method itself has side-effect, e.g.
710 * IO#each_line.
711 *
712 */
713
714 static VALUE
715 enumerator_next_values(VALUE obj)
716 {
717 struct enumerator *e = enumerator_ptr(obj);
718 VALUE vs;
719
720 if (e->lookahead != Qundef) {
721 vs = e->lookahead;
722 e->lookahead = Qundef;
723 return vs;
724 }
725
726 return get_next_values(obj, e);
727 }
728
729 static VALUE
730 ary2sv(VALUE args, int dup)
731 {
732 if (!RB_TYPE_P(args, T_ARRAY))
733 return args;
734
735 switch (RARRAY_LEN(args)) {
736 case 0:
737 return Qnil;
738
739 case 1:
740 return RARRAY_AREF(args, 0);
741
742 default:
743 if (dup)
744 return rb_ary_dup(args);
745 return args;
746 }
747 }
748
749 /*
750 * call-seq:
751 * e.next -> object
752 *
753 * Returns the next object in the enumerator, and move the internal position
754 * forward. When the position reached at the end, StopIteration is raised.
755 *
756 * === Example
757 *
758 * a = [1,2,3]
759 * e = a.to_enum
760 * p e.next #=> 1
761 * p e.next #=> 2
762 * p e.next #=> 3
763 * p e.next #raises StopIteration
764 *
765 * Note that enumeration sequence by +next+ does not affect other non-external
766 * enumeration methods, unless the underlying iteration methods itself has
767 * side-effect, e.g. IO#each_line.
768 *
769 */
770
771 static VALUE
772 enumerator_next(VALUE obj)
773 {
774 VALUE vs = enumerator_next_values(obj);
775 return ary2sv(vs, 0);
776 }
777
778 static VALUE
779 enumerator_peek_values(VALUE obj)
780 {
781 struct enumerator *e = enumerator_ptr(obj);
782
783 if (e->lookahead == Qundef) {
784 e->lookahead = get_next_values(obj, e);
785 }
786 return e->lookahead;
787 }
788
789 /*
790 * call-seq:
791 * e.peek_values -> array
792 *
793 * Returns the next object as an array, similar to Enumerator#next_values, but
794 * doesn't move the internal position forward. If the position is already at
795 * the end, StopIteration is raised.
796 *
797 * === Example
798 *
799 * o = Object.new
800 * def o.each
801 * yield
802 * yield 1
803 * yield 1, 2
804 * end
805 * e = o.to_enum
806 * p e.peek_values #=> []
807 * e.next
808 * p e.peek_values #=> [1]
809 * p e.peek_values #=> [1]
810 * e.next
811 * p e.peek_values #=> [1, 2]
812 * e.next
813 * p e.peek_values # raises StopIteration
814 *
815 */
816
817 static VALUE
818 enumerator_peek_values_m(VALUE obj)
819 {
820 return rb_ary_dup(enumerator_peek_values(obj));
821 }
822
823 /*
824 * call-seq:
825 * e.peek -> object
826 *
827 * Returns the next object in the enumerator, but doesn't move the internal
828 * position forward. If the position is already at the end, StopIteration
829 * is raised.
830 *
831 * === Example
832 *
833 * a = [1,2,3]
834 * e = a.to_enum
835 * p e.next #=> 1
836 * p e.peek #=> 2
837 * p e.peek #=> 2
838 * p e.peek #=> 2
839 * p e.next #=> 2
840 * p e.next #=> 3
841 * p e.peek #raises StopIteration
842 *
843 */
844
845 static VALUE
846 enumerator_peek(VALUE obj)
847 {
848 VALUE vs = enumerator_peek_values(obj);
849 return ary2sv(vs, 1);
850 }
851
852 /*
853 * call-seq:
854 * e.feed obj -> nil
855 *
856 * Sets the value to be returned by the next yield inside +e+.
857 *
858 * If the value is not set, the yield returns nil.
859 *
860 * This value is cleared after being yielded.
861 *
862 * # Array#map passes the array's elements to "yield" and collects the
863 * # results of "yield" as an array.
864 * # Following example shows that "next" returns the passed elements and
865 * # values passed to "feed" are collected as an array which can be
866 * # obtained by StopIteration#result.
867 * e = [1,2,3].map
868 * p e.next #=> 1
869 * e.feed "a"
870 * p e.next #=> 2
871 * e.feed "b"
872 * p e.next #=> 3
873 * e.feed "c"
874 * begin
875 * e.next
876 * rescue StopIteration
877 * p $!.result #=> ["a", "b", "c"]
878 * end
879 *
880 * o = Object.new
881 * def o.each
882 * x = yield # (2) blocks
883 * p x # (5) => "foo"
884 * x = yield # (6) blocks
885 * p x # (8) => nil
886 * x = yield # (9) blocks
887 * p x # not reached w/o another e.next
888 * end
889 *
890 * e = o.to_enum
891 * e.next # (1)
892 * e.feed "foo" # (3)
893 * e.next # (4)
894 * e.next # (7)
895 * # (10)
896 */
897
898 static VALUE
899 enumerator_feed(VALUE obj, VALUE v)
900 {
901 struct enumerator *e = enumerator_ptr(obj);
902
903 if (e->feedvalue != Qundef) {
904 rb_raise(rb_eTypeError, "feed value already set");
905 }
906 e->feedvalue = v;
907
908 return Qnil;
909 }
910
911 /*
912 * call-seq:
913 * e.rewind -> e
914 *
915 * Rewinds the enumeration sequence to the beginning.
916 *
917 * If the enclosed object responds to a "rewind" method, it is called.
918 */
919
920 static VALUE
921 enumerator_rewind(VALUE obj)
922 {
923 struct enumerator *e = enumerator_ptr(obj);
924
925 rb_check_funcall(e->obj, id_rewind, 0, 0);
926
927 e->fib = 0;
928 e->dst = Qnil;
929 e->lookahead = Qundef;
930 e->feedvalue = Qundef;
931 e->stop_exc = Qfalse;
932 return obj;
933 }
934
935 static VALUE append_method(VALUE obj, VALUE str, ID default_method, VALUE default_args);
936
937 static VALUE
938 inspect_enumerator(VALUE obj, VALUE dummy, int recur)
939 {
940 struct enumerator *e;
941 VALUE eobj, str, cname;
942
943 TypedData_Get_Struct(obj, struct enumerator, &enumerator_data_type, e);
944
945 cname = rb_obj_class(obj);
946
947 if (!e || e->obj == Qundef) {
948 return rb_sprintf("#<%"PRIsVALUE": uninitialized>", rb_class_path(cname));
949 }
950
951 if (recur) {
952 str = rb_sprintf("#<%"PRIsVALUE": ...>", rb_class_path(cname));
953 OBJ_TAINT(str);
954 return str;
955 }
956
957 eobj = rb_attr_get(obj, id_receiver);
958 if (NIL_P(eobj)) {
959 eobj = e->obj;
960 }
961
962 /* (1..100).each_cons(2) => "#<Enumerator: 1..100:each_cons(2)>" */
963 str = rb_sprintf("#<%"PRIsVALUE": %+"PRIsVALUE, rb_class_path(cname), eobj);
964 append_method(obj, str, e->meth, e->args);
965
966 rb_str_buf_cat2(str, ">");
967
968 return str;
969 }
970
971 static VALUE
972 append_method(VALUE obj, VALUE str, ID default_method, VALUE default_args)
973 {
974 VALUE method, eargs;
975
976 method = rb_attr_get(obj, id_method);
977 if (method != Qfalse) {
978 ID mid = default_method;
979 if (!NIL_P(method)) {
980 Check_Type(method, T_SYMBOL);
981 mid = SYM2ID(method);
982 }
983 rb_str_buf_cat2(str, ":");
984 rb_str_buf_append(str, rb_id2str(mid));
985 }
986
987 eargs = rb_attr_get(obj, id_arguments);
988 if (NIL_P(eargs)) {
989 eargs = default_args;
990 }
991 if (eargs != Qfalse) {
992 long argc = RARRAY_LEN(eargs);
993 const VALUE *argv = RARRAY_CONST_PTR(eargs); /* WB: no new reference */
994
995 if (argc > 0) {
996 rb_str_buf_cat2(str, "(");
997
998 while (argc--) {
999 VALUE arg = *argv++;
1000
1001 rb_str_append(str, rb_inspect(arg));
1002 rb_str_buf_cat2(str, argc > 0 ? ", " : ")");
1003 OBJ_INFECT(str, arg);
1004 }
1005 }
1006 }
1007
1008 return str;
1009 }
1010
1011 /*
1012 * call-seq:
1013 * e.inspect -> string
1014 *
1015 * Creates a printable version of <i>e</i>.
1016 */
1017
1018 static VALUE
1019 enumerator_inspect(VALUE obj)
1020 {
1021 return rb_exec_recursive(inspect_enumerator, obj, 0);
1022 }
1023
1024 /*
1025 * call-seq:
1026 * e.size -> int, Float::INFINITY or nil
1027 *
1028 * Returns the size of the enumerator, or +nil+ if it can't be calculated lazily.
1029 *
1030 * (1..100).to_a.permutation(4).size # => 94109400
1031 * loop.size # => Float::INFINITY
1032 * (1..100).drop_while.size # => nil
1033 */
1034
1035 static VALUE
1036 enumerator_size(VALUE obj)
1037 {
1038 struct enumerator *e = enumerator_ptr(obj);
1039 int argc = 0;
1040 const VALUE *argv = NULL;
1041 VALUE size;
1042
1043 if (e->size_fn) {
1044 return (*e->size_fn)(e->obj, e->args, obj);
1045 }
1046 if (e->args) {
1047 argc = (int)RARRAY_LEN(e->args);
1048 argv = RARRAY_CONST_PTR(e->args);
1049 }
1050 size = rb_check_funcall(e->size, id_call, argc, argv);
1051 if (size != Qundef) return size;
1052 return e->size;
1053 }
1054
1055 /*
1056 * Yielder
1057 */
1058 static void
1059 yielder_mark(void *p)
1060 {
1061 struct yielder *ptr = p;
1062 rb_gc_mark(ptr->proc);
1063 }
1064
1065 #define yielder_free RUBY_TYPED_DEFAULT_FREE
1066
1067 static size_t
1068 yielder_memsize(const void *p)
1069 {
1070 return p ? sizeof(struct yielder) : 0;
1071 }
1072
1073 static const rb_data_type_t yielder_data_type = {
1074 "yielder",
1075 {
1076 yielder_mark,
1077 yielder_free,
1078 yielder_memsize,
1079 },
1080 NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
1081 };
1082
1083 static struct yielder *
1084 yielder_ptr(VALUE obj)
1085 {
1086 struct yielder *ptr;
1087
1088 TypedData_Get_Struct(obj, struct yielder, &yielder_data_type, ptr);
1089 if (!ptr || ptr->proc == Qundef) {
1090 rb_raise(rb_eArgError, "uninitialized yielder");
1091 }
1092 return ptr;
1093 }
1094
1095 /* :nodoc: */
1096 static VALUE
1097 yielder_allocate(VALUE klass)
1098 {
1099 struct yielder *ptr;
1100 VALUE obj;
1101
1102 obj = TypedData_Make_Struct(klass, struct yielder, &yielder_data_type, ptr);
1103 ptr->proc = Qundef;
1104
1105 return obj;
1106 }
1107
1108 static VALUE
1109 yielder_init(VALUE obj, VALUE proc)
1110 {
1111 struct yielder *ptr;
1112
1113 TypedData_Get_Struct(obj, struct yielder, &yielder_data_type, ptr);
1114
1115 if (!ptr) {
1116 rb_raise(rb_eArgError, "unallocated yielder");
1117 }
1118
1119 ptr->proc = proc;
1120
1121 return obj;
1122 }
1123
1124 /* :nodoc: */
1125 static VALUE
1126 yielder_initialize(VALUE obj)
1127 {
1128 rb_need_block();
1129
1130 return yielder_init(obj, rb_block_proc());
1131 }
1132
1133 /* :nodoc: */
1134 static VALUE
1135 yielder_yield(VALUE obj, VALUE args)
1136 {
1137 struct yielder *ptr = yielder_ptr(obj);
1138
1139 return rb_proc_call(ptr->proc, args);
1140 }
1141
1142 /* :nodoc: */
1143 static VALUE yielder_yield_push(VALUE obj, VALUE args)
1144 {
1145 yielder_yield(obj, args);
1146 return obj;
1147 }
1148
1149 static VALUE
1150 yielder_yield_i(RB_BLOCK_CALL_FUNC_ARGLIST(obj, memo))
1151 {
1152 return rb_yield_values2(argc, argv);
1153 }
1154
1155 static VALUE
1156 yielder_new(void)
1157 {
1158 return yielder_init(yielder_allocate(rb_cYielder), rb_proc_new(yielder_yield_i, 0));
1159 }
1160
1161 /*
1162 * Generator
1163 */
1164 static void
1165 generator_mark(void *p)
1166 {
1167 struct generator *ptr = p;
1168 rb_gc_mark(ptr->proc);
1169 }
1170
1171 #define generator_free RUBY_TYPED_DEFAULT_FREE
1172
1173 static size_t
1174 generator_memsize(const void *p)
1175 {
1176 return p ? sizeof(struct generator) : 0;
1177 }
1178
1179 static const rb_data_type_t generator_data_type = {
1180 "generator",
1181 {
1182 generator_mark,
1183 generator_free,
1184 generator_memsize,
1185 },
1186 NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
1187 };
1188
1189 static struct generator *
1190 generator_ptr(VALUE obj)
1191 {
1192 struct generator *ptr;
1193
1194 TypedData_Get_Struct(obj, struct generator, &generator_data_type, ptr);
1195 if (!ptr || ptr->proc == Qundef) {
1196 rb_raise(rb_eArgError, "uninitialized generator");
1197 }
1198 return ptr;
1199 }
1200
1201 /* :nodoc: */
1202 static VALUE
1203 generator_allocate(VALUE klass)
1204 {
1205 struct generator *ptr;
1206 VALUE obj;
1207
1208 obj = TypedData_Make_Struct(klass, struct generator, &generator_data_type, ptr);
1209 ptr->proc = Qundef;
1210
1211 return obj;
1212 }
1213
1214 static VALUE
1215 generator_init(VALUE obj, VALUE proc)
1216 {
1217 struct generator *ptr;
1218
1219 rb_check_frozen(obj);
1220 TypedData_Get_Struct(obj, struct generator, &generator_data_type, ptr);
1221
1222 if (!ptr) {
1223 rb_raise(rb_eArgError, "unallocated generator");
1224 }
1225
1226 ptr->proc = proc;
1227
1228 return obj;
1229 }
1230
1231 /* :nodoc: */
1232 static VALUE
1233 generator_initialize(int argc, VALUE *argv, VALUE obj)
1234 {
1235 VALUE proc;
1236
1237 if (argc == 0) {
1238 rb_need_block();
1239
1240 proc = rb_block_proc();
1241 }
1242 else {
1243 rb_scan_args(argc, argv, "1", &proc);
1244
1245 if (!rb_obj_is_proc(proc))
1246 rb_raise(rb_eTypeError,
1247 "wrong argument type %s (expected Proc)",
1248 rb_obj_classname(proc));
1249
1250 if (rb_block_given_p()) {
1251 rb_warn("given block not used");
1252 }
1253 }
1254
1255 return generator_init(obj, proc);
1256 }
1257
1258 /* :nodoc: */
1259 static VALUE
1260 generator_init_copy(VALUE obj, VALUE orig)
1261 {
1262 struct generator *ptr0, *ptr1;
1263
1264 if (!OBJ_INIT_COPY(obj, orig)) return obj;
1265
1266 ptr0 = generator_ptr(orig);
1267
1268 TypedData_Get_Struct(obj, struct generator, &generator_data_type, ptr1);
1269
1270 if (!ptr1) {
1271 rb_raise(rb_eArgError, "unallocated generator");
1272 }
1273
1274 ptr1->proc = ptr0->proc;
1275
1276 return obj;
1277 }
1278
1279 /* :nodoc: */
1280 static VALUE
1281 generator_each(int argc, VALUE *argv, VALUE obj)
1282 {
1283 struct generator *ptr = generator_ptr(obj);
1284 VALUE args = rb_ary_new2(argc + 1);
1285
1286 rb_ary_push(args, yielder_new());
1287 if (argc > 0) {
1288 rb_ary_cat(args, argv, argc);
1289 }
1290
1291 return rb_proc_call(ptr->proc, args);
1292 }
1293
1294 /* Lazy Enumerator methods */
1295 static VALUE
1296 enum_size(VALUE self)
1297 {
1298 VALUE r = rb_check_funcall(self, id_size, 0, 0);
1299 return (r == Qundef) ? Qnil : r;
1300 }
1301
1302 static VALUE
1303 lazyenum_size(VALUE self, VALUE args, VALUE eobj)
1304 {
1305 return enum_size(self);
1306 }
1307
1308 static VALUE
1309 lazy_size(VALUE self)
1310 {
1311 return enum_size(rb_ivar_get(self, id_receiver));
1312 }
1313
1314 static VALUE
1315 lazy_receiver_size(VALUE generator, VALUE args, VALUE lazy)
1316 {
1317 return lazy_size(lazy);
1318 }
1319
1320 static VALUE
1321 lazy_init_iterator(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
1322 {
1323 VALUE result;
1324 if (argc == 1) {
1325 VALUE args[2];
1326 args[0] = m;
1327 args[1] = val;
1328 result = rb_yield_values2(2, args);
1329 }
1330 else {
1331 VALUE args;
1332 int len = rb_long2int((long)argc + 1);
1333
1334 args = rb_ary_tmp_new(len);
1335 rb_ary_push(args, m);
1336 if (argc > 0) {
1337 rb_ary_cat(args, argv, argc);
1338 }
1339 result = rb_yield_values2(len, RARRAY_CONST_PTR(args));
1340 RB_GC_GUARD(args);
1341 }
1342 if (result == Qundef) rb_iter_break();
1343 return Qnil;
1344 }
1345
1346 static VALUE
1347 lazy_init_block_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
1348 {
1349 rb_block_call(m, id_each, argc-1, argv+1, lazy_init_iterator, val);
1350 return Qnil;
1351 }
1352
1353 /*
1354 * call-seq:
1355 * Lazy.new(obj, size=nil) { |yielder, *values| ... }
1356 *
1357 * Creates a new Lazy enumerator. When the enumerator is actually enumerated
1358 * (e.g. by calling #force), +obj+ will be enumerated and each value passed
1359 * to the given block. The block can yield values back using +yielder+.
1360 * For example, to create a method +filter_map+ in both lazy and
1361 * non-lazy fashions:
1362 *
1363 * module Enumerable
1364 * def filter_map(&block)
1365 * map(&block).compact
1366 * end
1367 * end
1368 *
1369 * class Enumerator::Lazy
1370 * def filter_map
1371 * Lazy.new(self) do |yielder, *values|
1372 * result = yield *values
1373 * yielder << result if result
1374 * end
1375 * end
1376 * end
1377 *
1378 * (1..Float::INFINITY).lazy.filter_map{|i| i*i if i.even?}.first(5)
1379 * # => [4, 16, 36, 64, 100]
1380 */
1381 static VALUE
1382 lazy_initialize(int argc, VALUE *argv, VALUE self)
1383 {
1384 VALUE obj, size = Qnil;
1385 VALUE generator;
1386
1387 rb_check_arity(argc, 1, 2);
1388 if (!rb_block_given_p()) {
1389 rb_raise(rb_eArgError, "tried to call lazy new without a block");
1390 }
1391 obj = argv[0];
1392 if (argc > 1) {
1393 size = argv[1];
1394 }
1395 generator = generator_allocate(rb_cGenerator);
1396 rb_block_call(generator, id_initialize, 0, 0, lazy_init_block_i, obj);
1397 enumerator_init(self, generator, sym_each, 0, 0, 0, size);
1398 rb_ivar_set(self, id_receiver, obj);
1399
1400 return self;
1401 }
1402
1403 static VALUE
1404 lazy_set_method(VALUE lazy, VALUE args, rb_enumerator_size_func *size_fn)
1405 {
1406 ID id = rb_frame_this_func();
1407 struct enumerator *e = enumerator_ptr(lazy);
1408 rb_ivar_set(lazy, id_method, ID2SYM(id));
1409 if (NIL_P(args)) {
1410 /* Qfalse indicates that the arguments are empty */
1411 rb_ivar_set(lazy, id_arguments, Qfalse);
1412 }
1413 else {
1414 rb_ivar_set(lazy, id_arguments, args);
1415 }
1416 e->size_fn = size_fn;
1417 return lazy;
1418 }
1419
1420 /*
1421 * call-seq:
1422 * e.lazy -> lazy_enumerator
1423 *
1424 * Returns a lazy enumerator, whose methods map/collect,
1425 * flat_map/collect_concat, select/find_all, reject, grep, zip, take,
1426 * take_while, drop, and drop_while enumerate values only on an
1427 * as-needed basis. However, if a block is given to zip, values
1428 * are enumerated immediately.
1429 *
1430 * === Example
1431 *
1432 * The following program finds pythagorean triples:
1433 *
1434 * def pythagorean_triples
1435 * (1..Float::INFINITY).lazy.flat_map {|z|
1436 * (1..z).flat_map {|x|
1437 * (x..z).select {|y|
1438 * x**2 + y**2 == z**2
1439 * }.map {|y|
1440 * [x, y, z]
1441 * }
1442 * }
1443 * }
1444 * end
1445 * # show first ten pythagorean triples
1446 * p pythagorean_triples.take(10).force # take is lazy, so force is needed
1447 * p pythagorean_triples.first(10) # first is eager
1448 * # show pythagorean triples less than 100
1449 * p pythagorean_triples.take_while { |*, z| z < 100 }.force
1450 */
1451 static VALUE
1452 enumerable_lazy(VALUE obj)
1453 {
1454 VALUE result = lazy_to_enum_i(obj, sym_each, 0, 0, lazyenum_size);
1455 /* Qfalse indicates that the Enumerator::Lazy has no method name */
1456 rb_ivar_set(result, id_method, Qfalse);
1457 return result;
1458 }
1459
1460 static VALUE
1461 lazy_to_enum_i(VALUE obj, VALUE meth, int argc, VALUE *argv, rb_enumerator_size_func *size_fn)
1462 {
1463 return enumerator_init(enumerator_allocate(rb_cLazy),
1464 obj, meth, argc, argv, size_fn, Qnil);
1465 }
1466
1467 /*
1468 * call-seq:
1469 * lzy.to_enum(method = :each, *args) -> lazy_enum
1470 * lzy.enum_for(method = :each, *args) -> lazy_enum
1471 * lzy.to_enum(method = :each, *args) {|*args| block} -> lazy_enum
1472 * lzy.enum_for(method = :each, *args){|*args| block} -> lazy_enum
1473 *
1474 * Similar to Kernel#to_enum, except it returns a lazy enumerator.
1475 * This makes it easy to define Enumerable methods that will
1476 * naturally remain lazy if called from a lazy enumerator.
1477 *
1478 * For example, continuing from the example in Kernel#to_enum:
1479 *
1480 * # See Kernel#to_enum for the definition of repeat
1481 * r = 1..Float::INFINITY
1482 * r.repeat(2).first(5) # => [1, 1, 2, 2, 3]
1483 * r.repeat(2).class # => Enumerator
1484 * r.repeat(2).map{|n| n ** 2}.first(5) # => endless loop!
1485 * # works naturally on lazy enumerator:
1486 * r.lazy.repeat(2).class # => Enumerator::Lazy
1487 * r.lazy.repeat(2).map{|n| n ** 2}.first(5) # => [1, 1, 4, 4, 9]
1488 */
1489
1490 static VALUE
1491 lazy_to_enum(int argc, VALUE *argv, VALUE self)
1492 {
1493 VALUE lazy, meth = sym_each;
1494
1495 if (argc > 0) {
1496 --argc;
1497 meth = *argv++;
1498 }
1499 lazy = lazy_to_enum_i(self, meth, argc, argv, 0);
1500 if (rb_block_given_p()) {
1501 enumerator_ptr(lazy)->size = rb_block_proc();
1502 }
1503 return lazy;
1504 }
1505
1506 static VALUE
1507 lazy_map_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
1508 {
1509 VALUE result = rb_yield_values2(argc - 1, &argv[1]);
1510
1511 rb_funcall(argv[0], id_yield, 1, result);
1512 return Qnil;
1513 }
1514
1515 static VALUE
1516 lazy_map(VALUE obj)
1517 {
1518 if (!rb_block_given_p()) {
1519 rb_raise(rb_eArgError, "tried to call lazy map without a block");
1520 }
1521
1522 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
1523 lazy_map_func, 0),
1524 Qnil, lazy_receiver_size);
1525 }
1526
1527 static VALUE
1528 lazy_flat_map_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, yielder))
1529 {
1530 return rb_funcall2(yielder, id_yield, argc, argv);
1531 }
1532
1533 static VALUE
1534 lazy_flat_map_each(VALUE obj, VALUE yielder)
1535 {
1536 rb_block_call(obj, id_each, 0, 0, lazy_flat_map_i, yielder);
1537 return Qnil;
1538 }
1539
1540 static VALUE
1541 lazy_flat_map_to_ary(VALUE obj, VALUE yielder)
1542 {
1543 VALUE ary = rb_check_array_type(obj);
1544 if (NIL_P(ary)) {
1545 rb_funcall(yielder, id_yield, 1, obj);
1546 }
1547 else {
1548 long i;
1549 for (i = 0; i < RARRAY_LEN(ary); i++) {
1550 rb_funcall(yielder, id_yield, 1, RARRAY_AREF(ary, i));
1551 }
1552 }
1553 return Qnil;
1554 }
1555
1556 static VALUE
1557 lazy_flat_map_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
1558 {
1559 VALUE result = rb_yield_values2(argc - 1, &argv[1]);
1560 if (RB_TYPE_P(result, T_ARRAY)) {
1561 long i;
1562 for (i = 0; i < RARRAY_LEN(result); i++) {
1563 rb_funcall(argv[0], id_yield, 1, RARRAY_AREF(result, i));
1564 }
1565 }
1566 else {
1567 if (rb_respond_to(result, id_force) && rb_respond_to(result, id_each)) {
1568 lazy_flat_map_each(result, argv[0]);
1569 }
1570 else {
1571 lazy_flat_map_to_ary(result, argv[0]);
1572 }
1573 }
1574 return Qnil;
1575 }
1576
1577 /*
1578 * call-seq:
1579 * lazy.collect_concat { |obj| block } -> a_lazy_enumerator
1580 * lazy.flat_map { |obj| block } -> a_lazy_enumerator
1581 *
1582 * Returns a new lazy enumerator with the concatenated results of running
1583 * <i>block</i> once for every element in <i>lazy</i>.
1584 *
1585 * ["foo", "bar"].lazy.flat_map {|i| i.each_char.lazy}.force
1586 * #=> ["f", "o", "o", "b", "a", "r"]
1587 *
1588 * A value <i>x</i> returned by <i>block</i> is decomposed if either of
1589 * the following conditions is true:
1590 *
1591 * a) <i>x</i> responds to both each and force, which means that
1592 * <i>x</i> is a lazy enumerator.
1593 * b) <i>x</i> is an array or responds to to_ary.
1594 *
1595 * Otherwise, <i>x</i> is contained as-is in the return value.
1596 *
1597 * [{a:1}, {b:2}].lazy.flat_map {|i| i}.force
1598 * #=> [{:a=>1}, {:b=>2}]
1599 */
1600 static VALUE
1601 lazy_flat_map(VALUE obj)
1602 {
1603 if (!rb_block_given_p()) {
1604 rb_raise(rb_eArgError, "tried to call lazy flat_map without a block");
1605 }
1606
1607 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
1608 lazy_flat_map_func, 0),
1609 Qnil, 0);
1610 }
1611
1612 static VALUE
1613 lazy_select_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
1614 {
1615 VALUE element = rb_enum_values_pack(argc - 1, argv + 1);
1616
1617 if (RTEST(rb_yield(element))) {
1618 return rb_funcall(argv[0], id_yield, 1, element);
1619 }
1620 return Qnil;
1621 }
1622
1623 static VALUE
1624 lazy_select(VALUE obj)
1625 {
1626 if (!rb_block_given_p()) {
1627 rb_raise(rb_eArgError, "tried to call lazy select without a block");
1628 }
1629
1630 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
1631 lazy_select_func, 0),
1632 Qnil, 0);
1633 }
1634
1635 static VALUE
1636 lazy_reject_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
1637 {
1638 VALUE element = rb_enum_values_pack(argc - 1, argv + 1);
1639
1640 if (!RTEST(rb_yield(element))) {
1641 return rb_funcall(argv[0], id_yield, 1, element);
1642 }
1643 return Qnil;
1644 }
1645
1646 static VALUE
1647 lazy_reject(VALUE obj)
1648 {
1649 if (!rb_block_given_p()) {
1650 rb_raise(rb_eArgError, "tried to call lazy reject without a block");
1651 }
1652
1653 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
1654 lazy_reject_func, 0),
1655 Qnil, 0);
1656 }
1657
1658 static VALUE
1659 lazy_grep_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
1660 {
1661 VALUE i = rb_enum_values_pack(argc - 1, argv + 1);
1662 VALUE result = rb_funcall(m, id_eqq, 1, i);
1663
1664 if (RTEST(result)) {
1665 rb_funcall(argv[0], id_yield, 1, i);
1666 }
1667 return Qnil;
1668 }
1669
1670 static VALUE
1671 lazy_grep_iter(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
1672 {
1673 VALUE i = rb_enum_values_pack(argc - 1, argv + 1);
1674 VALUE result = rb_funcall(m, id_eqq, 1, i);
1675
1676 if (RTEST(result)) {
1677 rb_funcall(argv[0], id_yield, 1, rb_yield(i));
1678 }
1679 return Qnil;
1680 }
1681
1682 static VALUE
1683 lazy_grep(VALUE obj, VALUE pattern)
1684 {
1685 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
1686 rb_block_given_p() ?
1687 lazy_grep_iter : lazy_grep_func,
1688 pattern),
1689 rb_ary_new3(1, pattern), 0);
1690 }
1691
1692 static VALUE
1693 call_next(VALUE obj)
1694 {
1695 return rb_funcall(obj, id_next, 0);
1696 }
1697
1698 static VALUE
1699 next_stopped(VALUE obj)
1700 {
1701 return Qnil;
1702 }
1703
1704 static VALUE
1705 lazy_zip_arrays_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, arrays))
1706 {
1707 VALUE yielder, ary, memo;
1708 long i, count;
1709
1710 yielder = argv[0];
1711 memo = rb_attr_get(yielder, id_memo);
1712 count = NIL_P(memo) ? 0 : NUM2LONG(memo);
1713
1714 ary = rb_ary_new2(RARRAY_LEN(arrays) + 1);
1715 rb_ary_push(ary, argv[1]);
1716 for (i = 0; i < RARRAY_LEN(arrays); i++) {
1717 rb_ary_push(ary, rb_ary_entry(RARRAY_AREF(arrays, i), count));
1718 }
1719 rb_funcall(yielder, id_yield, 1, ary);
1720 rb_ivar_set(yielder, id_memo, LONG2NUM(++count));
1721 return Qnil;
1722 }
1723
1724 static VALUE
1725 lazy_zip_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, zip_args))
1726 {
1727 VALUE yielder, ary, arg, v;
1728 long i;
1729
1730 yielder = argv[0];
1731 arg = rb_attr_get(yielder, id_memo);
1732 if (NIL_P(arg)) {
1733 arg = rb_ary_new2(RARRAY_LEN(zip_args));
1734 for (i = 0; i < RARRAY_LEN(zip_args); i++) {
1735 rb_ary_push(arg, rb_funcall(RARRAY_AREF(zip_args, i), id_to_enum, 0));
1736 }
1737 rb_ivar_set(yielder, id_memo, arg);
1738 }
1739
1740 ary = rb_ary_new2(RARRAY_LEN(arg) + 1);
1741 v = Qnil;
1742 if (--argc > 0) {
1743 ++argv;
1744 v = argc > 1 ? rb_ary_new_from_values(argc, argv) : *argv;
1745 }
1746 rb_ary_push(ary, v);
1747 for (i = 0; i < RARRAY_LEN(arg); i++) {
1748 v = rb_rescue2(call_next, RARRAY_AREF(arg, i), next_stopped, 0,
1749 rb_eStopIteration, (VALUE)0);
1750 rb_ary_push(ary, v);
1751 }
1752 rb_funcall(yielder, id_yield, 1, ary);
1753 return Qnil;
1754 }
1755
1756 static VALUE
1757 lazy_zip(int argc, VALUE *argv, VALUE obj)
1758 {
1759 VALUE ary, v;
1760 long i;
1761 rb_block_call_func *func = lazy_zip_arrays_func;
1762
1763 if (rb_block_given_p()) {
1764 return rb_call_super(argc, argv);
1765 }
1766
1767 ary = rb_ary_new2(argc);
1768 for (i = 0; i < argc; i++) {
1769 v = rb_check_array_type(argv[i]);
1770 if (NIL_P(v)) {
1771 for (; i < argc; i++) {
1772 if (!rb_respond_to(argv[i], id_each)) {
1773 rb_raise(rb_eTypeError, "wrong argument type %s (must respond to :each)",
1774 rb_obj_classname(argv[i]));
1775 }
1776 }
1777 ary = rb_ary_new4(argc, argv);
1778 func = lazy_zip_func;
1779 break;
1780 }
1781 rb_ary_push(ary, v);
1782 }
1783
1784 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
1785 func, ary),
1786 ary, lazy_receiver_size);
1787 }
1788
1789 static VALUE
1790 lazy_take_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, args))
1791 {
1792 long remain;
1793 VALUE memo = rb_attr_get(argv[0], id_memo);
1794 if (NIL_P(memo)) {
1795 memo = args;
1796 }
1797
1798 rb_funcall2(argv[0], id_yield, argc - 1, argv + 1);
1799 if ((remain = NUM2LONG(memo)-1) == 0) {
1800 return Qundef;
1801 }
1802 else {
1803 rb_ivar_set(argv[0], id_memo, LONG2NUM(remain));
1804 return Qnil;
1805 }
1806 }
1807
1808 static VALUE
1809 lazy_take_size(VALUE generator, VALUE args, VALUE lazy)
1810 {
1811 VALUE receiver = lazy_size(lazy);
1812 long len = NUM2LONG(RARRAY_AREF(rb_ivar_get(lazy, id_arguments), 0));
1813 if (NIL_P(receiver) || (FIXNUM_P(receiver) && FIX2LONG(receiver) < len))
1814 return receiver;
1815 return LONG2NUM(len);
1816 }
1817
1818 static VALUE
1819 lazy_take(VALUE obj, VALUE n)
1820 {
1821 long len = NUM2LONG(n);
1822 VALUE lazy;
1823
1824 if (len < 0) {
1825 rb_raise(rb_eArgError, "attempt to take negative size");
1826 }
1827 if (len == 0) {
1828 VALUE len = INT2FIX(0);
1829 lazy = lazy_to_enum_i(obj, sym_cycle, 1, &len, 0);
1830 }
1831 else {
1832 lazy = rb_block_call(rb_cLazy, id_new, 1, &obj,
1833 lazy_take_func, n);
1834 }
1835 return lazy_set_method(lazy, rb_ary_new3(1, n), lazy_take_size);
1836 }
1837
1838 static VALUE
1839 lazy_take_while_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, args))
1840 {
1841 VALUE result = rb_yield_values2(argc - 1, &argv[1]);
1842 if (!RTEST(result)) return Qundef;
1843 rb_funcall2(argv[0], id_yield, argc - 1, argv + 1);
1844 return Qnil;
1845 }
1846
1847 static VALUE
1848 lazy_take_while(VALUE obj)
1849 {
1850 if (!rb_block_given_p()) {
1851 rb_raise(rb_eArgError, "tried to call lazy take_while without a block");
1852 }
1853 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
1854 lazy_take_while_func, 0),
1855 Qnil, 0);
1856 }
1857
1858 static VALUE
1859 lazy_drop_size(VALUE generator, VALUE args, VALUE lazy)
1860 {
1861 long len = NUM2LONG(RARRAY_AREF(rb_ivar_get(lazy, id_arguments), 0));
1862 VALUE receiver = lazy_size(lazy);
1863 if (NIL_P(receiver))
1864 return receiver;
1865 if (FIXNUM_P(receiver)) {
1866 len = FIX2LONG(receiver) - len;
1867 return LONG2FIX(len < 0 ? 0 : len);
1868 }
1869 return rb_funcall(receiver, '-', 1, LONG2NUM(len));
1870 }
1871
1872 static VALUE
1873 lazy_drop_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, args))
1874 {
1875 long remain;
1876 VALUE memo = rb_attr_get(argv[0], id_memo);
1877 if (NIL_P(memo)) {
1878 memo = args;
1879 }
1880 if ((remain = NUM2LONG(memo)) == 0) {
1881 rb_funcall2(argv[0], id_yield, argc - 1, argv + 1);
1882 }
1883 else {
1884 rb_ivar_set(argv[0], id_memo, LONG2NUM(--remain));
1885 }
1886 return Qnil;
1887 }
1888
1889 static VALUE
1890 lazy_drop(VALUE obj, VALUE n)
1891 {
1892 long len = NUM2LONG(n);
1893
1894 if (len < 0) {
1895 rb_raise(rb_eArgError, "attempt to drop negative size");
1896 }
1897 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
1898 lazy_drop_func, n),
1899 rb_ary_new3(1, n), lazy_drop_size);
1900 }
1901
1902 static VALUE
1903 lazy_drop_while_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, args))
1904 {
1905 VALUE memo = rb_attr_get(argv[0], id_memo);
1906 if (NIL_P(memo) && !RTEST(rb_yield_values2(argc - 1, &argv[1]))) {
1907 rb_ivar_set(argv[0], id_memo, memo = Qtrue);
1908 }
1909 if (memo == Qtrue) {
1910 rb_funcall2(argv[0], id_yield, argc - 1, argv + 1);
1911 }
1912 return Qnil;
1913 }
1914
1915 static VALUE
1916 lazy_drop_while(VALUE obj)
1917 {
1918 if (!rb_block_given_p()) {
1919 rb_raise(rb_eArgError, "tried to call lazy drop_while without a block");
1920 }
1921 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
1922 lazy_drop_while_func, 0),
1923 Qnil, 0);
1924 }
1925
1926 static VALUE
1927 lazy_super(int argc, VALUE *argv, VALUE lazy)
1928 {
1929 return enumerable_lazy(rb_call_super(argc, argv));
1930 }
1931
1932 static VALUE
1933 lazy_lazy(VALUE obj)
1934 {
1935 return obj;
1936 }
1937
1938 /*
1939 * Document-class: StopIteration
1940 *
1941 * Raised to stop the iteration, in particular by Enumerator#next. It is
1942 * rescued by Kernel#loop.
1943 *
1944 * loop do
1945 * puts "Hello"
1946 * raise StopIteration
1947 * puts "World"
1948 * end
1949 * puts "Done!"
1950 *
1951 * <em>produces:</em>
1952 *
1953 * Hello
1954 * Done!
1955 */
1956
1957 /*
1958 * call-seq:
1959 * result -> value
1960 *
1961 * Returns the return value of the iterator.
1962 *
1963 * o = Object.new
1964 * def o.each
1965 * yield 1
1966 * yield 2
1967 * yield 3
1968 * 100
1969 * end
1970 *
1971 * e = o.to_enum
1972 *
1973 * puts e.next #=> 1
1974 * puts e.next #=> 2
1975 * puts e.next #=> 3
1976 *
1977 * begin
1978 * e.next
1979 * rescue StopIteration => ex
1980 * puts ex.result #=> 100
1981 * end
1982 *
1983 */
1984
1985 static VALUE
1986 stop_result(VALUE self)
1987 {
1988 return rb_attr_get(self, id_result);
1989 }
1990
1991 void
1992 InitVM_Enumerator(void)
1993 {
1994 rb_define_method(rb_mKernel, "to_enum", obj_to_enum, -1);
1995 rb_define_method(rb_mKernel, "enum_for", obj_to_enum, -1);
1996
1997 rb_cEnumerator = rb_define_class("Enumerator", rb_cObject);
1998 rb_include_module(rb_cEnumerator, rb_mEnumerable);
1999
2000 rb_define_alloc_func(rb_cEnumerator, enumerator_allocate);
2001 rb_define_method(rb_cEnumerator, "initialize", enumerator_initialize, -1);
2002 rb_define_method(rb_cEnumerator, "initialize_copy", enumerator_init_copy, 1);
2003 rb_define_method(rb_cEnumerator, "each", enumerator_each, -1);
2004 rb_define_method(rb_cEnumerator, "each_with_index", enumerator_each_with_index, 0);
2005 rb_define_method(rb_cEnumerator, "each_with_object", enumerator_with_object, 1);
2006 rb_define_method(rb_cEnumerator, "with_index", enumerator_with_index, -1);
2007 rb_define_method(rb_cEnumerator, "with_object", enumerator_with_object, 1);
2008 rb_define_method(rb_cEnumerator, "next_values", enumerator_next_values, 0);
2009 rb_define_method(rb_cEnumerator, "peek_values", enumerator_peek_values_m, 0);
2010 rb_define_method(rb_cEnumerator, "next", enumerator_next, 0);
2011 rb_define_method(rb_cEnumerator, "peek", enumerator_peek, 0);
2012 rb_define_method(rb_cEnumerator, "feed", enumerator_feed, 1);
2013 rb_define_method(rb_cEnumerator, "rewind", enumerator_rewind, 0);
2014 rb_define_method(rb_cEnumerator, "inspect", enumerator_inspect, 0);
2015 rb_define_method(rb_cEnumerator, "size", enumerator_size, 0);
2016
2017 /* Lazy */
2018 rb_cLazy = rb_define_class_under(rb_cEnumerator, "Lazy", rb_cEnumerator);
2019 rb_define_method(rb_mEnumerable, "lazy", enumerable_lazy, 0);
2020 rb_define_method(rb_cLazy, "initialize", lazy_initialize, -1);
2021 rb_define_method(rb_cLazy, "to_enum", lazy_to_enum, -1);
2022 rb_define_method(rb_cLazy, "enum_for", lazy_to_enum, -1);
2023 rb_define_method(rb_cLazy, "map", lazy_map, 0);
2024 rb_define_method(rb_cLazy, "collect", lazy_map, 0);
2025 rb_define_method(rb_cLazy, "flat_map", lazy_flat_map, 0);
2026 rb_define_method(rb_cLazy, "collect_concat", lazy_flat_map, 0);
2027 rb_define_method(rb_cLazy, "select", lazy_select, 0);
2028 rb_define_method(rb_cLazy, "find_all", lazy_select, 0);
2029 rb_define_method(rb_cLazy, "reject", lazy_reject, 0);
2030 rb_define_method(rb_cLazy, "grep", lazy_grep, 1);
2031 rb_define_method(rb_cLazy, "zip", lazy_zip, -1);
2032 rb_define_method(rb_cLazy, "take", lazy_take, 1);
2033 rb_define_method(rb_cLazy, "take_while", lazy_take_while, 0);
2034 rb_define_method(rb_cLazy, "drop", lazy_drop, 1);
2035 rb_define_method(rb_cLazy, "drop_while", lazy_drop_while, 0);
2036 rb_define_method(rb_cLazy, "lazy", lazy_lazy, 0);
2037 rb_define_method(rb_cLazy, "chunk", lazy_super, -1);
2038 rb_define_method(rb_cLazy, "slice_before", lazy_super, -1);
2039
2040 rb_define_alias(rb_cLazy, "force", "to_a");
2041
2042 rb_eStopIteration = rb_define_class("StopIteration", rb_eIndexError);
2043 rb_define_method(rb_eStopIteration, "result", stop_result, 0);
2044
2045 /* Generator */
2046 rb_cGenerator = rb_define_class_under(rb_cEnumerator, "Generator", rb_cObject);
2047 rb_include_module(rb_cGenerator, rb_mEnumerable);
2048 rb_define_alloc_func(rb_cGenerator, generator_allocate);
2049 rb_define_method(rb_cGenerator, "initialize", generator_initialize, -1);
2050 rb_define_method(rb_cGenerator, "initialize_copy", generator_init_copy, 1);
2051 rb_define_method(rb_cGenerator, "each", generator_each, -1);
2052
2053 /* Yielder */
2054 rb_cYielder = rb_define_class_under(rb_cEnumerator, "Yielder", rb_cObject);
2055 rb_define_alloc_func(rb_cYielder, yielder_allocate);
2056 rb_define_method(rb_cYielder, "initialize", yielder_initialize, 0);
2057 rb_define_method(rb_cYielder, "yield", yielder_yield, -2);
2058 rb_define_method(rb_cYielder, "<<", yielder_yield_push, -2);
2059
2060 rb_provide("enumerator.so"); /* for backward compatibility */
2061 }
2062
2063 void
2064 Init_Enumerator(void)
2065 {
2066 id_rewind = rb_intern("rewind");
2067 id_each = rb_intern("each");
2068 id_call = rb_intern("call");
2069 id_size = rb_intern("size");
2070 id_yield = rb_intern("yield");
2071 id_new = rb_intern("new");
2072 id_initialize = rb_intern("initialize");
2073 id_next = rb_intern("next");
2074 id_result = rb_intern("result");
2075 id_lazy = rb_intern("lazy");
2076 id_eqq = rb_intern("===");
2077 id_receiver = rb_intern("receiver");
2078 id_arguments = rb_intern("arguments");
2079 id_memo = rb_intern("memo");
2080 id_method = rb_intern("method");
2081 id_force = rb_intern("force");
2082 id_to_enum = rb_intern("to_enum");
2083 sym_each = ID2SYM(id_each);
2084 sym_cycle = ID2SYM(rb_intern("cycle"));
2085
2086 InitVM(Enumerator);
2087 }
append_method
static VALUE append_method(VALUE obj, VALUE str, ID default_method, VALUE default_args)
Definition: enumerator.c:972
lazy_drop
static VALUE lazy_drop(VALUE obj, VALUE n)
Definition: enumerator.c:1890
next_ii
static VALUE next_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, obj))
Definition: enumerator.c:607
T_SYMBOL
#define T_SYMBOL
Definition: ruby.h:494
enumerator::size
VALUE size
Definition: enumerator.c:122
lazy_zip_func
static VALUE lazy_zip_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, zip_args))
Definition: enumerator.c:1725
enumerator_mark
static void enumerator_mark(void *p)
Definition: enumerator.c:143
rb_exc_new2
#define rb_exc_new2
Definition: intern.h:247
rb_ary_entry
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1171
next_i
static VALUE next_i(VALUE curr, VALUE obj)
Definition: enumerator.c:621
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:878
RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1015
rb_cGenerator
static VALUE rb_cGenerator
Definition: enumerator.c:126
sym_cycle
static VALUE sym_cycle
Definition: enumerator.c:109
enumerator_rewind
static VALUE enumerator_rewind(VALUE obj)
Definition: enumerator.c:921
enumerator
Definition: enumerator.c:113
lazy_reject
static VALUE lazy_reject(VALUE obj)
Definition: enumerator.c:1647
lazy_grep
static VALUE lazy_grep(VALUE obj, VALUE pattern)
Definition: enumerator.c:1683
rb_id2str
VALUE rb_id2str(ID id)
Definition: ripper.c:17160
rb_yield_values
VALUE rb_yield_values(int n,...)
Definition: vm_eval.c:953
count
int count
Definition: encoding.c:48
call_next
static VALUE call_next(VALUE obj)
Definition: enumerator.c:1693
generator_mark
static void generator_mark(void *p)
Definition: enumerator.c:1165
node.h
enumerator_peek_values
static VALUE enumerator_peek_values(VALUE obj)
Definition: enumerator.c:779
yielder_new
static VALUE yielder_new(void)
Definition: enumerator.c:1156
generator_init_copy
static VALUE generator_init_copy(VALUE obj, VALUE orig)
Definition: enumerator.c:1260
ruby.h
generator_memsize
static size_t generator_memsize(const void *p)
Definition: enumerator.c:1174
enumerator::feedvalue
VALUE feedvalue
Definition: enumerator.c:120
InitVM
#define InitVM(ext)
Definition: ruby.h:1789
enumerator_enum_size
static VALUE enumerator_enum_size(VALUE obj, VALUE args, VALUE eobj)
Definition: enumerator.c:512
Qtrue
#define Qtrue
Definition: ruby.h:426
rb_enumerator_size_func
VALUE rb_enumerator_size_func(VALUE, VALUE, VALUE)
Definition: intern.h:231
yielder_allocate
static VALUE yielder_allocate(VALUE klass)
Definition: enumerator.c:1097
OBJ_INIT_COPY
#define OBJ_INIT_COPY(obj, orig)
Definition: intern.h:287
TypedData_Get_Struct
#define TypedData_Get_Struct(obj, type, data_type, sval)
Definition: ruby.h:1041
lazy_size
static VALUE lazy_size(VALUE self)
Definition: enumerator.c:1309
yielder_init
static VALUE yielder_init(VALUE obj, VALUE proc)
Definition: enumerator.c:1109
enumerator_init
static VALUE enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, VALUE *argv, rb_enumerator_size_func *size_fn, VALUE size)
Definition: enumerator.c:270
rb_frame_this_func
ID rb_frame_this_func(void)
Definition: eval.c:943
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:548
rb_check_arity
#define rb_check_arity
Definition: intern.h:296
lazy_zip_arrays_func
static VALUE lazy_zip_arrays_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, arrays))
Definition: enumerator.c:1705
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:896
rb_long2int
#define rb_long2int(n)
Definition: ruby.h:317
SYM2ID
#define SYM2ID(x)
Definition: ruby.h:356
rb_fiber_yield
VALUE rb_fiber_yield(int argc, VALUE *argv)
Definition: cont.c:1496
generator_data_type
static const rb_data_type_t generator_data_type
Definition: enumerator.c:1179
rb_ary_tmp_new
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:534
rb_enumeratorize_with_size
VALUE rb_enumeratorize_with_size(VALUE obj, VALUE meth, int argc, VALUE *argv, rb_enumerator_size_func *size_fn)
Definition: enumerator.c:410
rb_funcall
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:775
enumerator_next_values
static VALUE enumerator_next_values(VALUE obj)
Definition: enumerator.c:715
rb_cEnumerator
VALUE rb_cEnumerator
Definition: enumerator.c:105
rb_fiber_alive_p
VALUE rb_fiber_alive_p(VALUE fibval)
Definition: cont.c:1524
rb_define_class_under
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:676
rb_to_int
VALUE rb_to_int(VALUE)
Definition: object.c:2679
Check_Type
#define Check_Type(v, t)
Definition: ruby.h:532
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1857
enumerator::obj
VALUE obj
Definition: enumerator.c:114
rb_ivar_get
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1115
rb_fiber_current
VALUE rb_fiber_current(void)
Definition: cont.c:1332
yielder_data_type
static const rb_data_type_t yielder_data_type
Definition: enumerator.c:1073
rb_exec_recursive
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:4982
RB_GC_GUARD
#define RB_GC_GUARD(v)
Definition: ruby.h:523
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
generator::proc
VALUE proc
Definition: enumerator.c:129
rb_obj_is_kind_of
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:652
enum_size
static VALUE enum_size(VALUE self)
Definition: enumerator.c:1296
lazy_flat_map_func
static VALUE lazy_flat_map_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
Definition: enumerator.c:1557
generator_free
#define generator_free
Definition: enumerator.c:1171
enumerator_next
static VALUE enumerator_next(VALUE obj)
Definition: enumerator.c:772
rb_include_module
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:827
enumerator_block_call
static VALUE enumerator_block_call(VALUE obj, rb_block_call_func *func, VALUE arg)
Definition: enumerator.c:422
rb_block_call
VALUE rb_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE)
rb_gc_mark
void rb_gc_mark(VALUE ptr)
Definition: gc.c:3604
id_lazy
static ID id_lazy
Definition: enumerator.c:108
T_ARRAY
#define T_ARRAY
Definition: ruby.h:484
lazy_init_iterator
static VALUE lazy_init_iterator(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
Definition: enumerator.c:1321
lazy_to_enum
static VALUE lazy_to_enum(int argc, VALUE *argv, VALUE self)
Definition: enumerator.c:1491
FIXNUM_P
#define FIXNUM_P(f)
Definition: ruby.h:347
yielder_yield
static VALUE yielder_yield(VALUE obj, VALUE args)
Definition: enumerator.c:1135
rb_str_buf_append
VALUE rb_str_buf_append(VALUE, VALUE)
Definition: string.c:2282
generator_initialize
static VALUE generator_initialize(int argc, VALUE *argv, VALUE obj)
Definition: enumerator.c:1233
generator_allocate
static VALUE generator_allocate(VALUE klass)
Definition: enumerator.c:1203
id_memo
static ID id_memo
Definition: enumerator.c:108
rb_obj_classname
const char * rb_obj_classname(VALUE)
Definition: variable.c:406
generator
Definition: enumerator.c:128
rb_ary_new2
#define rb_ary_new2
Definition: intern.h:90
enumerator_with_object
static VALUE enumerator_with_object(VALUE obj, VALUE memo)
Definition: enumerator.c:598
InitVM_Enumerator
void InitVM_Enumerator(void)
Definition: enumerator.c:1992
enumerator::size_fn
rb_enumerator_size_func * size_fn
Definition: enumerator.c:123
lazy_flat_map
static VALUE lazy_flat_map(VALUE obj)
Definition: enumerator.c:1601
RNode
Definition: node.h:239
RB_BLOCK_CALL_FUNC_ARGLIST
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Definition: ruby.h:1511
rb_enumeratorize
VALUE rb_enumeratorize(VALUE obj, VALUE meth, int argc, VALUE *argv)
Definition: enumerator.c:401
rb_exc_raise
void rb_exc_raise(VALUE mesg)
Definition: eval.c:567
lazy_map
static VALUE lazy_map(VALUE obj)
Definition: enumerator.c:1516
id_initialize
static ID id_initialize
Definition: enumerator.c:107
enumerator_ptr
static struct enumerator * enumerator_ptr(VALUE obj)
Definition: enumerator.c:175
rb_obj_dup
VALUE rb_obj_dup(VALUE)
Definition: object.c:406
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:1664
enumerable_lazy
static VALUE enumerable_lazy(VALUE obj)
Definition: enumerator.c:1452
rb_block_call_func
VALUE rb_block_call_func(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg))
Definition: ruby.h:1513
rb_iter_break
void rb_iter_break(void)
Definition: vm.c:1154
id_to_enum
static ID id_to_enum
Definition: enumerator.c:107
get_next_values
static VALUE get_next_values(VALUE obj, struct enumerator *e)
Definition: enumerator.c:643
lazy_flat_map_i
static VALUE lazy_flat_map_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, yielder))
Definition: enumerator.c:1528
rb_fiber_resume
VALUE rb_fiber_resume(VALUE fibval, int argc, VALUE *argv)
Definition: cont.c:1480
lazy_drop_while_func
static VALUE lazy_drop_while_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, args))
Definition: enumerator.c:1903
enumerator_each
static VALUE enumerator_each(int argc, VALUE *argv, VALUE obj)
Definition: enumerator.c:473
enumerator_with_index
static VALUE enumerator_with_index(int argc, VALUE *argv, VALUE obj)
Definition: enumerator.c:530
rb_block_given_p
int rb_block_given_p(void)
Definition: eval.c:712
obj_to_enum
static VALUE obj_to_enum(int argc, VALUE *argv, VALUE obj)
Definition: enumerator.c:242
rb_ary_cat
VALUE rb_ary_cat(VALUE ary, const VALUE *ptr, long len)
Definition: array.c:907
val
#define val
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1553
lazy_take_func
static VALUE lazy_take_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, args))
Definition: enumerator.c:1790
lazyenum_size
static VALUE lazyenum_size(VALUE self, VALUE args, VALUE eobj)
Definition: enumerator.c:1303
rb_str_buf_cat2
VALUE rb_str_buf_cat2(VALUE, const char *)
Definition: string.c:2134
lazy_to_enum_i
static VALUE lazy_to_enum_i(VALUE self, VALUE meth, int argc, VALUE *argv, rb_enumerator_size_func *size_fn)
Definition: enumerator.c:1461
id_next
static ID id_next
Definition: enumerator.c:108
rb_mKernel
RUBY_EXTERN VALUE rb_mKernel
Definition: ruby.h:1541
enumerator_peek_values_m
static VALUE enumerator_peek_values_m(VALUE obj)
Definition: enumerator.c:818
NIL_P
#define NIL_P(v)
Definition: ruby.h:438
enumerator_size
static VALUE enumerator_size(VALUE obj)
Definition: enumerator.c:1036
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:630
next_init
static void next_init(VALUE obj, struct enumerator *e)
Definition: enumerator.c:634
lazy_take_size
static VALUE lazy_take_size(VALUE generator, VALUE args, VALUE lazy)
Definition: enumerator.c:1809
RNode::value
VALUE value
Definition: node.h:245
yielder::proc
VALUE proc
Definition: enumerator.c:133
RNode::u1
union RNode::@129 u1
rb_fiber_new
VALUE rb_fiber_new(VALUE(*func)(ANYARGS), VALUE obj)
Definition: cont.c:1223
T_FLOAT
#define T_FLOAT
Definition: ruby.h:481
stop_result
static VALUE stop_result(VALUE self)
Definition: enumerator.c:1986
argc
int argc
Definition: ruby.c:131
Qfalse
#define Qfalse
Definition: ruby.h:425
lazy_init_block_i
static VALUE lazy_init_block_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
Definition: enumerator.c:1347
lazy_take_while
static VALUE lazy_take_while(VALUE obj)
Definition: enumerator.c:1848
lazy_select
static VALUE lazy_select(VALUE obj)
Definition: enumerator.c:1624
rb_cLazy
VALUE rb_cLazy
Definition: enumerator.c:106
rb_ary_new4
#define rb_ary_new4
Definition: intern.h:92
id_result
static ID id_result
Definition: enumerator.c:108
generator_init
static VALUE generator_init(VALUE obj, VALUE proc)
Definition: enumerator.c:1215
enumerator::lookahead
VALUE lookahead
Definition: enumerator.c:119
rb_eIndexError
VALUE rb_eIndexError
Definition: error.c:550
lazy_receiver_size
static VALUE lazy_receiver_size(VALUE generator, VALUE args, VALUE lazy)
Definition: enumerator.c:1315
rb_need_block
void rb_need_block(void)
Definition: eval.c:733
yielder_yield_push
static VALUE yielder_yield_push(VALUE obj, VALUE args)
Definition: enumerator.c:1143
rb_int_succ
VALUE rb_int_succ(VALUE num)
Definition: numeric.c:2474
rb_define_alias
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1697
enumerator_free
#define enumerator_free
Definition: enumerator.c:156
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:942
lazy_super
static VALUE lazy_super(int argc, VALUE *argv, VALUE lazy)
Definition: enumerator.c:1927
RARRAY_CONST_PTR
#define RARRAY_CONST_PTR(a)
Definition: ruby.h:886
id_yield
static ID id_yield
Definition: enumerator.c:107
func
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:113
rb_obj_is_proc
VALUE rb_obj_is_proc(VALUE)
Definition: proc.c:94
lazy_grep_func
static VALUE lazy_grep_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
Definition: enumerator.c:1659
rb_mEnumerable
VALUE rb_mEnumerable
Definition: enum.c:20
lazy_drop_size
static VALUE lazy_drop_size(VALUE generator, VALUE args, VALUE lazy)
Definition: enumerator.c:1859
lazy_take
static VALUE lazy_take(VALUE obj, VALUE n)
Definition: enumerator.c:1819
rb_sprintf
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1250
const
#define const
Definition: strftime.c:102
rb_class_path
VALUE rb_class_path(VALUE)
Definition: variable.c:257
lazy_map_func
static VALUE lazy_map_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
Definition: enumerator.c:1507
enumerator_each_with_index
static VALUE enumerator_each_with_index(VALUE obj)
Definition: enumerator.c:554
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1728
rb_ivar_set
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1133
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:137
internal.h
ID
unsigned long ID
Definition: ruby.h:89
enumerator::fib
VALUE fib
Definition: enumerator.c:117
Qnil
#define Qnil
Definition: ruby.h:427
rb_eStopIteration
VALUE rb_eStopIteration
Definition: enumerator.c:111
id_eqq
static ID id_eqq
Definition: enumerator.c:108
OBJ_TAINT
#define OBJ_TAINT(x)
Definition: ruby.h:1177
VALUE
unsigned long VALUE
Definition: ruby.h:88
rb_funcall2
#define rb_funcall2
Definition: ruby.h:1456
result
static VALUE result
Definition: nkf.c:40
RETURN_SIZED_ENUMERATOR
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
Definition: intern.h:237
enumerator_memsize
static size_t enumerator_memsize(const void *p)
Definition: enumerator.c:159
rb_rescue2
VALUE rb_rescue2(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*r_proc)(ANYARGS), VALUE data2,...)
Definition: eval.c:741
rb_ary_new3
#define rb_ary_new3
Definition: intern.h:91
enumerator::stop_exc
VALUE stop_exc
Definition: enumerator.c:121
rb_check_funcall
VALUE rb_check_funcall(VALUE, ID, int, const VALUE *)
Definition: vm_eval.c:409
rb_call_super
VALUE rb_call_super(int, const VALUE *)
Definition: vm_eval.c:274
INFINITY
#define INFINITY
Definition: missing.h:141
rb_proc_call
VALUE rb_proc_call(VALUE, VALUE)
Definition: proc.c:733
enumerator_initialize
static VALUE enumerator_initialize(int argc, VALUE *argv, VALUE obj)
Definition: enumerator.c:334
lazy_select_func
static VALUE lazy_select_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
Definition: enumerator.c:1613
RARRAY_LENINT
#define RARRAY_LENINT(ary)
Definition: ruby.h:884
lazy_reject_func
static VALUE lazy_reject_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
Definition: enumerator.c:1636
generator_each
static VALUE generator_each(int argc, VALUE *argv, VALUE obj)
Definition: enumerator.c:1281
lazy_lazy
static VALUE lazy_lazy(VALUE obj)
Definition: enumerator.c:1933
lazy_take_while_func
static VALUE lazy_take_while_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, args))
Definition: enumerator.c:1839
lazy_initialize
static VALUE lazy_initialize(int argc, VALUE *argv, VALUE self)
Definition: enumerator.c:1382
LONG2NUM
#define LONG2NUM(x)
Definition: ruby.h:1309
lazy_grep_iter
static VALUE lazy_grep_iter(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
Definition: enumerator.c:1671
rb_respond_to
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:1639
rb_ary_new_from_values
VALUE rb_ary_new_from_values(long n, const VALUE *elts)
Definition: array.c:520
recur
#define recur(fmt)
Definition: date_strptime.c:147
NEW_MEMO
#define NEW_MEMO(a, b, c)
Definition: node.h:466
id_receiver
static ID id_receiver
Definition: enumerator.c:108
enumerator::dst
VALUE dst
Definition: enumerator.c:118
RFLOAT_VALUE
#define RFLOAT_VALUE(v)
Definition: ruby.h:814
size
int size
Definition: encoding.c:49
rb_yield_values2
VALUE rb_yield_values2(int n, const VALUE *argv)
Definition: vm_eval.c:975
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:231
UNLIMITED_ARGUMENTS
#define UNLIMITED_ARGUMENTS
Definition: intern.h:44
sym_each
static VALUE sym_each
Definition: enumerator.c:109
rb_enum_values_pack
VALUE rb_enum_values_pack(int argc, const VALUE *argv)
Definition: enum.c:33
inspect_enumerator
static VALUE inspect_enumerator(VALUE obj, VALUE dummy, int recur)
Definition: enumerator.c:938
generator_ptr
static struct generator * generator_ptr(VALUE obj)
Definition: enumerator.c:1190
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: ruby.h:901
rb_block_proc
VALUE rb_block_proc(void)
Definition: proc.c:620
next_stopped
static VALUE next_stopped(VALUE obj)
Definition: enumerator.c:1699
rb_data_type_struct
Definition: ruby.h:966
rb_check_array_type
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:628
enumerator_with_object_i
static VALUE enumerator_with_object_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, memo))
Definition: enumerator.c:560
RARRAY_PTR
#define RARRAY_PTR(a)
Definition: ruby.h:907
yielder_mark
static void yielder_mark(void *p)
Definition: enumerator.c:1059
LONG2FIX
#define LONG2FIX(i)
Definition: ruby.h:232
RTEST
#define RTEST(v)
Definition: ruby.h:437
rb_proc_new
VALUE rb_proc_new(VALUE(*)(ANYARGS), VALUE)
Definition: proc.c:2301
OBJ_INFECT
#define OBJ_INFECT(x, s)
Definition: ruby.h:1180
id_arguments
static ID id_arguments
Definition: enumerator.c:108
id_force
static ID id_force
Definition: enumerator.c:108
Init_Enumerator
void Init_Enumerator(void)
Definition: enumerator.c:2064
id_size
static ID id_size
Definition: enumerator.c:107
TypedData_Make_Struct
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1030
rb_ary_dup
VALUE rb_ary_dup(VALUE ary)
Definition: array.c:1888
enumerator_allocate
static VALUE enumerator_allocate(VALUE klass)
Definition: enumerator.c:258
lazy_set_method
static VALUE lazy_set_method(VALUE lazy, VALUE args, rb_enumerator_size_func *size_fn)
Definition: enumerator.c:1404
enumerator_init_copy
static VALUE enumerator_init_copy(VALUE obj, VALUE orig)
Definition: enumerator.c:368
lazy_flat_map_to_ary
static VALUE lazy_flat_map_to_ary(VALUE obj, VALUE yielder)
Definition: enumerator.c:1541
enumerator_data_type
static const rb_data_type_t enumerator_data_type
Definition: enumerator.c:164
id_call
static ID id_call
Definition: enumerator.c:107
ID2SYM
#define ID2SYM(x)
Definition: ruby.h:355
yielder_initialize
static VALUE yielder_initialize(VALUE obj)
Definition: enumerator.c:1126
ary2sv
static VALUE ary2sv(VALUE args, int dup)
Definition: enumerator.c:730
enumerator::args
VALUE args
Definition: enumerator.c:116
rb_inspect
VALUE rb_inspect(VALUE)
Definition: object.c:470
id_new
static ID id_new
Definition: enumerator.c:107
enumerator_peek
static VALUE enumerator_peek(VALUE obj)
Definition: enumerator.c:846
rb_check_frozen
#define rb_check_frozen(obj)
Definition: intern.h:277
yielder_memsize
static size_t yielder_memsize(const void *p)
Definition: enumerator.c:1068
lazy_drop_while
static VALUE lazy_drop_while(VALUE obj)
Definition: enumerator.c:1916
enumerator_inspect
static VALUE enumerator_inspect(VALUE obj)
Definition: enumerator.c:1019
id_rewind
static ID id_rewind
Definition: enumerator.c:107
lazy_zip
static VALUE lazy_zip(int argc, VALUE *argv, VALUE obj)
Definition: enumerator.c:1757
yielder_free
#define yielder_free
Definition: enumerator.c:1065
rb_intern
#define rb_intern(str)
enumerator_with_index_i
static VALUE enumerator_with_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
Definition: enumerator.c:496
lazy_drop_func
static VALUE lazy_drop_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, args))
Definition: enumerator.c:1873
yielder
Definition: enumerator.c:132
yielder_yield_i
static VALUE yielder_yield_i(RB_BLOCK_CALL_FUNC_ARGLIST(obj, memo))
Definition: enumerator.c:1150
enumerator_feed
static VALUE enumerator_feed(VALUE obj, VALUE v)
Definition: enumerator.c:899
NULL
#define NULL
Definition: _sdbm.c:103
FIX2LONG
#define FIX2LONG(x)
Definition: ruby.h:345
Qundef
#define Qundef
Definition: ruby.h:428
rb_cYielder
static VALUE rb_cYielder
Definition: enumerator.c:126
yielder_ptr
static struct yielder * yielder_ptr(VALUE obj)
Definition: enumerator.c:1084
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1488
rb_str_append
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2298
id_each
static ID id_each
Definition: enumerator.c:107
rb_provide
void rb_provide(const char *)
Definition: load.c:572
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:223
rb_to_id
ID rb_to_id(VALUE)
Definition: string.c:8730
rb_eArgError
VALUE rb_eArgError
Definition: error.c:549
id_method
static ID id_method
Definition: enumerator.c:108
lazy_flat_map_each
static VALUE lazy_flat_map_each(VALUE obj, VALUE yielder)
Definition: enumerator.c:1534
NUM2LONG
#define NUM2LONG(x)
Definition: ruby.h:600
rb_attr_get
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1127
argv
char ** argv
Definition: ruby.c:132
rb_obj_class
VALUE rb_obj_class(VALUE)
Definition: object.c:226
enumerator::meth
ID meth
Definition: enumerator.c:115