Ruby 4.1.0dev (2026-09-27 revision f6ff9e7d02e46360f8930b280a3dd921cccbda29)
enumerator.c (f6ff9e7d02e46360f8930b280a3dd921cccbda29)
1/************************************************
2
3 enumerator.c - provides Enumerator class
4
5 $Author$
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$
12
13************************************************/
14
15#include "ruby/internal/config.h"
16
17#ifdef HAVE_FLOAT_H
18#include <float.h>
19#endif
20
21#include <limits.h>
22#include "id.h"
23#include "internal.h"
24#include "internal/class.h"
25#include "internal/enumerator.h"
26#include "internal/error.h"
27#include "internal/hash.h"
28#include "internal/imemo.h"
29#include "internal/numeric.h"
30#include "internal/range.h"
31#include "internal/rational.h"
32#include "internal/set.h"
33#include "ruby/ruby.h"
34
35/*
36 * Document-class: Enumerator
37 *
38 * \Class \Enumerator supports:
39 *
40 * - {External iteration}[rdoc-ref:Enumerator@External+Iteration].
41 * - {Internal iteration}[rdoc-ref:Enumerator@Internal+Iteration].
42 *
43 * An \Enumerator may be created by the following methods:
44 *
45 * - Object#to_enum.
46 * - Object#enum_for.
47 * - Enumerator.new.
48 *
49 * In addition, certain Ruby methods return \Enumerator objects:
50 * a Ruby iterator method that accepts a block
51 * may return an \Enumerator if no block is given.
52 * There are many such methods, for example, in classes Array and Hash.
53 * (In the documentation for those classes, search for `new_enumerator`.)
54 *
55 * == Internal Iteration
56 *
57 * In _internal iteration_, an iterator method drives the iteration
58 * and the caller's block handles the processing;
59 * this example uses method #each_with_index:
60 *
61 * words = %w[foo bar baz] # => ["foo", "bar", "baz"]
62 * enumerator = words.each # => #<Enumerator: ...>
63 * enumerator.each_with_index {|word, i| puts "#{i}: #{word}" }
64 * 0: foo
65 * 1: bar
66 * 2: baz
67 *
68 * Iterator methods in class \Enumerator include:
69 *
70 * - #each:
71 * passes each item to the block.
72 * - #each_with_index:
73 * passes each item and its index to the block.
74 * - #each_with_object (aliased as #with_object):
75 * passes each item and a given object to the block.
76 * - #with_index:
77 * like #each_with_index, but starting at a given offset (instead of zero).
78 *
79 * \Class \Enumerator includes module Enumerable,
80 * which provides many more iterator methods.
81 *
82 * == External Iteration
83 *
84 * In _external iteration_, the user's program both drives the iteration
85 * and handles the processing in stream-like fashion;
86 * this example uses method #next:
87 *
88 * words = %w[foo bar baz]
89 * enumerator = words.each
90 * enumerator.next # => "foo"
91 * enumerator.next # => "bar"
92 * enumerator.next # => "baz"
93 * enumerator.next # Raises StopIteration: iteration reached an end
94 *
95 * External iteration methods in class \Enumerator include:
96 *
97 * - #feed:
98 * sets the value that is next to be returned.
99 * - #next:
100 * returns the next value and increments the position.
101 * - #next_values:
102 * returns the next value in a 1-element array and increments the position.
103 * - #peek:
104 * returns the next value but does not increment the position.
105 * - #peek_values:
106 * returns the next value in a 1-element array but does not increment the position.
107 * - #rewind:
108 * sets the position to zero.
109 *
110 * Each of these methods raises FrozenError if called from a frozen \Enumerator.
111 *
112 * == External Iteration and \Fiber
113 *
114 * External iteration that uses Fiber differs *significantly* from internal iteration:
115 *
116 * - Using \Fiber adds some overhead compared to internal enumeration.
117 * - The stacktrace will only include the stack from the \Enumerator, not above.
118 * - \Fiber-local variables are *not* inherited inside the \Enumerator \Fiber,
119 * which instead starts with no \Fiber-local variables.
120 * - \Fiber storage variables *are* inherited and are designed
121 * to handle \Enumerator Fibers. Assigning to a \Fiber storage variable
122 * only affects the current \Fiber, so if you want to change state
123 * in the caller \Fiber of the \Enumerator \Fiber, you need to use an
124 * extra indirection (e.g., use some object in the \Fiber storage
125 * variable and mutate some ivar of it).
126 *
127 * Concretely:
128 *
129 * Thread.current[:fiber_local] = 1
130 * Fiber[:storage_var] = 1
131 * e = Enumerator.new do |y|
132 * p Thread.current[:fiber_local] # for external iteration: nil, for internal iteration: 1
133 * p Fiber[:storage_var] # => 1, inherited
134 * Fiber[:storage_var] += 1
135 * y << 42
136 * end
137 *
138 * p e.next # => 42
139 * p Fiber[:storage_var] # => 1 (it ran in a different Fiber)
140 *
141 * e.each { p _1 }
142 * p Fiber[:storage_var] # => 2 (it ran in the same Fiber/"stack" as the current Fiber)
143 *
144 * == Converting External Iteration to Internal Iteration
145 *
146 * You can use an external iterator to implement an internal iterator as follows:
147 *
148 * def ext_each(e)
149 * while true
150 * begin
151 * vs = e.next_values
152 * rescue StopIteration
153 * return $!.result
154 * end
155 * y = yield(*vs)
156 * e.feed y
157 * end
158 * end
159 *
160 * o = Object.new
161 *
162 * def o.each
163 * puts yield
164 * puts yield(1)
165 * puts yield(1, 2)
166 * 3
167 * end
168 *
169 * # use o.each as an internal iterator directly.
170 * puts o.each {|*x| puts x; [:b, *x] }
171 * # => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3
172 *
173 * # convert o.each to an external iterator for
174 * # implementing an internal iterator.
175 * puts ext_each(o.to_enum) {|*x| puts x; [:b, *x] }
176 * # => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3
177 *
178 */
180static VALUE rb_cLazy;
181static ID id_rewind, id_to_enum, id_each_entry;
182static ID id_next, id_result, id_receiver, id_arguments, id_memo, id_method, id_force;
183static VALUE sym_each, sym_yield;
184
185static VALUE lazy_use_super_method;
186
187extern ID ruby_static_id_cause;
188
189#define id_call idCall
190#define id_cause ruby_static_id_cause
191#define id_each idEach
192#define id_eqq idEqq
193#define id_initialize idInitialize
194#define id_size idSize
195
197
199 VALUE obj;
200 ID meth;
201 VALUE args;
202 VALUE fib;
203 VALUE dst;
204 VALUE lookahead;
205 VALUE feedvalue;
206 VALUE stop_exc;
207 VALUE size;
208 VALUE procs;
210 int kw_splat;
211};
212
213RUBY_REFERENCES(enumerator_refs) = {
214 RUBY_REF_EDGE(struct enumerator, obj),
215 RUBY_REF_EDGE(struct enumerator, args),
216 RUBY_REF_EDGE(struct enumerator, fib),
217 RUBY_REF_EDGE(struct enumerator, dst),
218 RUBY_REF_EDGE(struct enumerator, lookahead),
219 RUBY_REF_EDGE(struct enumerator, feedvalue),
220 RUBY_REF_EDGE(struct enumerator, stop_exc),
221 RUBY_REF_EDGE(struct enumerator, size),
222 RUBY_REF_EDGE(struct enumerator, procs),
223 RUBY_REF_END
224};
225
226static VALUE rb_cGenerator, rb_cYielder, rb_cEnumProducer;
227
228struct generator {
229 VALUE proc;
230 VALUE obj;
231};
232
233struct yielder {
234 VALUE proc;
235};
236
237struct producer {
238 VALUE init;
239 VALUE proc;
240 VALUE size;
241};
242
243typedef struct MEMO *lazyenum_proc_func(VALUE, struct MEMO *, VALUE, long);
244typedef VALUE lazyenum_size_func(VALUE, VALUE);
245typedef int lazyenum_precheck_func(VALUE proc_entry);
246typedef struct {
247 lazyenum_proc_func *proc;
248 lazyenum_size_func *size;
249 lazyenum_precheck_func *precheck;
251
253 VALUE proc;
254 VALUE memo;
255 const lazyenum_funcs *fn;
256};
257
258static VALUE generator_allocate(VALUE klass);
259static VALUE generator_init(VALUE obj, VALUE proc);
260
261static VALUE rb_cEnumChain;
262
264 VALUE enums;
265 long pos;
266};
267
268static VALUE rb_cEnumProduct;
269
271 VALUE enums;
272};
273
274VALUE rb_cArithSeq;
275
276static const rb_data_type_t enumerator_data_type = {
277 "enumerator",
278 {
279 RUBY_REFS_LIST_PTR(enumerator_refs),
281 NULL, // Nothing allocated externally, so don't need a memsize function
282 NULL,
283 },
284 0, NULL, RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_DECL_MARKING | RUBY_TYPED_EMBEDDABLE
285};
286
287static struct enumerator *
288enumerator_ptr(VALUE obj)
289{
290 struct enumerator *ptr;
291
292 TypedData_Get_Struct(obj, struct enumerator, &enumerator_data_type, ptr);
293 if (!ptr || UNDEF_P(ptr->obj)) {
294 rb_raise(rb_eArgError, "uninitialized enumerator");
295 }
296 return ptr;
297}
298
299static void
300proc_entry_mark_and_move(void *p)
301{
302 struct proc_entry *ptr = p;
303 rb_gc_mark_and_move(&ptr->proc);
304 rb_gc_mark_and_move(&ptr->memo);
305}
306
307static const rb_data_type_t proc_entry_data_type = {
308 "proc_entry",
309 {
310 proc_entry_mark_and_move,
312 NULL, // Nothing allocated externally, so don't need a memsize function
313 proc_entry_mark_and_move,
314 },
315 0, 0, RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
316};
317
318static struct proc_entry *
319proc_entry_ptr(VALUE proc_entry)
320{
321 struct proc_entry *ptr;
322
323 TypedData_Get_Struct(proc_entry, struct proc_entry, &proc_entry_data_type, ptr);
324
325 return ptr;
326}
327
328/*
329 * call-seq:
330 * obj.to_enum(method = :each, *args) -> enum
331 * obj.enum_for(method = :each, *args) -> enum
332 * obj.to_enum(method = :each, *args) {|*args| block} -> enum
333 * obj.enum_for(method = :each, *args){|*args| block} -> enum
334 *
335 * Creates a new Enumerator which will enumerate by calling +method+ on
336 * +obj+, passing +args+ if any. What was _yielded_ by method becomes
337 * values of enumerator.
338 *
339 * If a block is given, it will be used to calculate the size of
340 * the enumerator without the need to iterate it (see Enumerator#size).
341 *
342 * === Examples
343 *
344 * str = "xyz"
345 *
346 * enum = str.enum_for(:each_byte)
347 * enum.each { |b| puts b }
348 * # => 120
349 * # => 121
350 * # => 122
351 *
352 * # protect an array from being modified by some_method
353 * a = [1, 2, 3]
354 * some_method(a.to_enum)
355 *
356 * # String#split in block form is more memory-effective:
357 * very_large_string.split("|") { |chunk| return chunk if chunk.include?('DATE') }
358 * # This could be rewritten more idiomatically with to_enum:
359 * very_large_string.to_enum(:split, "|").lazy.grep(/DATE/).first
360 *
361 * It is typical to call to_enum when defining methods for
362 * a generic Enumerable, in case no block is passed.
363 *
364 * Here is such an example, with parameter passing and a sizing block:
365 *
366 * module Enumerable
367 * # a generic method to repeat the values of any enumerable
368 * def repeat(n)
369 * raise ArgumentError, "#{n} is negative!" if n < 0
370 * unless block_given?
371 * return to_enum(__method__, n) do # __method__ is :repeat here
372 * sz = size # Call size and multiply by n...
373 * sz * n if sz # but return nil if size itself is nil
374 * end
375 * end
376 * each do |*val|
377 * n.times { yield *val }
378 * end
379 * end
380 * end
381 *
382 * %i[hello world].repeat(2) { |w| puts w }
383 * # => Prints 'hello', 'hello', 'world', 'world'
384 * enum = (1..14).repeat(3)
385 * # => returns an Enumerator when called without a block
386 * enum.first(4) # => [1, 1, 1, 2]
387 * enum.size # => 42
388 */
389static VALUE
390obj_to_enum(int argc, VALUE *argv, VALUE obj)
391{
392 VALUE enumerator, meth = sym_each;
393
394 if (argc > 0) {
395 --argc;
396 meth = *argv++;
397 }
398 enumerator = rb_enumeratorize_with_size(obj, meth, argc, argv, 0);
399 if (rb_block_given_p()) {
400 RB_OBJ_WRITE(enumerator, &enumerator_ptr(enumerator)->size, rb_block_proc());
401 }
402 return enumerator;
403}
404
405static VALUE
406enumerator_allocate(VALUE klass)
407{
408 struct enumerator *ptr;
409 VALUE enum_obj;
410
411 enum_obj = TypedData_Make_Struct(klass, struct enumerator, &enumerator_data_type, ptr);
412 ptr->obj = Qundef;
413
414 return enum_obj;
415}
416
417static VALUE
418enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *size_fn, VALUE size, int kw_splat)
419{
420 struct enumerator *ptr;
421
422 rb_check_frozen(enum_obj);
423 TypedData_Get_Struct(enum_obj, struct enumerator, &enumerator_data_type, ptr);
424
425 if (!ptr) {
426 rb_raise(rb_eArgError, "unallocated enumerator");
427 }
428
429 RB_OBJ_WRITE(enum_obj, &ptr->obj, obj);
430 ptr->meth = rb_to_id(meth);
431 if (argc) RB_OBJ_WRITE(enum_obj, &ptr->args, rb_ary_new4(argc, argv));
432 ptr->fib = 0;
433 ptr->dst = Qnil;
434 ptr->lookahead = Qundef;
435 ptr->feedvalue = Qundef;
436 ptr->stop_exc = Qfalse;
437 RB_OBJ_WRITE(enum_obj, &ptr->size, size);
438 ptr->size_fn = size_fn;
439 ptr->kw_splat = kw_splat;
440
441 return enum_obj;
442}
443
444static VALUE
445convert_to_feasible_size_value(VALUE obj)
446{
447 if (NIL_P(obj)) {
448 return obj;
449 }
450 else if (rb_respond_to(obj, id_call)) {
451 return obj;
452 }
453 else if (RB_FLOAT_TYPE_P(obj) && RFLOAT_VALUE(obj) == HUGE_VAL) {
454 return obj;
455 }
456 else {
457 return rb_to_int(obj);
458 }
459}
460
461/*
462 * call-seq:
463 * Enumerator.new(size = nil) {|yielder| ... }
464 *
465 * Returns a new \Enumerator object that can be used for iteration.
466 *
467 * The given block defines the iteration;
468 * it is called with a "yielder" object that can yield an object
469 * via a call to method <tt>yielder.yield</tt>:
470 *
471 * fib = Enumerator.new do |yielder|
472 * n = next_n = 1
473 * while true do
474 * yielder.yield(n)
475 * n, next_n = next_n, n + next_n
476 * end
477 * end
478 *
479 * fib.take(10) # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
480 *
481 * Parameter +size+ specifies how the size is to be calculated (see #size);
482 * it can either be a value or a callable object:
483 *
484 * Enumerator.new{}.size # => nil
485 * Enumerator.new(42){}.size # => 42
486 * Enumerator.new(-> {42}){}.size # => 42
487 *
488 */
489static VALUE
490enumerator_initialize(int argc, VALUE *argv, VALUE obj)
491{
492 VALUE iter = rb_block_proc();
493 VALUE recv = generator_init(generator_allocate(rb_cGenerator), iter);
494 VALUE arg0 = rb_check_arity(argc, 0, 1) ? argv[0] : Qnil;
495 VALUE size = convert_to_feasible_size_value(arg0);
496
497 return enumerator_init(obj, recv, sym_each, 0, 0, 0, size, false);
498}
499
500/* :nodoc: */
501static VALUE
502enumerator_init_copy(VALUE obj, VALUE orig)
503{
504 struct enumerator *ptr0, *ptr1;
505
506 if (!OBJ_INIT_COPY(obj, orig)) return obj;
507 ptr0 = enumerator_ptr(orig);
508 if (ptr0->fib) {
509 /* Fibers cannot be copied */
510 rb_raise(rb_eTypeError, "can't copy execution context");
511 }
512
513 TypedData_Get_Struct(obj, struct enumerator, &enumerator_data_type, ptr1);
514
515 if (!ptr1) {
516 rb_raise(rb_eArgError, "unallocated enumerator");
517 }
518
519 RB_OBJ_WRITE(obj, &ptr1->obj, ptr0->obj);
520 ptr1->meth = ptr0->meth;
521 RB_OBJ_WRITE(obj, &ptr1->args, ptr0->args);
522 ptr1->fib = 0;
523 ptr1->lookahead = Qundef;
524 ptr1->feedvalue = Qundef;
525 RB_OBJ_WRITE(obj, &ptr1->size, ptr0->size);
526 ptr1->size_fn = ptr0->size_fn;
527
528 return obj;
529}
530
531/*
532 * For backwards compatibility; use rb_enumeratorize_with_size
533 */
534VALUE
535rb_enumeratorize(VALUE obj, VALUE meth, int argc, const VALUE *argv)
536{
537 return rb_enumeratorize_with_size(obj, meth, argc, argv, 0);
538}
539
540static VALUE lazy_to_enum_i(VALUE self, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *size_fn, int kw_splat);
541static int lazy_precheck(VALUE procs);
542
543VALUE
544rb_enumeratorize_with_size_kw(VALUE obj, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *size_fn, int kw_splat)
545{
546 VALUE base_class = rb_cEnumerator;
547
548 if (RTEST(rb_obj_is_kind_of(obj, rb_cLazy))) {
549 base_class = rb_cLazy;
550 }
551 else if (RTEST(rb_obj_is_kind_of(obj, rb_cEnumChain))) {
552 obj = enumerator_init(enumerator_allocate(rb_cEnumerator), obj, sym_each, 0, 0, 0, Qnil, false);
553 }
554
555 return enumerator_init(enumerator_allocate(base_class),
556 obj, meth, argc, argv, size_fn, Qnil, kw_splat);
557}
558
559VALUE
560rb_enumeratorize_with_size(VALUE obj, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *size_fn)
561{
562 return rb_enumeratorize_with_size_kw(obj, meth, argc, argv, size_fn, rb_keyword_given_p());
563}
564
565static VALUE
566enumerator_block_call(VALUE obj, rb_block_call_func *func, VALUE arg)
567{
568 int argc = 0;
569 const VALUE *argv = 0;
570 const struct enumerator *e = enumerator_ptr(obj);
571 ID meth = e->meth;
572
573 VALUE args = e->args;
574 if (args) {
575 argc = RARRAY_LENINT(args);
576 argv = RARRAY_CONST_PTR(args);
577 }
578
579 VALUE ret = rb_block_call_kw(e->obj, meth, argc, argv, func, arg, e->kw_splat);
580
581 RB_GC_GUARD(args);
582
583 return ret;
584}
585
586/*
587 * call-seq:
588 * enum.each { |elm| block } -> obj
589 * enum.each -> enum
590 * enum.each(*appending_args) { |elm| block } -> obj
591 * enum.each(*appending_args) -> an_enumerator
592 *
593 * Iterates over the block according to how this Enumerator was constructed.
594 * If no block and no arguments are given, returns self.
595 *
596 * === Examples
597 *
598 * "Hello, world!".scan(/\w+/) #=> ["Hello", "world"]
599 * "Hello, world!".to_enum(:scan, /\w+/).to_a #=> ["Hello", "world"]
600 * "Hello, world!".to_enum(:scan).each(/\w+/).to_a #=> ["Hello", "world"]
601 *
602 * obj = Object.new
603 *
604 * def obj.each_arg(a, b=:b, *rest)
605 * yield a
606 * yield b
607 * yield rest
608 * :method_returned
609 * end
610 *
611 * enum = obj.to_enum :each_arg, :a, :x
612 *
613 * enum.each.to_a #=> [:a, :x, []]
614 * enum.each.equal?(enum) #=> true
615 * enum.each { |elm| elm } #=> :method_returned
616 *
617 * enum.each(:y, :z).to_a #=> [:a, :x, [:y, :z]]
618 * enum.each(:y, :z).equal?(enum) #=> false
619 * enum.each(:y, :z) { |elm| elm } #=> :method_returned
620 *
621 */
622static VALUE
623enumerator_each(int argc, VALUE *argv, VALUE obj)
624{
625 struct enumerator *e = enumerator_ptr(obj);
626
627 if (argc > 0) {
628 VALUE args = (e = enumerator_ptr(obj = rb_obj_dup(obj)))->args;
629 if (args) {
630#if SIZEOF_INT < SIZEOF_LONG
631 /* check int range overflow */
632 rb_long2int(RARRAY_LEN(args) + argc);
633#endif
634 args = rb_ary_dup(args);
635 rb_ary_cat(args, argv, argc);
636 }
637 else {
638 args = rb_ary_new4(argc, argv);
639 }
640 RB_OBJ_WRITE(obj, &e->args, args);
641 e->size = Qnil;
642 e->size_fn = 0;
643 }
644 if (!rb_block_given_p()) return obj;
645
646 if (!lazy_precheck(e->procs)) return Qnil;
647
648 return enumerator_block_call(obj, 0, obj);
649}
650
651static VALUE
652enumerator_with_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
653{
654 struct MEMO *memo = (struct MEMO *)m;
655 VALUE idx = memo->v1;
656 MEMO_V1_SET(memo, rb_int_succ(idx));
657
658 if (argc <= 1)
659 return rb_yield_values(2, val, idx);
660
661 return rb_yield_values(2, rb_ary_new4(argc, argv), idx);
662}
663
664static VALUE
665enumerator_size(VALUE obj);
666
667static VALUE
668enumerator_enum_size(VALUE obj, VALUE args, VALUE eobj)
669{
670 return enumerator_size(obj);
671}
672
673/*
674 * call-seq:
675 * e.with_index(offset = 0) {|(*args), idx| ... }
676 * e.with_index(offset = 0)
677 *
678 * Iterates the given block for each element with an index, which
679 * starts from +offset+. If no block is given, returns a new Enumerator
680 * that includes the index, starting from +offset+
681 *
682 * +offset+:: the starting index to use
683 *
684 */
685static VALUE
686enumerator_with_index(int argc, VALUE *argv, VALUE obj)
687{
688 VALUE memo;
689
690 rb_check_arity(argc, 0, 1);
691 RETURN_SIZED_ENUMERATOR(obj, argc, argv, enumerator_enum_size);
692 memo = (!argc || NIL_P(memo = argv[0])) ? INT2FIX(0) : rb_to_int(memo);
693 return enumerator_block_call(obj, enumerator_with_index_i, (VALUE)rb_imemo_memo_new(memo, 0, 0));
694}
695
696/*
697 * call-seq:
698 * e.each_with_index {|(*args), idx| ... }
699 * e.each_with_index
700 *
701 * Same as Enumerator#with_index(0), i.e. there is no starting offset.
702 *
703 * If no block is given, a new Enumerator is returned that includes the index.
704 *
705 */
706static VALUE
707enumerator_each_with_index(VALUE obj)
708{
709 return enumerator_with_index(0, NULL, obj);
710}
711
712static VALUE
713enumerator_with_object_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, memo))
714{
715 if (argc <= 1)
716 return rb_yield_values(2, val, memo);
717
718 return rb_yield_values(2, rb_ary_new4(argc, argv), memo);
719}
720
721/*
722 * call-seq:
723 * e.each_with_object(obj) {|(*args), obj| ... }
724 * e.each_with_object(obj)
725 * e.with_object(obj) {|(*args), obj| ... }
726 * e.with_object(obj)
727 *
728 * Iterates the given block for each element with an arbitrary object, +obj+,
729 * and returns +obj+
730 *
731 * If no block is given, returns a new Enumerator.
732 *
733 * === Example
734 *
735 * to_three = Enumerator.new do |y|
736 * 3.times do |x|
737 * y << x
738 * end
739 * end
740 *
741 * to_three_with_string = to_three.with_object("foo")
742 * to_three_with_string.each do |x,string|
743 * puts "#{string}: #{x}"
744 * end
745 *
746 * # => foo: 0
747 * # => foo: 1
748 * # => foo: 2
749 */
750static VALUE
751enumerator_with_object(VALUE obj, VALUE memo)
752{
753 RETURN_SIZED_ENUMERATOR(obj, 1, &memo, enumerator_enum_size);
754 enumerator_block_call(obj, enumerator_with_object_i, memo);
755
756 return memo;
757}
758
759static VALUE
760next_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, obj))
761{
762 struct enumerator *e = enumerator_ptr(obj);
763 VALUE feedvalue = Qnil;
764 VALUE args = rb_ary_new4(argc, argv);
765 rb_fiber_yield(1, &args);
766 if (!UNDEF_P(e->feedvalue)) {
767 feedvalue = e->feedvalue;
768 e->feedvalue = Qundef;
769 }
770 return feedvalue;
771}
772
773static VALUE
774next_i(RB_BLOCK_CALL_FUNC_ARGLIST(_, obj))
775{
776 struct enumerator *e = enumerator_ptr(obj);
777 VALUE nil = Qnil;
778 VALUE result;
779
780 result = rb_block_call(obj, id_each, 0, 0, next_ii, obj);
781 RB_OBJ_WRITE(obj, &e->stop_exc, rb_exc_new2(rb_eStopIteration, "iteration reached an end"));
782 rb_ivar_set(e->stop_exc, id_result, result);
783 return rb_fiber_yield(1, &nil);
784}
785
786static void
787next_init(VALUE obj, struct enumerator *e)
788{
789 VALUE curr = rb_fiber_current();
790 RB_OBJ_WRITE(obj, &e->dst, curr);
791 RB_OBJ_WRITE(obj, &e->fib, rb_fiber_new(next_i, obj));
792 e->lookahead = Qundef;
793}
794
795static VALUE
796get_next_values(VALUE obj, struct enumerator *e)
797{
798 VALUE curr, vs;
799
800 if (e->stop_exc) {
801 VALUE exc = e->stop_exc;
802 VALUE result = rb_attr_get(exc, id_result);
803 VALUE mesg = rb_attr_get(exc, idMesg);
804 if (!NIL_P(mesg)) mesg = rb_str_dup(mesg);
805 VALUE stop_exc = rb_exc_new_str(rb_eStopIteration, mesg);
806 rb_ivar_set(stop_exc, id_cause, exc);
807 rb_ivar_set(stop_exc, id_result, result);
808 rb_exc_raise(stop_exc);
809 }
810
811 curr = rb_fiber_current();
812
813 if (!e->fib || !rb_fiber_alive_p(e->fib)) {
814 next_init(obj, e);
815 }
816
817 vs = rb_fiber_resume(e->fib, 1, &curr);
818 if (e->stop_exc) {
819 e->fib = 0;
820 e->dst = Qnil;
821 e->lookahead = Qundef;
822 e->feedvalue = Qundef;
823 rb_exc_raise(e->stop_exc);
824 }
825 return vs;
826}
827
828/*
829 * call-seq:
830 * e.next_values -> array
831 *
832 * Returns the next object as an array in the enumerator, and move the
833 * internal position forward. When the position reached at the end,
834 * StopIteration is raised.
835 *
836 * See class-level notes about external iterators.
837 *
838 * This method can be used to distinguish <code>yield</code> and <code>yield
839 * nil</code>.
840 *
841 * === Example
842 *
843 * o = Object.new
844 * def o.each
845 * yield
846 * yield 1
847 * yield 1, 2
848 * yield nil
849 * yield [1, 2]
850 * end
851 * e = o.to_enum
852 * p e.next_values
853 * p e.next_values
854 * p e.next_values
855 * p e.next_values
856 * p e.next_values
857 * e = o.to_enum
858 * p e.next
859 * p e.next
860 * p e.next
861 * p e.next
862 * p e.next
863 *
864 * ## yield args next_values next
865 * # yield [] nil
866 * # yield 1 [1] 1
867 * # yield 1, 2 [1, 2] [1, 2]
868 * # yield nil [nil] nil
869 * # yield [1, 2] [[1, 2]] [1, 2]
870 *
871 */
872
873static VALUE
874enumerator_next_values(VALUE obj)
875{
876 struct enumerator *e = enumerator_ptr(obj);
877 VALUE vs;
878
879 rb_check_frozen(obj);
880
881 if (!UNDEF_P(e->lookahead)) {
882 vs = e->lookahead;
883 e->lookahead = Qundef;
884 return vs;
885 }
886
887 return get_next_values(obj, e);
888}
889
890static VALUE
891ary2sv(VALUE args, int dup)
892{
893 if (!RB_TYPE_P(args, T_ARRAY))
894 return args;
895
896 switch (RARRAY_LEN(args)) {
897 case 0:
898 return Qnil;
899
900 case 1:
901 return RARRAY_AREF(args, 0);
902
903 default:
904 if (dup)
905 return rb_ary_dup(args);
906 return args;
907 }
908}
909
910/*
911 * call-seq:
912 * e.next -> object
913 *
914 * Returns the next object in the enumerator, and move the internal position
915 * forward. When the position reached at the end, StopIteration is raised.
916 *
917 * === Example
918 *
919 * a = [1,2,3]
920 * e = a.to_enum
921 * p e.next #=> 1
922 * p e.next #=> 2
923 * p e.next #=> 3
924 * p e.next #raises StopIteration
925 *
926 * See class-level notes about external iterators.
927 *
928 */
929
930static VALUE
931enumerator_next(VALUE obj)
932{
933 VALUE vs = enumerator_next_values(obj);
934 return ary2sv(vs, 0);
935}
936
937static VALUE
938enumerator_peek_values(VALUE obj)
939{
940 struct enumerator *e = enumerator_ptr(obj);
941
942 rb_check_frozen(obj);
943
944 if (UNDEF_P(e->lookahead)) {
945 RB_OBJ_WRITE(obj, &e->lookahead, get_next_values(obj, e));
946 }
947
948 return e->lookahead;
949}
950
951/*
952 * call-seq:
953 * e.peek_values -> array
954 *
955 * Returns the next object as an array, similar to Enumerator#next_values, but
956 * doesn't move the internal position forward. If the position is already at
957 * the end, StopIteration is raised.
958 *
959 * See class-level notes about external iterators.
960 *
961 * === Example
962 *
963 * o = Object.new
964 * def o.each
965 * yield
966 * yield 1
967 * yield 1, 2
968 * end
969 * e = o.to_enum
970 * p e.peek_values #=> []
971 * e.next
972 * p e.peek_values #=> [1]
973 * p e.peek_values #=> [1]
974 * e.next
975 * p e.peek_values #=> [1, 2]
976 * e.next
977 * p e.peek_values # raises StopIteration
978 *
979 */
980
981static VALUE
982enumerator_peek_values_m(VALUE obj)
983{
984 return rb_ary_dup(enumerator_peek_values(obj));
985}
986
987/*
988 * call-seq:
989 * e.peek -> object
990 *
991 * Returns the next object in the enumerator, but doesn't move the internal
992 * position forward. If the position is already at the end, StopIteration
993 * is raised.
994 *
995 * See class-level notes about external iterators.
996 *
997 * === Example
998 *
999 * a = [1,2,3]
1000 * e = a.to_enum
1001 * p e.next #=> 1
1002 * p e.peek #=> 2
1003 * p e.peek #=> 2
1004 * p e.peek #=> 2
1005 * p e.next #=> 2
1006 * p e.next #=> 3
1007 * p e.peek #raises StopIteration
1008 *
1009 */
1010
1011static VALUE
1012enumerator_peek(VALUE obj)
1013{
1014 VALUE vs = enumerator_peek_values(obj);
1015 return ary2sv(vs, 1);
1016}
1017
1018/*
1019 * call-seq:
1020 * e.feed obj -> nil
1021 *
1022 * Sets the value to be returned by the next yield inside +e+.
1023 *
1024 * If the value is not set, the yield returns nil.
1025 *
1026 * This value is cleared after being yielded.
1027 *
1028 * # Array#map passes the array's elements to "yield" and collects the
1029 * # results of "yield" as an array.
1030 * # Following example shows that "next" returns the passed elements and
1031 * # values passed to "feed" are collected as an array which can be
1032 * # obtained by StopIteration#result.
1033 * e = [1,2,3].map
1034 * p e.next #=> 1
1035 * e.feed "a"
1036 * p e.next #=> 2
1037 * e.feed "b"
1038 * p e.next #=> 3
1039 * e.feed "c"
1040 * begin
1041 * e.next
1042 * rescue StopIteration
1043 * p $!.result #=> ["a", "b", "c"]
1044 * end
1045 *
1046 * o = Object.new
1047 * def o.each
1048 * x = yield # (2) blocks
1049 * p x # (5) => "foo"
1050 * x = yield # (6) blocks
1051 * p x # (8) => nil
1052 * x = yield # (9) blocks
1053 * p x # not reached w/o another e.next
1054 * end
1055 *
1056 * e = o.to_enum
1057 * e.next # (1)
1058 * e.feed "foo" # (3)
1059 * e.next # (4)
1060 * e.next # (7)
1061 * # (10)
1062 */
1063
1064static VALUE
1065enumerator_feed(VALUE obj, VALUE v)
1066{
1067 struct enumerator *e = enumerator_ptr(obj);
1068
1069 rb_check_frozen(obj);
1070
1071 if (!UNDEF_P(e->feedvalue)) {
1072 rb_raise(rb_eTypeError, "feed value already set");
1073 }
1074 RB_OBJ_WRITE(obj, &e->feedvalue, v);
1075
1076 return Qnil;
1077}
1078
1079/*
1080 * call-seq:
1081 * e.rewind -> e
1082 *
1083 * Rewinds the enumeration sequence to the beginning.
1084 *
1085 * If the enclosed object responds to a "rewind" method, it is called.
1086 */
1087
1088static VALUE
1089enumerator_rewind(VALUE obj)
1090{
1091 struct enumerator *e = enumerator_ptr(obj);
1092
1093 rb_check_frozen(obj);
1094
1095 rb_check_funcall(e->obj, id_rewind, 0, 0);
1096
1097 e->fib = 0;
1098 e->dst = Qnil;
1099 e->lookahead = Qundef;
1100 e->feedvalue = Qundef;
1101 e->stop_exc = Qfalse;
1102 return obj;
1103}
1104
1105static struct generator *generator_ptr(VALUE obj);
1106static VALUE append_method(VALUE obj, VALUE str, ID default_method, VALUE default_args);
1107static VALUE append_method_args(VALUE obj, VALUE str, VALUE default_args);
1108
1109static VALUE
1110inspect_enumerator(VALUE obj, VALUE dummy, int recur)
1111{
1112 struct enumerator *e;
1113 VALUE eobj, str, cname;
1114
1115 TypedData_Get_Struct(obj, struct enumerator, &enumerator_data_type, e);
1116
1117 cname = rb_obj_class(obj);
1118
1119 if (!e || UNDEF_P(e->obj)) {
1120 return rb_sprintf("#<%"PRIsVALUE": uninitialized>", rb_class_path(cname));
1121 }
1122
1123 if (recur) {
1124 str = rb_sprintf("#<%"PRIsVALUE": ...>", rb_class_path(cname));
1125 return str;
1126 }
1127
1128 if (e->procs) {
1129 long i;
1130
1131 eobj = generator_ptr(e->obj)->obj;
1132 /* In case procs chained enumerator traversing all proc entries manually */
1133 if (rb_obj_class(eobj) == cname) {
1134 str = rb_inspect(eobj);
1135 }
1136 else {
1137 str = rb_sprintf("#<%"PRIsVALUE": %+"PRIsVALUE">", rb_class_path(cname), eobj);
1138 }
1139 for (i = 0; i < RARRAY_LEN(e->procs); i++) {
1140 str = rb_sprintf("#<%"PRIsVALUE": %"PRIsVALUE, cname, str);
1141 append_method(RARRAY_AREF(e->procs, i), str, e->meth, e->args);
1142 rb_str_buf_cat2(str, ">");
1143 }
1144 return str;
1145 }
1146
1147 eobj = rb_attr_get(obj, id_receiver);
1148 if (NIL_P(eobj)) {
1149 eobj = e->obj;
1150 }
1151
1152 /* (1..100).each_cons(2) => "#<Enumerator: 1..100:each_cons(2)>" */
1153 str = rb_sprintf("#<%"PRIsVALUE": %+"PRIsVALUE, rb_class_path(cname), eobj);
1154 append_method(obj, str, e->meth, e->args);
1155
1156 rb_str_buf_cat2(str, ">");
1157
1158 return str;
1159}
1160
1161static int
1162key_symbol_p(VALUE key, VALUE val, VALUE arg)
1163{
1164 if (SYMBOL_P(key)) return ST_CONTINUE;
1165 *(int *)arg = FALSE;
1166 return ST_STOP;
1167}
1168
1169static int
1170kwd_append(VALUE key, VALUE val, VALUE str)
1171{
1172 if (!SYMBOL_P(key)) rb_raise(rb_eRuntimeError, "non-symbol key inserted");
1173 rb_str_catf(str, "% "PRIsVALUE": %"PRIsVALUE", ", key, val);
1174 return ST_CONTINUE;
1175}
1176
1177static VALUE
1178append_method(VALUE obj, VALUE str, ID default_method, VALUE default_args)
1179{
1180 VALUE method;
1181
1182 method = rb_attr_get(obj, id_method);
1183 if (method != Qfalse) {
1184 if (!NIL_P(method)) {
1185 Check_Type(method, T_SYMBOL);
1186 method = rb_sym2str(method);
1187 }
1188 else {
1189 method = rb_id2str(default_method);
1190 }
1191 rb_str_buf_cat2(str, ":");
1192 rb_str_buf_append(str, method);
1193 }
1194 return append_method_args(obj, str, default_args);
1195}
1196
1197static VALUE
1198append_method_args(VALUE obj, VALUE str, VALUE default_args)
1199{
1200 VALUE eargs;
1201
1202 eargs = rb_attr_get(obj, id_arguments);
1203 if (NIL_P(eargs)) {
1204 eargs = default_args;
1205 }
1206 if (eargs != Qfalse) {
1207 long argc = RARRAY_LEN(eargs);
1208 const VALUE *argv = RARRAY_CONST_PTR(eargs); /* WB: no new reference */
1209
1210 if (argc > 0) {
1211 VALUE kwds = Qnil;
1212
1213 rb_str_buf_cat2(str, "(");
1214
1215 if (RB_TYPE_P(argv[argc-1], T_HASH) && !RHASH_EMPTY_P(argv[argc-1])) {
1216 int all_key = TRUE;
1217 rb_hash_foreach(argv[argc-1], key_symbol_p, (VALUE)&all_key);
1218 if (all_key) kwds = argv[--argc];
1219 }
1220
1221 while (argc--) {
1222 VALUE arg = *argv++;
1223
1224 rb_str_append(str, rb_inspect(arg));
1225 rb_str_buf_cat2(str, ", ");
1226 }
1227 if (!NIL_P(kwds)) {
1228 rb_hash_foreach(kwds, kwd_append, str);
1229 }
1230 rb_str_set_len(str, RSTRING_LEN(str)-2); /* drop the last ", " */
1231 rb_str_buf_cat2(str, ")");
1232 }
1233 }
1234 RB_GC_GUARD(eargs);
1235
1236 return str;
1237}
1238
1239/*
1240 * call-seq:
1241 * e.inspect -> string
1242 *
1243 * Creates a printable version of <i>e</i>.
1244 */
1245
1246static VALUE
1247enumerator_inspect(VALUE obj)
1248{
1249 return rb_exec_recursive(inspect_enumerator, obj, 0);
1250}
1251
1252/*
1253 * call-seq:
1254 * e.size -> int, Float::INFINITY or nil
1255 *
1256 * Returns the size of the enumerator, or +nil+ if it can't be calculated lazily.
1257 *
1258 * (1..100).to_a.permutation(4).size # => 94109400
1259 * loop.size # => Float::INFINITY
1260 * (1..100).drop_while.size # => nil
1261 *
1262 * Note that enumerator size might be inaccurate, and should be rather treated as a hint.
1263 * For example, there is no check that the size provided to ::new is accurate:
1264 *
1265 * e = Enumerator.new(5) { |y| 2.times { y << it} }
1266 * e.size # => 5
1267 * e.to_a.size # => 2
1268 *
1269 * Another example is an enumerator created by ::produce without a +size+ argument.
1270 * Such enumerators return +Infinity+ for size, but this is inaccurate if the passed
1271 * block raises StopIteration:
1272 *
1273 * e = Enumerator.produce(1) { it + 1 }
1274 * e.size # => Infinity
1275 *
1276 * e = Enumerator.produce(1) { it > 3 ? raise(StopIteration) : it + 1 }
1277 * e.size # => Infinity
1278 * e.to_a.size # => 4
1279 */
1280
1281static VALUE
1282enumerator_size(VALUE obj)
1283{
1284 struct enumerator *e = enumerator_ptr(obj);
1285 int argc = 0;
1286 const VALUE *argv = NULL;
1287 VALUE size;
1288
1289 if (e->procs) {
1290 struct generator *g = generator_ptr(e->obj);
1291 VALUE receiver = rb_check_funcall(g->obj, id_size, 0, 0);
1292 long i = 0;
1293
1294 for (i = 0; i < RARRAY_LEN(e->procs); i++) {
1295 VALUE proc = RARRAY_AREF(e->procs, i);
1296 struct proc_entry *entry = proc_entry_ptr(proc);
1297 lazyenum_size_func *size_fn = entry->fn->size;
1298 if (!size_fn) {
1299 return Qnil;
1300 }
1301 receiver = (*size_fn)(proc, receiver);
1302 }
1303 return receiver;
1304 }
1305
1306 if (e->size_fn) {
1307 return (*e->size_fn)(e->obj, e->args, obj);
1308 }
1309 if (e->args) {
1310 argc = (int)RARRAY_LEN(e->args);
1311 argv = RARRAY_CONST_PTR(e->args);
1312 }
1313 size = rb_check_funcall_kw(e->size, id_call, argc, argv, e->kw_splat);
1314 if (!UNDEF_P(size)) return size;
1315 return e->size;
1316}
1317
1318/*
1319 * Yielder
1320 */
1321static void
1322yielder_mark_and_move(void *p)
1323{
1324 struct yielder *ptr = p;
1325 rb_gc_mark_and_move(&ptr->proc);
1326}
1327
1328static const rb_data_type_t yielder_data_type = {
1329 "yielder",
1330 {
1331 yielder_mark_and_move,
1333 NULL,
1334 yielder_mark_and_move,
1335 },
1336 0, 0, RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
1337};
1338
1339static struct yielder *
1340yielder_ptr(VALUE obj)
1341{
1342 struct yielder *ptr;
1343
1344 TypedData_Get_Struct(obj, struct yielder, &yielder_data_type, ptr);
1345 if (!ptr || UNDEF_P(ptr->proc)) {
1346 rb_raise(rb_eArgError, "uninitialized yielder");
1347 }
1348 return ptr;
1349}
1350
1351/* :nodoc: */
1352static VALUE
1353yielder_allocate(VALUE klass)
1354{
1355 struct yielder *ptr;
1356 VALUE obj;
1357
1358 obj = TypedData_Make_Struct(klass, struct yielder, &yielder_data_type, ptr);
1359 ptr->proc = Qundef;
1360
1361 return obj;
1362}
1363
1364static VALUE
1365yielder_init(VALUE obj, VALUE proc)
1366{
1367 struct yielder *ptr;
1368
1369 TypedData_Get_Struct(obj, struct yielder, &yielder_data_type, ptr);
1370
1371 if (!ptr) {
1372 rb_raise(rb_eArgError, "unallocated yielder");
1373 }
1374
1375 RB_OBJ_WRITE(obj, &ptr->proc, proc);
1376
1377 return obj;
1378}
1379
1380/* :nodoc: */
1381static VALUE
1382yielder_initialize(VALUE obj)
1383{
1384 rb_need_block();
1385
1386 return yielder_init(obj, rb_block_proc());
1387}
1388
1389/* :nodoc: */
1390static VALUE
1391yielder_yield(VALUE obj, VALUE args)
1392{
1393 struct yielder *ptr = yielder_ptr(obj);
1394
1395 return rb_proc_call_kw(ptr->proc, args, RB_PASS_CALLED_KEYWORDS);
1396}
1397
1398/* :nodoc: */
1399static VALUE
1400yielder_yield_push(VALUE obj, VALUE arg)
1401{
1402 struct yielder *ptr = yielder_ptr(obj);
1403
1404 rb_proc_call_with_block(ptr->proc, 1, &arg, Qnil);
1405
1406 return obj;
1407}
1408
1409/*
1410 * Returns a Proc object that takes arguments and yields them.
1411 *
1412 * This method is implemented so that a Yielder object can be directly
1413 * passed to another method as a block argument.
1414 *
1415 * enum = Enumerator.new { |y|
1416 * Dir.glob("*.rb") { |file|
1417 * File.open(file) { |f| f.each_line(&y) }
1418 * }
1419 * }
1420 */
1421static VALUE
1422yielder_to_proc(VALUE obj)
1423{
1424 VALUE method = rb_obj_method(obj, sym_yield);
1425
1426 return rb_funcall(method, idTo_proc, 0);
1427}
1428
1429static VALUE
1430yielder_yield_i(RB_BLOCK_CALL_FUNC_ARGLIST(obj, memo))
1431{
1432 return rb_yield_values_kw(argc, argv, RB_PASS_CALLED_KEYWORDS);
1433}
1434
1435static VALUE
1436yielder_new(void)
1437{
1438 return yielder_init(yielder_allocate(rb_cYielder), rb_proc_new(yielder_yield_i, 0));
1439}
1440
1441/*
1442 * Generator
1443 */
1444static void
1445generator_mark_and_move(void *p)
1446{
1447 struct generator *ptr = p;
1448 rb_gc_mark_and_move(&ptr->proc);
1449 rb_gc_mark_and_move(&ptr->obj);
1450}
1451
1452static const rb_data_type_t generator_data_type = {
1453 "generator",
1454 {
1455 generator_mark_and_move,
1457 NULL,
1458 generator_mark_and_move,
1459 },
1460 0, 0, RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
1461};
1462
1463static struct generator *
1464generator_ptr(VALUE obj)
1465{
1466 struct generator *ptr;
1467
1468 TypedData_Get_Struct(obj, struct generator, &generator_data_type, ptr);
1469 if (!ptr || UNDEF_P(ptr->proc)) {
1470 rb_raise(rb_eArgError, "uninitialized generator");
1471 }
1472 return ptr;
1473}
1474
1475/* :nodoc: */
1476static VALUE
1477generator_allocate(VALUE klass)
1478{
1479 struct generator *ptr;
1480 VALUE obj;
1481
1482 obj = TypedData_Make_Struct(klass, struct generator, &generator_data_type, ptr);
1483 ptr->proc = Qundef;
1484
1485 return obj;
1486}
1487
1488static VALUE
1489generator_init(VALUE obj, VALUE proc)
1490{
1491 struct generator *ptr;
1492
1493 rb_check_frozen(obj);
1494 TypedData_Get_Struct(obj, struct generator, &generator_data_type, ptr);
1495
1496 if (!ptr) {
1497 rb_raise(rb_eArgError, "unallocated generator");
1498 }
1499
1500 RB_OBJ_WRITE(obj, &ptr->proc, proc);
1501
1502 return obj;
1503}
1504
1505/* :nodoc: */
1506static VALUE
1507generator_initialize(int argc, VALUE *argv, VALUE obj)
1508{
1509 VALUE proc;
1510
1511 if (argc == 0) {
1512 rb_need_block();
1513
1514 proc = rb_block_proc();
1515 }
1516 else {
1517 rb_scan_args(argc, argv, "1", &proc);
1518
1519 if (!rb_obj_is_proc(proc))
1520 rb_raise(rb_eTypeError,
1521 "wrong argument type %"PRIsVALUE" (expected Proc)",
1522 rb_obj_class(proc));
1523
1524 if (rb_block_given_p()) {
1525 rb_warn("given block not used");
1526 }
1527 }
1528
1529 return generator_init(obj, proc);
1530}
1531
1532/* :nodoc: */
1533static VALUE
1534generator_init_copy(VALUE obj, VALUE orig)
1535{
1536 struct generator *ptr0, *ptr1;
1537
1538 if (!OBJ_INIT_COPY(obj, orig)) return obj;
1539
1540 ptr0 = generator_ptr(orig);
1541
1542 TypedData_Get_Struct(obj, struct generator, &generator_data_type, ptr1);
1543
1544 if (!ptr1) {
1545 rb_raise(rb_eArgError, "unallocated generator");
1546 }
1547
1548 RB_OBJ_WRITE(obj, &ptr1->proc, ptr0->proc);
1549
1550 return obj;
1551}
1552
1553/* :nodoc: */
1554static VALUE
1555generator_each(int argc, VALUE *argv, VALUE obj)
1556{
1557 struct generator *ptr = generator_ptr(obj);
1558 VALUE args = rb_ary_new2(argc + 1);
1559
1560 rb_ary_push(args, yielder_new());
1561 if (argc > 0) {
1562 rb_ary_cat(args, argv, argc);
1563 }
1564
1565 return rb_proc_call_kw(ptr->proc, args, RB_PASS_CALLED_KEYWORDS);
1566}
1567
1568/* Lazy Enumerator methods */
1569static VALUE
1570enum_size(VALUE self)
1571{
1572 VALUE r = rb_check_funcall(self, id_size, 0, 0);
1573 return UNDEF_P(r) ? Qnil : r;
1574}
1575
1576static VALUE
1577lazyenum_size(VALUE self, VALUE args, VALUE eobj)
1578{
1579 return enum_size(self);
1580}
1581
1582#define lazy_receiver_size lazy_map_size
1583
1584static VALUE
1585lazy_init_iterator(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
1586{
1587 VALUE result;
1588 if (argc == 1) {
1589 VALUE args[2];
1590 args[0] = m;
1591 args[1] = val;
1592 result = rb_yield_values2(2, args);
1593 }
1594 else {
1595 VALUE args;
1596 int len = rb_long2int((long)argc + 1);
1597 VALUE *nargv = ALLOCV_N(VALUE, args, len);
1598
1599 nargv[0] = m;
1600 if (argc > 0) {
1601 MEMCPY(nargv + 1, argv, VALUE, argc);
1602 }
1603 result = rb_yield_values2(len, nargv);
1604 ALLOCV_END(args);
1605 }
1606 if (UNDEF_P(result)) rb_iter_break();
1607 return Qnil;
1608}
1609
1610static VALUE
1611lazy_init_block_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
1612{
1613 rb_block_call(m, id_each, argc-1, argv+1, lazy_init_iterator, val);
1614 return Qnil;
1615}
1616
1617#define memo_value v2
1618#define memo_flags u3.state
1619#define LAZY_MEMO_BREAK 1
1620#define LAZY_MEMO_PACKED 2
1621#define LAZY_MEMO_BREAK_P(memo) ((memo)->memo_flags & LAZY_MEMO_BREAK)
1622#define LAZY_MEMO_PACKED_P(memo) ((memo)->memo_flags & LAZY_MEMO_PACKED)
1623#define LAZY_MEMO_SET_BREAK(memo) ((memo)->memo_flags |= LAZY_MEMO_BREAK)
1624#define LAZY_MEMO_RESET_BREAK(memo) ((memo)->memo_flags &= ~LAZY_MEMO_BREAK)
1625#define LAZY_MEMO_SET_VALUE(memo, value) MEMO_V2_SET(memo, value)
1626#define LAZY_MEMO_SET_PACKED(memo) ((memo)->memo_flags |= LAZY_MEMO_PACKED)
1627#define LAZY_MEMO_RESET_PACKED(memo) ((memo)->memo_flags &= ~LAZY_MEMO_PACKED)
1628
1629#define LAZY_NEED_BLOCK(func) \
1630 if (!rb_block_given_p()) { \
1631 rb_raise(rb_eArgError, "tried to call lazy " #func " without a block"); \
1632 }
1633
1634static VALUE lazy_yielder_result(struct MEMO *result, VALUE yielder, VALUE procs_array, VALUE memos, long i);
1635
1636static VALUE
1637lazy_init_yielder(RB_BLOCK_CALL_FUNC_ARGLIST(_, m))
1638{
1639 VALUE yielder = RARRAY_AREF(m, 0);
1640 VALUE procs_array = RARRAY_AREF(m, 1);
1641 VALUE memos = rb_attr_get(yielder, id_memo);
1642 struct MEMO *result;
1643
1644 result = rb_imemo_memo_new(m, rb_enum_values_pack(argc, argv),
1645 argc > 1 ? LAZY_MEMO_PACKED : 0);
1646 return lazy_yielder_result(result, yielder, procs_array, memos, 0);
1647}
1648
1649static VALUE
1650lazy_yielder_yield(struct MEMO *result, long memo_index, int argc, const VALUE *argv)
1651{
1652 VALUE m = result->v1;
1653 VALUE yielder = RARRAY_AREF(m, 0);
1654 VALUE procs_array = RARRAY_AREF(m, 1);
1655 VALUE memos = rb_attr_get(yielder, id_memo);
1656 LAZY_MEMO_SET_VALUE(result, rb_enum_values_pack(argc, argv));
1657 if (argc > 1)
1658 LAZY_MEMO_SET_PACKED(result);
1659 else
1660 LAZY_MEMO_RESET_PACKED(result);
1661 return lazy_yielder_result(result, yielder, procs_array, memos, memo_index);
1662}
1663
1664static VALUE
1665lazy_yielder_result(struct MEMO *result, VALUE yielder, VALUE procs_array, VALUE memos, long i)
1666{
1667 int cont = 1;
1668
1669 for (; i < RARRAY_LEN(procs_array); i++) {
1670 VALUE proc = RARRAY_AREF(procs_array, i);
1671 struct proc_entry *entry = proc_entry_ptr(proc);
1672 if (!(*entry->fn->proc)(proc, result, memos, i)) {
1673 cont = 0;
1674 break;
1675 }
1676 }
1677
1678 if (cont) {
1679 rb_funcall2(yielder, idLTLT, 1, &(result->memo_value));
1680 }
1681 if (LAZY_MEMO_BREAK_P(result)) {
1682 rb_iter_break();
1683 }
1684 return result->memo_value;
1685}
1686
1687static VALUE
1688lazy_init_block(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
1689{
1690 VALUE procs = RARRAY_AREF(m, 1);
1691
1692 rb_ivar_set(val, id_memo, rb_ary_new2(RARRAY_LEN(procs)));
1693 rb_block_call(RARRAY_AREF(m, 0), id_each, 0, 0,
1694 lazy_init_yielder, rb_ary_new3(2, val, procs));
1695 return Qnil;
1696}
1697
1698static VALUE
1699lazy_generator_init(VALUE enumerator, VALUE procs)
1700{
1702 VALUE obj;
1703 struct generator *gen_ptr;
1704 struct enumerator *e = enumerator_ptr(enumerator);
1705
1706 if (RARRAY_LEN(procs) > 0) {
1707 struct generator *old_gen_ptr = generator_ptr(e->obj);
1708 obj = old_gen_ptr->obj;
1709 }
1710 else {
1711 obj = enumerator;
1712 }
1713
1714 generator = generator_allocate(rb_cGenerator);
1715
1716 rb_block_call(generator, id_initialize, 0, 0,
1717 lazy_init_block, rb_ary_new3(2, obj, procs));
1718
1719 gen_ptr = generator_ptr(generator);
1720 RB_OBJ_WRITE(generator, &gen_ptr->obj, obj);
1721
1722 return generator;
1723}
1724
1725static int
1726lazy_precheck(VALUE procs)
1727{
1728 if (RTEST(procs)) {
1729 long num_procs = RARRAY_LEN(procs), i = num_procs;
1730 while (i-- > 0) {
1731 VALUE proc = RARRAY_AREF(procs, i);
1732 struct proc_entry *entry = proc_entry_ptr(proc);
1733 lazyenum_precheck_func *precheck = entry->fn->precheck;
1734 if (precheck && !precheck(proc)) return FALSE;
1735 }
1736 }
1737
1738 return TRUE;
1739}
1740
1741/*
1742 * Document-class: Enumerator::Lazy
1743 *
1744 * Enumerator::Lazy is a special type of Enumerator, that allows constructing
1745 * chains of operations without evaluating them immediately, and evaluating
1746 * values on as-needed basis. In order to do so it redefines most of Enumerable
1747 * methods so that they just construct another lazy enumerator.
1748 *
1749 * Enumerator::Lazy can be constructed from any Enumerable with the
1750 * Enumerable#lazy method.
1751 *
1752 * lazy = (1..Float::INFINITY).lazy.select(&:odd?).drop(10).take_while { |i| i < 30 }
1753 * # => #<Enumerator::Lazy: #<Enumerator::Lazy: #<Enumerator::Lazy: #<Enumerator::Lazy: 1..Infinity>:select>:drop(10)>:take_while>
1754 *
1755 * The real enumeration is performed when any non-redefined Enumerable method
1756 * is called, like Enumerable#first or Enumerable#to_a (the latter is aliased
1757 * as #force for more semantic code):
1758 *
1759 * lazy.first(2)
1760 * #=> [21, 23]
1761 *
1762 * lazy.force
1763 * #=> [21, 23, 25, 27, 29]
1764 *
1765 * Note that most Enumerable methods that could be called with or without
1766 * a block, on Enumerator::Lazy will always require a block:
1767 *
1768 * [1, 2, 3].map #=> #<Enumerator: [1, 2, 3]:map>
1769 * [1, 2, 3].lazy.map # ArgumentError: tried to call lazy map without a block
1770 *
1771 * This class allows idiomatic calculations on long or infinite sequences, as well
1772 * as chaining of calculations without constructing intermediate arrays.
1773 *
1774 * Example for working with a slowly calculated sequence:
1775 *
1776 * require 'open-uri'
1777 *
1778 * # This will fetch all URLs before selecting
1779 * # necessary data
1780 * URLS.map { |u| JSON.parse(URI.open(u).read) }
1781 * .select { |data| data.key?('stats') }
1782 * .first(5)
1783 *
1784 * # This will fetch URLs one-by-one, only till
1785 * # there is enough data to satisfy the condition
1786 * URLS.lazy.map { |u| JSON.parse(URI.open(u).read) }
1787 * .select { |data| data.key?('stats') }
1788 * .first(5)
1789 *
1790 * Ending a chain with ".eager" generates a non-lazy enumerator, which
1791 * is suitable for returning or passing to another method that expects
1792 * a normal enumerator.
1793 *
1794 * def active_items
1795 * groups
1796 * .lazy
1797 * .flat_map(&:items)
1798 * .reject(&:disabled)
1799 * .eager
1800 * end
1801 *
1802 * # This works lazily; if a checked item is found, it stops
1803 * # iteration and does not look into remaining groups.
1804 * first_checked = active_items.find(&:checked)
1805 *
1806 * # This returns an array of items like a normal enumerator does.
1807 * all_checked = active_items.select(&:checked)
1808 *
1809 */
1810
1811/*
1812 * call-seq:
1813 * Lazy.new(obj, size=nil) { |yielder, *values| block }
1814 *
1815 * Creates a new Lazy enumerator. When the enumerator is actually enumerated
1816 * (e.g. by calling #force), +obj+ will be enumerated and each value passed
1817 * to the given block. The block can yield values back using +yielder+.
1818 * For example, to create a "filter+map" enumerator:
1819 *
1820 * def filter_map(sequence)
1821 * Lazy.new(sequence) do |yielder, *values|
1822 * result = yield *values
1823 * yielder << result if result
1824 * end
1825 * end
1826 *
1827 * filter_map(1..Float::INFINITY) {|i| i*i if i.even?}.first(5)
1828 * #=> [4, 16, 36, 64, 100]
1829 */
1830static VALUE
1831lazy_initialize(int argc, VALUE *argv, VALUE self)
1832{
1833 VALUE obj, size = Qnil;
1835
1836 rb_check_arity(argc, 1, 2);
1837 LAZY_NEED_BLOCK(new);
1838 obj = argv[0];
1839 if (argc > 1) {
1840 size = argv[1];
1841 }
1842 generator = generator_allocate(rb_cGenerator);
1843 rb_block_call(generator, id_initialize, 0, 0, lazy_init_block_i, obj);
1844 enumerator_init(self, generator, sym_each, 0, 0, 0, size, 0);
1845 rb_ivar_set(self, id_receiver, obj);
1846
1847 return self;
1848}
1849
1850#if 0 /* for RDoc */
1851/*
1852 * call-seq:
1853 * lazy.to_a -> array
1854 * lazy.force -> array
1855 *
1856 * Expands +lazy+ enumerator to an array.
1857 * See Enumerable#to_a.
1858 */
1859static VALUE
1860lazy_to_a(VALUE self)
1861{
1862}
1863#endif
1864
1865static void
1866lazy_set_args(VALUE lazy, VALUE args)
1867{
1868 ID id = rb_frame_this_func();
1869 rb_ivar_set(lazy, id_method, ID2SYM(id));
1870 if (NIL_P(args)) {
1871 /* Qfalse indicates that the arguments are empty */
1872 rb_ivar_set(lazy, id_arguments, Qfalse);
1873 }
1874 else {
1875 rb_ivar_set(lazy, id_arguments, args);
1876 }
1877}
1878
1879#if 0
1880static VALUE
1881lazy_set_method(VALUE lazy, VALUE args, rb_enumerator_size_func *size_fn)
1882{
1883 struct enumerator *e = enumerator_ptr(lazy);
1884 lazy_set_args(lazy, args);
1885 e->size_fn = size_fn;
1886 return lazy;
1887}
1888#endif
1889
1890static VALUE
1891lazy_add_method(VALUE obj, int argc, VALUE *argv, VALUE args, VALUE memo,
1892 const lazyenum_funcs *fn)
1893{
1894 struct enumerator *new_e;
1895 VALUE new_obj;
1896 VALUE new_generator;
1897 VALUE new_procs;
1898 struct enumerator *e = enumerator_ptr(obj);
1899 struct proc_entry *entry;
1901 &proc_entry_data_type, entry);
1902 if (rb_block_given_p()) {
1903 RB_OBJ_WRITE(entry_obj, &entry->proc, rb_block_proc());
1904 }
1905 entry->fn = fn;
1906 RB_OBJ_WRITE(entry_obj, &entry->memo, args);
1907
1908 lazy_set_args(entry_obj, memo);
1909
1910 new_procs = RTEST(e->procs) ? rb_ary_dup(e->procs) : rb_ary_new();
1911 new_generator = lazy_generator_init(obj, new_procs);
1912 rb_ary_push(new_procs, entry_obj);
1913
1914 new_obj = enumerator_init_copy(enumerator_allocate(rb_cLazy), obj);
1915 new_e = RTYPEDDATA_GET_DATA(new_obj);
1916 RB_OBJ_WRITE(new_obj, &new_e->obj, new_generator);
1917 RB_OBJ_WRITE(new_obj, &new_e->procs, new_procs);
1918
1919 if (argc > 0) {
1920 new_e->meth = rb_to_id(*argv++);
1921 --argc;
1922 }
1923 else {
1924 new_e->meth = id_each;
1925 }
1926
1927 RB_OBJ_WRITE(new_obj, &new_e->args, rb_ary_new4(argc, argv));
1928
1929 return new_obj;
1930}
1931
1932/*
1933 * call-seq:
1934 * e.lazy -> lazy_enumerator
1935 *
1936 * Returns an Enumerator::Lazy, which redefines most Enumerable
1937 * methods to postpone enumeration and enumerate values only on an
1938 * as-needed basis.
1939 *
1940 * === Example
1941 *
1942 * The following program finds pythagorean triples:
1943 *
1944 * def pythagorean_triples
1945 * (1..Float::INFINITY).lazy.flat_map {|z|
1946 * (1..z).flat_map {|x|
1947 * (x..z).select {|y|
1948 * x**2 + y**2 == z**2
1949 * }.map {|y|
1950 * [x, y, z]
1951 * }
1952 * }
1953 * }
1954 * end
1955 * # show first ten pythagorean triples
1956 * p pythagorean_triples.take(10).force # take is lazy, so force is needed
1957 * p pythagorean_triples.first(10) # first is eager
1958 * # show pythagorean triples less than 100
1959 * p pythagorean_triples.take_while { |*, z| z < 100 }.force
1960 */
1961static VALUE
1962enumerable_lazy(VALUE obj)
1963{
1964 VALUE result = lazy_to_enum_i(obj, sym_each, 0, 0, lazyenum_size, rb_keyword_given_p());
1965 /* Qfalse indicates that the Enumerator::Lazy has no method name */
1966 rb_ivar_set(result, id_method, Qfalse);
1967 return result;
1968}
1969
1970static VALUE
1971lazy_to_enum_i(VALUE obj, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *size_fn, int kw_splat)
1972{
1973 return enumerator_init(enumerator_allocate(rb_cLazy),
1974 obj, meth, argc, argv, size_fn, Qnil, kw_splat);
1975}
1976
1977/*
1978 * call-seq:
1979 * lzy.to_enum(method = :each, *args) -> lazy_enum
1980 * lzy.enum_for(method = :each, *args) -> lazy_enum
1981 * lzy.to_enum(method = :each, *args) {|*args| block } -> lazy_enum
1982 * lzy.enum_for(method = :each, *args) {|*args| block } -> lazy_enum
1983 *
1984 * Similar to Object#to_enum, except it returns a lazy enumerator.
1985 * This makes it easy to define Enumerable methods that will
1986 * naturally remain lazy if called from a lazy enumerator.
1987 *
1988 * For example, continuing from the example in Object#to_enum:
1989 *
1990 * # See Object#to_enum for the definition of repeat
1991 * r = 1..Float::INFINITY
1992 * r.repeat(2).first(5) # => [1, 1, 2, 2, 3]
1993 * r.repeat(2).class # => Enumerator
1994 * r.repeat(2).map{|n| n ** 2}.first(5) # => endless loop!
1995 * # works naturally on lazy enumerator:
1996 * r.lazy.repeat(2).class # => Enumerator::Lazy
1997 * r.lazy.repeat(2).map{|n| n ** 2}.first(5) # => [1, 1, 4, 4, 9]
1998 */
1999
2000static VALUE
2001lazy_to_enum(int argc, VALUE *argv, VALUE self)
2002{
2003 VALUE lazy, meth = sym_each, super_meth;
2004
2005 if (argc > 0) {
2006 --argc;
2007 meth = rb_to_symbol(*argv++);
2008 }
2009 if (RTEST((super_meth = rb_hash_aref(lazy_use_super_method, meth)))) {
2010 meth = super_meth;
2011 }
2012 lazy = lazy_to_enum_i(self, meth, argc, argv, 0, rb_keyword_given_p());
2013 if (rb_block_given_p()) {
2014 RB_OBJ_WRITE(lazy, &enumerator_ptr(lazy)->size, rb_block_proc());
2015 }
2016 return lazy;
2017}
2018
2019static VALUE
2020lazy_eager_size(VALUE self, VALUE args, VALUE eobj)
2021{
2022 return enum_size(self);
2023}
2024
2025/*
2026 * call-seq:
2027 * lzy.eager -> enum
2028 *
2029 * Returns a non-lazy Enumerator converted from the lazy enumerator.
2030 */
2031
2032static VALUE
2033lazy_eager(VALUE self)
2034{
2035 return enumerator_init(enumerator_allocate(rb_cEnumerator),
2036 self, sym_each, 0, 0, lazy_eager_size, Qnil, 0);
2037}
2038
2039static VALUE
2040lazyenum_yield(VALUE proc_entry, struct MEMO *result)
2041{
2042 struct proc_entry *entry = proc_entry_ptr(proc_entry);
2043 return rb_proc_call_with_block(entry->proc, 1, &result->memo_value, Qnil);
2044}
2045
2046static VALUE
2047lazyenum_yield_values(VALUE proc_entry, struct MEMO *result)
2048{
2049 struct proc_entry *entry = proc_entry_ptr(proc_entry);
2050 int argc = 1;
2051 const VALUE *argv = &result->memo_value;
2052 if (LAZY_MEMO_PACKED_P(result)) {
2053 const VALUE args = *argv;
2054 argc = RARRAY_LENINT(args);
2055 argv = RARRAY_CONST_PTR(args);
2056 }
2057 return rb_proc_call_with_block(entry->proc, argc, argv, Qnil);
2058}
2059
2060static struct MEMO *
2061lazy_map_proc(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_index)
2062{
2063 VALUE value = lazyenum_yield_values(proc_entry, result);
2064 LAZY_MEMO_SET_VALUE(result, value);
2065 LAZY_MEMO_RESET_PACKED(result);
2066 return result;
2067}
2068
2069static VALUE
2070lazy_map_size(VALUE entry, VALUE receiver)
2071{
2072 return receiver;
2073}
2074
2075static const lazyenum_funcs lazy_map_funcs = {
2076 lazy_map_proc, lazy_map_size,
2077};
2078
2079/*
2080 * call-seq:
2081 * lazy.collect { |obj| block } -> lazy_enumerator
2082 * lazy.map { |obj| block } -> lazy_enumerator
2083 *
2084 * Like Enumerable#map, but chains operation to be lazy-evaluated.
2085 *
2086 * (1..Float::INFINITY).lazy.map {|i| i**2 }
2087 * #=> #<Enumerator::Lazy: #<Enumerator::Lazy: 1..Infinity>:map>
2088 * (1..Float::INFINITY).lazy.map {|i| i**2 }.first(3)
2089 * #=> [1, 4, 9]
2090 */
2091
2092static VALUE
2093lazy_map(VALUE obj)
2094{
2095 LAZY_NEED_BLOCK(map);
2096 return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_map_funcs);
2097}
2098
2100 struct MEMO *result;
2101 long index;
2102};
2103
2104static VALUE
2105lazy_flat_map_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, y))
2106{
2107 struct flat_map_i_arg *arg = (struct flat_map_i_arg *)y;
2108
2109 return lazy_yielder_yield(arg->result, arg->index, argc, argv);
2110}
2111
2112static struct MEMO *
2113lazy_flat_map_proc(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_index)
2114{
2115 VALUE value = lazyenum_yield_values(proc_entry, result);
2116 VALUE ary = 0;
2117 const long proc_index = memo_index + 1;
2118 int break_p = LAZY_MEMO_BREAK_P(result);
2119
2120 if (RB_TYPE_P(value, T_ARRAY)) {
2121 ary = value;
2122 }
2123 else if (rb_respond_to(value, id_force) && rb_respond_to(value, id_each)) {
2124 struct flat_map_i_arg arg = {.result = result, .index = proc_index};
2125 LAZY_MEMO_RESET_BREAK(result);
2126 rb_block_call(value, id_each, 0, 0, lazy_flat_map_i, (VALUE)&arg);
2127 if (break_p) LAZY_MEMO_SET_BREAK(result);
2128 return 0;
2129 }
2130
2131 if (ary || !NIL_P(ary = rb_check_array_type(value))) {
2132 long i;
2133 LAZY_MEMO_RESET_BREAK(result);
2134 for (i = 0; i + 1 < RARRAY_LEN(ary); i++) {
2135 const VALUE argv = RARRAY_AREF(ary, i);
2136 lazy_yielder_yield(result, proc_index, 1, &argv);
2137 }
2138 if (break_p) LAZY_MEMO_SET_BREAK(result);
2139 if (i >= RARRAY_LEN(ary)) return 0;
2140 value = RARRAY_AREF(ary, i);
2141 }
2142 LAZY_MEMO_SET_VALUE(result, value);
2143 LAZY_MEMO_RESET_PACKED(result);
2144 return result;
2145}
2146
2147static const lazyenum_funcs lazy_flat_map_funcs = {
2148 lazy_flat_map_proc, 0,
2149};
2150
2151/*
2152 * call-seq:
2153 * lazy.collect_concat { |obj| block } -> a_lazy_enumerator
2154 * lazy.flat_map { |obj| block } -> a_lazy_enumerator
2155 *
2156 * Returns a new lazy enumerator with the concatenated results of running
2157 * +block+ once for every element in the lazy enumerator.
2158 *
2159 * ["foo", "bar"].lazy.flat_map {|i| i.each_char.lazy}.force
2160 * #=> ["f", "o", "o", "b", "a", "r"]
2161 *
2162 * A value +x+ returned by +block+ is decomposed if either of
2163 * the following conditions is true:
2164 *
2165 * * +x+ responds to both each and force, which means that
2166 * +x+ is a lazy enumerator.
2167 * * +x+ is an array or responds to to_ary.
2168 *
2169 * Otherwise, +x+ is contained as-is in the return value.
2170 *
2171 * [{a:1}, {b:2}].lazy.flat_map {|i| i}.force
2172 * #=> [{:a=>1}, {:b=>2}]
2173 */
2174static VALUE
2175lazy_flat_map(VALUE obj)
2176{
2177 LAZY_NEED_BLOCK(flat_map);
2178 return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_flat_map_funcs);
2179}
2180
2181static struct MEMO *
2182lazy_select_proc(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_index)
2183{
2184 VALUE chain = lazyenum_yield(proc_entry, result);
2185 if (!RTEST(chain)) return 0;
2186 return result;
2187}
2188
2189static const lazyenum_funcs lazy_select_funcs = {
2190 lazy_select_proc, 0,
2191};
2192
2193/*
2194 * call-seq:
2195 * lazy.find_all { |obj| block } -> lazy_enumerator
2196 * lazy.select { |obj| block } -> lazy_enumerator
2197 * lazy.filter { |obj| block } -> lazy_enumerator
2198 *
2199 * Like Enumerable#select, but chains operation to be lazy-evaluated.
2200 */
2201static VALUE
2202lazy_select(VALUE obj)
2203{
2204 LAZY_NEED_BLOCK(select);
2205 return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_select_funcs);
2206}
2207
2208static struct MEMO *
2209lazy_filter_map_proc(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_index)
2210{
2211 VALUE value = lazyenum_yield_values(proc_entry, result);
2212 if (!RTEST(value)) return 0;
2213 LAZY_MEMO_SET_VALUE(result, value);
2214 LAZY_MEMO_RESET_PACKED(result);
2215 return result;
2216}
2217
2218static const lazyenum_funcs lazy_filter_map_funcs = {
2219 lazy_filter_map_proc, 0,
2220};
2221
2222/*
2223 * call-seq:
2224 * lazy.filter_map { |obj| block } -> lazy_enumerator
2225 *
2226 * Like Enumerable#filter_map, but chains operation to be lazy-evaluated.
2227 *
2228 * (1..).lazy.filter_map { |i| i * 2 if i.even? }.first(5)
2229 * #=> [4, 8, 12, 16, 20]
2230 */
2231
2232static VALUE
2233lazy_filter_map(VALUE obj)
2234{
2235 LAZY_NEED_BLOCK(filter_map);
2236 return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_filter_map_funcs);
2237}
2238
2239static struct MEMO *
2240lazy_reject_proc(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_index)
2241{
2242 VALUE chain = lazyenum_yield(proc_entry, result);
2243 if (RTEST(chain)) return 0;
2244 return result;
2245}
2246
2247static const lazyenum_funcs lazy_reject_funcs = {
2248 lazy_reject_proc, 0,
2249};
2250
2251/*
2252 * call-seq:
2253 * lazy.reject { |obj| block } -> lazy_enumerator
2254 *
2255 * Like Enumerable#reject, but chains operation to be lazy-evaluated.
2256 */
2257
2258static VALUE
2259lazy_reject(VALUE obj)
2260{
2261 LAZY_NEED_BLOCK(reject);
2262 return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_reject_funcs);
2263}
2264
2265static struct MEMO *
2266lazy_grep_proc(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_index)
2267{
2268 struct proc_entry *entry = proc_entry_ptr(proc_entry);
2269 VALUE chain = rb_funcall(entry->memo, id_eqq, 1, result->memo_value);
2270 if (!RTEST(chain)) return 0;
2271 return result;
2272}
2273
2274static struct MEMO *
2275lazy_grep_iter_proc(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_index)
2276{
2277 struct proc_entry *entry = proc_entry_ptr(proc_entry);
2278 VALUE value, chain = rb_funcall(entry->memo, id_eqq, 1, result->memo_value);
2279
2280 if (!RTEST(chain)) return 0;
2281 value = rb_proc_call_with_block(entry->proc, 1, &(result->memo_value), Qnil);
2282 LAZY_MEMO_SET_VALUE(result, value);
2283 LAZY_MEMO_RESET_PACKED(result);
2284
2285 return result;
2286}
2287
2288static const lazyenum_funcs lazy_grep_iter_funcs = {
2289 lazy_grep_iter_proc, 0,
2290};
2291
2292static const lazyenum_funcs lazy_grep_funcs = {
2293 lazy_grep_proc, 0,
2294};
2295
2296/*
2297 * call-seq:
2298 * lazy.grep(pattern) -> lazy_enumerator
2299 * lazy.grep(pattern) { |obj| block } -> lazy_enumerator
2300 *
2301 * Like Enumerable#grep, but chains operation to be lazy-evaluated.
2302 */
2303
2304static VALUE
2305lazy_grep(VALUE obj, VALUE pattern)
2306{
2307 const lazyenum_funcs *const funcs = rb_block_given_p() ?
2308 &lazy_grep_iter_funcs : &lazy_grep_funcs;
2309 return lazy_add_method(obj, 0, 0, pattern, rb_ary_new3(1, pattern), funcs);
2310}
2311
2312static struct MEMO *
2313lazy_grep_v_proc(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_index)
2314{
2315 struct proc_entry *entry = proc_entry_ptr(proc_entry);
2316 VALUE chain = rb_funcall(entry->memo, id_eqq, 1, result->memo_value);
2317 if (RTEST(chain)) return 0;
2318 return result;
2319}
2320
2321static struct MEMO *
2322lazy_grep_v_iter_proc(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_index)
2323{
2324 struct proc_entry *entry = proc_entry_ptr(proc_entry);
2325 VALUE value, chain = rb_funcall(entry->memo, id_eqq, 1, result->memo_value);
2326
2327 if (RTEST(chain)) return 0;
2328 value = rb_proc_call_with_block(entry->proc, 1, &(result->memo_value), Qnil);
2329 LAZY_MEMO_SET_VALUE(result, value);
2330 LAZY_MEMO_RESET_PACKED(result);
2331
2332 return result;
2333}
2334
2335static const lazyenum_funcs lazy_grep_v_iter_funcs = {
2336 lazy_grep_v_iter_proc, 0,
2337};
2338
2339static const lazyenum_funcs lazy_grep_v_funcs = {
2340 lazy_grep_v_proc, 0,
2341};
2342
2343/*
2344 * call-seq:
2345 * lazy.grep_v(pattern) -> lazy_enumerator
2346 * lazy.grep_v(pattern) { |obj| block } -> lazy_enumerator
2347 *
2348 * Like Enumerable#grep_v, but chains operation to be lazy-evaluated.
2349 */
2350
2351static VALUE
2352lazy_grep_v(VALUE obj, VALUE pattern)
2353{
2354 const lazyenum_funcs *const funcs = rb_block_given_p() ?
2355 &lazy_grep_v_iter_funcs : &lazy_grep_v_funcs;
2356 return lazy_add_method(obj, 0, 0, pattern, rb_ary_new3(1, pattern), funcs);
2357}
2358
2359static VALUE
2360call_next(VALUE obj)
2361{
2362 return rb_funcall(obj, id_next, 0);
2363}
2364
2365static VALUE
2366next_stopped(VALUE obj, VALUE _)
2367{
2368 return Qnil;
2369}
2370
2371static struct MEMO *
2372lazy_zip_arrays_func(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_index)
2373{
2374 struct proc_entry *entry = proc_entry_ptr(proc_entry);
2375 VALUE ary, arrays = entry->memo;
2376 VALUE memo = rb_ary_entry(memos, memo_index);
2377 long i, count = NIL_P(memo) ? 0 : NUM2LONG(memo);
2378
2379 ary = rb_ary_new2(RARRAY_LEN(arrays) + 1);
2380 rb_ary_push(ary, result->memo_value);
2381 for (i = 0; i < RARRAY_LEN(arrays); i++) {
2382 rb_ary_push(ary, rb_ary_entry(RARRAY_AREF(arrays, i), count));
2383 }
2384 LAZY_MEMO_SET_VALUE(result, ary);
2385 rb_ary_store(memos, memo_index, LONG2NUM(++count));
2386 return result;
2387}
2388
2389static struct MEMO *
2390lazy_zip_func(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_index)
2391{
2392 struct proc_entry *entry = proc_entry_ptr(proc_entry);
2393 VALUE arg = rb_ary_entry(memos, memo_index);
2394 VALUE zip_args = entry->memo;
2395 VALUE ary, v;
2396 long i;
2397
2398 if (NIL_P(arg)) {
2399 arg = rb_ary_new2(RARRAY_LEN(zip_args));
2400 for (i = 0; i < RARRAY_LEN(zip_args); i++) {
2401 rb_ary_push(arg, rb_funcall(RARRAY_AREF(zip_args, i), id_to_enum, 0));
2402 }
2403 rb_ary_store(memos, memo_index, arg);
2404 }
2405
2406 ary = rb_ary_new2(RARRAY_LEN(arg) + 1);
2407 rb_ary_push(ary, result->memo_value);
2408 for (i = 0; i < RARRAY_LEN(arg); i++) {
2409 v = rb_rescue2(call_next, RARRAY_AREF(arg, i), next_stopped, 0,
2411 rb_ary_push(ary, v);
2412 }
2413 LAZY_MEMO_SET_VALUE(result, ary);
2414 return result;
2415}
2416
2417static const lazyenum_funcs lazy_zip_funcs[] = {
2418 {lazy_zip_func, lazy_receiver_size,},
2419 {lazy_zip_arrays_func, lazy_receiver_size,},
2420};
2421
2422/*
2423 * call-seq:
2424 * lazy.zip(arg, ...) -> lazy_enumerator
2425 * lazy.zip(arg, ...) { |arr| block } -> nil
2426 *
2427 * Like Enumerable#zip, but chains operation to be lazy-evaluated.
2428 * However, if a block is given to zip, values are enumerated immediately.
2429 */
2430static VALUE
2431lazy_zip(int argc, VALUE *argv, VALUE obj)
2432{
2433 VALUE ary, v;
2434 long i;
2435 const lazyenum_funcs *funcs = &lazy_zip_funcs[1];
2436
2437 if (rb_block_given_p()) {
2438 return rb_call_super(argc, argv);
2439 }
2440
2441 ary = rb_ary_new2(argc);
2442 for (i = 0; i < argc; i++) {
2443 v = rb_check_array_type(argv[i]);
2444 if (NIL_P(v)) {
2445 for (; i < argc; i++) {
2446 if (!rb_respond_to(argv[i], id_each)) {
2447 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
2448 rb_obj_class(argv[i]));
2449 }
2450 }
2451 ary = rb_ary_new4(argc, argv);
2452 funcs = &lazy_zip_funcs[0];
2453 break;
2454 }
2455 rb_ary_push(ary, v);
2456 }
2457
2458 return lazy_add_method(obj, 0, 0, ary, ary, funcs);
2459}
2460
2461static struct MEMO *
2462lazy_take_proc(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_index)
2463{
2464 long remain;
2465 struct proc_entry *entry = proc_entry_ptr(proc_entry);
2466 VALUE memo = rb_ary_entry(memos, memo_index);
2467
2468 if (NIL_P(memo)) {
2469 memo = entry->memo;
2470 }
2471
2472 remain = NUM2LONG(memo);
2473 if (--remain == 0) LAZY_MEMO_SET_BREAK(result);
2474 rb_ary_store(memos, memo_index, LONG2NUM(remain));
2475 return result;
2476}
2477
2478static VALUE
2479lazy_take_size(VALUE entry, VALUE receiver)
2480{
2481 long len = NUM2LONG(RARRAY_AREF(rb_ivar_get(entry, id_arguments), 0));
2482 if (NIL_P(receiver) || (FIXNUM_P(receiver) && FIX2LONG(receiver) < len))
2483 return receiver;
2484 return LONG2NUM(len);
2485}
2486
2487static int
2488lazy_take_precheck(VALUE proc_entry)
2489{
2490 struct proc_entry *entry = proc_entry_ptr(proc_entry);
2491 return entry->memo != INT2FIX(0);
2492}
2493
2494static const lazyenum_funcs lazy_take_funcs = {
2495 lazy_take_proc, lazy_take_size, lazy_take_precheck,
2496};
2497
2498/*
2499 * call-seq:
2500 * lazy.take(n) -> lazy_enumerator
2501 *
2502 * Like Enumerable#take, but chains operation to be lazy-evaluated.
2503 */
2504
2505static VALUE
2506lazy_take(VALUE obj, VALUE n)
2507{
2508 long len = NUM2LONG(n);
2509
2510 if (len < 0) {
2511 rb_raise(rb_eArgError, "attempt to take negative size");
2512 }
2513
2514 n = LONG2NUM(len); /* no more conversion */
2515
2516 return lazy_add_method(obj, 0, 0, n, rb_ary_new3(1, n), &lazy_take_funcs);
2517}
2518
2519static struct MEMO *
2520lazy_take_while_proc(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_index)
2521{
2522 VALUE take = lazyenum_yield_values(proc_entry, result);
2523 if (!RTEST(take)) {
2524 LAZY_MEMO_SET_BREAK(result);
2525 return 0;
2526 }
2527 return result;
2528}
2529
2530static const lazyenum_funcs lazy_take_while_funcs = {
2531 lazy_take_while_proc, 0,
2532};
2533
2534/*
2535 * call-seq:
2536 * lazy.take_while { |obj| block } -> lazy_enumerator
2537 *
2538 * Like Enumerable#take_while, but chains operation to be lazy-evaluated.
2539 */
2540
2541static VALUE
2542lazy_take_while(VALUE obj)
2543{
2544 LAZY_NEED_BLOCK(take_while);
2545 return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_take_while_funcs);
2546}
2547
2548static VALUE
2549lazy_drop_size(VALUE proc_entry, VALUE receiver)
2550{
2551 long len = NUM2LONG(RARRAY_AREF(rb_ivar_get(proc_entry, id_arguments), 0));
2552 if (NIL_P(receiver))
2553 return receiver;
2554 if (FIXNUM_P(receiver)) {
2555 len = FIX2LONG(receiver) - len;
2556 return LONG2FIX(len < 0 ? 0 : len);
2557 }
2558 return rb_funcall(receiver, '-', 1, LONG2NUM(len));
2559}
2560
2561static struct MEMO *
2562lazy_drop_proc(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_index)
2563{
2564 long remain;
2565 struct proc_entry *entry = proc_entry_ptr(proc_entry);
2566 VALUE memo = rb_ary_entry(memos, memo_index);
2567
2568 if (NIL_P(memo)) {
2569 memo = entry->memo;
2570 }
2571 remain = NUM2LONG(memo);
2572 if (remain > 0) {
2573 --remain;
2574 rb_ary_store(memos, memo_index, LONG2NUM(remain));
2575 return 0;
2576 }
2577
2578 return result;
2579}
2580
2581static const lazyenum_funcs lazy_drop_funcs = {
2582 lazy_drop_proc, lazy_drop_size,
2583};
2584
2585/*
2586 * call-seq:
2587 * lazy.drop(n) -> lazy_enumerator
2588 *
2589 * Like Enumerable#drop, but chains operation to be lazy-evaluated.
2590 */
2591
2592static VALUE
2593lazy_drop(VALUE obj, VALUE n)
2594{
2595 long len = NUM2LONG(n);
2596 VALUE argv[2];
2597 argv[0] = sym_each;
2598 argv[1] = n;
2599
2600 if (len < 0) {
2601 rb_raise(rb_eArgError, "attempt to drop negative size");
2602 }
2603
2604 return lazy_add_method(obj, 2, argv, n, rb_ary_new3(1, n), &lazy_drop_funcs);
2605}
2606
2607static struct MEMO *
2608lazy_drop_while_proc(VALUE proc_entry, struct MEMO* result, VALUE memos, long memo_index)
2609{
2610 struct proc_entry *entry = proc_entry_ptr(proc_entry);
2611 VALUE memo = rb_ary_entry(memos, memo_index);
2612
2613 if (NIL_P(memo)) {
2614 memo = entry->memo;
2615 }
2616
2617 if (!RTEST(memo)) {
2618 VALUE drop = lazyenum_yield_values(proc_entry, result);
2619 if (RTEST(drop)) return 0;
2620 rb_ary_store(memos, memo_index, Qtrue);
2621 }
2622 return result;
2623}
2624
2625static const lazyenum_funcs lazy_drop_while_funcs = {
2626 lazy_drop_while_proc, 0,
2627};
2628
2629/*
2630 * call-seq:
2631 * lazy.drop_while { |obj| block } -> lazy_enumerator
2632 *
2633 * Like Enumerable#drop_while, but chains operation to be lazy-evaluated.
2634 */
2635
2636static VALUE
2637lazy_drop_while(VALUE obj)
2638{
2639 LAZY_NEED_BLOCK(drop_while);
2640 return lazy_add_method(obj, 0, 0, Qfalse, Qnil, &lazy_drop_while_funcs);
2641}
2642
2643static int
2644lazy_uniq_check(VALUE chain, VALUE memos, long memo_index)
2645{
2646 VALUE set = rb_ary_entry(memos, memo_index);
2647
2648 if (NIL_P(set)) {
2649 set = rb_obj_hide(rb_set_new());
2650 rb_ary_store(memos, memo_index, set);
2651 }
2652
2653 return !rb_set_add_no_check(set, chain);
2654}
2655
2656static struct MEMO *
2657lazy_uniq_proc(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_index)
2658{
2659 if (lazy_uniq_check(result->memo_value, memos, memo_index)) return 0;
2660 return result;
2661}
2662
2663static struct MEMO *
2664lazy_uniq_iter_proc(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_index)
2665{
2666 VALUE chain = lazyenum_yield(proc_entry, result);
2667
2668 if (lazy_uniq_check(chain, memos, memo_index)) return 0;
2669 return result;
2670}
2671
2672static const lazyenum_funcs lazy_uniq_iter_funcs = {
2673 lazy_uniq_iter_proc, 0,
2674};
2675
2676static const lazyenum_funcs lazy_uniq_funcs = {
2677 lazy_uniq_proc, 0,
2678};
2679
2680/*
2681 * call-seq:
2682 * lazy.uniq -> lazy_enumerator
2683 * lazy.uniq { |item| block } -> lazy_enumerator
2684 *
2685 * Like Enumerable#uniq, but chains operation to be lazy-evaluated.
2686 */
2687
2688static VALUE
2689lazy_uniq(VALUE obj)
2690{
2691 const lazyenum_funcs *const funcs =
2692 rb_block_given_p() ? &lazy_uniq_iter_funcs : &lazy_uniq_funcs;
2693 return lazy_add_method(obj, 0, 0, Qnil, Qnil, funcs);
2694}
2695
2696static struct MEMO *
2697lazy_compact_proc(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_index)
2698{
2699 if (NIL_P(result->memo_value)) return 0;
2700 return result;
2701}
2702
2703static const lazyenum_funcs lazy_compact_funcs = {
2704 lazy_compact_proc, 0,
2705};
2706
2707/*
2708 * call-seq:
2709 * lazy.compact -> lazy_enumerator
2710 *
2711 * Like Enumerable#compact, but chains operation to be lazy-evaluated.
2712 */
2713
2714static VALUE
2715lazy_compact(VALUE obj)
2716{
2717 return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_compact_funcs);
2718}
2719
2720static struct MEMO *
2721lazy_with_index_proc(VALUE proc_entry, struct MEMO* result, VALUE memos, long memo_index)
2722{
2723 struct proc_entry *entry = proc_entry_ptr(proc_entry);
2724 VALUE memo = rb_ary_entry(memos, memo_index);
2725 VALUE argv[2];
2726
2727 if (NIL_P(memo)) {
2728 memo = entry->memo;
2729 }
2730
2731 argv[0] = result->memo_value;
2732 argv[1] = memo;
2733 if (entry->proc) {
2734 rb_proc_call_with_block(entry->proc, 2, argv, Qnil);
2735 LAZY_MEMO_RESET_PACKED(result);
2736 }
2737 else {
2738 LAZY_MEMO_SET_VALUE(result, rb_ary_new_from_values(2, argv));
2739 LAZY_MEMO_SET_PACKED(result);
2740 }
2741 rb_ary_store(memos, memo_index, LONG2NUM(NUM2LONG(memo) + 1));
2742 return result;
2743}
2744
2745static VALUE
2746lazy_with_index_size(VALUE proc, VALUE receiver)
2747{
2748 return receiver;
2749}
2750
2751static const lazyenum_funcs lazy_with_index_funcs = {
2752 lazy_with_index_proc, lazy_with_index_size,
2753};
2754
2755/*
2756 * call-seq:
2757 * lazy.with_index(offset = 0) {|(*args), idx| block }
2758 * lazy.with_index(offset = 0)
2759 *
2760 * If a block is given, returns a lazy enumerator that will
2761 * iterate over the given block for each element
2762 * with an index, which starts from +offset+, and returns a
2763 * lazy enumerator that yields the same values (without the index).
2764 *
2765 * If a block is not given, returns a new lazy enumerator that
2766 * includes the index, starting from +offset+.
2767 *
2768 * +offset+:: the starting index to use
2769 *
2770 * See Enumerator#with_index.
2771 */
2772static VALUE
2773lazy_with_index(int argc, VALUE *argv, VALUE obj)
2774{
2775 VALUE memo;
2776
2777 rb_scan_args(argc, argv, "01", &memo);
2778 if (NIL_P(memo))
2779 memo = LONG2NUM(0);
2780
2781 return lazy_add_method(obj, 0, 0, memo, rb_ary_new_from_values(1, &memo), &lazy_with_index_funcs);
2782}
2783
2784static struct MEMO *
2785lazy_tap_each_proc(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_index)
2786{
2787 struct proc_entry *entry = proc_entry_ptr(proc_entry);
2788
2789 rb_proc_call_with_block(entry->proc, 1, &result->memo_value, Qnil);
2790
2791 return result;
2792}
2793
2794static const lazyenum_funcs lazy_tap_each_funcs = {
2795 lazy_tap_each_proc, 0,
2796};
2797
2798/*
2799 * call-seq:
2800 * lazy.tap_each { |item| ... } -> lazy_enumerator
2801 *
2802 * Passes each element through to the block for side effects only,
2803 * without modifying the element or affecting the enumeration.
2804 * Returns a new lazy enumerator.
2805 *
2806 * This is useful for debugging or logging inside lazy chains,
2807 * without breaking laziness or misusing +map+.
2808 *
2809 * (1..).lazy
2810 * .tap_each { |x| puts "got #{x}" }
2811 * .select(&:even?)
2812 * .first(3)
2813 * # prints: got 1, got 2, ..., got 6
2814 * # returns: [2, 4, 6]
2815 *
2816 * Similar in intent to Java's Stream#peek.
2817 */
2818
2819static VALUE
2820lazy_tap_each(VALUE obj)
2821{
2822 if (!rb_block_given_p())
2823 {
2824 rb_raise(rb_eArgError, "tried to call lazy tap_each without a block");
2825 }
2826
2827 return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_tap_each_funcs);
2828}
2829
2830#if 0 /* for RDoc */
2831
2832/*
2833 * call-seq:
2834 * lazy.chunk { |elt| ... } -> lazy_enumerator
2835 *
2836 * Like Enumerable#chunk, but chains operation to be lazy-evaluated.
2837 */
2838static VALUE
2839lazy_chunk(VALUE self)
2840{
2841}
2842
2843/*
2844 * call-seq:
2845 * lazy.chunk_while {|elt_before, elt_after| bool } -> lazy_enumerator
2846 *
2847 * Like Enumerable#chunk_while, but chains operation to be lazy-evaluated.
2848 */
2849static VALUE
2850lazy_chunk_while(VALUE self)
2851{
2852}
2853
2854/*
2855 * call-seq:
2856 * lazy.slice_after(pattern) -> lazy_enumerator
2857 * lazy.slice_after { |elt| bool } -> lazy_enumerator
2858 *
2859 * Like Enumerable#slice_after, but chains operation to be lazy-evaluated.
2860 */
2861static VALUE
2862lazy_slice_after(VALUE self)
2863{
2864}
2865
2866/*
2867 * call-seq:
2868 * lazy.slice_before(pattern) -> lazy_enumerator
2869 * lazy.slice_before { |elt| bool } -> lazy_enumerator
2870 *
2871 * Like Enumerable#slice_before, but chains operation to be lazy-evaluated.
2872 */
2873static VALUE
2874lazy_slice_before(VALUE self)
2875{
2876}
2877
2878/*
2879 * call-seq:
2880 * lazy.slice_when {|elt_before, elt_after| bool } -> lazy_enumerator
2881 *
2882 * Like Enumerable#slice_when, but chains operation to be lazy-evaluated.
2883 */
2884static VALUE
2885lazy_slice_when(VALUE self)
2886{
2887}
2888# endif
2889
2890static VALUE
2891lazy_super(int argc, VALUE *argv, VALUE lazy)
2892{
2893 return enumerable_lazy(rb_call_super(argc, argv));
2894}
2895
2896/*
2897 * call-seq:
2898 * enum.lazy -> lazy_enumerator
2899 *
2900 * Returns self.
2901 */
2902
2903static VALUE
2904lazy_lazy(VALUE obj)
2905{
2906 return obj;
2907}
2908
2909/*
2910 * Document-class: StopIteration
2911 *
2912 * Raised to stop the iteration, in particular by Enumerator#next. It is
2913 * rescued by Kernel#loop.
2914 *
2915 * loop do
2916 * puts "Hello"
2917 * raise StopIteration
2918 * puts "World"
2919 * end
2920 * puts "Done!"
2921 *
2922 * <em>produces:</em>
2923 *
2924 * Hello
2925 * Done!
2926 */
2927
2928/*
2929 * call-seq:
2930 * result -> value
2931 *
2932 * Returns the return value of the iterator.
2933 *
2934 * o = Object.new
2935 * def o.each
2936 * yield 1
2937 * yield 2
2938 * yield 3
2939 * 100
2940 * end
2941 *
2942 * e = o.to_enum
2943 *
2944 * puts e.next #=> 1
2945 * puts e.next #=> 2
2946 * puts e.next #=> 3
2947 *
2948 * begin
2949 * e.next
2950 * rescue StopIteration => ex
2951 * puts ex.result #=> 100
2952 * end
2953 *
2954 */
2955
2956static VALUE
2957stop_result(VALUE self)
2958{
2959 return rb_attr_get(self, id_result);
2960}
2961
2962/*
2963 * Producer
2964 */
2965
2966static void
2967producer_mark_and_move(void *p)
2968{
2969 struct producer *ptr = p;
2970 rb_gc_mark_and_move(&ptr->init);
2971 rb_gc_mark_and_move(&ptr->proc);
2972 rb_gc_mark_and_move(&ptr->size);
2973}
2974
2975#define producer_free RUBY_TYPED_DEFAULT_FREE
2976
2977static size_t
2978producer_memsize(const void *p)
2979{
2980 return sizeof(struct producer);
2981}
2982
2983static const rb_data_type_t producer_data_type = {
2984 "producer",
2985 {
2986 producer_mark_and_move,
2987 producer_free,
2988 producer_memsize,
2989 producer_mark_and_move,
2990 },
2991 0, 0, RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
2992};
2993
2994static struct producer *
2995producer_ptr(VALUE obj)
2996{
2997 struct producer *ptr;
2998
2999 TypedData_Get_Struct(obj, struct producer, &producer_data_type, ptr);
3000 if (!ptr || UNDEF_P(ptr->proc)) {
3001 rb_raise(rb_eArgError, "uninitialized producer");
3002 }
3003 return ptr;
3004}
3005
3006/* :nodoc: */
3007static VALUE
3008producer_allocate(VALUE klass)
3009{
3010 struct producer *ptr;
3011 VALUE obj;
3012
3013 obj = TypedData_Make_Struct(klass, struct producer, &producer_data_type, ptr);
3014 ptr->init = Qundef;
3015 ptr->proc = Qundef;
3016 ptr->size = Qnil;
3017
3018 return obj;
3019}
3020
3021static VALUE
3022producer_init(VALUE obj, VALUE init, VALUE proc, VALUE size)
3023{
3024 struct producer *ptr;
3025
3026 TypedData_Get_Struct(obj, struct producer, &producer_data_type, ptr);
3027
3028 if (!ptr) {
3029 rb_raise(rb_eArgError, "unallocated producer");
3030 }
3031
3032 RB_OBJ_WRITE(obj, &ptr->init, init);
3033 RB_OBJ_WRITE(obj, &ptr->proc, proc);
3034 RB_OBJ_WRITE(obj, &ptr->size, size);
3035
3036 return obj;
3037}
3038
3039static VALUE
3040producer_each_stop(VALUE dummy, VALUE exc)
3041{
3042 return rb_attr_get(exc, id_result);
3043}
3044
3045NORETURN(static VALUE producer_each_i(VALUE obj));
3046
3047static VALUE
3048producer_each_i(VALUE obj)
3049{
3050 struct producer *ptr;
3051 VALUE init, proc, curr;
3052
3053 ptr = producer_ptr(obj);
3054 init = ptr->init;
3055 proc = ptr->proc;
3056
3057 if (UNDEF_P(init)) {
3058 curr = Qnil;
3059 }
3060 else {
3061 rb_yield(init);
3062 curr = init;
3063 }
3064
3065 for (;;) {
3066 curr = rb_funcall(proc, id_call, 1, curr);
3067 rb_yield(curr);
3068 }
3069
3071}
3072
3073/* :nodoc: */
3074static VALUE
3075producer_each(VALUE obj)
3076{
3077 rb_need_block();
3078
3079 return rb_rescue2(producer_each_i, obj, producer_each_stop, (VALUE)0, rb_eStopIteration, (VALUE)0);
3080}
3081
3082static VALUE
3083producer_size(VALUE obj, VALUE args, VALUE eobj)
3084{
3085 struct producer *ptr = producer_ptr(obj);
3086 VALUE size = ptr->size;
3087
3088 if (NIL_P(size)) return Qnil;
3089 if (RB_INTEGER_TYPE_P(size) || RB_FLOAT_TYPE_P(size)) return size;
3090
3091 return rb_funcall(size, id_call, 0);
3092}
3093
3094/*
3095 * call-seq:
3096 * Enumerator.produce(initial = nil, size: nil) { |prev| block } -> enumerator
3097 *
3098 * Creates an infinite enumerator from any block, just called over and
3099 * over. The result of the previous iteration is passed to the next one.
3100 * If +initial+ is provided, it is passed to the first iteration, and
3101 * becomes the first element of the enumerator; if it is not provided,
3102 * the first iteration receives +nil+, and its result becomes the first
3103 * element of the iterator.
3104 *
3105 * Raising StopIteration from the block stops an iteration.
3106 *
3107 * Enumerator.produce(1, &:succ) # => enumerator of 1, 2, 3, 4, ....
3108 *
3109 * Enumerator.produce { rand(10) } # => infinite random number sequence
3110 *
3111 * ancestors = Enumerator.produce(node) { |prev| node = prev.parent or raise StopIteration }
3112 * enclosing_section = ancestors.find { |n| n.type == :section }
3113 *
3114 * Using ::produce together with Enumerable methods like Enumerable#detect,
3115 * Enumerable#slice_after, Enumerable#take_while can provide Enumerator-based alternatives
3116 * for +while+ and +until+ cycles:
3117 *
3118 * # Find next Tuesday
3119 * require "date"
3120 * Enumerator.produce(Date.today, &:succ).detect(&:tuesday?)
3121 *
3122 * # Simple lexer:
3123 * require "strscan"
3124 * scanner = StringScanner.new("7+38/6")
3125 * PATTERN = %r{\d+|[-/+*]}
3126 * Enumerator.produce { scanner.scan(PATTERN) }.slice_after { scanner.eos? }.first
3127 * # => ["7", "+", "38", "/", "6"]
3128 *
3129 * The optional +size+ keyword argument specifies the size of the enumerator,
3130 * which can be retrieved by Enumerator#size. It can be an integer,
3131 * +Float::INFINITY+, a callable object (such as a lambda), or +nil+ to
3132 * indicate unknown size. When not specified, the size defaults to
3133 * +Float::INFINITY+.
3134 *
3135 * # Infinite enumerator
3136 * enum = Enumerator.produce(1, size: Float::INFINITY, &:succ)
3137 * enum.size # => Float::INFINITY
3138 *
3139 * # Finite enumerator with known/computable size
3140 * abs_dir = File.expand_path("./baz") # => "/foo/bar/baz"
3141 * traverser = Enumerator.produce(abs_dir, size: -> { abs_dir.count("/") + 1 }) {
3142 * raise StopIteration if it == "/"
3143 * File.dirname(it)
3144 * }
3145 * traverser.size # => 4
3146 *
3147 * # Finite enumerator with unknown size
3148 * calendar = Enumerator.produce(Date.today, size: nil) {
3149 * it.monday? ? raise(StopIteration) : it + 1
3150 * }
3151 * calendar.size # => nil
3152 */
3153static VALUE
3154enumerator_s_produce(int argc, VALUE *argv, VALUE klass)
3155{
3156 VALUE init, producer, opts, size;
3157 ID keyword_ids[1];
3158
3159 if (!rb_block_given_p()) rb_raise(rb_eArgError, "no block given");
3160
3161 keyword_ids[0] = rb_intern("size");
3162 rb_scan_args_kw(RB_SCAN_ARGS_LAST_HASH_KEYWORDS, argc, argv, "01:", &init, &opts);
3163 rb_get_kwargs(opts, keyword_ids, 0, 1, &size);
3164
3165 size = UNDEF_P(size) ? DBL2NUM(HUGE_VAL) : convert_to_feasible_size_value(size);
3166
3167 if (argc == 0 || (argc == 1 && !NIL_P(opts))) {
3168 init = Qundef;
3169 }
3170
3171 producer = producer_init(producer_allocate(rb_cEnumProducer), init, rb_block_proc(), size);
3172
3173 return rb_enumeratorize_with_size_kw(producer, sym_each, 0, 0, producer_size, RB_NO_KEYWORDS);
3174}
3175
3176/*
3177 * Document-class: Enumerator::Chain
3178 *
3179 * Enumerator::Chain is a subclass of Enumerator, which represents a
3180 * chain of enumerables that works as a single enumerator.
3181 *
3182 * This type of objects can be created by Enumerable#chain and
3183 * Enumerator#+.
3184 */
3185
3186static void
3187enum_chain_mark_and_move(void *p)
3188{
3189 struct enum_chain *ptr = p;
3190 rb_gc_mark_and_move(&ptr->enums);
3191}
3192
3193#define enum_chain_free RUBY_TYPED_DEFAULT_FREE
3194
3195static size_t
3196enum_chain_memsize(const void *p)
3197{
3198 return sizeof(struct enum_chain);
3199}
3200
3201static const rb_data_type_t enum_chain_data_type = {
3202 "chain",
3203 {
3204 enum_chain_mark_and_move,
3205 enum_chain_free,
3206 enum_chain_memsize,
3207 enum_chain_mark_and_move,
3208 },
3209 0, 0, RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_WB_PROTECTED
3210};
3211
3212static struct enum_chain *
3213enum_chain_ptr(VALUE obj)
3214{
3215 struct enum_chain *ptr;
3216
3217 TypedData_Get_Struct(obj, struct enum_chain, &enum_chain_data_type, ptr);
3218 if (!ptr || UNDEF_P(ptr->enums)) {
3219 rb_raise(rb_eArgError, "uninitialized chain");
3220 }
3221 return ptr;
3222}
3223
3224/* :nodoc: */
3225static VALUE
3226enum_chain_allocate(VALUE klass)
3227{
3228 struct enum_chain *ptr;
3229 VALUE obj;
3230
3231 obj = TypedData_Make_Struct(klass, struct enum_chain, &enum_chain_data_type, ptr);
3232 ptr->enums = Qundef;
3233 ptr->pos = -1;
3234
3235 return obj;
3236}
3237
3238/*
3239 * call-seq:
3240 * Enumerator::Chain.new(*enums) -> enum
3241 *
3242 * Generates a new enumerator object that iterates over the elements
3243 * of given enumerable objects in sequence.
3244 *
3245 * e = Enumerator::Chain.new(1..3, [4, 5])
3246 * e.to_a #=> [1, 2, 3, 4, 5]
3247 * e.size #=> 5
3248 */
3249static VALUE
3250enum_chain_initialize(VALUE obj, VALUE enums)
3251{
3252 struct enum_chain *ptr;
3253
3254 rb_check_frozen(obj);
3255 TypedData_Get_Struct(obj, struct enum_chain, &enum_chain_data_type, ptr);
3256
3257 if (!ptr) rb_raise(rb_eArgError, "unallocated chain");
3258
3259 RB_OBJ_WRITE(obj, &ptr->enums, rb_ary_freeze(enums));
3260 ptr->pos = -1;
3261
3262 return obj;
3263}
3264
3265static VALUE
3266new_enum_chain(VALUE enums)
3267{
3268 long i;
3269 VALUE obj = enum_chain_initialize(enum_chain_allocate(rb_cEnumChain), enums);
3270
3271 for (i = 0; i < RARRAY_LEN(enums); i++) {
3272 if (RTEST(rb_obj_is_kind_of(RARRAY_AREF(enums, i), rb_cLazy))) {
3273 return enumerable_lazy(obj);
3274 }
3275 }
3276
3277 return obj;
3278}
3279
3280/* :nodoc: */
3281static VALUE
3282enum_chain_init_copy(VALUE obj, VALUE orig)
3283{
3284 struct enum_chain *ptr0, *ptr1;
3285
3286 if (!OBJ_INIT_COPY(obj, orig)) return obj;
3287 ptr0 = enum_chain_ptr(orig);
3288
3289 TypedData_Get_Struct(obj, struct enum_chain, &enum_chain_data_type, ptr1);
3290
3291 if (!ptr1) rb_raise(rb_eArgError, "unallocated chain");
3292
3293 RB_OBJ_WRITE(obj, &ptr1->enums, ptr0->enums);
3294 ptr1->pos = ptr0->pos;
3295
3296 return obj;
3297}
3298
3299static VALUE
3300enum_chain_total_size(VALUE enums)
3301{
3302 VALUE total = INT2FIX(0);
3303 long i;
3304
3305 for (i = 0; i < RARRAY_LEN(enums); i++) {
3306 VALUE size = enum_size(RARRAY_AREF(enums, i));
3307
3308 if (NIL_P(size) || (RB_FLOAT_TYPE_P(size) && isinf(NUM2DBL(size)))) {
3309 return size;
3310 }
3311 if (!RB_INTEGER_TYPE_P(size)) {
3312 return Qnil;
3313 }
3314
3315 total = rb_funcall(total, '+', 1, size);
3316 }
3317
3318 return total;
3319}
3320
3321/*
3322 * call-seq:
3323 * obj.size -> int, Float::INFINITY or nil
3324 *
3325 * Returns the total size of the enumerator chain calculated by
3326 * summing up the size of each enumerable in the chain. If any of the
3327 * enumerables reports its size as nil or Float::INFINITY, that value
3328 * is returned as the total size.
3329 */
3330static VALUE
3331enum_chain_size(VALUE obj)
3332{
3333 return enum_chain_total_size(enum_chain_ptr(obj)->enums);
3334}
3335
3336static VALUE
3337enum_chain_enum_size(VALUE obj, VALUE args, VALUE eobj)
3338{
3339 return enum_chain_size(obj);
3340}
3341
3342static VALUE
3343enum_chain_enum_no_size(VALUE obj, VALUE args, VALUE eobj)
3344{
3345 return Qnil;
3346}
3347
3348/*
3349 * call-seq:
3350 * obj.each(*args) { |...| ... } -> obj
3351 * obj.each(*args) -> enumerator
3352 *
3353 * Iterates over the elements of the first enumerable by calling the
3354 * "each" method on it with the given arguments, then proceeds to the
3355 * following enumerables in sequence until all of the enumerables are
3356 * exhausted.
3357 *
3358 * If no block is given, returns an enumerator.
3359 */
3360static VALUE
3361enum_chain_each(int argc, VALUE *argv, VALUE obj)
3362{
3363 VALUE enums, block;
3364 struct enum_chain *objptr;
3365 long i;
3366
3367 RETURN_SIZED_ENUMERATOR(obj, argc, argv, argc > 0 ? enum_chain_enum_no_size : enum_chain_enum_size);
3368
3369 objptr = enum_chain_ptr(obj);
3370 enums = objptr->enums;
3371 block = rb_block_proc();
3372
3373 for (i = 0; i < RARRAY_LEN(enums); i++) {
3374 objptr->pos = i;
3375 rb_funcall_with_block(RARRAY_AREF(enums, i), id_each, argc, argv, block);
3376 }
3377
3378 return obj;
3379}
3380
3381/*
3382 * call-seq:
3383 * obj.rewind -> obj
3384 *
3385 * Rewinds the enumerator chain by calling the "rewind" method on each
3386 * enumerable in reverse order. Each call is performed only if the
3387 * enumerable responds to the method.
3388 */
3389static VALUE
3390enum_chain_rewind(VALUE obj)
3391{
3392 struct enum_chain *objptr = enum_chain_ptr(obj);
3393 VALUE enums = objptr->enums;
3394 long i;
3395
3396 for (i = objptr->pos; 0 <= i && i < RARRAY_LEN(enums); objptr->pos = --i) {
3397 rb_check_funcall(RARRAY_AREF(enums, i), id_rewind, 0, 0);
3398 }
3399
3400 return obj;
3401}
3402
3403static VALUE
3404inspect_enum_chain(VALUE obj, VALUE dummy, int recur)
3405{
3406 VALUE klass = rb_obj_class(obj);
3407 struct enum_chain *ptr;
3408
3409 TypedData_Get_Struct(obj, struct enum_chain, &enum_chain_data_type, ptr);
3410
3411 if (!ptr || UNDEF_P(ptr->enums)) {
3412 return rb_sprintf("#<%"PRIsVALUE": uninitialized>", rb_class_path(klass));
3413 }
3414
3415 if (recur) {
3416 return rb_sprintf("#<%"PRIsVALUE": ...>", rb_class_path(klass));
3417 }
3418
3419 return rb_sprintf("#<%"PRIsVALUE": %+"PRIsVALUE">", rb_class_path(klass), ptr->enums);
3420}
3421
3422/*
3423 * call-seq:
3424 * obj.inspect -> string
3425 *
3426 * Returns a printable version of the enumerator chain.
3427 */
3428static VALUE
3429enum_chain_inspect(VALUE obj)
3430{
3431 return rb_exec_recursive(inspect_enum_chain, obj, 0);
3432}
3433
3434/*
3435 * call-seq:
3436 * e.chain(*enums) -> enumerator
3437 *
3438 * Returns an enumerator object generated from this enumerator and
3439 * given enumerables.
3440 *
3441 * e = (1..3).chain([4, 5])
3442 * e.to_a #=> [1, 2, 3, 4, 5]
3443 */
3444static VALUE
3445enum_chain(int argc, VALUE *argv, VALUE obj)
3446{
3447 VALUE enums = rb_ary_new_from_values(1, &obj);
3448 rb_ary_cat(enums, argv, argc);
3449 return new_enum_chain(enums);
3450}
3451
3452/*
3453 * call-seq:
3454 * e + enum -> enumerator
3455 *
3456 * Returns an enumerator object generated from this enumerator and a
3457 * given enumerable.
3458 *
3459 * e = (1..3).each + [4, 5]
3460 * e.to_a #=> [1, 2, 3, 4, 5]
3461 */
3462static VALUE
3463enumerator_plus(VALUE obj, VALUE eobj)
3464{
3465 return new_enum_chain(rb_ary_new_from_args(2, obj, eobj));
3466}
3467
3468/*
3469 * Document-class: Enumerator::Product
3470 *
3471 * Enumerator::Product generates a Cartesian product of any number of
3472 * enumerable objects. Iterating over the product of enumerable
3473 * objects is roughly equivalent to nested each_entry loops where the
3474 * loop for the rightmost object is put innermost.
3475 *
3476 * innings = Enumerator::Product.new(1..9, ['top', 'bottom'])
3477 *
3478 * innings.each do |i, h|
3479 * p [i, h]
3480 * end
3481 * # [1, "top"]
3482 * # [1, "bottom"]
3483 * # [2, "top"]
3484 * # [2, "bottom"]
3485 * # [3, "top"]
3486 * # [3, "bottom"]
3487 * # ...
3488 * # [9, "top"]
3489 * # [9, "bottom"]
3490 *
3491 * The method used against each enumerable object is `each_entry`
3492 * instead of `each` so that the product of N enumerable objects
3493 * yields an array of exactly N elements in each iteration.
3494 *
3495 * When no enumerator is given, it calls a given block once yielding
3496 * an empty argument list.
3497 *
3498 * This type of objects can be created by Enumerator.product.
3499 */
3500
3501static void
3502enum_product_mark_and_move(void *p)
3503{
3504 struct enum_product *ptr = p;
3505 rb_gc_mark_and_move(&ptr->enums);
3506}
3507
3508#define enum_product_free RUBY_TYPED_DEFAULT_FREE
3509
3510static size_t
3511enum_product_memsize(const void *p)
3512{
3513 return sizeof(struct enum_product);
3514}
3515
3516static const rb_data_type_t enum_product_data_type = {
3517 "product",
3518 {
3519 enum_product_mark_and_move,
3520 enum_product_free,
3521 enum_product_memsize,
3522 enum_product_mark_and_move,
3523 },
3524 0, 0, RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_WB_PROTECTED
3525};
3526
3527static struct enum_product *
3528enum_product_ptr(VALUE obj)
3529{
3530 struct enum_product *ptr;
3531
3532 TypedData_Get_Struct(obj, struct enum_product, &enum_product_data_type, ptr);
3533 if (!ptr || UNDEF_P(ptr->enums)) {
3534 rb_raise(rb_eArgError, "uninitialized product");
3535 }
3536 return ptr;
3537}
3538
3539/* :nodoc: */
3540static VALUE
3541enum_product_allocate(VALUE klass)
3542{
3543 struct enum_product *ptr;
3544 VALUE obj;
3545
3546 obj = TypedData_Make_Struct(klass, struct enum_product, &enum_product_data_type, ptr);
3547 ptr->enums = Qundef;
3548
3549 return obj;
3550}
3551
3552/*
3553 * call-seq:
3554 * Enumerator::Product.new(*enums) -> enum
3555 *
3556 * Generates a new enumerator object that generates a Cartesian
3557 * product of given enumerable objects.
3558 *
3559 * e = Enumerator::Product.new(1..3, [4, 5])
3560 * e.to_a #=> [[1, 4], [1, 5], [2, 4], [2, 5], [3, 4], [3, 5]]
3561 * e.size #=> 6
3562 */
3563static VALUE
3564enum_product_initialize(int argc, VALUE *argv, VALUE obj)
3565{
3566 struct enum_product *ptr;
3567 VALUE enums = Qnil, options = Qnil;
3568
3569 rb_scan_args(argc, argv, "*:", &enums, &options);
3570
3571 if (!NIL_P(options) && !RHASH_EMPTY_P(options)) {
3572 rb_exc_raise(rb_keyword_error_new("unknown", rb_hash_keys(options)));
3573 }
3574
3575 rb_check_frozen(obj);
3576 TypedData_Get_Struct(obj, struct enum_product, &enum_product_data_type, ptr);
3577
3578 if (!ptr) rb_raise(rb_eArgError, "unallocated product");
3579
3580 RB_OBJ_WRITE(obj, &ptr->enums, rb_ary_freeze(enums));
3581
3582 return obj;
3583}
3584
3585/* :nodoc: */
3586static VALUE
3587enum_product_init_copy(VALUE obj, VALUE orig)
3588{
3589 struct enum_product *ptr0, *ptr1;
3590
3591 if (!OBJ_INIT_COPY(obj, orig)) return obj;
3592 ptr0 = enum_product_ptr(orig);
3593
3594 TypedData_Get_Struct(obj, struct enum_product, &enum_product_data_type, ptr1);
3595
3596 if (!ptr1) rb_raise(rb_eArgError, "unallocated product");
3597
3598 RB_OBJ_WRITE(obj, &ptr1->enums, ptr0->enums);
3599
3600 return obj;
3601}
3602
3603static VALUE
3604enum_product_total_size(VALUE enums)
3605{
3606 VALUE total = INT2FIX(1);
3607 VALUE sizes = rb_ary_hidden_new(RARRAY_LEN(enums));
3608 long i;
3609
3610 for (i = 0; i < RARRAY_LEN(enums); i++) {
3611 VALUE size = enum_size(RARRAY_AREF(enums, i));
3612 if (size == INT2FIX(0)) {
3613 rb_ary_resize(sizes, 0);
3614 return size;
3615 }
3616 rb_ary_push(sizes, size);
3617 }
3618 for (i = 0; i < RARRAY_LEN(sizes); i++) {
3619 VALUE size = RARRAY_AREF(sizes, i);
3620
3621 if (NIL_P(size) || (RB_TYPE_P(size, T_FLOAT) && isinf(NUM2DBL(size)))) {
3622 return size;
3623 }
3624 if (!RB_INTEGER_TYPE_P(size)) {
3625 return Qnil;
3626 }
3627
3628 total = rb_funcall(total, '*', 1, size);
3629 }
3630
3631 return total;
3632}
3633
3634/*
3635 * call-seq:
3636 * obj.size -> int, Float::INFINITY or nil
3637 *
3638 * Returns the total size of the enumerator product calculated by
3639 * multiplying the sizes of enumerables in the product. If any of the
3640 * enumerables reports its size as nil or Float::INFINITY, that value
3641 * is returned as the size.
3642 */
3643static VALUE
3644enum_product_size(VALUE obj)
3645{
3646 return enum_product_total_size(enum_product_ptr(obj)->enums);
3647}
3648
3649static VALUE
3650enum_product_enum_size(VALUE obj, VALUE args, VALUE eobj)
3651{
3652 return enum_product_size(obj);
3653}
3654
3656 VALUE obj;
3657 VALUE block;
3658 int index;
3659 int argc;
3660 VALUE *argv;
3661};
3662
3663static VALUE product_each(VALUE, struct product_state *);
3664
3665static VALUE
3666product_each_i(RB_BLOCK_CALL_FUNC_ARGLIST(value, state))
3667{
3668 struct product_state *pstate = (struct product_state *)state;
3669 pstate->argv[pstate->index++] = value;
3670
3671 VALUE val = product_each(pstate->obj, pstate);
3672 pstate->index--;
3673 return val;
3674}
3675
3676static VALUE
3677product_each(VALUE obj, struct product_state *pstate)
3678{
3679 struct enum_product *ptr = enum_product_ptr(obj);
3680 VALUE enums = ptr->enums;
3681
3682 if (pstate->index < pstate->argc) {
3683 VALUE eobj = RARRAY_AREF(enums, pstate->index);
3684
3685 rb_block_call(eobj, id_each_entry, 0, NULL, product_each_i, (VALUE)pstate);
3686 }
3687 else {
3688 rb_funcall(pstate->block, id_call, 1, rb_ary_new_from_values(pstate->argc, pstate->argv));
3689 }
3690
3691 return obj;
3692}
3693
3694static VALUE
3695enum_product_run(VALUE obj, VALUE block)
3696{
3697 struct enum_product *ptr = enum_product_ptr(obj);
3698 int argc = RARRAY_LENINT(ptr->enums);
3699 if (argc == 0) { /* no need to allocate state.argv */
3700 rb_funcall(block, id_call, 1, rb_ary_new());
3701 return obj;
3702 }
3703
3704 VALUE argsbuf = 0;
3705 struct product_state state = {
3706 .obj = obj,
3707 .block = block,
3708 .index = 0,
3709 .argc = argc,
3710 .argv = ALLOCV_N(VALUE, argsbuf, argc),
3711 };
3712
3713 VALUE ret = product_each(obj, &state);
3714 ALLOCV_END(argsbuf);
3715 return ret;
3716}
3717
3718/*
3719 * call-seq:
3720 * obj.each { |...| ... } -> obj
3721 * obj.each -> enumerator
3722 *
3723 * Iterates over the elements of the first enumerable by calling the
3724 * "each_entry" method on it with the given arguments, then proceeds
3725 * to the following enumerables in sequence until all of the
3726 * enumerables are exhausted.
3727 *
3728 * If no block is given, returns an enumerator. Otherwise, returns self.
3729 */
3730static VALUE
3731enum_product_each(VALUE obj)
3732{
3733 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_product_enum_size);
3734
3735 return enum_product_run(obj, rb_block_proc());
3736}
3737
3738/*
3739 * call-seq:
3740 * obj.rewind -> obj
3741 *
3742 * Rewinds the product enumerator by calling the "rewind" method on
3743 * each enumerable in reverse order. Each call is performed only if
3744 * the enumerable responds to the method.
3745 */
3746static VALUE
3747enum_product_rewind(VALUE obj)
3748{
3749 struct enum_product *ptr = enum_product_ptr(obj);
3750 VALUE enums = ptr->enums;
3751 long i;
3752
3753 for (i = 0; i < RARRAY_LEN(enums); i++) {
3754 rb_check_funcall(RARRAY_AREF(enums, i), id_rewind, 0, 0);
3755 }
3756
3757 return obj;
3758}
3759
3760static VALUE
3761inspect_enum_product(VALUE obj, VALUE dummy, int recur)
3762{
3763 VALUE klass = rb_obj_class(obj);
3764 struct enum_product *ptr;
3765
3766 TypedData_Get_Struct(obj, struct enum_product, &enum_product_data_type, ptr);
3767
3768 if (!ptr || UNDEF_P(ptr->enums)) {
3769 return rb_sprintf("#<%"PRIsVALUE": uninitialized>", rb_class_path(klass));
3770 }
3771
3772 if (recur) {
3773 return rb_sprintf("#<%"PRIsVALUE": ...>", rb_class_path(klass));
3774 }
3775
3776 return rb_sprintf("#<%"PRIsVALUE": %+"PRIsVALUE">", rb_class_path(klass), ptr->enums);
3777}
3778
3779/*
3780 * call-seq:
3781 * obj.inspect -> string
3782 *
3783 * Returns a printable version of the product enumerator.
3784 */
3785static VALUE
3786enum_product_inspect(VALUE obj)
3787{
3788 return rb_exec_recursive(inspect_enum_product, obj, 0);
3789}
3790
3791/*
3792 * call-seq:
3793 * Enumerator.product(*enums) -> enumerator
3794 * Enumerator.product(*enums) { |elts| ... } -> enumerator
3795 *
3796 * Generates a new enumerator object that generates a Cartesian
3797 * product of given enumerable objects. This is equivalent to
3798 * Enumerator::Product.new.
3799 *
3800 * e = Enumerator.product(1..3, [4, 5])
3801 * e.to_a #=> [[1, 4], [1, 5], [2, 4], [2, 5], [3, 4], [3, 5]]
3802 * e.size #=> 6
3803 *
3804 * When a block is given, calls the block with each N-element array
3805 * generated and returns +nil+.
3806 */
3807static VALUE
3808enumerator_s_product(int argc, VALUE *argv, VALUE klass)
3809{
3810 VALUE enums = Qnil, options = Qnil, block = Qnil;
3811
3812 rb_scan_args(argc, argv, "*:&", &enums, &options, &block);
3813
3814 if (!NIL_P(options) && !RHASH_EMPTY_P(options)) {
3815 rb_exc_raise(rb_keyword_error_new("unknown", rb_hash_keys(options)));
3816 }
3817
3818 VALUE obj = enum_product_initialize(argc, argv, enum_product_allocate(rb_cEnumProduct));
3819
3820 if (!NIL_P(block)) {
3821 enum_product_run(obj, block);
3822 return Qnil;
3823 }
3824
3825 return obj;
3826}
3827
3829 struct enumerator enumerator;
3830 VALUE begin;
3831 VALUE end;
3832 VALUE step;
3833 bool exclude_end;
3834};
3835
3836RUBY_REFERENCES(arith_seq_refs) = {
3837 RUBY_REF_EDGE(struct enumerator, obj),
3838 RUBY_REF_EDGE(struct enumerator, args),
3839 RUBY_REF_EDGE(struct enumerator, fib),
3840 RUBY_REF_EDGE(struct enumerator, dst),
3841 RUBY_REF_EDGE(struct enumerator, lookahead),
3842 RUBY_REF_EDGE(struct enumerator, feedvalue),
3843 RUBY_REF_EDGE(struct enumerator, stop_exc),
3844 RUBY_REF_EDGE(struct enumerator, size),
3845 RUBY_REF_EDGE(struct enumerator, procs),
3846
3847 RUBY_REF_EDGE(struct arith_seq, begin),
3848 RUBY_REF_EDGE(struct arith_seq, end),
3849 RUBY_REF_EDGE(struct arith_seq, step),
3850 RUBY_REF_END
3851};
3852
3853static const rb_data_type_t arith_seq_data_type = {
3854 "arithmetic_sequence",
3855 {
3856 RUBY_REFS_LIST_PTR(arith_seq_refs),
3858 NULL, // Nothing allocated externally, so don't need a memsize function
3859 NULL,
3860 },
3861 .parent = &enumerator_data_type,
3862 .flags = RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_DECL_MARKING | RUBY_TYPED_EMBEDDABLE
3863};
3864
3865static VALUE
3866arith_seq_allocate(VALUE klass)
3867{
3868 struct arith_seq *ptr;
3869 VALUE enum_obj;
3870
3871 enum_obj = TypedData_Make_Struct(klass, struct arith_seq, &arith_seq_data_type, ptr);
3872 ptr->enumerator.obj = Qundef;
3873
3874 return enum_obj;
3875}
3876
3877/*
3878 * Document-class: Enumerator::ArithmeticSequence
3879 *
3880 * Enumerator::ArithmeticSequence is a subclass of Enumerator,
3881 * that is a representation of sequences of numbers with common difference.
3882 * Instances of this class can be generated by the Range#step and Numeric#step
3883 * methods.
3884 *
3885 * The class can be used for slicing Array (see Array#slice) or custom
3886 * collections.
3887 */
3888
3889VALUE
3890rb_arith_seq_new(VALUE obj, VALUE meth, int argc, VALUE const *argv,
3891 rb_enumerator_size_func *size_fn,
3892 VALUE beg, VALUE end, VALUE step, int excl)
3893{
3894 VALUE aseq = enumerator_init(arith_seq_allocate(rb_cArithSeq),
3895 obj, meth, argc, argv, size_fn, Qnil, rb_keyword_given_p());
3896 struct arith_seq *ptr;
3897 TypedData_Get_Struct(aseq, struct arith_seq, &enumerator_data_type, ptr);
3898
3899 RB_OBJ_WRITE(aseq, &ptr->begin, beg);
3900 RB_OBJ_WRITE(aseq, &ptr->end, end);
3901 RB_OBJ_WRITE(aseq, &ptr->step, step);
3902 ptr->exclude_end = excl;
3903
3904 return aseq;
3905}
3906
3907/*
3908 * call-seq: aseq.begin -> num or nil
3909 *
3910 * Returns the number that defines the first element of this arithmetic
3911 * sequence.
3912 */
3913static inline VALUE
3914arith_seq_begin(VALUE self)
3915{
3916 struct arith_seq *ptr;
3917 TypedData_Get_Struct(self, struct arith_seq, &enumerator_data_type, ptr);
3918 return ptr->begin;
3919}
3920
3921/*
3922 * call-seq: aseq.end -> num or nil
3923 *
3924 * Returns the number that defines the end of this arithmetic sequence.
3925 */
3926static inline VALUE
3927arith_seq_end(VALUE self)
3928{
3929 struct arith_seq *ptr;
3930 TypedData_Get_Struct(self, struct arith_seq, &enumerator_data_type, ptr);
3931 return ptr->end;
3932}
3933
3934/*
3935 * call-seq: aseq.step -> num
3936 *
3937 * Returns the number that defines the common difference between
3938 * two adjacent elements in this arithmetic sequence.
3939 */
3940static inline VALUE
3941arith_seq_step(VALUE self)
3942{
3943 struct arith_seq *ptr;
3944 TypedData_Get_Struct(self, struct arith_seq, &enumerator_data_type, ptr);
3945 return ptr->step;
3946}
3947
3948/*
3949 * call-seq: aseq.exclude_end? -> true or false
3950 *
3951 * Returns <code>true</code> if this arithmetic sequence excludes its end value.
3952 */
3953static inline VALUE
3954arith_seq_exclude_end(VALUE self)
3955{
3956 struct arith_seq *ptr;
3957 TypedData_Get_Struct(self, struct arith_seq, &enumerator_data_type, ptr);
3958 return RBOOL(ptr->exclude_end);
3959}
3960
3961static inline int
3962arith_seq_exclude_end_p(VALUE self)
3963{
3964 struct arith_seq *ptr;
3965 TypedData_Get_Struct(self, struct arith_seq, &enumerator_data_type, ptr);
3966 return ptr->exclude_end;
3967}
3968
3969int
3970rb_arithmetic_sequence_extract(VALUE obj, rb_arithmetic_sequence_components_t *component)
3971{
3972 if (rb_obj_is_kind_of(obj, rb_cArithSeq)) {
3973 component->begin = arith_seq_begin(obj);
3974 component->end = arith_seq_end(obj);
3975 component->step = arith_seq_step(obj);
3976 component->exclude_end = arith_seq_exclude_end_p(obj);
3977 return 1;
3978 }
3979 else if (rb_range_values(obj, &component->begin, &component->end, &component->exclude_end)) {
3980 component->step = INT2FIX(1);
3981 return 1;
3982 }
3983
3984 return 0;
3985}
3986
3987VALUE
3988rb_arithmetic_sequence_beg_len_step(VALUE obj, long *begp, long *lenp, long *stepp, long len, int err)
3989{
3990 RBIMPL_NONNULL_ARG(begp);
3991 RBIMPL_NONNULL_ARG(lenp);
3992 RBIMPL_NONNULL_ARG(stepp);
3993
3995 if (!rb_arithmetic_sequence_extract(obj, &aseq)) {
3996 return Qfalse;
3997 }
3998
3999 long step = NIL_P(aseq.step) ? 1 : NUM2LONG(aseq.step);
4000 *stepp = step;
4001
4002 if (step < 0) {
4003 if (aseq.exclude_end && !NIL_P(aseq.end)) {
4004 /* Handle exclusion before range reversal */
4005 aseq.end = LONG2NUM(NUM2LONG(aseq.end) + 1);
4006
4007 /* Don't exclude the previous beginning */
4008 aseq.exclude_end = 0;
4009 }
4010 VALUE tmp = aseq.begin;
4011 aseq.begin = aseq.end;
4012 aseq.end = tmp;
4013 }
4014
4015 if (err == 0 && (step < -1 || step > 1)) {
4016 if (rb_range_component_beg_len(aseq.begin, aseq.end, aseq.exclude_end, begp, lenp, len, 1) == Qtrue) {
4017 if (*begp > len)
4018 goto out_of_range;
4019 if (*lenp > len)
4020 goto out_of_range;
4021 return Qtrue;
4022 }
4023 }
4024 else {
4025 return rb_range_component_beg_len(aseq.begin, aseq.end, aseq.exclude_end, begp, lenp, len, err);
4026 }
4027
4028 out_of_range:
4029 rb_raise(rb_eRangeError, "%+"PRIsVALUE" out of range", obj);
4030 return Qnil;
4031}
4032
4033static VALUE
4034arith_seq_take(VALUE self, VALUE num)
4035{
4036 VALUE b, e, s, ary;
4037 long n;
4038 int x;
4039
4040 n = NUM2LONG(num);
4041 if (n < 0) {
4042 rb_raise(rb_eArgError, "attempt to take negative size");
4043 }
4044 if (n == 0) {
4045 return rb_ary_new_capa(0);
4046 }
4047
4048 b = arith_seq_begin(self);
4049 e = arith_seq_end(self);
4050 s = arith_seq_step(self);
4051 x = arith_seq_exclude_end_p(self);
4052
4053 if (FIXNUM_P(b) && NIL_P(e) && FIXNUM_P(s)) {
4054 long i = FIX2LONG(b), unit = FIX2LONG(s);
4055 ary = rb_ary_new_capa(n);
4056 while (n > 0 && FIXABLE(i)) {
4057 rb_ary_push(ary, LONG2FIX(i));
4058 i += unit; // FIXABLE + FIXABLE never overflow;
4059 --n;
4060 }
4061 if (n > 0) {
4062 b = LONG2NUM(i);
4063 while (n > 0) {
4064 rb_ary_push(ary, b);
4065 b = rb_big_plus(b, s);
4066 --n;
4067 }
4068 }
4069 return ary;
4070 }
4071 else if (FIXNUM_P(b) && FIXNUM_P(e) && FIXNUM_P(s)) {
4072 long i = FIX2LONG(b);
4073 long end = FIX2LONG(e);
4074 long unit = FIX2LONG(s);
4075 long len;
4076
4077 if (unit >= 0) {
4078 if (!x) end += 1;
4079
4080 len = end - i;
4081 if (len < 0) len = 0;
4082 ary = rb_ary_new_capa((n < len) ? n : len);
4083 while (n > 0 && i < end) {
4084 rb_ary_push(ary, LONG2FIX(i));
4085 if (i > LONG_MAX - unit) break;
4086 i += unit;
4087 --n;
4088 }
4089 }
4090 else {
4091 if (!x) end -= 1;
4092
4093 len = i - end;
4094 if (len < 0) len = 0;
4095 ary = rb_ary_new_capa((n < len) ? n : len);
4096 while (n > 0 && i > end) {
4097 rb_ary_push(ary, LONG2FIX(i));
4098 if (i < LONG_MIN - unit) break;
4099 i += unit;
4100 --n;
4101 }
4102 }
4103 return ary;
4104 }
4105 else if (RB_FLOAT_TYPE_P(b) || RB_FLOAT_TYPE_P(e) || RB_FLOAT_TYPE_P(s)) {
4106 /* generate values like ruby_float_step */
4107
4108 double unit = NUM2DBL(s);
4109 double beg = NUM2DBL(b);
4110 double end = NIL_P(e) ? (unit < 0 ? -1 : 1)*HUGE_VAL : NUM2DBL(e);
4111 double len = ruby_float_step_size(beg, end, unit, x);
4112 long i;
4113
4114 if (n > len)
4115 n = (long)len;
4116
4117 if (isinf(unit)) {
4118 if (len > 0) {
4119 ary = rb_ary_new_capa(1);
4120 rb_ary_push(ary, DBL2NUM(beg));
4121 }
4122 else {
4123 ary = rb_ary_new_capa(0);
4124 }
4125 }
4126 else if (unit == 0) {
4127 VALUE val = DBL2NUM(beg);
4128 ary = rb_ary_new_capa(n);
4129 for (i = 0; i < len; ++i) {
4130 rb_ary_push(ary, val);
4131 }
4132 }
4133 else {
4134 ary = rb_ary_new_capa(n);
4135 for (i = 0; i < n; ++i) {
4136 double d = i*unit+beg;
4137 if (unit >= 0 ? end < d : d < end) d = end;
4138 rb_ary_push(ary, DBL2NUM(d));
4139 }
4140 }
4141
4142 return ary;
4143 }
4144
4145 {
4146 VALUE argv[1];
4147 argv[0] = num;
4148 return rb_call_super(1, argv);
4149 }
4150}
4151
4152/*
4153 * call-seq:
4154 * aseq.first -> num or nil
4155 * aseq.first(n) -> an_array
4156 *
4157 * Returns the first number in this arithmetic sequence,
4158 * or an array of the first +n+ elements.
4159 */
4160static VALUE
4161arith_seq_first(int argc, VALUE *argv, VALUE self)
4162{
4163 VALUE b, e, s;
4164
4165 rb_check_arity(argc, 0, 1);
4166
4167 b = arith_seq_begin(self);
4168 e = arith_seq_end(self);
4169 s = arith_seq_step(self);
4170 if (argc == 0) {
4171 if (NIL_P(b)) {
4172 return Qnil;
4173 }
4174 if (!NIL_P(e)) {
4175 VALUE zero = INT2FIX(0);
4176 int r = rb_cmpint(rb_num_coerce_cmp(s, zero, idCmp), s, zero);
4177 if (r > 0 && RTEST(rb_funcall(b, '>', 1, e))) {
4178 return Qnil;
4179 }
4180 if (r < 0 && RTEST(rb_funcall(b, '<', 1, e))) {
4181 return Qnil;
4182 }
4183 }
4184 return b;
4185 }
4186
4187 return arith_seq_take(self, argv[0]);
4188}
4189
4190static inline VALUE
4191num_plus(VALUE a, VALUE b)
4192{
4193 if (RB_INTEGER_TYPE_P(a)) {
4194 return rb_int_plus(a, b);
4195 }
4196 else if (RB_FLOAT_TYPE_P(a)) {
4197 return rb_float_plus(a, b);
4198 }
4199 else if (RB_TYPE_P(a, T_RATIONAL)) {
4200 return rb_rational_plus(a, b);
4201 }
4202 else {
4203 return rb_funcallv(a, '+', 1, &b);
4204 }
4205}
4206
4207static inline VALUE
4208num_minus(VALUE a, VALUE b)
4209{
4210 if (RB_INTEGER_TYPE_P(a)) {
4211 return rb_int_minus(a, b);
4212 }
4213 else if (RB_FLOAT_TYPE_P(a)) {
4214 return rb_float_minus(a, b);
4215 }
4216 else if (RB_TYPE_P(a, T_RATIONAL)) {
4217 return rb_rational_minus(a, b);
4218 }
4219 else {
4220 return rb_funcallv(a, '-', 1, &b);
4221 }
4222}
4223
4224static inline VALUE
4225num_mul(VALUE a, VALUE b)
4226{
4227 if (RB_INTEGER_TYPE_P(a)) {
4228 return rb_int_mul(a, b);
4229 }
4230 else if (RB_FLOAT_TYPE_P(a)) {
4231 return rb_float_mul(a, b);
4232 }
4233 else if (RB_TYPE_P(a, T_RATIONAL)) {
4234 return rb_rational_mul(a, b);
4235 }
4236 else {
4237 return rb_funcallv(a, '*', 1, &b);
4238 }
4239}
4240
4241static inline VALUE
4242num_idiv(VALUE a, VALUE b)
4243{
4244 VALUE q;
4245 if (RB_INTEGER_TYPE_P(a)) {
4246 q = rb_int_idiv(a, b);
4247 }
4248 else if (RB_FLOAT_TYPE_P(a)) {
4249 q = rb_float_div(a, b);
4250 }
4251 else if (RB_TYPE_P(a, T_RATIONAL)) {
4252 q = rb_rational_div(a, b);
4253 }
4254 else {
4255 q = rb_funcallv(a, idDiv, 1, &b);
4256 }
4257
4258 if (RB_INTEGER_TYPE_P(q)) {
4259 return q;
4260 }
4261 else if (RB_FLOAT_TYPE_P(q)) {
4262 return rb_float_floor(q, 0);
4263 }
4264 else if (RB_TYPE_P(q, T_RATIONAL)) {
4265 return rb_rational_floor(q, 0);
4266 }
4267 else {
4268 return rb_funcall(q, rb_intern("floor"), 0);
4269 }
4270}
4271
4272/*
4273 * call-seq:
4274 * aseq.last -> num or nil
4275 * aseq.last(n) -> an_array
4276 *
4277 * Returns the last number in this arithmetic sequence,
4278 * or an array of the last +n+ elements.
4279 */
4280static VALUE
4281arith_seq_last(int argc, VALUE *argv, VALUE self)
4282{
4283 VALUE b, e, s, len_1, len, last, nv, ary;
4284 int last_is_adjusted;
4285 long n;
4286
4287 e = arith_seq_end(self);
4288 if (NIL_P(e)) {
4289 rb_raise(rb_eRangeError,
4290 "cannot get the last element of endless arithmetic sequence");
4291 }
4292
4293 b = arith_seq_begin(self);
4294 s = arith_seq_step(self);
4295
4296 len_1 = num_idiv(num_minus(e, b), s);
4297 if (rb_num_negative_int_p(len_1)) {
4298 if (argc == 0) {
4299 return Qnil;
4300 }
4301 return rb_ary_new_capa(0);
4302 }
4303
4304 last = num_plus(b, num_mul(s, len_1));
4305 if ((last_is_adjusted = arith_seq_exclude_end_p(self) && rb_equal(last, e))) {
4306 last = num_minus(last, s);
4307 }
4308
4309 if (argc == 0) {
4310 return last;
4311 }
4312
4313 if (last_is_adjusted) {
4314 len = len_1;
4315 }
4316 else {
4317 len = rb_int_plus(len_1, INT2FIX(1));
4318 }
4319
4320 rb_scan_args(argc, argv, "1", &nv);
4321 if (!RB_INTEGER_TYPE_P(nv)) {
4322 nv = rb_to_int(nv);
4323 }
4324 if (RTEST(rb_int_gt(nv, len))) {
4325 nv = len;
4326 }
4327 n = NUM2LONG(nv);
4328 if (n < 0) {
4329 rb_raise(rb_eArgError, "negative array size");
4330 }
4331
4332 ary = rb_ary_new_capa(n);
4333 b = rb_int_minus(last, rb_int_mul(s, nv));
4334 while (n) {
4335 b = rb_int_plus(b, s);
4336 rb_ary_push(ary, b);
4337 --n;
4338 }
4339
4340 return ary;
4341}
4342
4343/*
4344 * call-seq:
4345 * aseq.inspect -> string
4346 *
4347 * Convert this arithmetic sequence to a printable form.
4348 */
4349static VALUE
4350arith_seq_inspect(VALUE self)
4351{
4352 struct enumerator *e;
4353 VALUE eobj, str;
4354 int range_p;
4355
4356 TypedData_Get_Struct(self, struct enumerator, &enumerator_data_type, e);
4357
4358 eobj = rb_attr_get(self, id_receiver);
4359 if (NIL_P(eobj)) {
4360 eobj = e->obj;
4361 }
4362
4363 range_p = RTEST(rb_obj_is_kind_of(eobj, rb_cRange));
4364 str = rb_sprintf("(%s%"PRIsVALUE"%s.", range_p ? "(" : "", eobj, range_p ? ")" : "");
4365
4366 rb_str_buf_append(str, rb_id2str(e->meth));
4367 append_method_args(eobj, str, e->args);
4368
4369 rb_str_buf_cat2(str, ")");
4370
4371 return str;
4372}
4373
4374/*
4375 * call-seq:
4376 * aseq == obj -> true or false
4377 *
4378 * Returns <code>true</code> only if +obj+ is an Enumerator::ArithmeticSequence,
4379 * has equivalent begin, end, step, and exclude_end? settings.
4380 */
4381static VALUE
4382arith_seq_eq(VALUE self, VALUE other)
4383{
4384 if (!RTEST(rb_obj_is_kind_of(other, rb_cArithSeq))) {
4385 return Qfalse;
4386 }
4387
4388 if (!rb_equal(arith_seq_begin(self), arith_seq_begin(other))) {
4389 return Qfalse;
4390 }
4391
4392 if (!rb_equal(arith_seq_end(self), arith_seq_end(other))) {
4393 return Qfalse;
4394 }
4395
4396 if (!rb_equal(arith_seq_step(self), arith_seq_step(other))) {
4397 return Qfalse;
4398 }
4399
4400 if (arith_seq_exclude_end_p(self) != arith_seq_exclude_end_p(other)) {
4401 return Qfalse;
4402 }
4403
4404 return Qtrue;
4405}
4406
4407/*
4408 * call-seq:
4409 * aseq.hash -> integer
4410 *
4411 * Compute a hash-value for this arithmetic sequence.
4412 * Two arithmetic sequences with same begin, end, step, and exclude_end?
4413 * values will generate the same hash-value.
4414 *
4415 * See also Object#hash.
4416 */
4417static VALUE
4418arith_seq_hash(VALUE self)
4419{
4420 st_index_t hash;
4421 VALUE v;
4422
4423 hash = rb_hash_start(arith_seq_exclude_end_p(self));
4424 v = rb_hash(arith_seq_begin(self));
4425 hash = rb_hash_uint(hash, NUM2LONG(v));
4426 v = rb_hash(arith_seq_end(self));
4427 hash = rb_hash_uint(hash, NUM2LONG(v));
4428 v = rb_hash(arith_seq_step(self));
4429 hash = rb_hash_uint(hash, NUM2LONG(v));
4430 hash = rb_hash_end(hash);
4431
4432 return ST2FIX(hash);
4433}
4434
4435#define NUM_GE(x, y) RTEST(rb_num_coerce_relop((x), (y), idGE))
4436
4438 VALUE current;
4439 VALUE end;
4440 VALUE step;
4441 int excl;
4442};
4443
4444/*
4445 * call-seq:
4446 * aseq.each {|i| block } -> aseq
4447 * aseq.each -> aseq
4448 */
4449static VALUE
4450arith_seq_each(VALUE self)
4451{
4452 VALUE c, e, s, len_1, last;
4453 int x;
4454
4455 if (!rb_block_given_p()) return self;
4456
4457 c = arith_seq_begin(self);
4458 e = arith_seq_end(self);
4459 s = arith_seq_step(self);
4460 x = arith_seq_exclude_end_p(self);
4461
4462 if (!RB_TYPE_P(s, T_COMPLEX) && ruby_float_step(c, e, s, x, TRUE)) {
4463 return self;
4464 }
4465
4466 if (NIL_P(e)) {
4467 while (1) {
4468 rb_yield(c);
4469 c = rb_int_plus(c, s);
4470 }
4471
4472 return self;
4473 }
4474
4475 if (rb_equal(s, INT2FIX(0))) {
4476 while (1) {
4477 rb_yield(c);
4478 }
4479
4480 return self;
4481 }
4482
4483 len_1 = num_idiv(num_minus(e, c), s);
4484 last = num_plus(c, num_mul(s, len_1));
4485 if (x && rb_equal(last, e)) {
4486 last = num_minus(last, s);
4487 }
4488
4489 if (rb_num_negative_int_p(s)) {
4490 while (NUM_GE(c, last)) {
4491 rb_yield(c);
4492 c = num_plus(c, s);
4493 }
4494 }
4495 else {
4496 while (NUM_GE(last, c)) {
4497 rb_yield(c);
4498 c = num_plus(c, s);
4499 }
4500 }
4501
4502 return self;
4503}
4504
4505/*
4506 * call-seq:
4507 * aseq.size -> num or nil
4508 *
4509 * Returns the number of elements in this arithmetic sequence if it is a finite
4510 * sequence. Otherwise, returns <code>nil</code>.
4511 */
4512static VALUE
4513arith_seq_size(VALUE self)
4514{
4515 VALUE b, e, s, len_1, len, last;
4516 int x;
4517
4518 b = arith_seq_begin(self);
4519 e = arith_seq_end(self);
4520 s = arith_seq_step(self);
4521 x = arith_seq_exclude_end_p(self);
4522
4523 if (RB_FLOAT_TYPE_P(b) || RB_FLOAT_TYPE_P(e) || RB_FLOAT_TYPE_P(s)) {
4524 double ee, n;
4525
4526 if (NIL_P(e)) {
4527 if (rb_num_negative_int_p(s)) {
4528 ee = -HUGE_VAL;
4529 }
4530 else {
4531 ee = HUGE_VAL;
4532 }
4533 }
4534 else {
4535 ee = NUM2DBL(e);
4536 }
4537
4538 n = ruby_float_step_size(NUM2DBL(b), ee, NUM2DBL(s), x);
4539 if (isinf(n)) return DBL2NUM(n);
4540 if (POSFIXABLE(n)) return LONG2FIX((long)n);
4541 return rb_dbl2big(n);
4542 }
4543
4544 if (NIL_P(e)) {
4545 return DBL2NUM(HUGE_VAL);
4546 }
4547
4548 if (!rb_obj_is_kind_of(s, rb_cNumeric)) {
4549 s = rb_to_int(s);
4550 }
4551
4552 if (rb_equal(s, INT2FIX(0))) {
4553 return DBL2NUM(HUGE_VAL);
4554 }
4555
4556 len_1 = rb_int_idiv(rb_int_minus(e, b), s);
4557 if (rb_num_negative_int_p(len_1)) {
4558 return INT2FIX(0);
4559 }
4560
4561 last = rb_int_plus(b, rb_int_mul(s, len_1));
4562 if (x && rb_equal(last, e)) {
4563 len = len_1;
4564 }
4565 else {
4566 len = rb_int_plus(len_1, INT2FIX(1));
4567 }
4568
4569 return len;
4570}
4571
4572#define sym(name) ID2SYM(rb_intern_const(name))
4573void
4574InitVM_Enumerator(void)
4575{
4576 ID id_private = rb_intern_const("private");
4577
4578 rb_define_method(rb_mKernel, "to_enum", obj_to_enum, -1);
4579 rb_define_method(rb_mKernel, "enum_for", obj_to_enum, -1);
4580
4581 rb_cEnumerator = rb_define_class("Enumerator", rb_cObject);
4583
4584 rb_define_alloc_func(rb_cEnumerator, enumerator_allocate);
4585 rb_define_method(rb_cEnumerator, "initialize", enumerator_initialize, -1);
4586 rb_define_method(rb_cEnumerator, "initialize_copy", enumerator_init_copy, 1);
4587 rb_define_method(rb_cEnumerator, "each", enumerator_each, -1);
4588 rb_define_method(rb_cEnumerator, "each_with_index", enumerator_each_with_index, 0);
4589 rb_define_method(rb_cEnumerator, "each_with_object", enumerator_with_object, 1);
4590 rb_define_method(rb_cEnumerator, "with_index", enumerator_with_index, -1);
4591 rb_define_method(rb_cEnumerator, "with_object", enumerator_with_object, 1);
4592 rb_define_method(rb_cEnumerator, "next_values", enumerator_next_values, 0);
4593 rb_define_method(rb_cEnumerator, "peek_values", enumerator_peek_values_m, 0);
4594 rb_define_method(rb_cEnumerator, "next", enumerator_next, 0);
4595 rb_define_method(rb_cEnumerator, "peek", enumerator_peek, 0);
4596 rb_define_method(rb_cEnumerator, "feed", enumerator_feed, 1);
4597 rb_define_method(rb_cEnumerator, "rewind", enumerator_rewind, 0);
4598 rb_define_method(rb_cEnumerator, "inspect", enumerator_inspect, 0);
4599 rb_define_method(rb_cEnumerator, "size", enumerator_size, 0);
4600 rb_define_method(rb_cEnumerator, "+", enumerator_plus, 1);
4602
4603 /* Lazy */
4604 rb_cLazy = rb_define_class_under(rb_cEnumerator, "Lazy", rb_cEnumerator);
4605 rb_define_method(rb_mEnumerable, "lazy", enumerable_lazy, 0);
4606
4607 rb_define_alias(rb_cLazy, "_enumerable_map", "map");
4608 rb_define_alias(rb_cLazy, "_enumerable_collect", "collect");
4609 rb_define_alias(rb_cLazy, "_enumerable_flat_map", "flat_map");
4610 rb_define_alias(rb_cLazy, "_enumerable_collect_concat", "collect_concat");
4611 rb_define_alias(rb_cLazy, "_enumerable_select", "select");
4612 rb_define_alias(rb_cLazy, "_enumerable_find_all", "find_all");
4613 rb_define_alias(rb_cLazy, "_enumerable_filter", "filter");
4614 rb_define_alias(rb_cLazy, "_enumerable_filter_map", "filter_map");
4615 rb_define_alias(rb_cLazy, "_enumerable_reject", "reject");
4616 rb_define_alias(rb_cLazy, "_enumerable_grep", "grep");
4617 rb_define_alias(rb_cLazy, "_enumerable_grep_v", "grep_v");
4618 rb_define_alias(rb_cLazy, "_enumerable_zip", "zip");
4619 rb_define_alias(rb_cLazy, "_enumerable_take", "take");
4620 rb_define_alias(rb_cLazy, "_enumerable_take_while", "take_while");
4621 rb_define_alias(rb_cLazy, "_enumerable_drop", "drop");
4622 rb_define_alias(rb_cLazy, "_enumerable_drop_while", "drop_while");
4623 rb_define_alias(rb_cLazy, "_enumerable_uniq", "uniq");
4624 rb_define_private_method(rb_cLazy, "_enumerable_with_index", enumerator_with_index, -1);
4625
4626 rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_map"));
4627 rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_collect"));
4628 rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_flat_map"));
4629 rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_collect_concat"));
4630 rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_select"));
4631 rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_find_all"));
4632 rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_filter"));
4633 rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_filter_map"));
4634 rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_reject"));
4635 rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_grep"));
4636 rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_grep_v"));
4637 rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_zip"));
4638 rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_take"));
4639 rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_take_while"));
4640 rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_drop"));
4641 rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_drop_while"));
4642 rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_uniq"));
4643
4644 rb_define_method(rb_cLazy, "initialize", lazy_initialize, -1);
4645 rb_define_method(rb_cLazy, "to_enum", lazy_to_enum, -1);
4646 rb_define_method(rb_cLazy, "enum_for", lazy_to_enum, -1);
4647 rb_define_method(rb_cLazy, "eager", lazy_eager, 0);
4648 rb_define_method(rb_cLazy, "map", lazy_map, 0);
4649 rb_define_method(rb_cLazy, "collect", lazy_map, 0);
4650 rb_define_method(rb_cLazy, "flat_map", lazy_flat_map, 0);
4651 rb_define_method(rb_cLazy, "collect_concat", lazy_flat_map, 0);
4652 rb_define_method(rb_cLazy, "select", lazy_select, 0);
4653 rb_define_method(rb_cLazy, "find_all", lazy_select, 0);
4654 rb_define_method(rb_cLazy, "filter", lazy_select, 0);
4655 rb_define_method(rb_cLazy, "filter_map", lazy_filter_map, 0);
4656 rb_define_method(rb_cLazy, "reject", lazy_reject, 0);
4657 rb_define_method(rb_cLazy, "grep", lazy_grep, 1);
4658 rb_define_method(rb_cLazy, "grep_v", lazy_grep_v, 1);
4659 rb_define_method(rb_cLazy, "zip", lazy_zip, -1);
4660 rb_define_method(rb_cLazy, "take", lazy_take, 1);
4661 rb_define_method(rb_cLazy, "take_while", lazy_take_while, 0);
4662 rb_define_method(rb_cLazy, "drop", lazy_drop, 1);
4663 rb_define_method(rb_cLazy, "drop_while", lazy_drop_while, 0);
4664 rb_define_method(rb_cLazy, "lazy", lazy_lazy, 0);
4665 rb_define_method(rb_cLazy, "chunk", lazy_super, -1);
4666 rb_define_method(rb_cLazy, "slice_before", lazy_super, -1);
4667 rb_define_method(rb_cLazy, "slice_after", lazy_super, -1);
4668 rb_define_method(rb_cLazy, "slice_when", lazy_super, -1);
4669 rb_define_method(rb_cLazy, "chunk_while", lazy_super, -1);
4670 rb_define_method(rb_cLazy, "uniq", lazy_uniq, 0);
4671 rb_define_method(rb_cLazy, "compact", lazy_compact, 0);
4672 rb_define_method(rb_cLazy, "with_index", lazy_with_index, -1);
4673 rb_define_method(rb_cLazy, "tap_each", lazy_tap_each, 0);
4674
4675 lazy_use_super_method = rb_hash_new_capa(18);
4676 rb_hash_aset(lazy_use_super_method, sym("map"), sym("_enumerable_map"));
4677 rb_hash_aset(lazy_use_super_method, sym("collect"), sym("_enumerable_collect"));
4678 rb_hash_aset(lazy_use_super_method, sym("flat_map"), sym("_enumerable_flat_map"));
4679 rb_hash_aset(lazy_use_super_method, sym("collect_concat"), sym("_enumerable_collect_concat"));
4680 rb_hash_aset(lazy_use_super_method, sym("select"), sym("_enumerable_select"));
4681 rb_hash_aset(lazy_use_super_method, sym("find_all"), sym("_enumerable_find_all"));
4682 rb_hash_aset(lazy_use_super_method, sym("filter"), sym("_enumerable_filter"));
4683 rb_hash_aset(lazy_use_super_method, sym("filter_map"), sym("_enumerable_filter_map"));
4684 rb_hash_aset(lazy_use_super_method, sym("reject"), sym("_enumerable_reject"));
4685 rb_hash_aset(lazy_use_super_method, sym("grep"), sym("_enumerable_grep"));
4686 rb_hash_aset(lazy_use_super_method, sym("grep_v"), sym("_enumerable_grep_v"));
4687 rb_hash_aset(lazy_use_super_method, sym("zip"), sym("_enumerable_zip"));
4688 rb_hash_aset(lazy_use_super_method, sym("take"), sym("_enumerable_take"));
4689 rb_hash_aset(lazy_use_super_method, sym("take_while"), sym("_enumerable_take_while"));
4690 rb_hash_aset(lazy_use_super_method, sym("drop"), sym("_enumerable_drop"));
4691 rb_hash_aset(lazy_use_super_method, sym("drop_while"), sym("_enumerable_drop_while"));
4692 rb_hash_aset(lazy_use_super_method, sym("uniq"), sym("_enumerable_uniq"));
4693 rb_hash_aset(lazy_use_super_method, sym("with_index"), sym("_enumerable_with_index"));
4694 rb_obj_freeze(lazy_use_super_method);
4695 rb_vm_register_global_object(lazy_use_super_method);
4696
4697#if 0 /* for RDoc */
4698 rb_define_method(rb_cLazy, "to_a", lazy_to_a, 0);
4699 rb_define_method(rb_cLazy, "chunk", lazy_chunk, 0);
4700 rb_define_method(rb_cLazy, "chunk_while", lazy_chunk_while, 0);
4701 rb_define_method(rb_cLazy, "slice_after", lazy_slice_after, 0);
4702 rb_define_method(rb_cLazy, "slice_before", lazy_slice_before, 0);
4703 rb_define_method(rb_cLazy, "slice_when", lazy_slice_when, 0);
4704#endif
4705 rb_define_alias(rb_cLazy, "force", "to_a");
4706
4707 rb_eStopIteration = rb_define_class("StopIteration", rb_eIndexError);
4708 rb_define_method(rb_eStopIteration, "result", stop_result, 0);
4709
4710 /* :nodoc: Generator */
4711 rb_cGenerator = rb_define_class_under(rb_cEnumerator, "Generator", rb_cObject);
4712 rb_include_module(rb_cGenerator, rb_mEnumerable);
4713 rb_define_alloc_func(rb_cGenerator, generator_allocate);
4714 rb_define_method(rb_cGenerator, "initialize", generator_initialize, -1);
4715 rb_define_method(rb_cGenerator, "initialize_copy", generator_init_copy, 1);
4716 rb_define_method(rb_cGenerator, "each", generator_each, -1);
4717
4718 /* :nodoc: Yielder */
4719 rb_cYielder = rb_define_class_under(rb_cEnumerator, "Yielder", rb_cObject);
4720 rb_define_alloc_func(rb_cYielder, yielder_allocate);
4721 rb_define_method(rb_cYielder, "initialize", yielder_initialize, 0);
4722 rb_define_method(rb_cYielder, "yield", yielder_yield, -2);
4723 rb_define_method(rb_cYielder, "<<", yielder_yield_push, 1);
4724 rb_define_method(rb_cYielder, "to_proc", yielder_to_proc, 0);
4725
4726 /* :nodoc: Producer */
4727 rb_cEnumProducer = rb_define_class_under(rb_cEnumerator, "Producer", rb_cObject);
4728 rb_define_alloc_func(rb_cEnumProducer, producer_allocate);
4729 rb_define_method(rb_cEnumProducer, "each", producer_each, 0);
4730 rb_define_singleton_method(rb_cEnumerator, "produce", enumerator_s_produce, -1);
4731
4732 /* Chain */
4733 rb_cEnumChain = rb_define_class_under(rb_cEnumerator, "Chain", rb_cEnumerator);
4734 rb_define_alloc_func(rb_cEnumChain, enum_chain_allocate);
4735 rb_define_method(rb_cEnumChain, "initialize", enum_chain_initialize, -2);
4736 rb_define_method(rb_cEnumChain, "initialize_copy", enum_chain_init_copy, 1);
4737 rb_define_method(rb_cEnumChain, "each", enum_chain_each, -1);
4738 rb_define_method(rb_cEnumChain, "size", enum_chain_size, 0);
4739 rb_define_method(rb_cEnumChain, "rewind", enum_chain_rewind, 0);
4740 rb_define_method(rb_cEnumChain, "inspect", enum_chain_inspect, 0);
4741 rb_undef_method(rb_cEnumChain, "feed");
4742 rb_undef_method(rb_cEnumChain, "next");
4743 rb_undef_method(rb_cEnumChain, "next_values");
4744 rb_undef_method(rb_cEnumChain, "peek");
4745 rb_undef_method(rb_cEnumChain, "peek_values");
4746
4747 /* Product */
4748 rb_cEnumProduct = rb_define_class_under(rb_cEnumerator, "Product", rb_cEnumerator);
4749 rb_define_alloc_func(rb_cEnumProduct, enum_product_allocate);
4750 rb_define_method(rb_cEnumProduct, "initialize", enum_product_initialize, -1);
4751 rb_define_method(rb_cEnumProduct, "initialize_copy", enum_product_init_copy, 1);
4752 rb_define_method(rb_cEnumProduct, "each", enum_product_each, 0);
4753 rb_define_method(rb_cEnumProduct, "size", enum_product_size, 0);
4754 rb_define_method(rb_cEnumProduct, "rewind", enum_product_rewind, 0);
4755 rb_define_method(rb_cEnumProduct, "inspect", enum_product_inspect, 0);
4756 rb_undef_method(rb_cEnumProduct, "feed");
4757 rb_undef_method(rb_cEnumProduct, "next");
4758 rb_undef_method(rb_cEnumProduct, "next_values");
4759 rb_undef_method(rb_cEnumProduct, "peek");
4760 rb_undef_method(rb_cEnumProduct, "peek_values");
4761 rb_define_singleton_method(rb_cEnumerator, "product", enumerator_s_product, -1);
4762
4763 /* ArithmeticSequence */
4764 rb_cArithSeq = rb_define_class_under(rb_cEnumerator, "ArithmeticSequence", rb_cEnumerator);
4765 rb_undef_alloc_func(rb_cArithSeq);
4766 rb_undef_method(CLASS_OF(rb_cArithSeq), "new");
4767 rb_define_method(rb_cArithSeq, "begin", arith_seq_begin, 0);
4768 rb_define_method(rb_cArithSeq, "end", arith_seq_end, 0);
4769 rb_define_method(rb_cArithSeq, "exclude_end?", arith_seq_exclude_end, 0);
4770 rb_define_method(rb_cArithSeq, "step", arith_seq_step, 0);
4771 rb_define_method(rb_cArithSeq, "first", arith_seq_first, -1);
4772 rb_define_method(rb_cArithSeq, "last", arith_seq_last, -1);
4773 rb_define_method(rb_cArithSeq, "inspect", arith_seq_inspect, 0);
4774 rb_define_method(rb_cArithSeq, "==", arith_seq_eq, 1);
4775 rb_define_method(rb_cArithSeq, "===", arith_seq_eq, 1);
4776 rb_define_method(rb_cArithSeq, "eql?", arith_seq_eq, 1);
4777 rb_define_method(rb_cArithSeq, "hash", arith_seq_hash, 0);
4778 rb_define_method(rb_cArithSeq, "each", arith_seq_each, 0);
4779 rb_define_method(rb_cArithSeq, "size", arith_seq_size, 0);
4780
4781 rb_provide("enumerator.so"); /* for backward compatibility */
4782}
4783#undef sym
4784
4785void
4786Init_Enumerator(void)
4787{
4788 id_rewind = rb_intern_const("rewind");
4789 id_next = rb_intern_const("next");
4790 id_result = rb_intern_const("result");
4791 id_receiver = rb_intern_const("receiver");
4792 id_arguments = rb_intern_const("arguments");
4793 id_memo = rb_intern_const("memo");
4794 id_method = rb_intern_const("method");
4795 id_force = rb_intern_const("force");
4796 id_to_enum = rb_intern_const("to_enum");
4797 id_each_entry = rb_intern_const("each_entry");
4798 sym_each = ID2SYM(id_each);
4799 sym_yield = ID2SYM(rb_intern_const("yield"));
4800
4801 InitVM(Enumerator);
4802}
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
#define rb_define_private_method(klass, mid, func, arity)
Defines klass#mid and makes it private.
void rb_include_module(VALUE klass, VALUE module)
Includes a module to a class.
Definition class.c:1769
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition class.c:3094
void rb_need_block(void)
Declares that the current method needs a block.
Definition eval.c:1056
void rb_undef_method(VALUE klass, const char *name)
Defines an undef of a method.
Definition class.c:2897
int rb_scan_args_kw(int kw_flag, int argc, const VALUE *argv, const char *fmt,...)
Identical to rb_scan_args(), except it also accepts kw_splat.
Definition class.c:3397
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Retrieves argument from argc and argv to given VALUE references according to the format string.
Definition class.c:3384
int rb_keyword_given_p(void)
Determines if the current method is given a keyword argument.
Definition eval.c:1048
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition eval.c:1035
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Keyword argument deconstructor.
Definition class.c:3173
#define T_COMPLEX
Old name of RUBY_T_COMPLEX.
Definition value_type.h:59
#define RB_INTEGER_TYPE_P
Old name of rb_integer_type_p.
Definition value_type.h:87
#define rb_str_buf_cat2
Old name of rb_usascii_str_new_cstr.
Definition string.h:1683
#define OBJ_INIT_COPY(obj, orig)
Old name of RB_OBJ_INIT_COPY.
Definition object.h:41
#define RFLOAT_VALUE
Old name of rb_float_value.
Definition double.h:28
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
Definition long.h:48
#define T_FLOAT
Old name of RUBY_T_FLOAT.
Definition value_type.h:64
#define ID2SYM
Old name of RB_ID2SYM.
Definition symbol.h:44
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
Definition assume.h:29
#define CLASS_OF
Old name of rb_class_of.
Definition globals.h:205
#define rb_ary_new4
Old name of rb_ary_new_from_values.
Definition array.h:659
#define FIXABLE
Old name of RB_FIXABLE.
Definition fixnum.h:25
#define rb_exc_new2
Old name of rb_exc_new_cstr.
Definition error.h:37
#define LONG2FIX
Old name of RB_INT2FIX.
Definition long.h:49
#define T_RATIONAL
Old name of RUBY_T_RATIONAL.
Definition value_type.h:76
#define T_HASH
Old name of RUBY_T_HASH.
Definition value_type.h:65
#define NUM2DBL
Old name of rb_num2dbl.
Definition double.h:27
#define rb_ary_new3
Old name of rb_ary_new_from_args.
Definition array.h:658
#define LONG2NUM
Old name of RB_LONG2NUM.
Definition long.h:50
#define Qtrue
Old name of RUBY_Qtrue.
#define ST2FIX
Old name of RB_ST2FIX.
Definition st_data_t.h:33
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define FIX2LONG
Old name of RB_FIX2LONG.
Definition long.h:46
#define T_ARRAY
Old name of RUBY_T_ARRAY.
Definition value_type.h:56
#define NIL_P
Old name of RB_NIL_P.
#define ALLOCV_N
Old name of RB_ALLOCV_N.
Definition memory.h:405
#define POSFIXABLE
Old name of RB_POSFIXABLE.
Definition fixnum.h:29
#define T_SYMBOL
Old name of RUBY_T_SYMBOL.
Definition value_type.h:80
#define DBL2NUM
Old name of rb_float_new.
Definition double.h:29
#define NUM2LONG
Old name of RB_NUM2LONG.
Definition long.h:51
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define rb_ary_new2
Old name of rb_ary_new_capa.
Definition array.h:657
#define ALLOCV_END
Old name of RB_ALLOCV_END.
Definition memory.h:406
#define SYMBOL_P
Old name of RB_SYMBOL_P.
Definition value_type.h:88
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition eval.c:678
void rb_iter_break(void)
Breaks from a block.
Definition vm.c:2381
VALUE rb_eRangeError
RangeError exception.
Definition error.c:1477
VALUE rb_eTypeError
TypeError exception.
Definition error.c:1473
VALUE rb_eRuntimeError
RuntimeError exception.
Definition error.c:1471
VALUE rb_eStopIteration
StopIteration exception.
Definition enumerator.c:196
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports unless $VERBOSE is nil.
Definition error.c:468
VALUE rb_exc_new_str(VALUE etype, VALUE str)
Identical to rb_exc_new_cstr(), except it takes a Ruby's string instead of C's.
Definition error.c:1524
VALUE rb_eIndexError
IndexError exception.
Definition error.c:1475
VALUE rb_mKernel
Kernel module.
Definition object.c:59
VALUE rb_cObject
Object class.
Definition object.c:60
VALUE rb_mEnumerable
Enumerable module.
Definition enum.c:28
VALUE rb_cEnumerator
Enumerator class.
Definition enumerator.c:179
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
Definition object.c:94
VALUE rb_cNumeric
Numeric class.
Definition numeric.c:200
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
Definition object.c:234
VALUE rb_obj_dup(VALUE obj)
Duplicates the given object.
Definition object.c:556
VALUE rb_inspect(VALUE obj)
Generates a human-readable textual representation of the given object.
Definition object.c:669
VALUE rb_cRange
Range class.
Definition range.c:35
VALUE rb_equal(VALUE lhs, VALUE rhs)
This function is an optimised version of calling #==.
Definition object.c:140
VALUE rb_obj_is_kind_of(VALUE obj, VALUE klass)
Queries if the given object is an instance (of possibly descendants) of the given class.
Definition object.c:906
VALUE rb_obj_freeze(VALUE obj)
Same as RB_OBJ_FREEZE(), but returns the given object.
Definition object.c:1309
VALUE rb_to_int(VALUE val)
Identical to rb_check_to_int(), except it raises in case of conversion mismatch.
Definition object.c:3328
#define RB_OBJ_WRITE(old, slot, young)
Declaration of a "back" pointer.
Definition gc.h:492
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
Definition vm_eval.c:1123
VALUE rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcall(), except it takes the method arguments as a C array.
Definition vm_eval.c:1081
VALUE rb_funcall_with_block(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE procval)
Identical to rb_funcallv_public(), except you can pass a block.
Definition vm_eval.c:1200
#define rb_funcall2
Definition eval.h:207
VALUE rb_call_super(int argc, const VALUE *argv)
This resembles ruby's super.
Definition vm_eval.c:363
VALUE rb_ary_new_from_values(long n, const VALUE *elts)
Identical to rb_ary_new_from_args(), except how objects are passed.
VALUE rb_ary_dup(VALUE ary)
Duplicates an array.
VALUE rb_ary_cat(VALUE ary, const VALUE *train, long len)
Destructively appends multiple elements at the end of the array.
VALUE rb_check_array_type(VALUE obj)
Try converting an object to its array representation using its to_ary method, if any.
VALUE rb_ary_new(void)
Allocates a new, empty array.
VALUE rb_ary_new_capa(long capa)
Identical to rb_ary_new(), except it additionally specifies how many rooms of objects it should alloc...
VALUE rb_ary_resize(VALUE ary, long len)
Expands or shrinks the passed array to the passed length.
VALUE rb_ary_hidden_new(long capa)
Allocates a hidden (no class) empty array.
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
VALUE rb_ary_freeze(VALUE obj)
Freeze an array, preventing further modifications.
VALUE rb_ary_entry(VALUE ary, long off)
Queries an element of an array.
void rb_ary_store(VALUE ary, long key, VALUE val)
Destructively stores the passed value to the passed array's passed index.
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
This roughly resembles return enum_for(__callee__) unless block_given?.
Definition enumerator.h:208
VALUE rb_enumerator_size_func(VALUE recv, VALUE argv, VALUE eobj)
This is the type of functions that rb_enumeratorize_with_size() expects.
Definition enumerator.h:45
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
Definition error.h:284
void rb_provide(const char *feature)
Declares that the given feature is already provided by someone else.
Definition load.c:710
VALUE rb_num_coerce_cmp(VALUE lhs, VALUE rhs, ID op)
Identical to rb_num_coerce_bin(), except for return values.
Definition numeric.c:488
VALUE rb_obj_method(VALUE recv, VALUE mid)
Creates a method object.
Definition proc.c:2916
VALUE rb_block_proc(void)
Constructs a Proc object from implicitly passed components.
Definition proc.c:1575
VALUE rb_proc_call_with_block(VALUE recv, int argc, const VALUE *argv, VALUE proc)
Identical to rb_proc_call(), except you can additionally pass another proc object,...
Definition proc.c:1763
VALUE rb_proc_call_kw(VALUE recv, VALUE args, int kw_splat)
Identical to rb_proc_call(), except you can specify how to handle the last element of the given array...
Definition proc.c:1717
VALUE rb_obj_is_proc(VALUE recv)
Queries if the given object is a proc.
Definition proc.c:386
int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
Deconstructs a range into its components.
Definition range.c:1857
VALUE rb_set_new(void)
Creates a new, empty set object.
Definition set.c:2338
#define rb_hash_uint(h, i)
Just another name of st_hash_uint.
Definition string.h:943
#define rb_hash_end(h)
Just another name of st_hash_end.
Definition string.h:946
VALUE rb_str_append(VALUE dst, VALUE src)
Identical to rb_str_buf_append(), except it converts the right hand side before concatenating.
Definition string.c:3906
VALUE rb_str_dup(VALUE str)
Duplicates a string.
Definition string.c:2031
VALUE rb_str_buf_append(VALUE dst, VALUE src)
Identical to rb_str_cat_cstr(), except it takes Ruby's string instead of C's.
Definition string.c:3872
void rb_str_set_len(VALUE str, long len)
Overwrites the length of the string.
Definition string.c:3493
st_index_t rb_hash_start(st_index_t i)
Starts a series of hashing.
Definition random.c:1714
VALUE rb_exec_recursive(VALUE(*f)(VALUE g, VALUE h, int r), VALUE g, VALUE h)
"Recursion" API entry point.
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
Identical to rb_iv_set(), except it accepts the name as an ID instead of a C string.
Definition variable.c:2141
VALUE rb_ivar_get(VALUE obj, ID name)
Identical to rb_iv_get(), except it accepts the name as an ID instead of a C string.
Definition variable.c:1641
VALUE rb_class_path(VALUE mod)
Identical to rb_mod_name(), except it returns #<Class: ...> style inspection for anonymous modules.
Definition variable.c:398
int rb_respond_to(VALUE obj, ID mid)
Queries if the object responds to the method.
Definition vm_method.c:3683
void rb_undef_alloc_func(VALUE klass)
Deletes the allocator function of a class.
Definition vm_method.c:1843
VALUE rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcallv(), except it returns RUBY_Qundef instead of raising rb_eNoMethodError.
Definition vm_eval.c:691
VALUE rb_check_funcall_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
Identical to rb_check_funcall(), except you can specify how to handle the last element of the given a...
Definition vm_eval.c:685
void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func)
Sets the allocator function of a class.
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
Definition symbol.h:285
VALUE rb_sym2str(VALUE symbol)
Obtain a frozen string representation of a symbol (not including the leading colon).
Definition symbol.c:1148
VALUE rb_to_symbol(VALUE name)
Identical to rb_intern_str(), except it generates a dynamic symbol if necessary.
Definition string.c:14138
ID rb_to_id(VALUE str)
Identical to rb_intern_str(), except it tries to convert the parameter object to an instance of rb_cS...
Definition string.c:14128
int len
Length of the buffer.
Definition io.h:8
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Shim for block function parameters.
Definition iterator.h:58
VALUE rb_yield_values(int n,...)
Identical to rb_yield(), except it takes variadic number of parameters and pass them to the block.
Definition vm_eval.c:1401
VALUE rb_yield_values2(int n, const VALUE *argv)
Identical to rb_yield_values(), except it takes the parameters as a C array instead of variadic argum...
Definition vm_eval.c:1423
VALUE rb_yield(VALUE val)
Yields the block.
Definition vm_eval.c:1378
VALUE rb_yield_values_kw(int n, const VALUE *argv, int kw_splat)
Identical to rb_yield_values2(), except you can specify how to handle the last element of the given a...
Definition vm_eval.c:1429
VALUE rb_block_call_func(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg))
This is the type of a function that the interpreter expect for C-backended blocks.
Definition iterator.h:83
VALUE rb_block_call_kw(VALUE obj, ID mid, int argc, const VALUE *argv, rb_block_call_func_t proc, VALUE data2, int kw_splat)
Identical to rb_funcallv_kw(), except it additionally passes a function as a block.
Definition vm_eval.c:1570
#define rb_long2int
Just another name of rb_long2int_inline.
Definition long.h:62
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
Definition memory.h:372
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
Definition memory.h:167
VALUE rb_block_call(VALUE q, ID w, int e, const VALUE *r, type *t, VALUE y)
Call a method with a block.
VALUE rb_proc_new(type *q, VALUE w)
Creates a rb_cProc instance.
VALUE rb_fiber_new(type *q, VALUE w)
Creates a rb_cFiber instance.
void rb_hash_foreach(VALUE q, int_type *w, VALUE e)
Iteration over the given hash.
VALUE rb_rescue2(type *q, VALUE w, type *e, VALUE r,...)
An equivalent of rescue clause.
#define RARRAY_LEN
Just another name of rb_array_len.
Definition rarray.h:50
static int RARRAY_LENINT(VALUE ary)
Identical to rb_array_len(), except it differs for the return type.
Definition rarray.h:280
#define RARRAY_AREF(a, i)
Definition rarray.h:402
#define RARRAY_CONST_PTR
Just another name of rb_array_const_ptr.
Definition rarray.h:51
#define RHASH_EMPTY_P(h)
Checks if the hash is empty.
Definition rhash.h:79
#define RUBY_TYPED_DEFAULT_FREE
This is a value you can set to rb_data_type_struct::dfree.
Definition rtypeddata.h:81
#define TypedData_Get_Struct(obj, type, data_type, sval)
Obtains a C struct from inside of a wrapper Ruby object.
Definition rtypeddata.h:773
#define TypedData_Make_Struct(klass, type, data_type, sval)
Identical to TypedData_Wrap_Struct, except it allocates a new data region internally instead of takin...
Definition rtypeddata.h:604
#define InitVM(ext)
This macro is for internal use.
Definition ruby.h:231
#define RB_SCAN_ARGS_LAST_HASH_KEYWORDS
Treat a final argument as keywords if it is a hash, and not as keywords otherwise.
Definition scan_args.h:59
#define RB_PASS_CALLED_KEYWORDS
Pass keywords if current method is called with keywords, useful for argument delegation.
Definition scan_args.h:78
#define RB_NO_KEYWORDS
Do not pass keywords.
Definition scan_args.h:69
#define RTEST
This is an old name of RB_TEST.
#define _(args)
This was a transition path from K&R to ANSI.
Definition stdarg.h:35
MEMO.
Definition imemo.h:116
Definition enumerator.c:252
Decomposed Enumerator::ArithmeicSequence.
Definition enumerator.h:53
int exclude_end
Whether the endpoint is open or closed.
Definition enumerator.h:57
VALUE end
"Right" or "highest" endpoint of the sequence.
Definition enumerator.h:55
VALUE step
Step between a sequence.
Definition enumerator.h:56
VALUE begin
"Left" or "lowest" endpoint of the sequence.
Definition enumerator.h:54
This is the struct that holds necessary info for a struct.
Definition rtypeddata.h:242
VALUE flags
Type-specific behavioural characteristics.
Definition rtypeddata.h:356
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
Definition value.h:52
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40
static bool RB_FLOAT_TYPE_P(VALUE obj)
Queries if the object is an instance of rb_cFloat.
Definition value_type.h:264
static void Check_Type(VALUE v, enum ruby_value_type t)
Identical to RB_TYPE_P(), except it raises exceptions on predication failure.
Definition value_type.h:425
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.
Definition value_type.h:376