00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "ruby.h"
00014 #include "node.h"
00015 #include "util.h"
00016
00017 VALUE rb_mEnumerable;
00018 static ID id_each, id_eqq, id_cmp;
00019
00020 VALUE
00021 rb_each(obj)
00022 VALUE obj;
00023 {
00024 return rb_funcall(obj, id_each, 0, 0);
00025 }
00026
00027 static VALUE
00028 grep_i(i, arg)
00029 VALUE i, *arg;
00030 {
00031 if (RTEST(rb_funcall(arg[0], id_eqq, 1, i))) {
00032 rb_ary_push(arg[1], i);
00033 }
00034 return Qnil;
00035 }
00036
00037 static VALUE
00038 grep_iter_i(i, arg)
00039 VALUE i, *arg;
00040 {
00041 if (RTEST(rb_funcall(arg[0], id_eqq, 1, i))) {
00042 rb_ary_push(arg[1], rb_yield(i));
00043 }
00044 return Qnil;
00045 }
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 static VALUE
00066 enum_grep(obj, pat)
00067 VALUE obj, pat;
00068 {
00069 VALUE ary = rb_ary_new();
00070 VALUE arg[2];
00071
00072 arg[0] = pat;
00073 arg[1] = ary;
00074
00075 rb_iterate(rb_each, obj, rb_block_given_p() ? grep_iter_i : grep_i, (VALUE)arg);
00076
00077 return ary;
00078 }
00079
00080 static VALUE
00081 find_i(i, memo)
00082 VALUE i;
00083 VALUE *memo;
00084 {
00085 if (RTEST(rb_yield(i))) {
00086 *memo = i;
00087 rb_iter_break();
00088 }
00089 return Qnil;
00090 }
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 static VALUE
00108 enum_find(argc, argv, obj)
00109 int argc;
00110 VALUE* argv;
00111 VALUE obj;
00112 {
00113 VALUE memo = Qundef;
00114 VALUE if_none;
00115
00116 rb_scan_args(argc, argv, "01", &if_none);
00117 rb_iterate(rb_each, obj, find_i, (VALUE)&memo);
00118 if (memo != Qundef) {
00119 return memo;
00120 }
00121 if (!NIL_P(if_none)) {
00122 return rb_funcall(if_none, rb_intern("call"), 0, 0);
00123 }
00124 return Qnil;
00125 }
00126
00127 static VALUE
00128 find_all_i(i, ary)
00129 VALUE i, ary;
00130 {
00131 if (RTEST(rb_yield(i))) {
00132 rb_ary_push(ary, i);
00133 }
00134 return Qnil;
00135 }
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 static VALUE
00151 enum_find_all(obj)
00152 VALUE obj;
00153 {
00154 VALUE ary = rb_ary_new();
00155
00156 rb_iterate(rb_each, obj, find_all_i, ary);
00157
00158 return ary;
00159 }
00160
00161 static VALUE
00162 reject_i(i, ary)
00163 VALUE i, ary;
00164 {
00165 if (!RTEST(rb_yield(i))) {
00166 rb_ary_push(ary, i);
00167 }
00168 return Qnil;
00169 }
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 static VALUE
00183 enum_reject(obj)
00184 VALUE obj;
00185 {
00186 VALUE ary = rb_ary_new();
00187
00188 rb_iterate(rb_each, obj, reject_i, ary);
00189
00190 return ary;
00191 }
00192
00193 static VALUE
00194 collect_i(i, ary)
00195 VALUE i, ary;
00196 {
00197 rb_ary_push(ary, rb_yield(i));
00198
00199 return Qnil;
00200 }
00201
00202 static VALUE
00203 collect_all(i, ary)
00204 VALUE i, ary;
00205 {
00206 rb_ary_push(ary, i);
00207
00208 return Qnil;
00209 }
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 static VALUE
00225 enum_collect(obj)
00226 VALUE obj;
00227 {
00228 VALUE ary = rb_ary_new();
00229
00230 rb_iterate(rb_each, obj, rb_block_given_p() ? collect_i : collect_all, ary);
00231
00232 return ary;
00233 }
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245 static VALUE
00246 enum_to_a(obj)
00247 VALUE obj;
00248 {
00249 VALUE ary = rb_ary_new();
00250
00251 rb_iterate(rb_each, obj, collect_all, ary);
00252
00253 return ary;
00254 }
00255
00256 static VALUE
00257 inject_i(i, memo)
00258 VALUE i;
00259 VALUE *memo;
00260 {
00261 if (*memo == Qundef) {
00262 *memo = i;
00263 }
00264 else {
00265 *memo = rb_yield_values(2, *memo, i);
00266 }
00267 return Qnil;
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 static VALUE
00302 enum_inject(argc, argv, obj)
00303 int argc;
00304 VALUE *argv, obj;
00305 {
00306 VALUE memo = Qundef;
00307
00308 if (rb_scan_args(argc, argv, "01", &memo) == 0)
00309 memo = Qundef;
00310 rb_iterate(rb_each, obj, inject_i, (VALUE)&memo);
00311 if (memo == Qundef) return Qnil;
00312 return memo;
00313 }
00314
00315 static VALUE
00316 partition_i(i, ary)
00317 VALUE i, *ary;
00318 {
00319 if (RTEST(rb_yield(i))) {
00320 rb_ary_push(ary[0], i);
00321 }
00322 else {
00323 rb_ary_push(ary[1], i);
00324 }
00325 return Qnil;
00326 }
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340 static VALUE
00341 enum_partition(obj)
00342 VALUE obj;
00343 {
00344 VALUE ary[2];
00345
00346 ary[0] = rb_ary_new();
00347 ary[1] = rb_ary_new();
00348 rb_iterate(rb_each, obj, partition_i, (VALUE)ary);
00349
00350 return rb_assoc_new(ary[0], ary[1]);
00351 }
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 static VALUE
00371 enum_sort(obj)
00372 VALUE obj;
00373 {
00374 return rb_ary_sort(enum_to_a(obj));
00375 }
00376
00377 static VALUE
00378 sort_by_i(i, ary)
00379 VALUE i, ary;
00380 {
00381 VALUE v;
00382 NODE *memo;
00383
00384 v = rb_yield(i);
00385 if (RBASIC(ary)->klass) {
00386 rb_raise(rb_eRuntimeError, "sort_by reentered");
00387 }
00388 memo = rb_node_newnode(NODE_MEMO, v, i, 0);
00389 rb_ary_push(ary, (VALUE)memo);
00390 return Qnil;
00391 }
00392
00393 static int
00394 sort_by_cmp(aa, bb)
00395 NODE **aa, **bb;
00396 {
00397 VALUE a = aa[0]->u1.value;
00398 VALUE b = bb[0]->u1.value;
00399
00400 return rb_cmpint(rb_funcall(a, id_cmp, 1, b), a, b);
00401 }
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
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 enum_sort_by(obj)
00474 VALUE obj;
00475 {
00476 VALUE ary;
00477 long i;
00478
00479 if (TYPE(obj) == T_ARRAY) {
00480 ary = rb_ary_new2(RARRAY(obj)->len);
00481 }
00482 else {
00483 ary = rb_ary_new();
00484 }
00485 RBASIC(ary)->klass = 0;
00486 rb_iterate(rb_each, obj, sort_by_i, ary);
00487 if (RARRAY(ary)->len > 1) {
00488 qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE), sort_by_cmp, 0);
00489 }
00490 if (RBASIC(ary)->klass) {
00491 rb_raise(rb_eRuntimeError, "sort_by reentered");
00492 }
00493 for (i=0; i<RARRAY(ary)->len; i++) {
00494 RARRAY(ary)->ptr[i] = RNODE(RARRAY(ary)->ptr[i])->u2.value;
00495 }
00496 RBASIC(ary)->klass = rb_cArray;
00497 return ary;
00498 }
00499
00500 static VALUE
00501 all_iter_i(i, memo)
00502 VALUE i;
00503 VALUE *memo;
00504 {
00505 if (!RTEST(rb_yield(i))) {
00506 *memo = Qfalse;
00507 rb_iter_break();
00508 }
00509 return Qnil;
00510 }
00511
00512 static VALUE
00513 all_i(i, memo)
00514 VALUE i;
00515 VALUE *memo;
00516 {
00517 if (!RTEST(i)) {
00518 *memo = Qfalse;
00519 rb_iter_break();
00520 }
00521 return Qnil;
00522 }
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541 static VALUE
00542 enum_all(obj)
00543 VALUE obj;
00544 {
00545 VALUE result = Qtrue;
00546
00547 rb_iterate(rb_each, obj, rb_block_given_p() ? all_iter_i : all_i, (VALUE)&result);
00548 return result;
00549 }
00550
00551 static VALUE
00552 any_iter_i(i, memo)
00553 VALUE i;
00554 VALUE *memo;
00555 {
00556 if (RTEST(rb_yield(i))) {
00557 *memo = Qtrue;
00558 rb_iter_break();
00559 }
00560 return Qnil;
00561 }
00562
00563 static VALUE
00564 any_i(i, memo)
00565 VALUE i;
00566 VALUE *memo;
00567 {
00568 if (RTEST(i)) {
00569 *memo = Qtrue;
00570 rb_iter_break();
00571 }
00572 return Qnil;
00573 }
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593 static VALUE
00594 enum_any(obj)
00595 VALUE obj;
00596 {
00597 VALUE result = Qfalse;
00598
00599 rb_iterate(rb_each, obj, rb_block_given_p() ? any_iter_i : any_i, (VALUE)&result);
00600 return result;
00601 }
00602
00603 static VALUE
00604 min_i(i, memo)
00605 VALUE i;
00606 VALUE *memo;
00607 {
00608 VALUE cmp;
00609
00610 if (*memo == Qundef) {
00611 *memo = i;
00612 }
00613 else {
00614 cmp = rb_funcall(i, id_cmp, 1, *memo);
00615 if (rb_cmpint(cmp, i, *memo) < 0) {
00616 *memo = i;
00617 }
00618 }
00619 return Qnil;
00620 }
00621
00622 static VALUE
00623 min_ii(i, memo)
00624 VALUE i;
00625 VALUE *memo;
00626 {
00627 VALUE cmp;
00628
00629 if (*memo == Qundef) {
00630 *memo = i;
00631 }
00632 else {
00633 cmp = rb_yield_values(2, i, *memo);
00634 if (rb_cmpint(cmp, i, *memo) < 0) {
00635 *memo = i;
00636 }
00637 }
00638 return Qnil;
00639 }
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656 static VALUE
00657 enum_min(obj)
00658 VALUE obj;
00659 {
00660 VALUE result = Qundef;
00661
00662 rb_iterate(rb_each, obj, rb_block_given_p() ? min_ii : min_i, (VALUE)&result);
00663 if (result == Qundef) return Qnil;
00664 return result;
00665 }
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681 static VALUE
00682 max_i(i, memo)
00683 VALUE i;
00684 VALUE *memo;
00685 {
00686 VALUE cmp;
00687
00688 if (*memo == Qundef) {
00689 *memo = i;
00690 }
00691 else {
00692 cmp = rb_funcall(i, id_cmp, 1, *memo);
00693 if (rb_cmpint(cmp, i, *memo) > 0) {
00694 *memo = i;
00695 }
00696 }
00697 return Qnil;
00698 }
00699
00700 static VALUE
00701 max_ii(i, memo)
00702 VALUE i;
00703 VALUE *memo;
00704 {
00705 VALUE cmp;
00706
00707 if (*memo == Qundef) {
00708 *memo = i;
00709 }
00710 else {
00711 cmp = rb_yield_values(2, i, *memo);
00712 if (rb_cmpint(cmp, i, *memo) > 0) {
00713 *memo = i;
00714 }
00715 }
00716 return Qnil;
00717 }
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733 static VALUE
00734 enum_max(obj)
00735 VALUE obj;
00736 {
00737 VALUE result = Qundef;
00738
00739 rb_iterate(rb_each, obj, rb_block_given_p() ? max_ii : max_i, (VALUE)&result);
00740 if (result == Qundef) return Qnil;
00741 return result;
00742 }
00743
00744 static VALUE
00745 member_i(item, memo)
00746 VALUE item;
00747 VALUE *memo;
00748 {
00749 if (rb_equal(item, memo[0])) {
00750 memo[1] = Qtrue;
00751 rb_iter_break();
00752 }
00753 return Qnil;
00754 }
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769 static VALUE
00770 enum_member(obj, val)
00771 VALUE obj, val;
00772 {
00773 VALUE memo[2];
00774
00775 memo[0] = val;
00776 memo[1] = Qfalse;
00777 rb_iterate(rb_each, obj, member_i, (VALUE)memo);
00778 return memo[1];
00779 }
00780
00781 static VALUE
00782 each_with_index_i(val, memo)
00783 VALUE val;
00784 VALUE *memo;
00785 {
00786 rb_yield_values(2, val, INT2FIX(*memo));
00787 ++*memo;
00788 return Qnil;
00789 }
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806 static VALUE
00807 enum_each_with_index(obj)
00808 VALUE obj;
00809 {
00810 VALUE memo = 0;
00811
00812 rb_need_block();
00813 rb_iterate(rb_each, obj, each_with_index_i, (VALUE)&memo);
00814 return obj;
00815 }
00816
00817 static VALUE
00818 zip_i(val, memo)
00819 VALUE val;
00820 VALUE *memo;
00821 {
00822 VALUE result = memo[0];
00823 VALUE args = memo[1];
00824 int idx = memo[2]++;
00825 VALUE tmp;
00826 int i;
00827
00828 tmp = rb_ary_new2(RARRAY(args)->len + 1);
00829 rb_ary_store(tmp, 0, val);
00830 for (i=0; i<RARRAY(args)->len; i++) {
00831 rb_ary_push(tmp, rb_ary_entry(RARRAY(args)->ptr[i], idx));
00832 }
00833 if (rb_block_given_p()) {
00834 rb_yield(tmp);
00835 }
00836 else {
00837 rb_ary_push(result, tmp);
00838 }
00839 return Qnil;
00840 }
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865 static VALUE
00866 enum_zip(argc, argv, obj)
00867 int argc;
00868 VALUE *argv;
00869 VALUE obj;
00870 {
00871 int i;
00872 VALUE result;
00873 VALUE memo[3];
00874
00875 for (i=0; i<argc; i++) {
00876 argv[i] = rb_convert_type(argv[i], T_ARRAY, "Array", "to_a");
00877 }
00878 result = rb_block_given_p() ? Qnil : rb_ary_new();
00879 memo[0] = result;
00880 memo[1] = rb_ary_new4(argc, argv);
00881 memo[2] = 0;
00882 rb_iterate(rb_each, obj, zip_i, (VALUE)memo);
00883
00884 return result;
00885 }
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898 void
00899 Init_Enumerable()
00900 {
00901 rb_mEnumerable = rb_define_module("Enumerable");
00902
00903 rb_define_method(rb_mEnumerable,"to_a", enum_to_a, 0);
00904 rb_define_method(rb_mEnumerable,"entries", enum_to_a, 0);
00905
00906 rb_define_method(rb_mEnumerable,"sort", enum_sort, 0);
00907 rb_define_method(rb_mEnumerable,"sort_by", enum_sort_by, 0);
00908 rb_define_method(rb_mEnumerable,"grep", enum_grep, 1);
00909 rb_define_method(rb_mEnumerable,"find", enum_find, -1);
00910 rb_define_method(rb_mEnumerable,"detect", enum_find, -1);
00911 rb_define_method(rb_mEnumerable,"find_all", enum_find_all, 0);
00912 rb_define_method(rb_mEnumerable,"select", enum_find_all, 0);
00913 rb_define_method(rb_mEnumerable,"reject", enum_reject, 0);
00914 rb_define_method(rb_mEnumerable,"collect", enum_collect, 0);
00915 rb_define_method(rb_mEnumerable,"map", enum_collect, 0);
00916 rb_define_method(rb_mEnumerable,"inject", enum_inject, -1);
00917 rb_define_method(rb_mEnumerable,"partition", enum_partition, 0);
00918 rb_define_method(rb_mEnumerable,"all?", enum_all, 0);
00919 rb_define_method(rb_mEnumerable,"any?", enum_any, 0);
00920 rb_define_method(rb_mEnumerable,"min", enum_min, 0);
00921 rb_define_method(rb_mEnumerable,"max", enum_max, 0);
00922 rb_define_method(rb_mEnumerable,"member?", enum_member, 1);
00923 rb_define_method(rb_mEnumerable,"include?", enum_member, 1);
00924 rb_define_method(rb_mEnumerable,"each_with_index", enum_each_with_index, 0);
00925 rb_define_method(rb_mEnumerable, "zip", enum_zip, -1);
00926
00927 id_eqq = rb_intern("===");
00928 id_each = rb_intern("each");
00929 id_cmp = rb_intern("<=>");
00930 }
00931
00932