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

Changeset 1694

Show
Ignore:
Timestamp:
06/25/10 03:06:54 (14 years ago)
Author:
dsimcha
Message:

More unittest improvements and wholesale fixing/cleanup for std.range.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/docsrc/changelog.dd

    r1692 r1694  
    1313    $(LI $(BUGZILLA 978): std.utf's toUTF* functions accept some invalid and reject some valid UTF) 
    1414    $(LI $(BUGZILLA 996): Error in doc on implicit conversion between pointer and array) 
    1515    $(LI $(BUGZILLA 2275): std.utf.toUTF16z() should return const(wchar)*) 
    1616    $(LI $(BUGZILLA 2872): Length, opIndex for Map) 
    1717    $(LI $(BUGZILLA 3202): std.math.pow cause dead loop) 
    1818    $(LI $(BUGZILLA 3355): std.string.cmp works incorrectly for mixed-type and different-length strings) 
    1919    $(LI $(BUGZILLA 3386): to!bool(string) is not implemented) 
    2020    $(LI $(BUGZILLA 3436): std.functional.compose with only one function) 
    2121    $(LI $(BUGZILLA 3439): std.range.Sequence.opIndex not consistent after calling popFront().) 
    2222    $(LI $(BUGZILLA 3447): std.file uses unconventional file permissions) 
     23    $(LI $(BUGZILLA 3874): std.range.stride assumes a bidirectional input range) 
    2324    $(LI $(BUGZILLA 3937): os.path.dirname fails on absolute path) 
    2425    $(LI $(BUGZILLA 3961): Error with to!(somestruct)) 
    2526    $(LI $(BUGZILLA 4109): (reopened) writeln doesn't work with empty static array) 
    2627    $(LI $(BUGZILLA 4171): std.random.uniform does not work for a range of characters) 
    2728    $(LI $(BUGZILLA 4260): windows & basename) 
     29    $(LI $(BUGZILLA 4305): Take, Chain on top of ranges w/o moveFront() ) 
    2830    $(LI $(BUGZILLA 4327): std.container.Array.Range.~this() tries to call free(T[])) 
    2931    $(LI $(BUGZILLA 4362): std.range.repeat and cycle do not have a .save() method 
    3032    $(LI $(BUGZILLA 4363): std.algorithm.Until is not a forward range) 
    3133    ) 
    3234) 
    3335 
    3436<div id=version> 
    3537$(UL 
    3638    $(NEW 048) 
    3739    $(NEW 047) 
  • trunk/phobos/std/range.d

    r1691 r1694  
    119119            } 
    120120        } 
    121121 
    122122        static if(l == Length.Yes) { 
    123123            @property size_t length() { 
    124124                return arr.length; 
    125125            } 
    126126        } 
    127127    } 
    128128 
     129    enum dummyLength = 10; 
     130 
    129131    alias TypeTuple!( 
    130132        DummyRange!(ReturnBy.Reference, Length.Yes, RangeType.Input), 
    131133        DummyRange!(ReturnBy.Reference, Length.Yes, RangeType.Forward), 
    132134        DummyRange!(ReturnBy.Reference, Length.Yes, RangeType.Bidirectional), 
    133135        DummyRange!(ReturnBy.Reference, Length.Yes, RangeType.Random), 
    134136        DummyRange!(ReturnBy.Reference, Length.No, RangeType.Input), 
    135137        DummyRange!(ReturnBy.Reference, Length.No, RangeType.Forward), 
    136138        DummyRange!(ReturnBy.Reference, Length.No, RangeType.Bidirectional), 
    137         DummyRange!(ReturnBy.Reference, Length.No, RangeType.Random), 
    138139        DummyRange!(ReturnBy.Value, Length.Yes, RangeType.Input), 
    139140        DummyRange!(ReturnBy.Value, Length.Yes, RangeType.Forward), 
    140141        DummyRange!(ReturnBy.Value, Length.Yes, RangeType.Bidirectional), 
    141142        DummyRange!(ReturnBy.Value, Length.Yes, RangeType.Random), 
    142143        DummyRange!(ReturnBy.Value, Length.No, RangeType.Input), 
    143144        DummyRange!(ReturnBy.Value, Length.No, RangeType.Forward), 
    144         DummyRange!(ReturnBy.Value, Length.No, RangeType.Bidirectional), 
    145         DummyRange!(ReturnBy.Value, Length.No, RangeType.Random) 
     145        DummyRange!(ReturnBy.Value, Length.No, RangeType.Bidirectional) 
    146146    ) AllDummyRanges; 
    147147 
    148148    alias TypeTuple!(1,2,3,4,5,6,7,8,9,0,11,12,13,14,15,16) DummyIndices; 
    149149} 
    150150 
    151151/** 
    152152Returns $(D true) if $(D R) is an input range. An input range must 
    153153define the primitives $(D empty), $(D popFront), and $(D front). The 
    154154following code should compile for any input range. 
    155155 
     
    347347compilation) are assumed to be the following ($(D r) is an object of 
    348348type $(D R)): 
    349349$(UL $(LI $(D r.opIndex(n)) returns a reference to the $(D n)th 
    350350element in the range.)) 
    351351 */ 
    352352template isRandomAccessRange(R) 
    353353{ 
    354354    enum bool isRandomAccessRange = 
    355355        (isBidirectionalRange!(R) || isInfinite!(R)) 
    356356        && is(typeof(R.init[1])) 
    357         && !isNarrowString!R; 
     357        && !isNarrowString!R 
     358        && (hasLength!R || isInfinite!R); 
    358359} 
    359360 
    360361unittest 
    361362{ 
    362363    struct A {} 
    363364    static assert(!isRandomAccessRange!(A)); 
    364365    struct B 
    365366    { 
    366367        void popFront(); 
    367368        bool empty(); 
     
    379380    static assert(!isRandomAccessRange!(C)); 
    380381    struct D 
    381382    { 
    382383        bool empty(); 
    383384        @property D save(); 
    384385        int front(); 
    385386        void popFront(); 
    386387        int back(); 
    387388        void popBack(); 
    388389        ref int opIndex(uint); 
     390        @property size_t length(); 
    389391        //int opSlice(uint, uint); 
    390392    } 
    391393    static assert(isRandomAccessRange!(D)); 
    392394    static assert(isRandomAccessRange!(int[])); 
    393395} 
    394396 
    395397/** 
    396398The element type of $(D R). $(D R) does not have to be a range. The 
    397399element type is determined as the type yielded by $(D r.front) for an 
    398400object $(D r) or type $(D R). For example, $(D ElementType!(T[])) is 
     
    931933    } 
    932934    test(1, [], []); 
    933935    int[] arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]; 
    934936    test(1, arr, arr); 
    935937    test(2, arr, [1, 3, 5, 7, 9]); 
    936938    test(3, arr, [1, 4, 7, 10]); 
    937939    test(4, arr, [1, 5, 9]); 
    938940 
    939941    foreach(DummyType; AllDummyRanges) { 
    940942        static if(DummyType.r == ReturnBy.Reference) { 
    941             // Doesn't work yet w/o ref returns, see DMD bug 3294
     943            // Doesn't work yet w/o ref returns, see DMD bug 3294 and 3894
    942944            DummyType dummyRange; 
    943945            dummyRange.reinit(); 
    944946 
    945947            auto myStride = stride(dummyRange, 4); 
    946948            assert(myStride.front == 1); 
    947949            assert(equal(myStride, [1, 5, 9])); 
    948950 
    949951            static if(hasLength!DummyType) { 
    950952                assert(myStride.length == 3); 
    951953            } 
     
    12361238        uint[] foo = [1,2,3,4,5]; 
    12371239        uint[] bar = [1,2,3,4,5]; 
    12381240        auto c = chain(foo, bar); 
    12391241        c[3] = 42; 
    12401242        assert(c[3] == 42); 
    12411243    } 
    12421244 
    12431245    // Make sure bug 3311 is fixed.  ChainImpl should compile even if not all 
    12441246    // elements are mutable. 
    12451247    auto c = chain( iota(0, 10), iota(0, 10) ); 
     1248 
     1249    // Check that chain at least instantiates and compiles with every possible 
     1250    // pair of DummyRange types, in either order. 
     1251 
     1252// This test should be uncommented when DMD bug 4379 gets fixed. 
     1253//    foreach(DummyType1; AllDummyRanges) { 
     1254//        DummyType1 dummy1; 
     1255//        foreach(DummyType2; AllDummyRanges) { 
     1256//            DummyType2 dummy2; 
     1257//            auto myChain = chain(dummy1, dummy2); 
     1258//            assert(myChain.front == 1); 
     1259//            foreach(i; 0..dummyLength) { 
     1260//                myChain.popFront(); 
     1261//            } 
     1262//            assert(myChain.front == 1); 
     1263//        } 
     1264//    } 
     1265 
    12461266} 
    12471267 
    12481268/** 
    12491269Iterates a random-access range starting from a given point and 
    12501270progressively extending left and right from that point. If no initial 
    12511271point is given, iteration starts from the middle of the 
    12521272range. Iteration spans the entire range. 
    12531273 
    12541274Example: 
    12551275---- 
     
    13861406    } 
    13871407    test([], []); 
    13881408    test([ 1 ], [ 1 ]); 
    13891409    test([ 1, 2 ], [ 1, 2 ]); 
    13901410    test([ 1, 2, 3 ], [ 2, 3, 1 ]); 
    13911411    test([ 1, 2, 3, 4 ], [ 2, 3, 1, 4 ]); 
    13921412    test([ 1, 2, 3, 4, 5 ], [ 3, 4, 2, 5, 1 ]); 
    13931413    test([ 1, 2, 3, 4, 5, 6 ], [ 3, 4, 2, 5, 1, 6 ]); 
    13941414    int[] a = [ 1, 2, 3, 4, 5 ]; 
    13951415    assert(equal(radial(a, 1), [ 2, 3, 1, 4, 5 ][])); 
     1416 
     1417    // Test instantiation without lvalue elements. 
     1418 
     1419    // Doesn't instantiate! 
     1420    //DummyRange!(ReturnBy.Value, Length.Yes, RangeType.Random) dummy; 
     1421    //assert(equal(radial(dummy, 4), [5, 6, 4, 7, 3, 8, 2, 9, 1])); 
    13961422} 
    13971423 
    13981424/** 
    13991425Lazily takes only up to $(D n) elements of a range. This is 
    14001426particulary useful when using with infinite ranges. If the range 
    14011427offers random access and $(D length), $(D Take) offers them as well. 
    14021428 
    14031429Example: 
    14041430---- 
    14051431int[] arr1 = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]; 
     
    15401566} 
    15411567 
    15421568unittest 
    15431569{ 
    15441570    int[] arr1 = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]; 
    15451571    auto s = take(arr1, 5); 
    15461572    assert(s.length == 5); 
    15471573    assert(s[4] == 5); 
    15481574    assert(equal(s, [ 1, 2, 3, 4, 5 ][])); 
    15491575    assert(equal(retro(s), [ 5, 4, 3, 2, 1 ][])); 
     1576 
     1577    foreach(DummyType; AllDummyRanges) { 
     1578        DummyType dummy; 
     1579        auto t = take(dummy, 5); 
     1580        assert(equal(t, [1,2,3,4,5])); 
     1581    } 
    15501582} 
    15511583 
    15521584/** 
    15531585Eagerly advances $(D r) itself (not a copy) $(D n) times (by calling 
    15541586$(D r.popFront) $(D n) times). The pass of $(D r) into $(D popFrontN) 
    15551587is by reference, so the original range is affected. Completes in 
    15561588$(BIGOH 1) steps for ranges that support slicing, and in $(BIGOH n) 
    15571589time for all other ranges. 
    15581590 
    15591591Example: 
     
    17161748        /// Ditto 
    17171749        @property Cycle!(R) save() { 
    17181750            return Cycle!(R)(this._original.save, this._index); 
    17191751        } 
    17201752    } 
    17211753    else 
    17221754    { 
    17231755        R _original, _current; 
    17241756        this(R input) { _original = input; _current = input.save; } 
    17251757        /// Range primitive implementations. 
    1726         auto ref front() { return _current.front; } 
     1758        ref ElementType!(R) front() { return _current.front; } 
    17271759        /// Ditto 
    17281760        static if (isBidirectionalRange!(R)) 
    17291761            ref ElementType!(R) back() { return _current.back; } 
    17301762        /// Ditto 
    17311763        enum bool empty = false; 
    17321764        /// Ditto 
    17331765        void popFront() 
    17341766        { 
    17351767            _current.popFront; 
    17361768            if (_current.empty) _current = _original; 
     
    18111843{ 
    18121844    assert(equal(take(cycle([1, 2][]), 5), [ 1, 2, 1, 2, 1 ][])); 
    18131845    static assert(isForwardRange!(Cycle!(uint[]))); 
    18141846 
    18151847    int[3] a = [ 1, 2, 3 ]; 
    18161848    static assert(isStaticArray!(typeof(a))); 
    18171849    auto c = cycle(a); 
    18181850    assert(a.ptr == c._ptr); 
    18191851    assert(equal(take(cycle(a), 5), [ 1, 2, 3, 1, 2 ][])); 
    18201852    static assert(isForwardRange!(typeof(c))); 
     1853 
     1854    foreach(DummyType; AllDummyRanges) { 
     1855        // Bug 4387 
     1856        static if(isForwardRange!(DummyType) && DummyType.r == ReturnBy.Reference) { 
     1857            DummyType dummy; 
     1858            auto cy = cycle(dummy); 
     1859            static assert(isForwardRange!(typeof(cy))); 
     1860            auto t = take(cy, 20); 
     1861            assert(equal(t, [1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10])); 
     1862        } 
     1863    } 
    18211864} 
    18221865 
    18231866unittest // For infinite ranges 
    18241867{ 
    18251868    struct InfRange 
    18261869    { 
    18271870        void popFront() { } 
    18281871        int front() { return 0; } 
    18291872        enum empty = false; 
    18301873    } 
     
    28392882    auto tr = transposed(x); 
    28402883    int[][] witness = [ [ 1, 3 ], [ 2, 4 ] ]; 
    28412884    uint i; 
    28422885 
    28432886    foreach (e; tr) 
    28442887    { 
    28452888        assert(array(e) == witness[i++]); 
    28462889    } 
    28472890} 
    28482891 
     2892// Tests to see whether a struct has a postblit.  Hacky, probably needs to 
     2893// be fixed if a new frontend is ever written. 
     2894private template hasPostblit(R) { 
     2895    static if(!is(R == struct)) { 
     2896        enum bool hasPostblit = false; 
     2897    } else { 
     2898        enum hasPostblit = is(typeof({ 
     2899            R r; 
     2900            return &r.__postblit; 
     2901        })); 
     2902    } 
     2903} 
     2904 
     2905unittest { 
     2906    struct S { 
     2907        this(this) {} 
     2908    } 
     2909 
     2910    struct S2 {} 
     2911 
     2912    static assert(hasPostblit!S); 
     2913    static assert(!hasPostblit!S2); 
     2914} 
     2915 
    28492916/** 
    28502917Moves the front of $(D r) out and returns it. Leaves $(D r.front) in a 
    28512918destroyable state that does not allocate any resources (usually equal 
    28522919to its $(D .init) value). 
    28532920 */ 
    28542921ElementType!R moveFront(R)(R r) 
    2855 if (is(typeof(&r.front()) == ElementType!R*)) 
    2856 
    2857     return move(r.front); 
     2922
     2923    static if(is(typeof(&R.moveFront))) { 
     2924        return r.moveFront(); 
     2925    } else static if(!hasPostblit!(ElementType!(R))) { 
     2926        return r.front; 
     2927    } else static if(is(typeof(&r.front()) == ElementType!R*)) { 
     2928        return move(r.front); 
     2929    } else { 
     2930        static assert(0, 
     2931            "Cannot move front of a range with a postblit and an rvalue front."); 
     2932    } 
    28582933} 
    28592934 
    28602935unittest 
    28612936{ 
    28622937    struct R 
    28632938    { 
    28642939        ref int front() { static int x = 42; return x; } 
     2940        this(this){} 
    28652941    } 
    28662942    R r; 
    28672943    assert(moveFront(r) == 42); 
    2868 } 
    2869  
    2870 /// Ditto 
    2871 ElementType!R moveFront(R)(R r) 
    2872 if (is(typeof(&R.moveFront))) 
    2873 { 
    2874     return r.moveFront(); 
    28752944} 
    28762945 
    28772946/** 
    28782947Moves the front of $(D r) out and returns it. Leaves $(D r.front) in a 
    28792948destroyable state that does not allocate any resources (usually equal 
    28802949to its $(D .init) value). 
    28812950 */ 
    28822951ElementType!R moveBack(R)(R r) 
    28832952if (isInputRange!R && is(typeof(&r.front) == ElementType!R*)) 
    28842953{