Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

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