Project

General

Profile

Feature #14781 ยป 0001-Implement-Enumerator.produce-Feature-14781.patch

knu (Akinori MUSHA), 08/29/2019 11:06 AM

View differences:

enumerator.c
135 135
    rb_enumerator_size_func *size_fn;
136 136
};
137 137

  
138
static VALUE rb_cGenerator, rb_cYielder;
138
static VALUE rb_cGenerator, rb_cYielder, rb_cEnumProducer;
139 139

  
140 140
struct generator {
141 141
    VALUE proc;
......
146 146
    VALUE proc;
147 147
};
148 148

  
149
struct producer {
150
    VALUE init;
151
    VALUE proc;
152
};
153

  
149 154
typedef struct MEMO *lazyenum_proc_func(VALUE, struct MEMO *, VALUE, long);
150 155
typedef VALUE lazyenum_size_func(VALUE, VALUE);
151 156
typedef struct {
......
2701 2706
    return rb_attr_get(self, id_result);
2702 2707
}
2703 2708

  
2709
/*
2710
 * Producer
2711
 */
2712

  
2713
static void
2714
producer_mark(void *p)
2715
{
2716
    struct producer *ptr = p;
2717
    rb_gc_mark_movable(ptr->init);
2718
    rb_gc_mark_movable(ptr->proc);
2719
}
2720

  
2721
static void
2722
producer_compact(void *p)
2723
{
2724
    struct producer *ptr = p;
2725
    ptr->init = rb_gc_location(ptr->init);
2726
    ptr->proc = rb_gc_location(ptr->proc);
2727
}
2728

  
2729
#define producer_free RUBY_TYPED_DEFAULT_FREE
2730

  
2731
static size_t
2732
producer_memsize(const void *p)
2733
{
2734
    return sizeof(struct producer);
2735
}
2736

  
2737
static const rb_data_type_t producer_data_type = {
2738
    "producer",
2739
    {
2740
        producer_mark,
2741
        producer_free,
2742
        producer_memsize,
2743
        producer_compact,
2744
    },
2745
    0, 0, RUBY_TYPED_FREE_IMMEDIATELY
2746
};
2747

  
2748
static struct producer *
2749
producer_ptr(VALUE obj)
2750
{
2751
    struct producer *ptr;
2752

  
2753
    TypedData_Get_Struct(obj, struct producer, &producer_data_type, ptr);
2754
    if (!ptr || ptr->proc == Qundef) {
2755
        rb_raise(rb_eArgError, "uninitialized producer");
2756
    }
2757
    return ptr;
2758
}
2759

  
2760
/* :nodoc: */
2761
static VALUE
2762
producer_allocate(VALUE klass)
2763
{
2764
    struct producer *ptr;
2765
    VALUE obj;
2766

  
2767
    obj = TypedData_Make_Struct(klass, struct producer, &producer_data_type, ptr);
2768
    ptr->init = Qundef;
2769
    ptr->proc = Qundef;
2770

  
2771
    return obj;
2772
}
2773

  
2774
static VALUE
2775
producer_init(VALUE obj, VALUE init, VALUE proc)
2776
{
2777
    struct producer *ptr;
2778

  
2779
    TypedData_Get_Struct(obj, struct producer, &producer_data_type, ptr);
2780

  
2781
    if (!ptr) {
2782
        rb_raise(rb_eArgError, "unallocated producer");
2783
    }
2784

  
2785
    ptr->init = init;
2786
    ptr->proc = proc;
2787

  
2788
    return obj;
2789
}
2790

  
2791
static VALUE
2792
producer_each_stop(VALUE dummy, VALUE exc)
2793
{
2794
    return rb_attr_get(exc, id_result);
2795
}
2796

  
2797
static VALUE
2798
producer_each_i(VALUE obj)
2799
{
2800
    struct producer *ptr;
2801
    VALUE init, proc, curr;
2802

  
2803
    ptr = producer_ptr(obj);
2804
    init = ptr->init;
2805
    proc = ptr->proc;
2806

  
2807
    if (init == Qundef) {
2808
        curr = Qnil;
2809
    } else {
2810
        rb_yield(init);
2811
        curr = init;
2812
    }
2813

  
2814
    for (;;) {
2815
        curr = rb_funcall(proc, id_call, 1, curr);
2816
        rb_yield(curr);
2817
    }
2818

  
2819
    return Qnil;
2820
}
2821

  
2822
/* :nodoc: */
2823
static VALUE
2824
producer_each(VALUE obj)
2825
{
2826
    rb_need_block();
2827

  
2828
    return rb_rescue2(producer_each_i, obj, producer_each_stop, (VALUE)0, rb_eStopIteration, (VALUE)0);
2829
}
2830

  
2831
static VALUE
2832
producer_size(VALUE obj, VALUE args, VALUE eobj)
2833
{
2834
    return DBL2NUM(HUGE_VAL);
2835
}
2836

  
2837
static VALUE
2838
enumerator_s_produce(int argc, VALUE *argv, VALUE klass)
2839
{
2840
    VALUE init, producer;
2841

  
2842
    rb_need_block();
2843

  
2844
    if (rb_scan_args(argc, argv, "01", &init) == 0) {
2845
        init = Qundef;
2846
    }
2847

  
2848
    producer = producer_init(producer_allocate(rb_cEnumProducer), init, rb_block_proc());
2849

  
2850
    return rb_enumeratorize_with_size(producer, sym_each, 0, 0, producer_size);
2851
}
2852

  
2704 2853
/*
2705 2854
 * Document-class: Enumerator::Chain
2706 2855
 *
......
3684 3833
    rb_define_method(rb_cYielder, "<<", yielder_yield_push, 1);
3685 3834
    rb_define_method(rb_cYielder, "to_proc", yielder_to_proc, 0);
3686 3835

  
3836
    /* Producer */
3837
    rb_cEnumProducer = rb_define_class_under(rb_cEnumerator, "Producer", rb_cObject);
3838
    rb_define_alloc_func(rb_cEnumProducer, producer_allocate);
3839
    rb_define_method(rb_cEnumProducer, "each", producer_each, 0);
3840
    rb_define_singleton_method(rb_cEnumerator, "produce", enumerator_s_produce, -1);
3841

  
3687 3842
    /* Chain */
3688 3843
    rb_cEnumChain = rb_define_class_under(rb_cEnumerator, "Chain", rb_cEnumerator);
3689 3844
    rb_define_alloc_func(rb_cEnumChain, enum_chain_allocate);
3690
-