Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Changeset 1712

Show
Ignore:
Timestamp:
07/03/10 21:42:27 (14 years ago)
Author:
dsimcha
Message:

More higher order range testing improvements.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/phobos/std/algorithm.d

    r1703 r1712  
    265265 
    266266    auto repeatMap = map!"a"(repeat(1)); 
    267267    static assert(isInfinite!(typeof(repeatMap))); 
    268268 
    269269    auto intRange = map!"a"([1,2,3]); 
    270270    static assert(isRandomAccessRange!(typeof(intRange))); 
    271271 
    272272    foreach(DummyType; AllDummyRanges) { 
    273273        DummyType d; 
    274274        auto m = map!"a * a"(d); 
     275 
     276        static assert(propagatesRangeType!(typeof(m), DummyType)); 
    275277        assert(equal(m, [1,4,9,16,25,36,49,64,81,100])); 
    276278    } 
    277279} 
    278280 
    279281// reduce 
    280282/** 
    281283Implements the homonym function (also known as $(D accumulate), $(D 
    282284compress), $(D inject), or $(D foldl)) present in various programming 
    283285languages of functional flavor. The call $(D reduce!(fun)(seed, 
    284286range)) first assigns $(D seed) to an internal variable $(D result), 
     
    18271829                b.length - (b.length - 1) / 2); 
    18281830    } 
    18291831} 
    18301832 
    18311833unittest 
    18321834{ 
    18331835    int[] a = [ -1, 0, 1, 2, 3, 4, 5 ]; 
    18341836    int[] b = [ 1, 2, 3 ]; 
    18351837    assert(find(a, b) == [ 1, 2, 3, 4, 5 ]); 
    18361838    assert(find(b, a).empty); 
     1839 
     1840    foreach(DummyType; AllDummyRanges) { 
     1841        DummyType d; 
     1842        auto findRes = find(d, 5); 
     1843        assert(equal(findRes, [5,6,7,8,9,10])); 
     1844    } 
    18371845} 
    18381846 
    18391847/// Ditto 
    18401848struct BoyerMooreFinder(alias pred, Range) 
    18411849{ 
    18421850private: 
    18431851    size_t skip[]; 
    18441852    int[ElementType!(Range)] occ; 
    18451853    Range needle; 
    18461854 
  • trunk/phobos/std/range.d

    r1704 r1712  
    147147    ) AllDummyRanges; 
    148148 
    149149    alias TypeTuple!(1,2,3,4,5,6,7,8,9,0,11,12,13,14,15,16) DummyIndices; 
    150150}; 
    151151 
    152152version(unittest) 
    153153{ 
    154154    import std.container, std.conv, std.math, std.stdio; 
    155155 
    156156    mixin(dummyRanges); 
     157 
     158    // Tests whether forward, bidirectional and random access properties are 
     159    // propagated properly from the base range(s) R to the higher order range 
     160    // H.  Useful in combination with DummyRange for testing several higher 
     161    // order ranges. 
     162    template propagatesRangeType(H, R...) { 
     163        static if(allSatisfy!(isRandomAccessRange, R)) { 
     164           enum bool propagatesRangeType = isRandomAccessRange!H; 
     165        } else static if(allSatisfy!(isBidirectionalRange, R)) { 
     166            enum bool propagatesRangeType = isBidirectionalRange!H; 
     167        } else static if(allSatisfy!(isForwardRange, R)) { 
     168            enum bool propagatesRangeType = isForwardRange!H; 
     169        } else { 
     170            enum bool propagatesRangeType = isInputRange!H; 
     171        } 
     172    } 
     173 
     174    template propagatesLength(H, R...) { 
     175        static if(allSatisfy!(hasLength, R)) { 
     176            enum bool propagatesLength = hasLength!H; 
     177        } else { 
     178            enum bool propagatesLength = !hasLength!H; 
     179        } 
     180    } 
    157181} 
    158182 
    159183/** 
    160184Returns $(D true) if $(D R) is an input range. An input range must 
    161185define the primitives $(D empty), $(D popFront), and $(D front). The 
    162186following code should compile for any input range. 
    163187 
    164188---- 
    165189R r;             // can define a range object 
    166190if (r.empty) {}  // can test for empty 
     
    753777    test([ 1, 2, 3, 4, 5, 6 ], [ 6, 5, 4, 3, 2, 1 ]); 
    754778 
    755779    foreach(DummyType; AllDummyRanges) { 
    756780        static if(!isBidirectionalRange!DummyType) { 
    757781            static assert(!__traits(compiles, Retro!DummyType)); 
    758782        } else { 
    759783            DummyType dummyRange; 
    760784            dummyRange.reinit(); 
    761785 
    762786            auto myRetro = retro(dummyRange); 
     787            static assert(propagatesRangeType!(typeof(myRetro), DummyType)); 
    763788            assert(myRetro.front == 10); 
    764789            assert(myRetro.back == 1); 
    765790 
    766791            static if(isRandomAccessRange!DummyType && hasLength!DummyType) { 
    767792                assert(myRetro[0] == myRetro.front); 
    768793 
    769794                static if(DummyType.r == ReturnBy.Reference) { 
    770795                    myRetro[9]++; 
    771796                    assert(dummyRange[0] == 2); 
    772797                    myRetro.front++; 
     
    946971    test(3, arr, [1, 4, 7, 10]); 
    947972    test(4, arr, [1, 5, 9]); 
    948973 
    949974    foreach(DummyType; AllDummyRanges) { 
    950975        static if(DummyType.r == ReturnBy.Reference) { 
    951976            // Doesn't work yet w/o ref returns, see DMD bug 3294 and 3894. 
    952977            DummyType dummyRange; 
    953978            dummyRange.reinit(); 
    954979 
    955980            auto myStride = stride(dummyRange, 4); 
     981 
     982            // Should fail if no length and bidirectional b/c there's no way 
     983            // to know how much slack we have. 
     984            static if(hasLength!DummyType || !isBidirectionalRange!DummyType) { 
     985                static assert(propagatesRangeType!(typeof(myStride), DummyType)); 
     986            } 
    956987            assert(myStride.front == 1); 
    957988            assert(equal(myStride, [1, 5, 9])); 
    958989 
    959990            static if(hasLength!DummyType) { 
    960991                assert(myStride.length == 3); 
    961992            } 
    962993 
    963994            static if(isBidirectionalRange!DummyType && hasLength!DummyType) { 
    964995                assert(myStride.back == 9); 
    965996            } 
     
    12501281        assert(c[3] == 42); 
    12511282    } 
    12521283 
    12531284    // Make sure bug 3311 is fixed.  ChainImpl should compile even if not all 
    12541285    // elements are mutable. 
    12551286    auto c = chain( iota(0, 10), iota(0, 10) ); 
    12561287 
    12571288    // Check that chain at least instantiates and compiles with every possible 
    12581289    // pair of DummyRange types, in either order. 
    12591290 
    1260 // This test should be uncommented when DMD bug 4379 gets fixed. 
     1291    // This test should be uncommented when DMD bug 4379 gets fixed, or if 
     1292    // you've made sure you've turned off -O.  (Bug 4379 is triggered by -O). 
    12611293//    foreach(DummyType1; AllDummyRanges) { 
    12621294//        DummyType1 dummy1; 
    12631295//        foreach(DummyType2; AllDummyRanges) { 
    12641296//            DummyType2 dummy2; 
    12651297//            auto myChain = chain(dummy1, dummy2); 
     1298// 
     1299//            static assert( 
     1300//                propagatesRangeType!(typeof(myChain), DummyType1, DummyType2) 
     1301//            ); 
     1302// 
    12661303//            assert(myChain.front == 1); 
    12671304//            foreach(i; 0..dummyLength) { 
    12681305//                myChain.popFront(); 
    12691306//            } 
    12701307//            assert(myChain.front == 1); 
     1308// 
     1309//            static if(isBidirectionalRange!DummyType1 && 
     1310//                      isBidirectionalRange!DummyType2) { 
     1311//                assert(myChain.back == 10); 
     1312//            } 
     1313// 
     1314//            static if(isRandomAccessRange!DummyType1 && 
     1315//                      isRandomAccessRange!DummyType2) { 
     1316//                assert(myChain[0] == 1); 
     1317//            } 
    12711318//        } 
    12721319//    } 
    1273  
    12741320} 
    12751321 
    12761322/** 
    12771323Iterates a random-access range starting from a given point and 
    12781324progressively extending left and right from that point. If no initial 
    12791325point is given, iteration starts from the middle of the 
    12801326range. Iteration spans the entire range. 
    12811327 
    12821328Example: 
    12831329---- 
     
    15041550        } 
    15051551    } 
    15061552    else static if (hasLength!(R)) 
    15071553    { 
    15081554        @property size_t length() 
    15091555        { 
    15101556            return min(_maxAvailable, original.length); 
    15111557        } 
    15121558    } 
    15131559 
    1514     static if (isRandomAccessRange!(R) && (hasLength!(R) || isInfinite!(R))
     1560    static if (isRandomAccessRange!(R)
    15151561    { 
    15161562        void popBack() 
    15171563        { 
    15181564            enforce(_maxAvailable > 0, 
    15191565                "Attempting to popBack() past the beginning of a " 
    15201566                ~ Take.stringof); 
    15211567            --_maxAvailable; 
    15221568        } 
    15231569 
    15241570        mixin( 
    15251571            (byRef ? "ref " : "")~ 
    15261572            q{/+auto ref+/ ElementType back() 
    15271573            { 
    15281574                return original[this.length - 1]; 
    15291575            }}); 
    1530     } 
    1531  
    1532     static if (isRandomAccessRange!(R)) 
    1533     { 
     1576 
    15341577        mixin( 
    15351578            (byRef ? "ref " : "")~ 
    15361579            q{/+auto ref+/ ElementType opIndex(size_t index) 
    15371580            { 
    15381581                enforce(index < this.length, 
    15391582                    "Attempting to index out of the bounds of a " 
    15401583                    ~ Take.stringof); 
    15411584                return original[index]; 
    15421585            }}); 
    15431586    } 
     
    15781621    int[] arr1 = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]; 
    15791622    auto s = take(arr1, 5); 
    15801623    assert(s.length == 5); 
    15811624    assert(s[4] == 5); 
    15821625    assert(equal(s, [ 1, 2, 3, 4, 5 ][])); 
    15831626    assert(equal(retro(s), [ 5, 4, 3, 2, 1 ][])); 
    15841627 
    15851628    foreach(DummyType; AllDummyRanges) { 
    15861629        DummyType dummy; 
    15871630        auto t = take(dummy, 5); 
     1631        alias typeof(t) T; 
     1632 
     1633        static if(isRandomAccessRange!DummyType) { 
     1634            static assert(isRandomAccessRange!T); 
     1635            assert(t[4] == 5); 
     1636        } else static if(isForwardRange!DummyType) { 
     1637            static assert(isForwardRange!T); 
     1638        } 
     1639 
     1640        // Bidirectional ranges can't be propagated properly if they don't 
     1641        // also have random access. 
     1642 
    15881643        assert(equal(t, [1,2,3,4,5])); 
    15891644    } 
    15901645} 
    15911646 
    15921647/** 
    15931648Eagerly advances $(D r) itself (not a copy) $(D n) times (by calling 
    15941649$(D r.popFront) $(D n) times). The pass of $(D r) into $(D popFrontN) 
    15951650is by reference, so the original range is affected. Completes in 
    15961651$(BIGOH 1) steps for ranges that support slicing, and in $(BIGOH n) 
    15971652time for all other ranges.