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