00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "ruby/ruby.h"
00016 #include "node.h"
00017 #include "internal.h"
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 VALUE rb_cEnumerator;
00106 VALUE rb_cLazy;
00107 static ID id_rewind, id_each, id_new, id_initialize, id_yield, id_call, id_size, id_to_enum;
00108 static ID id_eqq, id_next, id_result, id_lazy, id_receiver, id_arguments, id_memo, id_method, id_force;
00109 static VALUE sym_each, sym_cycle;
00110
00111 VALUE rb_eStopIteration;
00112
00113 struct enumerator {
00114 VALUE obj;
00115 ID meth;
00116 VALUE args;
00117 VALUE fib;
00118 VALUE dst;
00119 VALUE lookahead;
00120 VALUE feedvalue;
00121 VALUE stop_exc;
00122 VALUE size;
00123 VALUE (*size_fn)(ANYARGS);
00124 };
00125
00126 static VALUE rb_cGenerator, rb_cYielder;
00127
00128 struct generator {
00129 VALUE proc;
00130 };
00131
00132 struct yielder {
00133 VALUE proc;
00134 };
00135
00136 static VALUE generator_allocate(VALUE klass);
00137 static VALUE generator_init(VALUE obj, VALUE proc);
00138
00139
00140
00141
00142 static void
00143 enumerator_mark(void *p)
00144 {
00145 struct enumerator *ptr = p;
00146 rb_gc_mark(ptr->obj);
00147 rb_gc_mark(ptr->args);
00148 rb_gc_mark(ptr->fib);
00149 rb_gc_mark(ptr->dst);
00150 rb_gc_mark(ptr->lookahead);
00151 rb_gc_mark(ptr->feedvalue);
00152 rb_gc_mark(ptr->stop_exc);
00153 rb_gc_mark(ptr->size);
00154 }
00155
00156 #define enumerator_free RUBY_TYPED_DEFAULT_FREE
00157
00158 static size_t
00159 enumerator_memsize(const void *p)
00160 {
00161 return p ? sizeof(struct enumerator) : 0;
00162 }
00163
00164 static const rb_data_type_t enumerator_data_type = {
00165 "enumerator",
00166 {
00167 enumerator_mark,
00168 enumerator_free,
00169 enumerator_memsize,
00170 },
00171 };
00172
00173 static struct enumerator *
00174 enumerator_ptr(VALUE obj)
00175 {
00176 struct enumerator *ptr;
00177
00178 TypedData_Get_Struct(obj, struct enumerator, &enumerator_data_type, ptr);
00179 if (!ptr || ptr->obj == Qundef) {
00180 rb_raise(rb_eArgError, "uninitialized enumerator");
00181 }
00182 return ptr;
00183 }
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 static VALUE
00241 obj_to_enum(int argc, VALUE *argv, VALUE obj)
00242 {
00243 VALUE enumerator, meth = sym_each;
00244
00245 if (argc > 0) {
00246 --argc;
00247 meth = *argv++;
00248 }
00249 enumerator = rb_enumeratorize_with_size(obj, meth, argc, argv, 0);
00250 if (rb_block_given_p()) {
00251 enumerator_ptr(enumerator)->size = rb_block_proc();
00252 }
00253 return enumerator;
00254 }
00255
00256 static VALUE
00257 enumerator_allocate(VALUE klass)
00258 {
00259 struct enumerator *ptr;
00260 VALUE enum_obj;
00261
00262 enum_obj = TypedData_Make_Struct(klass, struct enumerator, &enumerator_data_type, ptr);
00263 ptr->obj = Qundef;
00264
00265 return enum_obj;
00266 }
00267
00268 static VALUE
00269 enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, VALUE *argv, VALUE (*size_fn)(ANYARGS), VALUE size)
00270 {
00271 struct enumerator *ptr;
00272
00273 TypedData_Get_Struct(enum_obj, struct enumerator, &enumerator_data_type, ptr);
00274
00275 if (!ptr) {
00276 rb_raise(rb_eArgError, "unallocated enumerator");
00277 }
00278
00279 ptr->obj = obj;
00280 ptr->meth = rb_to_id(meth);
00281 if (argc) ptr->args = rb_ary_new4(argc, argv);
00282 ptr->fib = 0;
00283 ptr->dst = Qnil;
00284 ptr->lookahead = Qundef;
00285 ptr->feedvalue = Qundef;
00286 ptr->stop_exc = Qfalse;
00287 ptr->size = size;
00288 ptr->size_fn = size_fn;
00289
00290 return enum_obj;
00291 }
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331 static VALUE
00332 enumerator_initialize(int argc, VALUE *argv, VALUE obj)
00333 {
00334 VALUE recv, meth = sym_each;
00335 VALUE size = Qnil;
00336
00337 if (rb_block_given_p()) {
00338 rb_check_arity(argc, 0, 1);
00339 recv = generator_init(generator_allocate(rb_cGenerator), rb_block_proc());
00340 if (argc) {
00341 if (NIL_P(argv[0]) || rb_obj_is_proc(argv[0]) ||
00342 (RB_TYPE_P(argv[0], T_FLOAT) && RFLOAT_VALUE(argv[0]) == INFINITY)) {
00343 size = argv[0];
00344 } else {
00345 size = rb_to_int(argv[0]);
00346 }
00347 argc = 0;
00348 }
00349 }
00350 else {
00351 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
00352 rb_warn("Enumerator.new without a block is deprecated; use Object#to_enum");
00353 recv = *argv++;
00354 if (--argc) {
00355 meth = *argv++;
00356 --argc;
00357 }
00358 }
00359
00360 return enumerator_init(obj, recv, meth, argc, argv, 0, size);
00361 }
00362
00363
00364 static VALUE
00365 enumerator_init_copy(VALUE obj, VALUE orig)
00366 {
00367 struct enumerator *ptr0, *ptr1;
00368
00369 if (!OBJ_INIT_COPY(obj, orig)) return obj;
00370 ptr0 = enumerator_ptr(orig);
00371 if (ptr0->fib) {
00372
00373 rb_raise(rb_eTypeError, "can't copy execution context");
00374 }
00375
00376 TypedData_Get_Struct(obj, struct enumerator, &enumerator_data_type, ptr1);
00377
00378 if (!ptr1) {
00379 rb_raise(rb_eArgError, "unallocated enumerator");
00380 }
00381
00382 ptr1->obj = ptr0->obj;
00383 ptr1->meth = ptr0->meth;
00384 ptr1->args = ptr0->args;
00385 ptr1->fib = 0;
00386 ptr1->lookahead = Qundef;
00387 ptr1->feedvalue = Qundef;
00388 ptr1->size = ptr0->size;
00389 ptr1->size_fn = ptr0->size_fn;
00390
00391 return obj;
00392 }
00393
00394
00395
00396
00397 VALUE
00398 rb_enumeratorize(VALUE obj, VALUE meth, int argc, VALUE *argv)
00399 {
00400 return rb_enumeratorize_with_size(obj, meth, argc, argv, 0);
00401 }
00402
00403 static VALUE
00404 lazy_to_enum_i(VALUE self, VALUE meth, int argc, VALUE *argv, VALUE (*size_fn)(ANYARGS));
00405
00406 VALUE
00407 rb_enumeratorize_with_size(VALUE obj, VALUE meth, int argc, VALUE *argv, VALUE (*size_fn)(ANYARGS))
00408 {
00409
00410
00411 if (RTEST(rb_obj_is_kind_of(obj, rb_cLazy)))
00412 return lazy_to_enum_i(obj, meth, argc, argv, size_fn);
00413 else
00414 return enumerator_init(enumerator_allocate(rb_cEnumerator),
00415 obj, meth, argc, argv, size_fn, Qnil);
00416 }
00417
00418 static VALUE
00419 enumerator_block_call(VALUE obj, rb_block_call_func *func, VALUE arg)
00420 {
00421 int argc = 0;
00422 VALUE *argv = 0;
00423 const struct enumerator *e = enumerator_ptr(obj);
00424 ID meth = e->meth;
00425
00426 if (e->args) {
00427 argc = RARRAY_LENINT(e->args);
00428 argv = RARRAY_PTR(e->args);
00429 }
00430 return rb_block_call(e->obj, meth, argc, argv, func, arg);
00431 }
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441 static VALUE
00442 enumerator_each(int argc, VALUE *argv, VALUE obj)
00443 {
00444 if (argc > 0) {
00445 struct enumerator *e = enumerator_ptr(obj = rb_obj_dup(obj));
00446 VALUE args = e->args;
00447 if (args) {
00448 args = rb_ary_dup(args);
00449 rb_ary_cat(args, argv, argc);
00450 }
00451 else {
00452 args = rb_ary_new4(argc, argv);
00453 }
00454 e->args = args;
00455 }
00456 if (!rb_block_given_p()) return obj;
00457 return enumerator_block_call(obj, 0, obj);
00458 }
00459
00460 static VALUE
00461 enumerator_with_index_i(VALUE val, VALUE m, int argc, VALUE *argv)
00462 {
00463 NODE *memo = (NODE *)m;
00464 VALUE idx = memo->u1.value;
00465 memo->u1.value = rb_int_succ(idx);
00466
00467 if (argc <= 1)
00468 return rb_yield_values(2, val, idx);
00469
00470 return rb_yield_values(2, rb_ary_new4(argc, argv), idx);
00471 }
00472
00473 static VALUE
00474 enumerator_size(VALUE obj);
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488 static VALUE
00489 enumerator_with_index(int argc, VALUE *argv, VALUE obj)
00490 {
00491 VALUE memo;
00492
00493 rb_scan_args(argc, argv, "01", &memo);
00494 RETURN_SIZED_ENUMERATOR(obj, argc, argv, enumerator_size);
00495 if (NIL_P(memo))
00496 memo = INT2FIX(0);
00497 else
00498 memo = rb_to_int(memo);
00499 return enumerator_block_call(obj, enumerator_with_index_i, (VALUE)NEW_MEMO(memo, 0, 0));
00500 }
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512 static VALUE
00513 enumerator_each_with_index(VALUE obj)
00514 {
00515 return enumerator_with_index(0, NULL, obj);
00516 }
00517
00518 static VALUE
00519 enumerator_with_object_i(VALUE val, VALUE memo, int argc, VALUE *argv)
00520 {
00521 if (argc <= 1)
00522 return rb_yield_values(2, val, memo);
00523
00524 return rb_yield_values(2, rb_ary_new4(argc, argv), memo);
00525 }
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554 static VALUE
00555 enumerator_with_object(VALUE obj, VALUE memo)
00556 {
00557 RETURN_SIZED_ENUMERATOR(obj, 1, &memo, enumerator_size);
00558 enumerator_block_call(obj, enumerator_with_object_i, memo);
00559
00560 return memo;
00561 }
00562
00563 static VALUE
00564 next_ii(VALUE i, VALUE obj, int argc, VALUE *argv)
00565 {
00566 struct enumerator *e = enumerator_ptr(obj);
00567 VALUE feedvalue = Qnil;
00568 VALUE args = rb_ary_new4(argc, argv);
00569 rb_fiber_yield(1, &args);
00570 if (e->feedvalue != Qundef) {
00571 feedvalue = e->feedvalue;
00572 e->feedvalue = Qundef;
00573 }
00574 return feedvalue;
00575 }
00576
00577 static VALUE
00578 next_i(VALUE curr, VALUE obj)
00579 {
00580 struct enumerator *e = enumerator_ptr(obj);
00581 VALUE nil = Qnil;
00582 VALUE result;
00583
00584 result = rb_block_call(obj, id_each, 0, 0, next_ii, obj);
00585 e->stop_exc = rb_exc_new2(rb_eStopIteration, "iteration reached an end");
00586 rb_ivar_set(e->stop_exc, id_result, result);
00587 return rb_fiber_yield(1, &nil);
00588 }
00589
00590 static void
00591 next_init(VALUE obj, struct enumerator *e)
00592 {
00593 VALUE curr = rb_fiber_current();
00594 e->dst = curr;
00595 e->fib = rb_fiber_new(next_i, obj);
00596 e->lookahead = Qundef;
00597 }
00598
00599 static VALUE
00600 get_next_values(VALUE obj, struct enumerator *e)
00601 {
00602 VALUE curr, vs;
00603
00604 if (e->stop_exc)
00605 rb_exc_raise(e->stop_exc);
00606
00607 curr = rb_fiber_current();
00608
00609 if (!e->fib || !rb_fiber_alive_p(e->fib)) {
00610 next_init(obj, e);
00611 }
00612
00613 vs = rb_fiber_resume(e->fib, 1, &curr);
00614 if (e->stop_exc) {
00615 e->fib = 0;
00616 e->dst = Qnil;
00617 e->lookahead = Qundef;
00618 e->feedvalue = Qundef;
00619 rb_exc_raise(e->stop_exc);
00620 }
00621 return vs;
00622 }
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671 static VALUE
00672 enumerator_next_values(VALUE obj)
00673 {
00674 struct enumerator *e = enumerator_ptr(obj);
00675 VALUE vs;
00676
00677 if (e->lookahead != Qundef) {
00678 vs = e->lookahead;
00679 e->lookahead = Qundef;
00680 return vs;
00681 }
00682
00683 return get_next_values(obj, e);
00684 }
00685
00686 static VALUE
00687 ary2sv(VALUE args, int dup)
00688 {
00689 if (!RB_TYPE_P(args, T_ARRAY))
00690 return args;
00691
00692 switch (RARRAY_LEN(args)) {
00693 case 0:
00694 return Qnil;
00695
00696 case 1:
00697 return RARRAY_PTR(args)[0];
00698
00699 default:
00700 if (dup)
00701 return rb_ary_dup(args);
00702 return args;
00703 }
00704 }
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728 static VALUE
00729 enumerator_next(VALUE obj)
00730 {
00731 VALUE vs = enumerator_next_values(obj);
00732 return ary2sv(vs, 0);
00733 }
00734
00735 static VALUE
00736 enumerator_peek_values(VALUE obj)
00737 {
00738 struct enumerator *e = enumerator_ptr(obj);
00739
00740 if (e->lookahead == Qundef) {
00741 e->lookahead = get_next_values(obj, e);
00742 }
00743 return e->lookahead;
00744 }
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774 static VALUE
00775 enumerator_peek_values_m(VALUE obj)
00776 {
00777 return rb_ary_dup(enumerator_peek_values(obj));
00778 }
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802 static VALUE
00803 enumerator_peek(VALUE obj)
00804 {
00805 VALUE vs = enumerator_peek_values(obj);
00806 return ary2sv(vs, 1);
00807 }
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837 static VALUE
00838 enumerator_feed(VALUE obj, VALUE v)
00839 {
00840 struct enumerator *e = enumerator_ptr(obj);
00841
00842 if (e->feedvalue != Qundef) {
00843 rb_raise(rb_eTypeError, "feed value already set");
00844 }
00845 e->feedvalue = v;
00846
00847 return Qnil;
00848 }
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859 static VALUE
00860 enumerator_rewind(VALUE obj)
00861 {
00862 struct enumerator *e = enumerator_ptr(obj);
00863
00864 rb_check_funcall(e->obj, id_rewind, 0, 0);
00865
00866 e->fib = 0;
00867 e->dst = Qnil;
00868 e->lookahead = Qundef;
00869 e->feedvalue = Qundef;
00870 e->stop_exc = Qfalse;
00871 return obj;
00872 }
00873
00874 static VALUE
00875 inspect_enumerator(VALUE obj, VALUE dummy, int recur)
00876 {
00877 struct enumerator *e;
00878 const char *cname;
00879 VALUE eobj, eargs, str, method;
00880 int tainted, untrusted;
00881
00882 TypedData_Get_Struct(obj, struct enumerator, &enumerator_data_type, e);
00883
00884 cname = rb_obj_classname(obj);
00885
00886 if (!e || e->obj == Qundef) {
00887 return rb_sprintf("#<%s: uninitialized>", cname);
00888 }
00889
00890 if (recur) {
00891 str = rb_sprintf("#<%s: ...>", cname);
00892 OBJ_TAINT(str);
00893 return str;
00894 }
00895
00896 eobj = rb_attr_get(obj, id_receiver);
00897 if (NIL_P(eobj)) {
00898 eobj = e->obj;
00899 }
00900
00901 tainted = OBJ_TAINTED(eobj);
00902 untrusted = OBJ_UNTRUSTED(eobj);
00903
00904
00905 str = rb_sprintf("#<%s: ", cname);
00906 rb_str_concat(str, rb_inspect(eobj));
00907 method = rb_attr_get(obj, id_method);
00908 if (NIL_P(method)) {
00909 rb_str_buf_cat2(str, ":");
00910 rb_str_buf_cat2(str, rb_id2name(e->meth));
00911 }
00912 else if (method != Qfalse) {
00913 Check_Type(method, T_SYMBOL);
00914 rb_str_buf_cat2(str, ":");
00915 rb_str_buf_cat2(str, rb_id2name(SYM2ID(method)));
00916 }
00917
00918 eargs = rb_attr_get(obj, id_arguments);
00919 if (NIL_P(eargs)) {
00920 eargs = e->args;
00921 }
00922 if (eargs != Qfalse) {
00923 long argc = RARRAY_LEN(eargs);
00924 VALUE *argv = RARRAY_PTR(eargs);
00925
00926 if (argc > 0) {
00927 rb_str_buf_cat2(str, "(");
00928
00929 while (argc--) {
00930 VALUE arg = *argv++;
00931
00932 rb_str_concat(str, rb_inspect(arg));
00933 rb_str_buf_cat2(str, argc > 0 ? ", " : ")");
00934
00935 if (OBJ_TAINTED(arg)) tainted = TRUE;
00936 if (OBJ_UNTRUSTED(arg)) untrusted = TRUE;
00937 }
00938 }
00939 }
00940
00941 rb_str_buf_cat2(str, ">");
00942
00943 if (tainted) OBJ_TAINT(str);
00944 if (untrusted) OBJ_UNTRUST(str);
00945 return str;
00946 }
00947
00948
00949
00950
00951
00952
00953
00954
00955 static VALUE
00956 enumerator_inspect(VALUE obj)
00957 {
00958 return rb_exec_recursive(inspect_enumerator, obj, 0);
00959 }
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972 static VALUE
00973 enumerator_size(VALUE obj)
00974 {
00975 struct enumerator *e = enumerator_ptr(obj);
00976
00977 if (e->size_fn) {
00978 return (*e->size_fn)(e->obj, e->args, obj);
00979 }
00980 if (rb_obj_is_proc(e->size)) {
00981 if (e->args)
00982 return rb_proc_call(e->size, e->args);
00983 else
00984 return rb_proc_call_with_block(e->size, 0, 0, Qnil);
00985 }
00986 return e->size;
00987 }
00988
00989
00990
00991
00992 static void
00993 yielder_mark(void *p)
00994 {
00995 struct yielder *ptr = p;
00996 rb_gc_mark(ptr->proc);
00997 }
00998
00999 #define yielder_free RUBY_TYPED_DEFAULT_FREE
01000
01001 static size_t
01002 yielder_memsize(const void *p)
01003 {
01004 return p ? sizeof(struct yielder) : 0;
01005 }
01006
01007 static const rb_data_type_t yielder_data_type = {
01008 "yielder",
01009 {
01010 yielder_mark,
01011 yielder_free,
01012 yielder_memsize,
01013 },
01014 };
01015
01016 static struct yielder *
01017 yielder_ptr(VALUE obj)
01018 {
01019 struct yielder *ptr;
01020
01021 TypedData_Get_Struct(obj, struct yielder, &yielder_data_type, ptr);
01022 if (!ptr || ptr->proc == Qundef) {
01023 rb_raise(rb_eArgError, "uninitialized yielder");
01024 }
01025 return ptr;
01026 }
01027
01028
01029 static VALUE
01030 yielder_allocate(VALUE klass)
01031 {
01032 struct yielder *ptr;
01033 VALUE obj;
01034
01035 obj = TypedData_Make_Struct(klass, struct yielder, &yielder_data_type, ptr);
01036 ptr->proc = Qundef;
01037
01038 return obj;
01039 }
01040
01041 static VALUE
01042 yielder_init(VALUE obj, VALUE proc)
01043 {
01044 struct yielder *ptr;
01045
01046 TypedData_Get_Struct(obj, struct yielder, &yielder_data_type, ptr);
01047
01048 if (!ptr) {
01049 rb_raise(rb_eArgError, "unallocated yielder");
01050 }
01051
01052 ptr->proc = proc;
01053
01054 return obj;
01055 }
01056
01057
01058 static VALUE
01059 yielder_initialize(VALUE obj)
01060 {
01061 rb_need_block();
01062
01063 return yielder_init(obj, rb_block_proc());
01064 }
01065
01066
01067 static VALUE
01068 yielder_yield(VALUE obj, VALUE args)
01069 {
01070 struct yielder *ptr = yielder_ptr(obj);
01071
01072 return rb_proc_call(ptr->proc, args);
01073 }
01074
01075
01076 static VALUE yielder_yield_push(VALUE obj, VALUE args)
01077 {
01078 yielder_yield(obj, args);
01079 return obj;
01080 }
01081
01082 static VALUE
01083 yielder_yield_i(VALUE obj, VALUE memo, int argc, VALUE *argv)
01084 {
01085 return rb_yield_values2(argc, argv);
01086 }
01087
01088 static VALUE
01089 yielder_new(void)
01090 {
01091 return yielder_init(yielder_allocate(rb_cYielder), rb_proc_new(yielder_yield_i, 0));
01092 }
01093
01094
01095
01096
01097 static void
01098 generator_mark(void *p)
01099 {
01100 struct generator *ptr = p;
01101 rb_gc_mark(ptr->proc);
01102 }
01103
01104 #define generator_free RUBY_TYPED_DEFAULT_FREE
01105
01106 static size_t
01107 generator_memsize(const void *p)
01108 {
01109 return p ? sizeof(struct generator) : 0;
01110 }
01111
01112 static const rb_data_type_t generator_data_type = {
01113 "generator",
01114 {
01115 generator_mark,
01116 generator_free,
01117 generator_memsize,
01118 },
01119 };
01120
01121 static struct generator *
01122 generator_ptr(VALUE obj)
01123 {
01124 struct generator *ptr;
01125
01126 TypedData_Get_Struct(obj, struct generator, &generator_data_type, ptr);
01127 if (!ptr || ptr->proc == Qundef) {
01128 rb_raise(rb_eArgError, "uninitialized generator");
01129 }
01130 return ptr;
01131 }
01132
01133
01134 static VALUE
01135 generator_allocate(VALUE klass)
01136 {
01137 struct generator *ptr;
01138 VALUE obj;
01139
01140 obj = TypedData_Make_Struct(klass, struct generator, &generator_data_type, ptr);
01141 ptr->proc = Qundef;
01142
01143 return obj;
01144 }
01145
01146 static VALUE
01147 generator_init(VALUE obj, VALUE proc)
01148 {
01149 struct generator *ptr;
01150
01151 TypedData_Get_Struct(obj, struct generator, &generator_data_type, ptr);
01152
01153 if (!ptr) {
01154 rb_raise(rb_eArgError, "unallocated generator");
01155 }
01156
01157 ptr->proc = proc;
01158
01159 return obj;
01160 }
01161
01162
01163 static VALUE
01164 generator_initialize(int argc, VALUE *argv, VALUE obj)
01165 {
01166 VALUE proc;
01167
01168 if (argc == 0) {
01169 rb_need_block();
01170
01171 proc = rb_block_proc();
01172 }
01173 else {
01174 rb_scan_args(argc, argv, "1", &proc);
01175
01176 if (!rb_obj_is_proc(proc))
01177 rb_raise(rb_eTypeError,
01178 "wrong argument type %s (expected Proc)",
01179 rb_obj_classname(proc));
01180
01181 if (rb_block_given_p()) {
01182 rb_warn("given block not used");
01183 }
01184 }
01185
01186 return generator_init(obj, proc);
01187 }
01188
01189
01190 static VALUE
01191 generator_init_copy(VALUE obj, VALUE orig)
01192 {
01193 struct generator *ptr0, *ptr1;
01194
01195 if (!OBJ_INIT_COPY(obj, orig)) return obj;
01196
01197 ptr0 = generator_ptr(orig);
01198
01199 TypedData_Get_Struct(obj, struct generator, &generator_data_type, ptr1);
01200
01201 if (!ptr1) {
01202 rb_raise(rb_eArgError, "unallocated generator");
01203 }
01204
01205 ptr1->proc = ptr0->proc;
01206
01207 return obj;
01208 }
01209
01210
01211 static VALUE
01212 generator_each(int argc, VALUE *argv, VALUE obj)
01213 {
01214 struct generator *ptr = generator_ptr(obj);
01215 VALUE args = rb_ary_new2(argc + 1);
01216
01217 rb_ary_push(args, yielder_new());
01218 if (argc > 0) {
01219 rb_ary_cat(args, argv, argc);
01220 }
01221
01222 return rb_proc_call(ptr->proc, args);
01223 }
01224
01225
01226 static VALUE
01227 enum_size(VALUE self)
01228 {
01229 VALUE r = rb_check_funcall(self, id_size, 0, 0);
01230 return (r == Qundef) ? Qnil : r;
01231 }
01232
01233 static VALUE
01234 lazy_size(VALUE self)
01235 {
01236 return enum_size(rb_ivar_get(self, id_receiver));
01237 }
01238
01239 static VALUE
01240 lazy_receiver_size(VALUE generator, VALUE args, VALUE lazy)
01241 {
01242 return lazy_size(lazy);
01243 }
01244
01245 static VALUE
01246 lazy_init_iterator(VALUE val, VALUE m, int argc, VALUE *argv)
01247 {
01248 VALUE result;
01249 if (argc == 1) {
01250 VALUE args[2];
01251 args[0] = m;
01252 args[1] = val;
01253 result = rb_yield_values2(2, args);
01254 }
01255 else {
01256 VALUE args;
01257 int len = rb_long2int((long)argc + 1);
01258
01259 args = rb_ary_tmp_new(len);
01260 rb_ary_push(args, m);
01261 if (argc > 0) {
01262 rb_ary_cat(args, argv, argc);
01263 }
01264 result = rb_yield_values2(len, RARRAY_PTR(args));
01265 RB_GC_GUARD(args);
01266 }
01267 if (result == Qundef) rb_iter_break();
01268 return Qnil;
01269 }
01270
01271 static VALUE
01272 lazy_init_block_i(VALUE val, VALUE m, int argc, VALUE *argv)
01273 {
01274 rb_block_call(m, id_each, argc-1, argv+1, lazy_init_iterator, val);
01275 return Qnil;
01276 }
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306 static VALUE
01307 lazy_initialize(int argc, VALUE *argv, VALUE self)
01308 {
01309 VALUE obj, size = Qnil;
01310 VALUE generator;
01311
01312 rb_check_arity(argc, 1, 2);
01313 if (!rb_block_given_p()) {
01314 rb_raise(rb_eArgError, "tried to call lazy new without a block");
01315 }
01316 obj = argv[0];
01317 if (argc > 1) {
01318 size = argv[1];
01319 }
01320 generator = generator_allocate(rb_cGenerator);
01321 rb_block_call(generator, id_initialize, 0, 0, lazy_init_block_i, obj);
01322 enumerator_init(self, generator, sym_each, 0, 0, 0, size);
01323 rb_ivar_set(self, id_receiver, obj);
01324
01325 return self;
01326 }
01327
01328 static VALUE
01329 lazy_set_method(VALUE lazy, VALUE args, VALUE (*size_fn)(ANYARGS))
01330 {
01331 ID id = rb_frame_this_func();
01332 struct enumerator *e = enumerator_ptr(lazy);
01333 rb_ivar_set(lazy, id_method, ID2SYM(id));
01334 if (NIL_P(args)) {
01335
01336 rb_ivar_set(lazy, id_arguments, Qfalse);
01337 }
01338 else {
01339 rb_ivar_set(lazy, id_arguments, args);
01340 }
01341 e->size_fn = size_fn;
01342 return lazy;
01343 }
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376 static VALUE
01377 enumerable_lazy(VALUE obj)
01378 {
01379 VALUE result = lazy_to_enum_i(obj, sym_each, 0, 0, enum_size);
01380
01381 rb_ivar_set(result, id_method, Qfalse);
01382 return result;
01383 }
01384
01385 static VALUE
01386 lazy_to_enum_i(VALUE obj, VALUE meth, int argc, VALUE *argv, VALUE (*size_fn)(ANYARGS))
01387 {
01388 return enumerator_init(enumerator_allocate(rb_cLazy),
01389 obj, meth, argc, argv, size_fn, Qnil);
01390 }
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415 static VALUE
01416 lazy_to_enum(int argc, VALUE *argv, VALUE self)
01417 {
01418 VALUE lazy, meth = sym_each;
01419
01420 if (argc > 0) {
01421 --argc;
01422 meth = *argv++;
01423 }
01424 lazy = lazy_to_enum_i(self, meth, argc, argv, 0);
01425 if (rb_block_given_p()) {
01426 enumerator_ptr(lazy)->size = rb_block_proc();
01427 }
01428 return lazy;
01429 }
01430
01431 static VALUE
01432 lazy_map_func(VALUE val, VALUE m, int argc, VALUE *argv)
01433 {
01434 VALUE result = rb_yield_values2(argc - 1, &argv[1]);
01435
01436 rb_funcall(argv[0], id_yield, 1, result);
01437 return Qnil;
01438 }
01439
01440 static VALUE
01441 lazy_map(VALUE obj)
01442 {
01443 if (!rb_block_given_p()) {
01444 rb_raise(rb_eArgError, "tried to call lazy map without a block");
01445 }
01446
01447 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
01448 lazy_map_func, 0),
01449 Qnil, lazy_receiver_size);
01450 }
01451
01452 static VALUE
01453 lazy_flat_map_i(VALUE i, VALUE yielder, int argc, VALUE *argv)
01454 {
01455 return rb_funcall2(yielder, id_yield, argc, argv);
01456 }
01457
01458 static VALUE
01459 lazy_flat_map_each(VALUE obj, VALUE yielder)
01460 {
01461 rb_block_call(obj, id_each, 0, 0, lazy_flat_map_i, yielder);
01462 return Qnil;
01463 }
01464
01465 static VALUE
01466 lazy_flat_map_to_ary(VALUE obj, VALUE yielder)
01467 {
01468 VALUE ary = rb_check_array_type(obj);
01469 if (NIL_P(ary)) {
01470 rb_funcall(yielder, id_yield, 1, obj);
01471 }
01472 else {
01473 long i;
01474 for (i = 0; i < RARRAY_LEN(ary); i++) {
01475 rb_funcall(yielder, id_yield, 1, RARRAY_PTR(ary)[i]);
01476 }
01477 }
01478 return Qnil;
01479 }
01480
01481 static VALUE
01482 lazy_flat_map_func(VALUE val, VALUE m, int argc, VALUE *argv)
01483 {
01484 VALUE result = rb_yield_values2(argc - 1, &argv[1]);
01485 if (RB_TYPE_P(result, T_ARRAY)) {
01486 long i;
01487 for (i = 0; i < RARRAY_LEN(result); i++) {
01488 rb_funcall(argv[0], id_yield, 1, RARRAY_PTR(result)[i]);
01489 }
01490 }
01491 else {
01492 if (rb_respond_to(result, id_force) && rb_respond_to(result, id_each)) {
01493 lazy_flat_map_each(result, argv[0]);
01494 }
01495 else {
01496 lazy_flat_map_to_ary(result, argv[0]);
01497 }
01498 }
01499 return Qnil;
01500 }
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524 static VALUE
01525 lazy_flat_map(VALUE obj)
01526 {
01527 if (!rb_block_given_p()) {
01528 rb_raise(rb_eArgError, "tried to call lazy flat_map without a block");
01529 }
01530
01531 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
01532 lazy_flat_map_func, 0),
01533 Qnil, 0);
01534 }
01535
01536 static VALUE
01537 lazy_select_func(VALUE val, VALUE m, int argc, VALUE *argv)
01538 {
01539 VALUE element = rb_enum_values_pack(argc - 1, argv + 1);
01540
01541 if (RTEST(rb_yield(element))) {
01542 return rb_funcall(argv[0], id_yield, 1, element);
01543 }
01544 return Qnil;
01545 }
01546
01547 static VALUE
01548 lazy_select(VALUE obj)
01549 {
01550 if (!rb_block_given_p()) {
01551 rb_raise(rb_eArgError, "tried to call lazy select without a block");
01552 }
01553
01554 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
01555 lazy_select_func, 0),
01556 Qnil, 0);
01557 }
01558
01559 static VALUE
01560 lazy_reject_func(VALUE val, VALUE m, int argc, VALUE *argv)
01561 {
01562 VALUE element = rb_enum_values_pack(argc - 1, argv + 1);
01563
01564 if (!RTEST(rb_yield(element))) {
01565 return rb_funcall(argv[0], id_yield, 1, element);
01566 }
01567 return Qnil;
01568 }
01569
01570 static VALUE
01571 lazy_reject(VALUE obj)
01572 {
01573 if (!rb_block_given_p()) {
01574 rb_raise(rb_eArgError, "tried to call lazy reject without a block");
01575 }
01576
01577 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
01578 lazy_reject_func, 0),
01579 Qnil, 0);
01580 }
01581
01582 static VALUE
01583 lazy_grep_func(VALUE val, VALUE m, int argc, VALUE *argv)
01584 {
01585 VALUE i = rb_enum_values_pack(argc - 1, argv + 1);
01586 VALUE result = rb_funcall(m, id_eqq, 1, i);
01587
01588 if (RTEST(result)) {
01589 rb_funcall(argv[0], id_yield, 1, i);
01590 }
01591 return Qnil;
01592 }
01593
01594 static VALUE
01595 lazy_grep_iter(VALUE val, VALUE m, int argc, VALUE *argv)
01596 {
01597 VALUE i = rb_enum_values_pack(argc - 1, argv + 1);
01598 VALUE result = rb_funcall(m, id_eqq, 1, i);
01599
01600 if (RTEST(result)) {
01601 rb_funcall(argv[0], id_yield, 1, rb_yield(i));
01602 }
01603 return Qnil;
01604 }
01605
01606 static VALUE
01607 lazy_grep(VALUE obj, VALUE pattern)
01608 {
01609 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
01610 rb_block_given_p() ?
01611 lazy_grep_iter : lazy_grep_func,
01612 pattern),
01613 rb_ary_new3(1, pattern), 0);
01614 }
01615
01616 static VALUE
01617 call_next(VALUE obj)
01618 {
01619 return rb_funcall(obj, id_next, 0);
01620 }
01621
01622 static VALUE
01623 next_stopped(VALUE obj)
01624 {
01625 return Qnil;
01626 }
01627
01628 static VALUE
01629 lazy_zip_arrays_func(VALUE val, VALUE arrays, int argc, VALUE *argv)
01630 {
01631 VALUE yielder, ary, memo;
01632 long i, count;
01633
01634 yielder = argv[0];
01635 memo = rb_attr_get(yielder, id_memo);
01636 count = NIL_P(memo) ? 0 : NUM2LONG(memo);
01637
01638 ary = rb_ary_new2(RARRAY_LEN(arrays) + 1);
01639 rb_ary_push(ary, argv[1]);
01640 for (i = 0; i < RARRAY_LEN(arrays); i++) {
01641 rb_ary_push(ary, rb_ary_entry(RARRAY_PTR(arrays)[i], count));
01642 }
01643 rb_funcall(yielder, id_yield, 1, ary);
01644 rb_ivar_set(yielder, id_memo, LONG2NUM(++count));
01645 return Qnil;
01646 }
01647
01648 static VALUE
01649 lazy_zip_func(VALUE val, VALUE zip_args, int argc, VALUE *argv)
01650 {
01651 VALUE yielder, ary, arg, v;
01652 long i;
01653
01654 yielder = argv[0];
01655 arg = rb_attr_get(yielder, id_memo);
01656 if (NIL_P(arg)) {
01657 arg = rb_ary_new2(RARRAY_LEN(zip_args));
01658 for (i = 0; i < RARRAY_LEN(zip_args); i++) {
01659 rb_ary_push(arg, rb_funcall(RARRAY_PTR(zip_args)[i], id_to_enum, 0));
01660 }
01661 rb_ivar_set(yielder, id_memo, arg);
01662 }
01663
01664 ary = rb_ary_new2(RARRAY_LEN(arg) + 1);
01665 v = Qnil;
01666 if (--argc > 0) {
01667 ++argv;
01668 v = argc > 1 ? rb_ary_new4(argc, argv) : *argv;
01669 }
01670 rb_ary_push(ary, v);
01671 for (i = 0; i < RARRAY_LEN(arg); i++) {
01672 v = rb_rescue2(call_next, RARRAY_PTR(arg)[i], next_stopped, 0,
01673 rb_eStopIteration, (VALUE)0);
01674 rb_ary_push(ary, v);
01675 }
01676 rb_funcall(yielder, id_yield, 1, ary);
01677 return Qnil;
01678 }
01679
01680 static VALUE
01681 lazy_zip(int argc, VALUE *argv, VALUE obj)
01682 {
01683 VALUE ary, v;
01684 long i;
01685 rb_block_call_func *func = lazy_zip_arrays_func;
01686
01687 if (rb_block_given_p()) {
01688 return rb_call_super(argc, argv);
01689 }
01690
01691 ary = rb_ary_new2(argc);
01692 for (i = 0; i < argc; i++) {
01693 v = rb_check_array_type(argv[i]);
01694 if (NIL_P(v)) {
01695 for (; i < argc; i++) {
01696 if (!rb_respond_to(argv[i], id_each)) {
01697 rb_raise(rb_eTypeError, "wrong argument type %s (must respond to :each)",
01698 rb_obj_classname(argv[i]));
01699 }
01700 }
01701 ary = rb_ary_new4(argc, argv);
01702 func = lazy_zip_func;
01703 break;
01704 }
01705 rb_ary_push(ary, v);
01706 }
01707
01708 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
01709 func, ary),
01710 ary, lazy_receiver_size);
01711 }
01712
01713 static VALUE
01714 lazy_take_func(VALUE val, VALUE args, int argc, VALUE *argv)
01715 {
01716 long remain;
01717 VALUE memo = rb_attr_get(argv[0], id_memo);
01718 if (NIL_P(memo)) {
01719 memo = args;
01720 }
01721
01722 rb_funcall2(argv[0], id_yield, argc - 1, argv + 1);
01723 if ((remain = NUM2LONG(memo)-1) == 0) {
01724 return Qundef;
01725 }
01726 else {
01727 rb_ivar_set(argv[0], id_memo, LONG2NUM(remain));
01728 return Qnil;
01729 }
01730 }
01731
01732 static VALUE
01733 lazy_take_size(VALUE generator, VALUE args, VALUE lazy)
01734 {
01735 VALUE receiver = lazy_size(lazy);
01736 long len = NUM2LONG(RARRAY_PTR(rb_ivar_get(lazy, id_arguments))[0]);
01737 if (NIL_P(receiver) || (FIXNUM_P(receiver) && FIX2LONG(receiver) < len))
01738 return receiver;
01739 return LONG2NUM(len);
01740 }
01741
01742 static VALUE
01743 lazy_take(VALUE obj, VALUE n)
01744 {
01745 long len = NUM2LONG(n);
01746 VALUE lazy;
01747
01748 if (len < 0) {
01749 rb_raise(rb_eArgError, "attempt to take negative size");
01750 }
01751 if (len == 0) {
01752 VALUE len = INT2NUM(0);
01753 lazy = lazy_to_enum_i(obj, sym_cycle, 1, &len, 0);
01754 }
01755 else {
01756 lazy = rb_block_call(rb_cLazy, id_new, 1, &obj,
01757 lazy_take_func, n);
01758 }
01759 return lazy_set_method(lazy, rb_ary_new3(1, n), lazy_take_size);
01760 }
01761
01762 static VALUE
01763 lazy_take_while_func(VALUE val, VALUE args, int argc, VALUE *argv)
01764 {
01765 VALUE result = rb_yield_values2(argc - 1, &argv[1]);
01766 if (!RTEST(result)) return Qundef;
01767 rb_funcall2(argv[0], id_yield, argc - 1, argv + 1);
01768 return Qnil;
01769 }
01770
01771 static VALUE
01772 lazy_take_while(VALUE obj)
01773 {
01774 if (!rb_block_given_p()) {
01775 rb_raise(rb_eArgError, "tried to call lazy take_while without a block");
01776 }
01777 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
01778 lazy_take_while_func, 0),
01779 Qnil, 0);
01780 }
01781
01782 static VALUE
01783 lazy_drop_size(VALUE generator, VALUE args, VALUE lazy)
01784 {
01785 long len = NUM2LONG(RARRAY_PTR(rb_ivar_get(lazy, id_arguments))[0]);
01786 VALUE receiver = lazy_size(lazy);
01787 if (NIL_P(receiver))
01788 return receiver;
01789 if (FIXNUM_P(receiver)) {
01790 len = FIX2LONG(receiver) - len;
01791 return LONG2FIX(len < 0 ? 0 : len);
01792 }
01793 return rb_funcall(receiver, '-', 1, LONG2NUM(len));
01794 }
01795
01796 static VALUE
01797 lazy_drop_func(VALUE val, VALUE args, int argc, VALUE *argv)
01798 {
01799 long remain;
01800 VALUE memo = rb_attr_get(argv[0], id_memo);
01801 if (NIL_P(memo)) {
01802 memo = args;
01803 }
01804 if ((remain = NUM2LONG(memo)) == 0) {
01805 rb_funcall2(argv[0], id_yield, argc - 1, argv + 1);
01806 }
01807 else {
01808 rb_ivar_set(argv[0], id_memo, LONG2NUM(--remain));
01809 }
01810 return Qnil;
01811 }
01812
01813 static VALUE
01814 lazy_drop(VALUE obj, VALUE n)
01815 {
01816 long len = NUM2LONG(n);
01817
01818 if (len < 0) {
01819 rb_raise(rb_eArgError, "attempt to drop negative size");
01820 }
01821 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
01822 lazy_drop_func, n),
01823 rb_ary_new3(1, n), lazy_drop_size);
01824 }
01825
01826 static VALUE
01827 lazy_drop_while_func(VALUE val, VALUE args, int argc, VALUE *argv)
01828 {
01829 VALUE memo = rb_attr_get(argv[0], id_memo);
01830 if (NIL_P(memo) && !RTEST(rb_yield_values2(argc - 1, &argv[1]))) {
01831 rb_ivar_set(argv[0], id_memo, memo = Qtrue);
01832 }
01833 if (memo == Qtrue) {
01834 rb_funcall2(argv[0], id_yield, argc - 1, argv + 1);
01835 }
01836 return Qnil;
01837 }
01838
01839 static VALUE
01840 lazy_drop_while(VALUE obj)
01841 {
01842 if (!rb_block_given_p()) {
01843 rb_raise(rb_eArgError, "tried to call lazy drop_while without a block");
01844 }
01845 return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
01846 lazy_drop_while_func, 0),
01847 Qnil, 0);
01848 }
01849
01850 static VALUE
01851 lazy_super(int argc, VALUE *argv, VALUE lazy)
01852 {
01853 return enumerable_lazy(rb_call_super(argc, argv));
01854 }
01855
01856 static VALUE
01857 lazy_lazy(VALUE obj)
01858 {
01859 return obj;
01860 }
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909 static VALUE
01910 stop_result(VALUE self)
01911 {
01912 return rb_attr_get(self, id_result);
01913 }
01914
01915 void
01916 InitVM_Enumerator(void)
01917 {
01918 rb_define_method(rb_mKernel, "to_enum", obj_to_enum, -1);
01919 rb_define_method(rb_mKernel, "enum_for", obj_to_enum, -1);
01920
01921 rb_cEnumerator = rb_define_class("Enumerator", rb_cObject);
01922 rb_include_module(rb_cEnumerator, rb_mEnumerable);
01923
01924 rb_define_alloc_func(rb_cEnumerator, enumerator_allocate);
01925 rb_define_method(rb_cEnumerator, "initialize", enumerator_initialize, -1);
01926 rb_define_method(rb_cEnumerator, "initialize_copy", enumerator_init_copy, 1);
01927 rb_define_method(rb_cEnumerator, "each", enumerator_each, -1);
01928 rb_define_method(rb_cEnumerator, "each_with_index", enumerator_each_with_index, 0);
01929 rb_define_method(rb_cEnumerator, "each_with_object", enumerator_with_object, 1);
01930 rb_define_method(rb_cEnumerator, "with_index", enumerator_with_index, -1);
01931 rb_define_method(rb_cEnumerator, "with_object", enumerator_with_object, 1);
01932 rb_define_method(rb_cEnumerator, "next_values", enumerator_next_values, 0);
01933 rb_define_method(rb_cEnumerator, "peek_values", enumerator_peek_values_m, 0);
01934 rb_define_method(rb_cEnumerator, "next", enumerator_next, 0);
01935 rb_define_method(rb_cEnumerator, "peek", enumerator_peek, 0);
01936 rb_define_method(rb_cEnumerator, "feed", enumerator_feed, 1);
01937 rb_define_method(rb_cEnumerator, "rewind", enumerator_rewind, 0);
01938 rb_define_method(rb_cEnumerator, "inspect", enumerator_inspect, 0);
01939 rb_define_method(rb_cEnumerator, "size", enumerator_size, 0);
01940
01941
01942 rb_cLazy = rb_define_class_under(rb_cEnumerator, "Lazy", rb_cEnumerator);
01943 rb_define_method(rb_mEnumerable, "lazy", enumerable_lazy, 0);
01944 rb_define_method(rb_cLazy, "initialize", lazy_initialize, -1);
01945 rb_define_method(rb_cLazy, "to_enum", lazy_to_enum, -1);
01946 rb_define_method(rb_cLazy, "enum_for", lazy_to_enum, -1);
01947 rb_define_method(rb_cLazy, "map", lazy_map, 0);
01948 rb_define_method(rb_cLazy, "collect", lazy_map, 0);
01949 rb_define_method(rb_cLazy, "flat_map", lazy_flat_map, 0);
01950 rb_define_method(rb_cLazy, "collect_concat", lazy_flat_map, 0);
01951 rb_define_method(rb_cLazy, "select", lazy_select, 0);
01952 rb_define_method(rb_cLazy, "find_all", lazy_select, 0);
01953 rb_define_method(rb_cLazy, "reject", lazy_reject, 0);
01954 rb_define_method(rb_cLazy, "grep", lazy_grep, 1);
01955 rb_define_method(rb_cLazy, "zip", lazy_zip, -1);
01956 rb_define_method(rb_cLazy, "take", lazy_take, 1);
01957 rb_define_method(rb_cLazy, "take_while", lazy_take_while, 0);
01958 rb_define_method(rb_cLazy, "drop", lazy_drop, 1);
01959 rb_define_method(rb_cLazy, "drop_while", lazy_drop_while, 0);
01960 rb_define_method(rb_cLazy, "lazy", lazy_lazy, 0);
01961 rb_define_method(rb_cLazy, "chunk", lazy_super, -1);
01962 rb_define_method(rb_cLazy, "slice_before", lazy_super, -1);
01963
01964 rb_define_alias(rb_cLazy, "force", "to_a");
01965
01966 rb_eStopIteration = rb_define_class("StopIteration", rb_eIndexError);
01967 rb_define_method(rb_eStopIteration, "result", stop_result, 0);
01968
01969
01970 rb_cGenerator = rb_define_class_under(rb_cEnumerator, "Generator", rb_cObject);
01971 rb_include_module(rb_cGenerator, rb_mEnumerable);
01972 rb_define_alloc_func(rb_cGenerator, generator_allocate);
01973 rb_define_method(rb_cGenerator, "initialize", generator_initialize, -1);
01974 rb_define_method(rb_cGenerator, "initialize_copy", generator_init_copy, 1);
01975 rb_define_method(rb_cGenerator, "each", generator_each, -1);
01976
01977
01978 rb_cYielder = rb_define_class_under(rb_cEnumerator, "Yielder", rb_cObject);
01979 rb_define_alloc_func(rb_cYielder, yielder_allocate);
01980 rb_define_method(rb_cYielder, "initialize", yielder_initialize, 0);
01981 rb_define_method(rb_cYielder, "yield", yielder_yield, -2);
01982 rb_define_method(rb_cYielder, "<<", yielder_yield_push, -2);
01983
01984 rb_provide("enumerator.so");
01985 }
01986
01987 void
01988 Init_Enumerator(void)
01989 {
01990 id_rewind = rb_intern("rewind");
01991 id_each = rb_intern("each");
01992 id_call = rb_intern("call");
01993 id_size = rb_intern("size");
01994 id_yield = rb_intern("yield");
01995 id_new = rb_intern("new");
01996 id_initialize = rb_intern("initialize");
01997 id_next = rb_intern("next");
01998 id_result = rb_intern("result");
01999 id_lazy = rb_intern("lazy");
02000 id_eqq = rb_intern("===");
02001 id_receiver = rb_intern("receiver");
02002 id_arguments = rb_intern("arguments");
02003 id_memo = rb_intern("memo");
02004 id_method = rb_intern("method");
02005 id_force = rb_intern("force");
02006 id_to_enum = rb_intern("to_enum");
02007 sym_each = ID2SYM(id_each);
02008 sym_cycle = ID2SYM(rb_intern("cycle"));
02009
02010 InitVM(Enumerator);
02011 }
02012