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