Ruby: enumerator.c Source File

Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)

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