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