00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "ruby/ruby.h"
00013 #include "ruby/util.h"
00014 #include "node.h"
00015 #include "id.h"
00016 #include "internal.h"
00017
00018 VALUE rb_f_send(int argc, VALUE *argv, VALUE recv);
00019
00020 VALUE rb_mEnumerable;
00021
00022 static ID id_next;
00023 static ID id_div;
00024 static ID id_call;
00025 static ID id_size;
00026
00027 #define id_each idEach
00028 #define id_eqq idEqq
00029 #define id_cmp idCmp
00030 #define id_lshift idLTLT
00031
00032 VALUE
00033 rb_enum_values_pack(int argc, const VALUE *argv)
00034 {
00035 if (argc == 0) return Qnil;
00036 if (argc == 1) return argv[0];
00037 return rb_ary_new4(argc, argv);
00038 }
00039
00040 #define ENUM_WANT_SVALUE() do { \
00041 i = rb_enum_values_pack(argc, argv); \
00042 } while (0)
00043
00044 #define enum_yield rb_yield_values2
00045
00046 static VALUE
00047 grep_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
00048 {
00049 NODE *memo = RNODE(args);
00050 ENUM_WANT_SVALUE();
00051
00052 if (RTEST(rb_funcall(memo->u1.value, id_eqq, 1, i))) {
00053 rb_ary_push(memo->u2.value, i);
00054 }
00055 return Qnil;
00056 }
00057
00058 static VALUE
00059 grep_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
00060 {
00061 NODE *memo = RNODE(args);
00062 ENUM_WANT_SVALUE();
00063
00064 if (RTEST(rb_funcall(memo->u1.value, id_eqq, 1, i))) {
00065 rb_ary_push(memo->u2.value, rb_yield(i));
00066 }
00067 return Qnil;
00068 }
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 static VALUE
00089 enum_grep(VALUE obj, VALUE pat)
00090 {
00091 VALUE ary = rb_ary_new();
00092 NODE *memo = NEW_MEMO(pat, ary, 0);
00093
00094 rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? grep_iter_i : grep_i, (VALUE)memo);
00095
00096 return ary;
00097 }
00098
00099 static VALUE
00100 count_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
00101 {
00102 NODE *memo = RNODE(memop);
00103
00104 ENUM_WANT_SVALUE();
00105
00106 if (rb_equal(i, memo->u1.value)) {
00107 memo->u3.cnt++;
00108 }
00109 return Qnil;
00110 }
00111
00112 static VALUE
00113 count_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
00114 {
00115 NODE *memo = RNODE(memop);
00116
00117 if (RTEST(enum_yield(argc, argv))) {
00118 memo->u3.cnt++;
00119 }
00120 return Qnil;
00121 }
00122
00123 static VALUE
00124 count_all_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
00125 {
00126 NODE *memo = RNODE(memop);
00127
00128 memo->u3.cnt++;
00129 return Qnil;
00130 }
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 static VALUE
00151 enum_count(int argc, VALUE *argv, VALUE obj)
00152 {
00153 VALUE item = Qnil;
00154 NODE *memo;
00155 rb_block_call_func *func;
00156
00157 if (argc == 0) {
00158 if (rb_block_given_p()) {
00159 func = count_iter_i;
00160 }
00161 else {
00162 func = count_all_i;
00163 }
00164 }
00165 else {
00166 rb_scan_args(argc, argv, "1", &item);
00167 if (rb_block_given_p()) {
00168 rb_warn("given block not used");
00169 }
00170 func = count_i;
00171 }
00172
00173 memo = NEW_MEMO(item, 0, 0);
00174 rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
00175 return INT2NUM(memo->u3.cnt);
00176 }
00177
00178 static VALUE
00179 find_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
00180 {
00181 ENUM_WANT_SVALUE();
00182
00183 if (RTEST(rb_yield(i))) {
00184 NODE *memo = RNODE(memop);
00185 memo->u1.value = i;
00186 memo->u3.cnt = 1;
00187 rb_iter_break();
00188 }
00189 return Qnil;
00190 }
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211 static VALUE
00212 enum_find(int argc, VALUE *argv, VALUE obj)
00213 {
00214 NODE *memo;
00215 VALUE if_none;
00216
00217 rb_scan_args(argc, argv, "01", &if_none);
00218 RETURN_ENUMERATOR(obj, argc, argv);
00219 memo = NEW_MEMO(Qundef, 0, 0);
00220 rb_block_call(obj, id_each, 0, 0, find_i, (VALUE)memo);
00221 if (memo->u3.cnt) {
00222 return memo->u1.value;
00223 }
00224 if (!NIL_P(if_none)) {
00225 return rb_funcall(if_none, id_call, 0, 0);
00226 }
00227 return Qnil;
00228 }
00229
00230 static VALUE
00231 find_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
00232 {
00233 NODE *memo = RNODE(memop);
00234
00235 ENUM_WANT_SVALUE();
00236
00237 if (rb_equal(i, memo->u2.value)) {
00238 memo->u1.value = UINT2NUM(memo->u3.cnt);
00239 rb_iter_break();
00240 }
00241 memo->u3.cnt++;
00242 return Qnil;
00243 }
00244
00245 static VALUE
00246 find_index_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
00247 {
00248 NODE *memo = RNODE(memop);
00249
00250 if (RTEST(enum_yield(argc, argv))) {
00251 memo->u1.value = UINT2NUM(memo->u3.cnt);
00252 rb_iter_break();
00253 }
00254 memo->u3.cnt++;
00255 return Qnil;
00256 }
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 static VALUE
00278 enum_find_index(int argc, VALUE *argv, VALUE obj)
00279 {
00280 NODE *memo;
00281 VALUE condition_value = Qnil;
00282 rb_block_call_func *func;
00283
00284 if (argc == 0) {
00285 RETURN_ENUMERATOR(obj, 0, 0);
00286 func = find_index_iter_i;
00287 }
00288 else {
00289 rb_scan_args(argc, argv, "1", &condition_value);
00290 if (rb_block_given_p()) {
00291 rb_warn("given block not used");
00292 }
00293 func = find_index_i;
00294 }
00295
00296 memo = NEW_MEMO(Qnil, condition_value, 0);
00297 rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
00298 return memo->u1.value;
00299 }
00300
00301 static VALUE
00302 find_all_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
00303 {
00304 ENUM_WANT_SVALUE();
00305
00306 if (RTEST(rb_yield(i))) {
00307 rb_ary_push(ary, i);
00308 }
00309 return Qnil;
00310 }
00311
00312 static VALUE
00313 enum_size(VALUE self, VALUE args, VALUE eobj)
00314 {
00315 VALUE r;
00316 r = rb_check_funcall(self, id_size, 0, 0);
00317 return (r == Qundef) ? Qnil : r;
00318 }
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340 static VALUE
00341 enum_find_all(VALUE obj)
00342 {
00343 VALUE ary;
00344
00345 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
00346
00347 ary = rb_ary_new();
00348 rb_block_call(obj, id_each, 0, 0, find_all_i, ary);
00349
00350 return ary;
00351 }
00352
00353 static VALUE
00354 reject_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
00355 {
00356 ENUM_WANT_SVALUE();
00357
00358 if (!RTEST(rb_yield(i))) {
00359 rb_ary_push(ary, i);
00360 }
00361 return Qnil;
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381 static VALUE
00382 enum_reject(VALUE obj)
00383 {
00384 VALUE ary;
00385
00386 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
00387
00388 ary = rb_ary_new();
00389 rb_block_call(obj, id_each, 0, 0, reject_i, ary);
00390
00391 return ary;
00392 }
00393
00394 static VALUE
00395 collect_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
00396 {
00397 rb_ary_push(ary, enum_yield(argc, argv));
00398
00399 return Qnil;
00400 }
00401
00402 static VALUE
00403 collect_all(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
00404 {
00405 rb_thread_check_ints();
00406 rb_ary_push(ary, rb_enum_values_pack(argc, argv));
00407
00408 return Qnil;
00409 }
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428 static VALUE
00429 enum_collect(VALUE obj)
00430 {
00431 VALUE ary;
00432
00433 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
00434
00435 ary = rb_ary_new();
00436 rb_block_call(obj, id_each, 0, 0, collect_i, ary);
00437
00438 return ary;
00439 }
00440
00441 static VALUE
00442 flat_map_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
00443 {
00444 VALUE tmp;
00445
00446 i = enum_yield(argc, argv);
00447 tmp = rb_check_array_type(i);
00448
00449 if (NIL_P(tmp)) {
00450 rb_ary_push(ary, i);
00451 }
00452 else {
00453 rb_ary_concat(ary, tmp);
00454 }
00455 return Qnil;
00456 }
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475 static VALUE
00476 enum_flat_map(VALUE obj)
00477 {
00478 VALUE ary;
00479
00480 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
00481
00482 ary = rb_ary_new();
00483 rb_block_call(obj, id_each, 0, 0, flat_map_i, ary);
00484
00485 return ary;
00486 }
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501 static VALUE
00502 enum_to_a(int argc, VALUE *argv, VALUE obj)
00503 {
00504 VALUE ary = rb_ary_new();
00505
00506 rb_block_call(obj, id_each, argc, argv, collect_all, ary);
00507 OBJ_INFECT(ary, obj);
00508
00509 return ary;
00510 }
00511
00512 static VALUE
00513 enum_to_h_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
00514 {
00515 VALUE key_value_pair;
00516 ENUM_WANT_SVALUE();
00517 rb_thread_check_ints();
00518 key_value_pair = rb_check_array_type(i);
00519 if (NIL_P(key_value_pair)) {
00520 rb_raise(rb_eTypeError, "wrong element type %s (expected array)",
00521 rb_builtin_class_name(i));
00522 }
00523 if (RARRAY_LEN(key_value_pair) != 2) {
00524 rb_raise(rb_eArgError, "element has wrong array length (expected 2, was %ld)",
00525 RARRAY_LEN(key_value_pair));
00526 }
00527 rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
00528 return Qnil;
00529 }
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542 static VALUE
00543 enum_to_h(int argc, VALUE *argv, VALUE obj)
00544 {
00545 VALUE hash = rb_hash_new();
00546 rb_block_call(obj, id_each, argc, argv, enum_to_h_i, hash);
00547 OBJ_INFECT(hash, obj);
00548 return hash;
00549 }
00550
00551 static VALUE
00552 inject_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
00553 {
00554 NODE *memo = RNODE(p);
00555
00556 ENUM_WANT_SVALUE();
00557
00558 if (memo->u2.argc == 0) {
00559 memo->u2.argc = 1;
00560 memo->u1.value = i;
00561 }
00562 else {
00563 memo->u1.value = rb_yield_values(2, memo->u1.value, i);
00564 }
00565 return Qnil;
00566 }
00567
00568 static VALUE
00569 inject_op_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
00570 {
00571 NODE *memo = RNODE(p);
00572 VALUE name;
00573
00574 ENUM_WANT_SVALUE();
00575
00576 if (memo->u2.argc == 0) {
00577 memo->u2.argc = 1;
00578 memo->u1.value = i;
00579 }
00580 else if (SYMBOL_P(name = memo->u3.value)) {
00581 memo->u1.value = rb_funcall(memo->u1.value, SYM2ID(name), 1, i);
00582 }
00583 else {
00584 VALUE args[2];
00585 args[0] = name;
00586 args[1] = i;
00587 memo->u1.value = rb_f_send(numberof(args), args, memo->u1.value);
00588 }
00589 return Qnil;
00590 }
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635 static VALUE
00636 enum_inject(int argc, VALUE *argv, VALUE obj)
00637 {
00638 NODE *memo;
00639 VALUE init, op;
00640 rb_block_call_func *iter = inject_i;
00641 ID id;
00642
00643 switch (rb_scan_args(argc, argv, "02", &init, &op)) {
00644 case 0:
00645 break;
00646 case 1:
00647 if (rb_block_given_p()) {
00648 break;
00649 }
00650 id = rb_check_id(&init);
00651 op = id ? ID2SYM(id) : init;
00652 argc = 0;
00653 init = Qnil;
00654 iter = inject_op_i;
00655 break;
00656 case 2:
00657 if (rb_block_given_p()) {
00658 rb_warning("given block not used");
00659 }
00660 id = rb_check_id(&op);
00661 if (id) op = ID2SYM(id);
00662 iter = inject_op_i;
00663 break;
00664 }
00665 memo = NEW_MEMO(init, argc, op);
00666 rb_block_call(obj, id_each, 0, 0, iter, (VALUE)memo);
00667 return memo->u1.value;
00668 }
00669
00670 static VALUE
00671 partition_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arys))
00672 {
00673 NODE *memo = RNODE(arys);
00674 VALUE ary;
00675 ENUM_WANT_SVALUE();
00676
00677 if (RTEST(rb_yield(i))) {
00678 ary = memo->u1.value;
00679 }
00680 else {
00681 ary = memo->u2.value;
00682 }
00683 rb_ary_push(ary, i);
00684 return Qnil;
00685 }
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702 static VALUE
00703 enum_partition(VALUE obj)
00704 {
00705 NODE *memo;
00706
00707 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
00708
00709 memo = NEW_MEMO(rb_ary_new(), rb_ary_new(), 0);
00710 rb_block_call(obj, id_each, 0, 0, partition_i, (VALUE)memo);
00711
00712 return rb_assoc_new(memo->u1.value, memo->u2.value);
00713 }
00714
00715 static VALUE
00716 group_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
00717 {
00718 VALUE group;
00719 VALUE values;
00720
00721 ENUM_WANT_SVALUE();
00722
00723 group = rb_yield(i);
00724 values = rb_hash_aref(hash, group);
00725 if (!RB_TYPE_P(values, T_ARRAY)) {
00726 values = rb_ary_new3(1, i);
00727 rb_hash_aset(hash, group, values);
00728 }
00729 else {
00730 rb_ary_push(values, i);
00731 }
00732 return Qnil;
00733 }
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750 static VALUE
00751 enum_group_by(VALUE obj)
00752 {
00753 VALUE hash;
00754
00755 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
00756
00757 hash = rb_hash_new();
00758 rb_block_call(obj, id_each, 0, 0, group_by_i, hash);
00759 OBJ_INFECT(hash, obj);
00760
00761 return hash;
00762 }
00763
00764 static VALUE
00765 first_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, params))
00766 {
00767 NODE *memo = RNODE(params);
00768 ENUM_WANT_SVALUE();
00769
00770 memo->u1.value = i;
00771 rb_iter_break();
00772
00773 UNREACHABLE;
00774 }
00775
00776 static VALUE enum_take(VALUE obj, VALUE n);
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794 static VALUE
00795 enum_first(int argc, VALUE *argv, VALUE obj)
00796 {
00797 NODE *memo;
00798 rb_check_arity(argc, 0, 1);
00799 if (argc > 0) {
00800 return enum_take(obj, argv[0]);
00801 }
00802 else {
00803 memo = NEW_MEMO(Qnil, 0, 0);
00804 rb_block_call(obj, id_each, 0, 0, first_i, (VALUE)memo);
00805 return memo->u1.value;
00806 }
00807 }
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827 static VALUE
00828 enum_sort(VALUE obj)
00829 {
00830 return rb_ary_sort(enum_to_a(0, 0, obj));
00831 }
00832
00833 #define SORT_BY_BUFSIZE 16
00834 struct sort_by_data {
00835 VALUE ary;
00836 VALUE buf;
00837 long n;
00838 };
00839
00840 static VALUE
00841 sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _data))
00842 {
00843 struct sort_by_data *data = (struct sort_by_data *)&RNODE(_data)->u1;
00844 VALUE ary = data->ary;
00845 VALUE v;
00846
00847 ENUM_WANT_SVALUE();
00848
00849 v = rb_yield(i);
00850
00851 if (RBASIC(ary)->klass) {
00852 rb_raise(rb_eRuntimeError, "sort_by reentered");
00853 }
00854 if (RARRAY_LEN(data->buf) != SORT_BY_BUFSIZE*2) {
00855 rb_raise(rb_eRuntimeError, "sort_by reentered");
00856 }
00857
00858 RARRAY_ASET(data->buf, data->n*2, v);
00859 RARRAY_ASET(data->buf, data->n*2+1, i);
00860 data->n++;
00861 if (data->n == SORT_BY_BUFSIZE) {
00862 rb_ary_concat(ary, data->buf);
00863 data->n = 0;
00864 }
00865 return Qnil;
00866 }
00867
00868 static int
00869 sort_by_cmp(const void *ap, const void *bp, void *data)
00870 {
00871 VALUE a;
00872 VALUE b;
00873 VALUE ary = (VALUE)data;
00874
00875 if (RBASIC(ary)->klass) {
00876 rb_raise(rb_eRuntimeError, "sort_by reentered");
00877 }
00878
00879 a = *(VALUE *)ap;
00880 b = *(VALUE *)bp;
00881
00882 return rb_cmpint(rb_funcall(a, id_cmp, 1, b), a, b);
00883 }
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956 static VALUE
00957 enum_sort_by(VALUE obj)
00958 {
00959 VALUE ary, buf;
00960 NODE *memo;
00961 long i;
00962 struct sort_by_data *data;
00963
00964 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
00965
00966 if (RB_TYPE_P(obj, T_ARRAY) && RARRAY_LEN(obj) <= LONG_MAX/2) {
00967 ary = rb_ary_new2(RARRAY_LEN(obj)*2);
00968 }
00969 else {
00970 ary = rb_ary_new();
00971 }
00972 RBASIC_CLEAR_CLASS(ary);
00973 buf = rb_ary_tmp_new(SORT_BY_BUFSIZE*2);
00974 rb_ary_store(buf, SORT_BY_BUFSIZE*2-1, Qnil);
00975 memo = NEW_MEMO(0, 0, 0);
00976 OBJ_INFECT(memo, obj);
00977 data = (struct sort_by_data *)&memo->u1;
00978 data->ary = ary;
00979 data->buf = buf;
00980 data->n = 0;
00981 rb_block_call(obj, id_each, 0, 0, sort_by_i, (VALUE)memo);
00982 ary = data->ary;
00983 buf = data->buf;
00984 if (data->n) {
00985 rb_ary_resize(buf, data->n*2);
00986 rb_ary_concat(ary, buf);
00987 }
00988 if (RARRAY_LEN(ary) > 2) {
00989 RARRAY_PTR_USE(ary, ptr,
00990 ruby_qsort(ptr, RARRAY_LEN(ary)/2, 2*sizeof(VALUE),
00991 sort_by_cmp, (void *)ary));
00992 }
00993 if (RBASIC(ary)->klass) {
00994 rb_raise(rb_eRuntimeError, "sort_by reentered");
00995 }
00996 for (i=1; i<RARRAY_LEN(ary); i+=2) {
00997 RARRAY_ASET(ary, i/2, RARRAY_AREF(ary, i));
00998 }
00999 rb_ary_resize(ary, RARRAY_LEN(ary)/2);
01000 RBASIC_SET_CLASS_RAW(ary, rb_cArray);
01001 OBJ_INFECT(ary, memo);
01002
01003 return ary;
01004 }
01005
01006 #define ENUMFUNC(name) rb_block_given_p() ? name##_iter_i : name##_i
01007
01008 #define DEFINE_ENUMFUNCS(name) \
01009 static VALUE enum_##name##_func(VALUE result, NODE *memo); \
01010 \
01011 static VALUE \
01012 name##_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) \
01013 { \
01014 return enum_##name##_func(rb_enum_values_pack(argc, argv), RNODE(memo)); \
01015 } \
01016 \
01017 static VALUE \
01018 name##_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) \
01019 { \
01020 return enum_##name##_func(enum_yield(argc, argv), RNODE(memo)); \
01021 } \
01022 \
01023 static VALUE \
01024 enum_##name##_func(VALUE result, NODE *memo)
01025
01026 DEFINE_ENUMFUNCS(all)
01027 {
01028 if (!RTEST(result)) {
01029 memo->u1.value = Qfalse;
01030 rb_iter_break();
01031 }
01032 return Qnil;
01033 }
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052 static VALUE
01053 enum_all(VALUE obj)
01054 {
01055 NODE *memo = NEW_MEMO(Qtrue, 0, 0);
01056 rb_block_call(obj, id_each, 0, 0, ENUMFUNC(all), (VALUE)memo);
01057 return memo->u1.value;
01058 }
01059
01060 DEFINE_ENUMFUNCS(any)
01061 {
01062 if (RTEST(result)) {
01063 memo->u1.value = Qtrue;
01064 rb_iter_break();
01065 }
01066 return Qnil;
01067 }
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086 static VALUE
01087 enum_any(VALUE obj)
01088 {
01089 NODE *memo = NEW_MEMO(Qfalse, 0, 0);
01090 rb_block_call(obj, id_each, 0, 0, ENUMFUNC(any), (VALUE)memo);
01091 return memo->u1.value;
01092 }
01093
01094 DEFINE_ENUMFUNCS(one)
01095 {
01096 if (RTEST(result)) {
01097 if (memo->u1.value == Qundef) {
01098 memo->u1.value = Qtrue;
01099 }
01100 else if (memo->u1.value == Qtrue) {
01101 memo->u1.value = Qfalse;
01102 rb_iter_break();
01103 }
01104 }
01105 return Qnil;
01106 }
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126 static VALUE
01127 enum_one(VALUE obj)
01128 {
01129 NODE *memo = NEW_MEMO(Qundef, 0, 0);
01130 VALUE result;
01131
01132 rb_block_call(obj, id_each, 0, 0, ENUMFUNC(one), (VALUE)memo);
01133 result = memo->u1.value;
01134 if (result == Qundef) return Qfalse;
01135 return result;
01136 }
01137
01138 DEFINE_ENUMFUNCS(none)
01139 {
01140 if (RTEST(result)) {
01141 memo->u1.value = Qfalse;
01142 rb_iter_break();
01143 }
01144 return Qnil;
01145 }
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162 static VALUE
01163 enum_none(VALUE obj)
01164 {
01165 NODE *memo = NEW_MEMO(Qtrue, 0, 0);
01166 rb_block_call(obj, id_each, 0, 0, ENUMFUNC(none), (VALUE)memo);
01167 return memo->u1.value;
01168 }
01169
01170 static VALUE
01171 min_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
01172 {
01173 VALUE cmp;
01174 NODE *memo = RNODE(args);
01175
01176 ENUM_WANT_SVALUE();
01177
01178 if (memo->u1.value == Qundef) {
01179 memo->u1.value = i;
01180 }
01181 else {
01182 cmp = rb_funcall(i, id_cmp, 1, memo->u1.value);
01183 if (rb_cmpint(cmp, i, memo->u1.value) < 0) {
01184 memo->u1.value = i;
01185 }
01186 }
01187 return Qnil;
01188 }
01189
01190 static VALUE
01191 min_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
01192 {
01193 VALUE cmp;
01194 NODE *memo = RNODE(args);
01195
01196 ENUM_WANT_SVALUE();
01197
01198 if (memo->u1.value == Qundef) {
01199 memo->u1.value = i;
01200 }
01201 else {
01202 cmp = rb_yield_values(2, i, memo->u1.value);
01203 if (rb_cmpint(cmp, i, memo->u1.value) < 0) {
01204 memo->u1.value = i;
01205 }
01206 }
01207 return Qnil;
01208 }
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225 static VALUE
01226 enum_min(VALUE obj)
01227 {
01228 NODE *memo = NEW_MEMO(Qundef, 0, 0);
01229 VALUE result;
01230
01231 if (rb_block_given_p()) {
01232 rb_block_call(obj, id_each, 0, 0, min_ii, (VALUE)memo);
01233 }
01234 else {
01235 rb_block_call(obj, id_each, 0, 0, min_i, (VALUE)memo);
01236 }
01237 result = memo->u1.value;
01238 if (result == Qundef) return Qnil;
01239 return result;
01240 }
01241
01242 static VALUE
01243 max_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
01244 {
01245 NODE *memo = RNODE(args);
01246 VALUE cmp;
01247
01248 ENUM_WANT_SVALUE();
01249
01250 if (memo->u1.value == Qundef) {
01251 memo->u1.value = i;
01252 }
01253 else {
01254 cmp = rb_funcall(i, id_cmp, 1, memo->u1.value);
01255 if (rb_cmpint(cmp, i, memo->u1.value) > 0) {
01256 memo->u1.value = i;
01257 }
01258 }
01259 return Qnil;
01260 }
01261
01262 static VALUE
01263 max_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
01264 {
01265 NODE *memo = RNODE(args);
01266 VALUE cmp;
01267
01268 ENUM_WANT_SVALUE();
01269
01270 if (memo->u1.value == Qundef) {
01271 memo->u1.value = i;
01272 }
01273 else {
01274 cmp = rb_yield_values(2, i, memo->u1.value);
01275 if (rb_cmpint(cmp, i, memo->u1.value) > 0) {
01276 memo->u1.value = i;
01277 }
01278 }
01279 return Qnil;
01280 }
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296 static VALUE
01297 enum_max(VALUE obj)
01298 {
01299 NODE *memo = NEW_MEMO(Qundef, 0, 0);
01300 VALUE result;
01301
01302 if (rb_block_given_p()) {
01303 rb_block_call(obj, id_each, 0, 0, max_ii, (VALUE)memo);
01304 }
01305 else {
01306 rb_block_call(obj, id_each, 0, 0, max_i, (VALUE)memo);
01307 }
01308 result = memo->u1.value;
01309 if (result == Qundef) return Qnil;
01310 return result;
01311 }
01312
01313 struct minmax_t {
01314 VALUE min;
01315 VALUE max;
01316 VALUE last;
01317 };
01318
01319 STATIC_ASSERT(minmax_t, sizeof(struct minmax_t) <= sizeof(NODE) - offsetof(NODE, u1));
01320
01321 static void
01322 minmax_i_update(VALUE i, VALUE j, struct minmax_t *memo)
01323 {
01324 int n;
01325
01326 if (memo->min == Qundef) {
01327 memo->min = i;
01328 memo->max = j;
01329 }
01330 else {
01331 n = rb_cmpint(rb_funcall(i, id_cmp, 1, memo->min), i, memo->min);
01332 if (n < 0) {
01333 memo->min = i;
01334 }
01335 n = rb_cmpint(rb_funcall(j, id_cmp, 1, memo->max), j, memo->max);
01336 if (n > 0) {
01337 memo->max = j;
01338 }
01339 }
01340 }
01341
01342 static VALUE
01343 minmax_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
01344 {
01345 struct minmax_t *memo = (struct minmax_t *)&RNODE(_memo)->u1.value;
01346 int n;
01347 VALUE j;
01348
01349 ENUM_WANT_SVALUE();
01350
01351 if (memo->last == Qundef) {
01352 memo->last = i;
01353 return Qnil;
01354 }
01355 j = memo->last;
01356 memo->last = Qundef;
01357
01358 n = rb_cmpint(rb_funcall(j, id_cmp, 1, i), j, i);
01359 if (n == 0)
01360 i = j;
01361 else if (n < 0) {
01362 VALUE tmp;
01363 tmp = i;
01364 i = j;
01365 j = tmp;
01366 }
01367
01368 minmax_i_update(i, j, memo);
01369
01370 return Qnil;
01371 }
01372
01373 static void
01374 minmax_ii_update(VALUE i, VALUE j, struct minmax_t *memo)
01375 {
01376 int n;
01377
01378 if (memo->min == Qundef) {
01379 memo->min = i;
01380 memo->max = j;
01381 }
01382 else {
01383 n = rb_cmpint(rb_yield_values(2, i, memo->min), i, memo->min);
01384 if (n < 0) {
01385 memo->min = i;
01386 }
01387 n = rb_cmpint(rb_yield_values(2, j, memo->max), j, memo->max);
01388 if (n > 0) {
01389 memo->max = j;
01390 }
01391 }
01392 }
01393
01394 static VALUE
01395 minmax_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
01396 {
01397 struct minmax_t *memo = (struct minmax_t *)&RNODE(_memo)->u1.value;
01398 int n;
01399 VALUE j;
01400
01401 ENUM_WANT_SVALUE();
01402
01403 if (memo->last == Qundef) {
01404 memo->last = i;
01405 return Qnil;
01406 }
01407 j = memo->last;
01408 memo->last = Qundef;
01409
01410 n = rb_cmpint(rb_yield_values(2, j, i), j, i);
01411 if (n == 0)
01412 i = j;
01413 else if (n < 0) {
01414 VALUE tmp;
01415 tmp = i;
01416 i = j;
01417 j = tmp;
01418 }
01419
01420 minmax_ii_update(i, j, memo);
01421
01422 return Qnil;
01423 }
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440 static VALUE
01441 enum_minmax(VALUE obj)
01442 {
01443 NODE *memo = NEW_MEMO(Qundef, Qundef, Qundef);
01444 struct minmax_t *m = (struct minmax_t *)&memo->u1.value;
01445 VALUE ary = rb_ary_new3(2, Qnil, Qnil);
01446
01447 m->min = Qundef;
01448 m->last = Qundef;
01449 if (rb_block_given_p()) {
01450 rb_block_call(obj, id_each, 0, 0, minmax_ii, (VALUE)memo);
01451 if (m->last != Qundef)
01452 minmax_ii_update(m->last, m->last, m);
01453 }
01454 else {
01455 rb_block_call(obj, id_each, 0, 0, minmax_i, (VALUE)memo);
01456 if (m->last != Qundef)
01457 minmax_i_update(m->last, m->last, m);
01458 }
01459 if (m->min != Qundef) {
01460 rb_ary_store(ary, 0, m->min);
01461 rb_ary_store(ary, 1, m->max);
01462 }
01463 return ary;
01464 }
01465
01466 static VALUE
01467 min_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
01468 {
01469 NODE *memo = RNODE(args);
01470 VALUE v;
01471
01472 ENUM_WANT_SVALUE();
01473
01474 v = rb_yield(i);
01475 if (memo->u1.value == Qundef) {
01476 memo->u1.value = v;
01477 memo->u2.value = i;
01478 }
01479 else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo->u1.value), v, memo->u1.value) < 0) {
01480 memo->u1.value = v;
01481 memo->u2.value = i;
01482 }
01483 return Qnil;
01484 }
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500 static VALUE
01501 enum_min_by(VALUE obj)
01502 {
01503 NODE *memo;
01504
01505 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
01506
01507 memo = NEW_MEMO(Qundef, Qnil, 0);
01508 rb_block_call(obj, id_each, 0, 0, min_by_i, (VALUE)memo);
01509 return memo->u2.value;
01510 }
01511
01512 static VALUE
01513 max_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
01514 {
01515 NODE *memo = RNODE(args);
01516 VALUE v;
01517
01518 ENUM_WANT_SVALUE();
01519
01520 v = rb_yield(i);
01521 if (memo->u1.value == Qundef) {
01522 memo->u1.value = v;
01523 memo->u2.value = i;
01524 }
01525 else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo->u1.value), v, memo->u1.value) > 0) {
01526 memo->u1.value = v;
01527 memo->u2.value = i;
01528 }
01529 return Qnil;
01530 }
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546 static VALUE
01547 enum_max_by(VALUE obj)
01548 {
01549 NODE *memo;
01550
01551 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
01552
01553 memo = NEW_MEMO(Qundef, Qnil, 0);
01554 rb_block_call(obj, id_each, 0, 0, max_by_i, (VALUE)memo);
01555 return memo->u2.value;
01556 }
01557
01558 struct minmax_by_t {
01559 VALUE min_bv;
01560 VALUE max_bv;
01561 VALUE min;
01562 VALUE max;
01563 VALUE last_bv;
01564 VALUE last;
01565 };
01566
01567 static void
01568 minmax_by_i_update(VALUE v1, VALUE v2, VALUE i1, VALUE i2, struct minmax_by_t *memo)
01569 {
01570 if (memo->min_bv == Qundef) {
01571 memo->min_bv = v1;
01572 memo->max_bv = v2;
01573 memo->min = i1;
01574 memo->max = i2;
01575 }
01576 else {
01577 if (rb_cmpint(rb_funcall(v1, id_cmp, 1, memo->min_bv), v1, memo->min_bv) < 0) {
01578 memo->min_bv = v1;
01579 memo->min = i1;
01580 }
01581 if (rb_cmpint(rb_funcall(v2, id_cmp, 1, memo->max_bv), v2, memo->max_bv) > 0) {
01582 memo->max_bv = v2;
01583 memo->max = i2;
01584 }
01585 }
01586 }
01587
01588 static VALUE
01589 minmax_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
01590 {
01591 struct minmax_by_t *memo = MEMO_FOR(struct minmax_by_t, _memo);
01592 VALUE vi, vj, j;
01593 int n;
01594
01595 ENUM_WANT_SVALUE();
01596
01597 vi = rb_yield(i);
01598
01599 if (memo->last_bv == Qundef) {
01600 memo->last_bv = vi;
01601 memo->last = i;
01602 return Qnil;
01603 }
01604 vj = memo->last_bv;
01605 j = memo->last;
01606 memo->last_bv = Qundef;
01607
01608 n = rb_cmpint(rb_funcall(vj, id_cmp, 1, vi), vj, vi);
01609 if (n == 0) {
01610 i = j;
01611 vi = vj;
01612 }
01613 else if (n < 0) {
01614 VALUE tmp;
01615 tmp = i;
01616 i = j;
01617 j = tmp;
01618 tmp = vi;
01619 vi = vj;
01620 vj = tmp;
01621 }
01622
01623 minmax_by_i_update(vi, vj, i, j, memo);
01624
01625 return Qnil;
01626 }
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643 static VALUE
01644 enum_minmax_by(VALUE obj)
01645 {
01646 VALUE memo;
01647 struct minmax_by_t *m = NEW_MEMO_FOR(struct minmax_by_t, memo);
01648
01649 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
01650
01651 m->min_bv = Qundef;
01652 m->max_bv = Qundef;
01653 m->min = Qnil;
01654 m->max = Qnil;
01655 m->last_bv = Qundef;
01656 m->last = Qundef;
01657 rb_block_call(obj, id_each, 0, 0, minmax_by_i, memo);
01658 if (m->last_bv != Qundef)
01659 minmax_by_i_update(m->last_bv, m->last_bv, m->last, m->last, m);
01660 m = MEMO_FOR(struct minmax_by_t, memo);
01661 return rb_assoc_new(m->min, m->max);
01662 }
01663
01664 static VALUE
01665 member_i(RB_BLOCK_CALL_FUNC_ARGLIST(iter, args))
01666 {
01667 NODE *memo = RNODE(args);
01668
01669 if (rb_equal(rb_enum_values_pack(argc, argv), memo->u1.value)) {
01670 memo->u2.value = Qtrue;
01671 rb_iter_break();
01672 }
01673 return Qnil;
01674 }
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689 static VALUE
01690 enum_member(VALUE obj, VALUE val)
01691 {
01692 NODE *memo = NEW_MEMO(val, Qfalse, 0);
01693
01694 rb_block_call(obj, id_each, 0, 0, member_i, (VALUE)memo);
01695 return memo->u2.value;
01696 }
01697
01698 static VALUE
01699 each_with_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo))
01700 {
01701 long n = RNODE(memo)->u3.cnt++;
01702
01703 return rb_yield_values(2, rb_enum_values_pack(argc, argv), INT2NUM(n));
01704 }
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725 static VALUE
01726 enum_each_with_index(int argc, VALUE *argv, VALUE obj)
01727 {
01728 NODE *memo;
01729
01730 RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
01731
01732 memo = NEW_MEMO(0, 0, 0);
01733 rb_block_call(obj, id_each, argc, argv, each_with_index_i, (VALUE)memo);
01734 return obj;
01735 }
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756 static VALUE
01757 enum_reverse_each(int argc, VALUE *argv, VALUE obj)
01758 {
01759 VALUE ary;
01760 long i;
01761
01762 RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
01763
01764 ary = enum_to_a(argc, argv, obj);
01765
01766 for (i = RARRAY_LEN(ary); --i >= 0; ) {
01767 rb_yield(RARRAY_AREF(ary, i));
01768 }
01769
01770 return obj;
01771 }
01772
01773
01774 static VALUE
01775 each_val_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
01776 {
01777 ENUM_WANT_SVALUE();
01778 rb_yield(i);
01779 return Qnil;
01780 }
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811 static VALUE
01812 enum_each_entry(int argc, VALUE *argv, VALUE obj)
01813 {
01814 RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
01815 rb_block_call(obj, id_each, argc, argv, each_val_i, 0);
01816 return obj;
01817 }
01818
01819 static VALUE
01820 each_slice_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, m))
01821 {
01822 NODE *memo = RNODE(m);
01823 VALUE ary = memo->u1.value;
01824 VALUE v = Qnil;
01825 long size = memo->u3.cnt;
01826 ENUM_WANT_SVALUE();
01827
01828 rb_ary_push(ary, i);
01829
01830 if (RARRAY_LEN(ary) == size) {
01831 v = rb_yield(ary);
01832 memo->u1.value = rb_ary_new2(size);
01833 }
01834
01835 return v;
01836 }
01837
01838 static VALUE
01839 enum_each_slice_size(VALUE obj, VALUE args, VALUE eobj)
01840 {
01841 VALUE n, size;
01842 long slice_size = NUM2LONG(RARRAY_AREF(args, 0));
01843 if (slice_size <= 0) rb_raise(rb_eArgError, "invalid slice size");
01844
01845 size = enum_size(obj, 0, 0);
01846 if (size == Qnil) return Qnil;
01847
01848 n = rb_funcall(size, '+', 1, LONG2NUM(slice_size-1));
01849 return rb_funcall(n, id_div, 1, LONG2FIX(slice_size));
01850 }
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868 static VALUE
01869 enum_each_slice(VALUE obj, VALUE n)
01870 {
01871 long size = NUM2LONG(n);
01872 VALUE ary;
01873 NODE *memo;
01874
01875 if (size <= 0) rb_raise(rb_eArgError, "invalid slice size");
01876 RETURN_SIZED_ENUMERATOR(obj, 1, &n, enum_each_slice_size);
01877 ary = rb_ary_new2(size);
01878 memo = NEW_MEMO(ary, 0, size);
01879 rb_block_call(obj, id_each, 0, 0, each_slice_i, (VALUE)memo);
01880 ary = memo->u1.value;
01881 if (RARRAY_LEN(ary) > 0) rb_yield(ary);
01882
01883 return Qnil;
01884 }
01885
01886 static VALUE
01887 each_cons_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
01888 {
01889 NODE *memo = RNODE(args);
01890 VALUE ary = memo->u1.value;
01891 VALUE v = Qnil;
01892 long size = memo->u3.cnt;
01893 ENUM_WANT_SVALUE();
01894
01895 if (RARRAY_LEN(ary) == size) {
01896 rb_ary_shift(ary);
01897 }
01898 rb_ary_push(ary, i);
01899 if (RARRAY_LEN(ary) == size) {
01900 v = rb_yield(rb_ary_dup(ary));
01901 }
01902 return v;
01903 }
01904
01905 static VALUE
01906 enum_each_cons_size(VALUE obj, VALUE args, VALUE eobj)
01907 {
01908 VALUE n, size;
01909 long cons_size = NUM2LONG(RARRAY_AREF(args, 0));
01910 if (cons_size <= 0) rb_raise(rb_eArgError, "invalid size");
01911
01912 size = enum_size(obj, 0, 0);
01913 if (size == Qnil) return Qnil;
01914
01915 n = rb_funcall(size, '+', 1, LONG2NUM(1 - cons_size));
01916 return (rb_cmpint(rb_funcall(n, id_cmp, 1, LONG2FIX(0)), n, LONG2FIX(0)) == -1) ? LONG2FIX(0) : n;
01917 }
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940 static VALUE
01941 enum_each_cons(VALUE obj, VALUE n)
01942 {
01943 long size = NUM2LONG(n);
01944 NODE *memo;
01945
01946 if (size <= 0) rb_raise(rb_eArgError, "invalid size");
01947 RETURN_SIZED_ENUMERATOR(obj, 1, &n, enum_each_cons_size);
01948 memo = NEW_MEMO(rb_ary_new2(size), 0, size);
01949 rb_block_call(obj, id_each, 0, 0, each_cons_i, (VALUE)memo);
01950
01951 return Qnil;
01952 }
01953
01954 static VALUE
01955 each_with_object_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo))
01956 {
01957 ENUM_WANT_SVALUE();
01958 return rb_yield_values(2, i, memo);
01959 }
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975 static VALUE
01976 enum_each_with_object(VALUE obj, VALUE memo)
01977 {
01978 RETURN_SIZED_ENUMERATOR(obj, 1, &memo, enum_size);
01979
01980 rb_block_call(obj, id_each, 0, 0, each_with_object_i, memo);
01981
01982 return memo;
01983 }
01984
01985 static VALUE
01986 zip_ary(RB_BLOCK_CALL_FUNC_ARGLIST(val, memoval))
01987 {
01988 NODE *memo = (NODE *)memoval;
01989 volatile VALUE result = memo->u1.value;
01990 volatile VALUE args = memo->u2.value;
01991 long n = memo->u3.cnt++;
01992 volatile VALUE tmp;
01993 int i;
01994
01995 tmp = rb_ary_new2(RARRAY_LEN(args) + 1);
01996 rb_ary_store(tmp, 0, rb_enum_values_pack(argc, argv));
01997 for (i=0; i<RARRAY_LEN(args); i++) {
01998 VALUE e = RARRAY_AREF(args, i);
01999
02000 if (RARRAY_LEN(e) <= n) {
02001 rb_ary_push(tmp, Qnil);
02002 }
02003 else {
02004 rb_ary_push(tmp, RARRAY_AREF(e, n));
02005 }
02006 }
02007 if (NIL_P(result)) {
02008 rb_yield(tmp);
02009 }
02010 else {
02011 rb_ary_push(result, tmp);
02012 }
02013 return Qnil;
02014 }
02015
02016 static VALUE
02017 call_next(VALUE *v)
02018 {
02019 return v[0] = rb_funcall(v[1], id_next, 0, 0);
02020 }
02021
02022 static VALUE
02023 call_stop(VALUE *v)
02024 {
02025 return v[0] = Qundef;
02026 }
02027
02028 static VALUE
02029 zip_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, memoval))
02030 {
02031 NODE *memo = (NODE *)memoval;
02032 volatile VALUE result = memo->u1.value;
02033 volatile VALUE args = memo->u2.value;
02034 volatile VALUE tmp;
02035 int i;
02036
02037 tmp = rb_ary_new2(RARRAY_LEN(args) + 1);
02038 rb_ary_store(tmp, 0, rb_enum_values_pack(argc, argv));
02039 for (i=0; i<RARRAY_LEN(args); i++) {
02040 if (NIL_P(RARRAY_AREF(args, i))) {
02041 rb_ary_push(tmp, Qnil);
02042 }
02043 else {
02044 VALUE v[2];
02045
02046 v[1] = RARRAY_AREF(args, i);
02047 rb_rescue2(call_next, (VALUE)v, call_stop, (VALUE)v, rb_eStopIteration, (VALUE)0);
02048 if (v[0] == Qundef) {
02049 RARRAY_ASET(args, i, Qnil);
02050 v[0] = Qnil;
02051 }
02052 rb_ary_push(tmp, v[0]);
02053 }
02054 }
02055 if (NIL_P(result)) {
02056 rb_yield(tmp);
02057 }
02058 else {
02059 rb_ary_push(result, tmp);
02060 }
02061 return Qnil;
02062 }
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087 static VALUE
02088 enum_zip(int argc, VALUE *argv, VALUE obj)
02089 {
02090 int i;
02091 ID conv;
02092 NODE *memo;
02093 VALUE result = Qnil;
02094 VALUE args = rb_ary_new4(argc, argv);
02095 int allary = TRUE;
02096
02097 argv = RARRAY_PTR(args);
02098 for (i=0; i<argc; i++) {
02099 VALUE ary = rb_check_array_type(argv[i]);
02100 if (NIL_P(ary)) {
02101 allary = FALSE;
02102 break;
02103 }
02104 argv[i] = ary;
02105 }
02106 if (!allary) {
02107 CONST_ID(conv, "to_enum");
02108 for (i=0; i<argc; i++) {
02109 if (!rb_respond_to(argv[i], id_each)) {
02110 rb_raise(rb_eTypeError, "wrong argument type %s (must respond to :each)",
02111 rb_obj_classname(argv[i]));
02112 }
02113 argv[i] = rb_funcall(argv[i], conv, 1, ID2SYM(id_each));
02114 }
02115 }
02116 if (!rb_block_given_p()) {
02117 result = rb_ary_new();
02118 }
02119
02120 memo = rb_node_newnode(NODE_DOT2, result, args, 0);
02121 rb_block_call(obj, id_each, 0, 0, allary ? zip_ary : zip_i, (VALUE)memo);
02122
02123 return result;
02124 }
02125
02126 static VALUE
02127 take_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
02128 {
02129 NODE *memo = RNODE(args);
02130 rb_ary_push(memo->u1.value, rb_enum_values_pack(argc, argv));
02131 if (--memo->u3.cnt == 0) rb_iter_break();
02132 return Qnil;
02133 }
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146 static VALUE
02147 enum_take(VALUE obj, VALUE n)
02148 {
02149 NODE *memo;
02150 VALUE result;
02151 long len = NUM2LONG(n);
02152
02153 if (len < 0) {
02154 rb_raise(rb_eArgError, "attempt to take negative size");
02155 }
02156
02157 if (len == 0) return rb_ary_new2(0);
02158 result = rb_ary_new2(len);
02159 memo = NEW_MEMO(result, 0, len);
02160 rb_block_call(obj, id_each, 0, 0, take_i, (VALUE)memo);
02161 return result;
02162 }
02163
02164
02165 static VALUE
02166 take_while_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
02167 {
02168 if (!RTEST(enum_yield(argc, argv))) rb_iter_break();
02169 rb_ary_push(ary, rb_enum_values_pack(argc, argv));
02170 return Qnil;
02171 }
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188 static VALUE
02189 enum_take_while(VALUE obj)
02190 {
02191 VALUE ary;
02192
02193 RETURN_ENUMERATOR(obj, 0, 0);
02194 ary = rb_ary_new();
02195 rb_block_call(obj, id_each, 0, 0, take_while_i, ary);
02196 return ary;
02197 }
02198
02199 static VALUE
02200 drop_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
02201 {
02202 NODE *memo = RNODE(args);
02203 if (memo->u3.cnt == 0) {
02204 rb_ary_push(memo->u1.value, rb_enum_values_pack(argc, argv));
02205 }
02206 else {
02207 memo->u3.cnt--;
02208 }
02209 return Qnil;
02210 }
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224 static VALUE
02225 enum_drop(VALUE obj, VALUE n)
02226 {
02227 VALUE result;
02228 NODE *memo;
02229 long len = NUM2LONG(n);
02230
02231 if (len < 0) {
02232 rb_raise(rb_eArgError, "attempt to drop negative size");
02233 }
02234
02235 result = rb_ary_new();
02236 memo = NEW_MEMO(result, 0, len);
02237 rb_block_call(obj, id_each, 0, 0, drop_i, (VALUE)memo);
02238 return result;
02239 }
02240
02241
02242 static VALUE
02243 drop_while_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
02244 {
02245 NODE *memo = RNODE(args);
02246 ENUM_WANT_SVALUE();
02247
02248 if (!memo->u3.state && !RTEST(rb_yield(i))) {
02249 memo->u3.state = TRUE;
02250 }
02251 if (memo->u3.state) {
02252 rb_ary_push(memo->u1.value, i);
02253 }
02254 return Qnil;
02255 }
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268
02269
02270
02271
02272
02273 static VALUE
02274 enum_drop_while(VALUE obj)
02275 {
02276 VALUE result;
02277 NODE *memo;
02278
02279 RETURN_ENUMERATOR(obj, 0, 0);
02280 result = rb_ary_new();
02281 memo = NEW_MEMO(result, 0, FALSE);
02282 rb_block_call(obj, id_each, 0, 0, drop_while_i, (VALUE)memo);
02283 return result;
02284 }
02285
02286 static VALUE
02287 cycle_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
02288 {
02289 ENUM_WANT_SVALUE();
02290
02291 rb_ary_push(ary, i);
02292 rb_yield(i);
02293 return Qnil;
02294 }
02295
02296 static VALUE
02297 enum_cycle_size(VALUE self, VALUE args, VALUE eobj)
02298 {
02299 long mul;
02300 VALUE n = Qnil;
02301 VALUE size = enum_size(self, args, 0);
02302
02303 if (size == Qnil) return Qnil;
02304
02305 if (args && (RARRAY_LEN(args) > 0)) {
02306 n = RARRAY_AREF(args, 0);
02307 }
02308 if (n == Qnil) return DBL2NUM(INFINITY);
02309 mul = NUM2LONG(n);
02310 if (mul <= 0) return INT2FIX(0);
02311 return rb_funcall(size, '*', 1, LONG2FIX(mul));
02312 }
02313
02314
02315
02316
02317
02318
02319
02320
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333
02334
02335 static VALUE
02336 enum_cycle(int argc, VALUE *argv, VALUE obj)
02337 {
02338 VALUE ary;
02339 VALUE nv = Qnil;
02340 long n, i, len;
02341
02342 rb_scan_args(argc, argv, "01", &nv);
02343
02344 RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_cycle_size);
02345 if (NIL_P(nv)) {
02346 n = -1;
02347 }
02348 else {
02349 n = NUM2LONG(nv);
02350 if (n <= 0) return Qnil;
02351 }
02352 ary = rb_ary_new();
02353 RBASIC_CLEAR_CLASS(ary);
02354 rb_block_call(obj, id_each, 0, 0, cycle_i, ary);
02355 len = RARRAY_LEN(ary);
02356 if (len == 0) return Qnil;
02357 while (n < 0 || 0 < --n) {
02358 for (i=0; i<len; i++) {
02359 rb_yield(RARRAY_AREF(ary, i));
02360 }
02361 }
02362 return Qnil;
02363 }
02364
02365 struct chunk_arg {
02366 VALUE categorize;
02367 VALUE state;
02368 VALUE prev_value;
02369 VALUE prev_elts;
02370 VALUE yielder;
02371 };
02372
02373 static VALUE
02374 chunk_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _argp))
02375 {
02376 struct chunk_arg *argp = MEMO_FOR(struct chunk_arg, _argp);
02377 VALUE v;
02378 VALUE alone = ID2SYM(rb_intern("_alone"));
02379 VALUE separator = ID2SYM(rb_intern("_separator"));
02380
02381 ENUM_WANT_SVALUE();
02382
02383 if (NIL_P(argp->state))
02384 v = rb_funcall(argp->categorize, id_call, 1, i);
02385 else
02386 v = rb_funcall(argp->categorize, id_call, 2, i, argp->state);
02387
02388 if (v == alone) {
02389 if (!NIL_P(argp->prev_value)) {
02390 rb_funcall(argp->yielder, id_lshift, 1, rb_assoc_new(argp->prev_value, argp->prev_elts));
02391 argp->prev_value = argp->prev_elts = Qnil;
02392 }
02393 rb_funcall(argp->yielder, id_lshift, 1, rb_assoc_new(v, rb_ary_new3(1, i)));
02394 }
02395 else if (NIL_P(v) || v == separator) {
02396 if (!NIL_P(argp->prev_value)) {
02397 rb_funcall(argp->yielder, id_lshift, 1, rb_assoc_new(argp->prev_value, argp->prev_elts));
02398 argp->prev_value = argp->prev_elts = Qnil;
02399 }
02400 }
02401 else if (SYMBOL_P(v) && rb_id2name(SYM2ID(v))[0] == '_') {
02402 rb_raise(rb_eRuntimeError, "symbols beginning with an underscore are reserved");
02403 }
02404 else {
02405 if (NIL_P(argp->prev_value)) {
02406 argp->prev_value = v;
02407 argp->prev_elts = rb_ary_new3(1, i);
02408 }
02409 else {
02410 if (rb_equal(argp->prev_value, v)) {
02411 rb_ary_push(argp->prev_elts, i);
02412 }
02413 else {
02414 rb_funcall(argp->yielder, id_lshift, 1, rb_assoc_new(argp->prev_value, argp->prev_elts));
02415 argp->prev_value = v;
02416 argp->prev_elts = rb_ary_new3(1, i);
02417 }
02418 }
02419 }
02420 return Qnil;
02421 }
02422
02423 static VALUE
02424 chunk_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator))
02425 {
02426 VALUE enumerable;
02427 VALUE arg;
02428 struct chunk_arg *memo = NEW_MEMO_FOR(struct chunk_arg, arg);
02429
02430 enumerable = rb_ivar_get(enumerator, rb_intern("chunk_enumerable"));
02431 memo->categorize = rb_ivar_get(enumerator, rb_intern("chunk_categorize"));
02432 memo->state = rb_ivar_get(enumerator, rb_intern("chunk_initial_state"));
02433 memo->prev_value = Qnil;
02434 memo->prev_elts = Qnil;
02435 memo->yielder = yielder;
02436
02437 if (!NIL_P(memo->state))
02438 memo->state = rb_obj_dup(memo->state);
02439
02440 rb_block_call(enumerable, id_each, 0, 0, chunk_ii, arg);
02441 memo = MEMO_FOR(struct chunk_arg, arg);
02442 if (!NIL_P(memo->prev_elts))
02443 rb_funcall(memo->yielder, id_lshift, 1, rb_assoc_new(memo->prev_value, memo->prev_elts));
02444 return Qnil;
02445 }
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501
02502
02503
02504
02505
02506
02507
02508
02509
02510
02511
02512
02513
02514
02515
02516
02517
02518
02519
02520
02521
02522
02523
02524
02525
02526
02527
02528
02529
02530
02531
02532
02533
02534
02535
02536
02537
02538
02539
02540
02541 static VALUE
02542 enum_chunk(int argc, VALUE *argv, VALUE enumerable)
02543 {
02544 VALUE initial_state;
02545 VALUE enumerator;
02546
02547 if (!rb_block_given_p())
02548 rb_raise(rb_eArgError, "no block given");
02549 rb_scan_args(argc, argv, "01", &initial_state);
02550
02551 enumerator = rb_obj_alloc(rb_cEnumerator);
02552 rb_ivar_set(enumerator, rb_intern("chunk_enumerable"), enumerable);
02553 rb_ivar_set(enumerator, rb_intern("chunk_categorize"), rb_block_proc());
02554 rb_ivar_set(enumerator, rb_intern("chunk_initial_state"), initial_state);
02555 rb_block_call(enumerator, idInitialize, 0, 0, chunk_i, enumerator);
02556 return enumerator;
02557 }
02558
02559
02560 struct slicebefore_arg {
02561 VALUE sep_pred;
02562 VALUE sep_pat;
02563 VALUE state;
02564 VALUE prev_elts;
02565 VALUE yielder;
02566 };
02567
02568 static VALUE
02569 slicebefore_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _argp))
02570 {
02571 struct slicebefore_arg *argp = MEMO_FOR(struct slicebefore_arg, _argp);
02572 VALUE header_p;
02573
02574 ENUM_WANT_SVALUE();
02575
02576 if (!NIL_P(argp->sep_pat))
02577 header_p = rb_funcall(argp->sep_pat, id_eqq, 1, i);
02578 else if (NIL_P(argp->state))
02579 header_p = rb_funcall(argp->sep_pred, id_call, 1, i);
02580 else
02581 header_p = rb_funcall(argp->sep_pred, id_call, 2, i, argp->state);
02582 if (RTEST(header_p)) {
02583 if (!NIL_P(argp->prev_elts))
02584 rb_funcall(argp->yielder, id_lshift, 1, argp->prev_elts);
02585 argp->prev_elts = rb_ary_new3(1, i);
02586 }
02587 else {
02588 if (NIL_P(argp->prev_elts))
02589 argp->prev_elts = rb_ary_new3(1, i);
02590 else
02591 rb_ary_push(argp->prev_elts, i);
02592 }
02593
02594 return Qnil;
02595 }
02596
02597 static VALUE
02598 slicebefore_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator))
02599 {
02600 VALUE enumerable;
02601 VALUE arg;
02602 struct slicebefore_arg *memo = NEW_MEMO_FOR(struct slicebefore_arg, arg);
02603
02604 enumerable = rb_ivar_get(enumerator, rb_intern("slicebefore_enumerable"));
02605 memo->sep_pred = rb_attr_get(enumerator, rb_intern("slicebefore_sep_pred"));
02606 memo->sep_pat = NIL_P(memo->sep_pred) ? rb_ivar_get(enumerator, rb_intern("slicebefore_sep_pat")) : Qnil;
02607 memo->state = rb_attr_get(enumerator, rb_intern("slicebefore_initial_state"));
02608 memo->prev_elts = Qnil;
02609 memo->yielder = yielder;
02610
02611 if (!NIL_P(memo->state))
02612 memo->state = rb_obj_dup(memo->state);
02613
02614 rb_block_call(enumerable, id_each, 0, 0, slicebefore_ii, arg);
02615 memo = MEMO_FOR(struct slicebefore_arg, arg);
02616 if (!NIL_P(memo->prev_elts))
02617 rb_funcall(memo->yielder, id_lshift, 1, memo->prev_elts);
02618 return Qnil;
02619 }
02620
02621
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643
02644
02645
02646
02647
02648
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658
02659
02660
02661
02662
02663
02664
02665
02666
02667
02668
02669
02670
02671
02672
02673
02674
02675
02676
02677
02678
02679
02680
02681
02682
02683
02684
02685
02686
02687
02688
02689
02690
02691
02692
02693
02694
02695
02696
02697
02698
02699
02700
02701
02702
02703
02704
02705
02706
02707
02708
02709
02710
02711
02712
02713
02714
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747
02748
02749
02750
02751
02752
02753
02754
02755
02756
02757
02758 static VALUE
02759 enum_slice_before(int argc, VALUE *argv, VALUE enumerable)
02760 {
02761 VALUE enumerator;
02762
02763 if (rb_block_given_p()) {
02764 VALUE initial_state;
02765 rb_scan_args(argc, argv, "01", &initial_state);
02766 enumerator = rb_obj_alloc(rb_cEnumerator);
02767 rb_ivar_set(enumerator, rb_intern("slicebefore_sep_pred"), rb_block_proc());
02768 rb_ivar_set(enumerator, rb_intern("slicebefore_initial_state"), initial_state);
02769 }
02770 else {
02771 VALUE sep_pat;
02772 rb_scan_args(argc, argv, "1", &sep_pat);
02773 enumerator = rb_obj_alloc(rb_cEnumerator);
02774 rb_ivar_set(enumerator, rb_intern("slicebefore_sep_pat"), sep_pat);
02775 }
02776 rb_ivar_set(enumerator, rb_intern("slicebefore_enumerable"), enumerable);
02777 rb_block_call(enumerator, idInitialize, 0, 0, slicebefore_i, enumerator);
02778 return enumerator;
02779 }
02780
02781
02782
02783
02784
02785
02786
02787
02788
02789
02790
02791
02792 void
02793 Init_Enumerable(void)
02794 {
02795 #undef rb_intern
02796 #define rb_intern(str) rb_intern_const(str)
02797
02798 rb_mEnumerable = rb_define_module("Enumerable");
02799
02800 rb_define_method(rb_mEnumerable, "to_a", enum_to_a, -1);
02801 rb_define_method(rb_mEnumerable, "entries", enum_to_a, -1);
02802 rb_define_method(rb_mEnumerable, "to_h", enum_to_h, -1);
02803
02804 rb_define_method(rb_mEnumerable, "sort", enum_sort, 0);
02805 rb_define_method(rb_mEnumerable, "sort_by", enum_sort_by, 0);
02806 rb_define_method(rb_mEnumerable, "grep", enum_grep, 1);
02807 rb_define_method(rb_mEnumerable, "count", enum_count, -1);
02808 rb_define_method(rb_mEnumerable, "find", enum_find, -1);
02809 rb_define_method(rb_mEnumerable, "detect", enum_find, -1);
02810 rb_define_method(rb_mEnumerable, "find_index", enum_find_index, -1);
02811 rb_define_method(rb_mEnumerable, "find_all", enum_find_all, 0);
02812 rb_define_method(rb_mEnumerable, "select", enum_find_all, 0);
02813 rb_define_method(rb_mEnumerable, "reject", enum_reject, 0);
02814 rb_define_method(rb_mEnumerable, "collect", enum_collect, 0);
02815 rb_define_method(rb_mEnumerable, "map", enum_collect, 0);
02816 rb_define_method(rb_mEnumerable, "flat_map", enum_flat_map, 0);
02817 rb_define_method(rb_mEnumerable, "collect_concat", enum_flat_map, 0);
02818 rb_define_method(rb_mEnumerable, "inject", enum_inject, -1);
02819 rb_define_method(rb_mEnumerable, "reduce", enum_inject, -1);
02820 rb_define_method(rb_mEnumerable, "partition", enum_partition, 0);
02821 rb_define_method(rb_mEnumerable, "group_by", enum_group_by, 0);
02822 rb_define_method(rb_mEnumerable, "first", enum_first, -1);
02823 rb_define_method(rb_mEnumerable, "all?", enum_all, 0);
02824 rb_define_method(rb_mEnumerable, "any?", enum_any, 0);
02825 rb_define_method(rb_mEnumerable, "one?", enum_one, 0);
02826 rb_define_method(rb_mEnumerable, "none?", enum_none, 0);
02827 rb_define_method(rb_mEnumerable, "min", enum_min, 0);
02828 rb_define_method(rb_mEnumerable, "max", enum_max, 0);
02829 rb_define_method(rb_mEnumerable, "minmax", enum_minmax, 0);
02830 rb_define_method(rb_mEnumerable, "min_by", enum_min_by, 0);
02831 rb_define_method(rb_mEnumerable, "max_by", enum_max_by, 0);
02832 rb_define_method(rb_mEnumerable, "minmax_by", enum_minmax_by, 0);
02833 rb_define_method(rb_mEnumerable, "member?", enum_member, 1);
02834 rb_define_method(rb_mEnumerable, "include?", enum_member, 1);
02835 rb_define_method(rb_mEnumerable, "each_with_index", enum_each_with_index, -1);
02836 rb_define_method(rb_mEnumerable, "reverse_each", enum_reverse_each, -1);
02837 rb_define_method(rb_mEnumerable, "each_entry", enum_each_entry, -1);
02838 rb_define_method(rb_mEnumerable, "each_slice", enum_each_slice, 1);
02839 rb_define_method(rb_mEnumerable, "each_cons", enum_each_cons, 1);
02840 rb_define_method(rb_mEnumerable, "each_with_object", enum_each_with_object, 1);
02841 rb_define_method(rb_mEnumerable, "zip", enum_zip, -1);
02842 rb_define_method(rb_mEnumerable, "take", enum_take, 1);
02843 rb_define_method(rb_mEnumerable, "take_while", enum_take_while, 0);
02844 rb_define_method(rb_mEnumerable, "drop", enum_drop, 1);
02845 rb_define_method(rb_mEnumerable, "drop_while", enum_drop_while, 0);
02846 rb_define_method(rb_mEnumerable, "cycle", enum_cycle, -1);
02847 rb_define_method(rb_mEnumerable, "chunk", enum_chunk, -1);
02848 rb_define_method(rb_mEnumerable, "slice_before", enum_slice_before, -1);
02849
02850 id_next = rb_intern("next");
02851 id_call = rb_intern("call");
02852 id_size = rb_intern("size");
02853 id_div = rb_intern("div");
02854 }
02855