diff --git a/dub.json b/dub.json index 0584081..2d03969 100644 --- a/dub.json +++ b/dub.json @@ -10,18 +10,12 @@ "targetType": "library", "dependencies": { - "tanya:meta": "*", - "tanya:os": "*", "tanya:middle": "*", - "tanya:test": "*", "mir-linux-kernel": "~>1.0.0" }, "subPackages": [ - "./meta", - "./os", - "./middle", - "./test" + "./middle" ], "configurations": [ diff --git a/meta/dub.json b/meta/dub.json deleted file mode 100644 index 4b7651b..0000000 --- a/meta/dub.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "meta", - "description": "Template metaprogramming", - "targetType": "library", - - "sourcePaths": [ - "." - ], - "importPaths": [ - "." - ], - "dflags-dmd": ["-dip1000"] -} diff --git a/meta/tanya/meta/package.d b/meta/tanya/meta/package.d deleted file mode 100644 index daf8d9e..0000000 --- a/meta/tanya/meta/package.d +++ /dev/null @@ -1,22 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/** - * Template metaprogramming. - * - * This package contains utilities to acquire type information at compile-time, - * to transform from one type to another. It has also different algorithms for - * iterating, searching and modifying template arguments. - * - * Copyright: Eugene Wissner 2017-2025. - * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, - * Mozilla Public License, v. 2.0). - * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) - * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/meta/tanya/meta/package.d, - * tanya/meta/package.d) - */ -module tanya.meta; - -public import tanya.meta.metafunction; -public import tanya.meta.trait; diff --git a/meta/tanya/meta/trait.d b/meta/tanya/meta/trait.d deleted file mode 100644 index 243c123..0000000 --- a/meta/tanya/meta/trait.d +++ /dev/null @@ -1,150 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/** - * Type traits. - * - * Templates in this module are used to obtain type information at compile - * time. - * - * Copyright: Eugene Wissner 2017-2025. - * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, - * Mozilla Public License, v. 2.0). - * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) - * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/meta/tanya/meta/trait.d, - * tanya/meta/trait.d) - */ -module tanya.meta.trait; - -import std.traits : OriginalType, Unqual, isStaticArray, isUnsigned; -import tanya.meta.metafunction; - -/** - * Determines whether $(D_PARAM T) is a wide string, i.e. consists of - * $(D_KEYWORD dchar). - * - * The character type of the string and the string itself can have any type - * qualifiers. - * - * Static $(D_KEYWORD dchar) arrays are not considered strings. - * - * Params: - * T = A type. - * - * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a wide string, - * $(D_KEYWORD false) otherwise. - */ -enum bool isWideString(T) = is(immutable T == immutable dchar[]); - -/// -@nogc nothrow pure @safe unittest -{ - static assert(isWideString!(dchar[])); - static assert(!isWideString!(char[])); - static assert(!isWideString!(wchar[])); - - static assert(isWideString!dstring); - static assert(!isWideString!string); - static assert(!isWideString!wstring); - - static assert(isWideString!(const dstring)); - static assert(!isWideString!(const string)); - static assert(!isWideString!(const wstring)); - - static assert(isWideString!(shared dstring)); - static assert(!isWideString!(shared string)); - static assert(!isWideString!(shared wstring)); - - static assert(isWideString!(const(dchar)[])); - static assert(isWideString!(inout(dchar)[])); - static assert(isWideString!(shared(const(dchar))[])); - static assert(isWideString!(shared(dchar)[])); - static assert(!isWideString!(dchar[10])); -} - -/* - * Tests whether $(D_PARAM T) is an interface. - * - * Params: - * T = A type. - * - * Returns: $(D_KEYWORD true) if $(D_PARAM T) is an interface, - * $(D_KEYWORD false) otherwise. - */ -private enum bool isInterface(T) = is(T == interface); - -/** - * Determines whether $(D_PARAM T) is a polymorphic type, i.e. a - * $(D_KEYWORD class) or an $(D_KEYWORD interface). - * - * Params: - * T = A type. - * - * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a $(D_KEYWORD class) or an - * $(D_KEYWORD interface), $(D_KEYWORD false) otherwise. - */ -enum bool isPolymorphicType(T) = is(T == class) || is(T == interface); - -/// -@nogc nothrow pure @safe unittest -{ - interface I - { - } - static assert(isPolymorphicType!Object); - static assert(isPolymorphicType!I); - static assert(!isPolymorphicType!short); -} - -/** - * Returns the size in bytes of the state that needs to be allocated to hold an - * object of type $(D_PARAM T). - * - * There is a difference between the `.sizeof`-property and - * $(D_PSYMBOL stateSize) if $(D_PARAM T) is a class or an interface. - * `T.sizeof` is constant on the given architecture then and is the same as - * `size_t.sizeof` and `ptrdiff_t.sizeof`. This is because classes and - * interfaces are reference types and `.sizeof` returns the size of the - * reference which is the same as the size of a pointer. $(D_PSYMBOL stateSize) - * returns the size of the instance itself. - * - * The size of a dynamic array is `size_t.sizeof * 2` since a dynamic array - * stores its length and a data pointer. The size of the static arrays is - * calculated differently since they are value types. It is the array length - * multiplied by the element size. - * - * `stateSize!void` is `1` since $(D_KEYWORD void) is mostly used as a synonym - * for $(D_KEYWORD byte)/$(D_KEYWORD ubyte) in `void*`. - * - * Params: - * T = Object type. - * - * Returns: Size of an instance of type $(D_PARAM T). - */ -template stateSize(T) -{ - static if (isPolymorphicType!T) - { - enum size_t stateSize = __traits(classInstanceSize, T); - } - else - { - enum size_t stateSize = T.sizeof; - } -} - -/// -@nogc nothrow pure @safe unittest -{ - static assert(stateSize!int == 4); - static assert(stateSize!bool == 1); - static assert(stateSize!(int[]) == (size_t.sizeof * 2)); - static assert(stateSize!(short[3]) == 6); - - static struct Empty - { - } - static assert(stateSize!Empty == 1); - static assert(stateSize!void == 1); -} diff --git a/middle/dub.json b/middle/dub.json index 0e91cd0..aef09d2 100644 --- a/middle/dub.json +++ b/middle/dub.json @@ -3,11 +3,6 @@ "description": "Runtime, middle-level utilities", "targetType": "library", - "dependencies": { - "tanya:meta": "*", - "tanya:os": "*" - }, - "dependencies-linux": { "mir-linux-kernel": "~>1.0.0" }, diff --git a/middle/tanya/memory/allocator.d b/middle/tanya/memory/allocator.d index 2acd044..30ef03b 100644 --- a/middle/tanya/memory/allocator.d +++ b/middle/tanya/memory/allocator.d @@ -17,9 +17,9 @@ */ module tanya.memory.allocator; -import std.traits : hasElaborateDestructor, isAssociativeArray, isArray; +import std.traits; import tanya.memory.lifetime; -import tanya.meta.trait; +import tanya.meta; /** * Abstract class implementing a basic allocator. diff --git a/middle/tanya/memory/lifetime.d b/middle/tanya/memory/lifetime.d index a5b98cd..aa9c7d1 100644 --- a/middle/tanya/memory/lifetime.d +++ b/middle/tanya/memory/lifetime.d @@ -14,11 +14,10 @@ */ module tanya.memory.lifetime; -import std.traits : isInnerClass, hasElaborateAssign, hasElaborateCopyConstructor, hasElaborateDestructor, - isAssignable, isNested, isAbstractClass, isAggregateType, isStaticArray; +import std.traits; +import std.meta : AliasSeq; import tanya.memory.allocator; -import tanya.meta.metafunction; -import tanya.meta.trait; +import tanya.meta; package(tanya) void destroyAllImpl(R, E)(R p) { diff --git a/middle/tanya/memory/smartref.d b/middle/tanya/memory/smartref.d index 59ac3af..6134a04 100644 --- a/middle/tanya/memory/smartref.d +++ b/middle/tanya/memory/smartref.d @@ -23,10 +23,10 @@ */ module tanya.memory.smartref; -import std.traits : isPointer, isAbstractClass, isAssociativeArray, isDynamicArray, isArray; +import std.traits; import tanya.memory.allocator; import tanya.memory.lifetime; -import tanya.meta.trait; +import tanya.meta; private template Payload(T) { diff --git a/meta/tanya/meta/metafunction.d b/middle/tanya/meta.d similarity index 50% rename from meta/tanya/meta/metafunction.d rename to middle/tanya/meta.d index ef4acfb..909415e 100644 --- a/meta/tanya/meta/metafunction.d +++ b/middle/tanya/meta.d @@ -3,24 +3,152 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** - * This module is suited for computations on template arguments, both types and - * values at compile time. + * Template metaprogramming. * - * It contains different algorithms for iterating, searching and modifying - * template arguments. + * This package contains utilities to acquire type information at compile-time, + * to transform from one type to another. It has also different algorithms for + * iterating, searching and modifying template arguments. * * Copyright: Eugene Wissner 2017-2025. * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * Mozilla Public License, v. 2.0). * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) - * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/meta/tanya/meta/metafunction.d, - * tanya/meta/metafunction.d) + * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/meta/tanya/meta/package.d, + * tanya/meta/package.d) */ -module tanya.meta.metafunction; +module tanya.meta; -import std.traits : Unqual, isInstanceOf, isMutable, isTypeTuple, isUnsigned, isSigned, isIntegral; -import std.meta : NoDuplicates; -import tanya.meta.trait; +import std.meta; +import std.traits; + +/** + * Determines whether $(D_PARAM T) is a wide string, i.e. consists of + * $(D_KEYWORD dchar). + * + * The character type of the string and the string itself can have any type + * qualifiers. + * + * Static $(D_KEYWORD dchar) arrays are not considered strings. + * + * Params: + * T = A type. + * + * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a wide string, + * $(D_KEYWORD false) otherwise. + */ +enum bool isWideString(T) = is(immutable T == immutable dchar[]); + +/// +@nogc nothrow pure @safe unittest +{ + static assert(isWideString!(dchar[])); + static assert(!isWideString!(char[])); + static assert(!isWideString!(wchar[])); + + static assert(isWideString!dstring); + static assert(!isWideString!string); + static assert(!isWideString!wstring); + + static assert(isWideString!(const dstring)); + static assert(!isWideString!(const string)); + static assert(!isWideString!(const wstring)); + + static assert(isWideString!(shared dstring)); + static assert(!isWideString!(shared string)); + static assert(!isWideString!(shared wstring)); + + static assert(isWideString!(const(dchar)[])); + static assert(isWideString!(inout(dchar)[])); + static assert(isWideString!(shared(const(dchar))[])); + static assert(isWideString!(shared(dchar)[])); + static assert(!isWideString!(dchar[10])); +} + +/* + * Tests whether $(D_PARAM T) is an interface. + * + * Params: + * T = A type. + * + * Returns: $(D_KEYWORD true) if $(D_PARAM T) is an interface, + * $(D_KEYWORD false) otherwise. + */ +private enum bool isInterface(T) = is(T == interface); + +/** + * Determines whether $(D_PARAM T) is a polymorphic type, i.e. a + * $(D_KEYWORD class) or an $(D_KEYWORD interface). + * + * Params: + * T = A type. + * + * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a $(D_KEYWORD class) or an + * $(D_KEYWORD interface), $(D_KEYWORD false) otherwise. + */ +enum bool isPolymorphicType(T) = is(T == class) || is(T == interface); + +/// +@nogc nothrow pure @safe unittest +{ + interface I + { + } + static assert(isPolymorphicType!Object); + static assert(isPolymorphicType!I); + static assert(!isPolymorphicType!short); +} + +/** + * Returns the size in bytes of the state that needs to be allocated to hold an + * object of type $(D_PARAM T). + * + * There is a difference between the `.sizeof`-property and + * $(D_PSYMBOL stateSize) if $(D_PARAM T) is a class or an interface. + * `T.sizeof` is constant on the given architecture then and is the same as + * `size_t.sizeof` and `ptrdiff_t.sizeof`. This is because classes and + * interfaces are reference types and `.sizeof` returns the size of the + * reference which is the same as the size of a pointer. $(D_PSYMBOL stateSize) + * returns the size of the instance itself. + * + * The size of a dynamic array is `size_t.sizeof * 2` since a dynamic array + * stores its length and a data pointer. The size of the static arrays is + * calculated differently since they are value types. It is the array length + * multiplied by the element size. + * + * `stateSize!void` is `1` since $(D_KEYWORD void) is mostly used as a synonym + * for $(D_KEYWORD byte)/$(D_KEYWORD ubyte) in `void*`. + * + * Params: + * T = Object type. + * + * Returns: Size of an instance of type $(D_PARAM T). + */ +template stateSize(T) +{ + static if (isPolymorphicType!T) + { + enum size_t stateSize = __traits(classInstanceSize, T); + } + else + { + enum size_t stateSize = T.sizeof; + } +} + +/// +@nogc nothrow pure @safe unittest +{ + static assert(stateSize!int == 4); + static assert(stateSize!bool == 1); + static assert(stateSize!(int[]) == (size_t.sizeof * 2)); + static assert(stateSize!(short[3]) == 6); + + static struct Empty + { + } + static assert(stateSize!Empty == 1); + static assert(stateSize!void == 1); +} /** * Finds the minimum value in $(D_PARAM Args) according to $(D_PARAM pred). @@ -202,7 +330,7 @@ if (Packs.length > 0 * --- * template A(Args...) * { - * static assert(Args.length == 4); + * static assert(Args.length == 4); * } * * alias AInstance = A!(AliasSeq!(int, uint), AliasSeq!(float, double)); @@ -217,7 +345,7 @@ if (Packs.length > 0 * --- * template B(Args...) * { - * static assert(Args.length == 2); + * static assert(Args.length == 2); * } * * alias BInstance = B!(Pack!(int, uint), Pack!(float, double)); @@ -681,202 +809,6 @@ if (Args.length == 2) static assert(isNotEqual!(5, 8)); } -/** - * Instantiates the template $(D_PARAM T) with $(D_PARAM Args). - * - * Params: - * T = Template. - * Args = Template parameters. - * - * Returns: Instantiated template. - */ -alias Instantiate(alias T, Args...) = T!Args; - -/// -@nogc nothrow pure @safe unittest -{ - template Template(T) - { - alias Template = T; - } - alias Seq = AliasSeq!(Template, Template); - - alias Instance1 = Instantiate!(Seq[0], int); - static assert(is(Instance1 == int)); - - alias Instance2 = Instantiate!(Seq[1], float); - static assert(is(Instance2 == float)); -} - -/** - * Creates an alias for $(D_PARAM T). - * - * In contrast to the $(D_KEYWORD alias)-keyword $(D_PSYMBOL Alias) can alias - * any kind of D symbol that can be used as argument to template alias - * parameters. - * - * $(UL - * $(LI Types) - * $(LI Local and global names) - * $(LI Module names) - * $(LI Template names) - * $(LI Template instance names) - * $(LI Literals) - * ) - * - * Params: - * T = A symbol. - * - * Returns: An alias for $(D_PARAM T). - * - * See_Also: $(LINK2 https://dlang.org/spec/template.html#aliasparameters, - * Template Alias Parameters). - */ -alias Alias(alias T) = T; - -/// ditto -alias Alias(T) = T; - -/// -@nogc nothrow pure @safe unittest -{ - static assert(is(Alias!int)); - - static assert(is(typeof(Alias!5))); - static assert(is(typeof(Alias!(() {})))); - - int i; - static assert(is(typeof(Alias!i))); -} - -/** - * Holds a sequence of aliases. - * - * $(D_PSYMBOL AliasSeq) can be used to pass multiple parameters to a template - * at once. $(D_PSYMBOL AliasSeq) behaves as it were just $(D_PARAM Args). Note - * that because of this property, if multiple instances of - * $(D_PSYMBOL AliasSeq) are passed to a template, they are not distinguishable - * from each other and act as a single sequence. There is also no way to make - * $(D_PSYMBOL AliasSeq) nested, it always unpacks its elements. - * - * Params: - * Args = Symbol sequence. - * - * Returns: An alias for sequence $(D_PARAM Args). - * - * See_Also: $(D_PSYMBOL Alias). - */ -alias AliasSeq(Args...) = Args; - -/// -@nogc nothrow pure @safe unittest -{ - static assert(is(typeof({ alias T = AliasSeq!(short, 5); }))); - static assert(is(typeof({ alias T = AliasSeq!(int, short, 5); }))); - static assert(is(typeof({ alias T = AliasSeq!(() {}, short, 5); }))); - static assert(is(typeof({ alias T = AliasSeq!(); }))); - - static assert(AliasSeq!().length == 0); - static assert(AliasSeq!(int, short, 5).length == 3); - - alias A = AliasSeq!(short, float); - alias B = AliasSeq!(ushort, double); - alias C = AliasSeq!(A, B); - static assert(C.length == 4); -} - -/** - * Tests whether all the items of $(D_PARAM L) satisfy the condition - * $(D_PARAM F). - * - * $(D_PARAM F) is a template that accepts one parameter and returns a boolean, - * so $(D_INLINECODE F!([0]) && F!([1])) and so on, can be called. - * - * Params: - * F = Template predicate. - * L = List of items to test. - * - * Returns: $(D_KEYWORD true) if all the items of $(D_PARAM L) satisfy - * $(D_PARAM F), $(D_KEYWORD false) otherwise. - */ -enum bool allSatisfy(alias F, L...) = Filter!(templateNot!F, L).length == 0; - -/// -@nogc nothrow pure @safe unittest -{ - static assert(allSatisfy!(isSigned, int, short, byte, long)); - static assert(!allSatisfy!(isUnsigned, uint, ushort, float, ulong)); -} - -/** - * Tests whether any of the items of $(D_PARAM L) satisfy the condition - * $(D_PARAM F). - * - * $(D_PARAM F) is a template that accepts one parameter and returns a boolean, - * so $(D_INLINECODE F!([0]) && F!([1])) and so on, can be called. - * - * Params: - * F = Template predicate. - * L = List of items to test. - * - * Returns: $(D_KEYWORD true) if any of the items of $(D_PARAM L) satisfy - * $(D_PARAM F), $(D_KEYWORD false) otherwise. - */ -enum bool anySatisfy(alias F, L...) = Filter!(F, L).length != 0; - -/// -@nogc nothrow pure @safe unittest -{ - static assert(anySatisfy!(isSigned, int, short, byte, long)); - static assert(anySatisfy!(isUnsigned, uint, ushort, float, ulong)); - static assert(!anySatisfy!(isSigned, uint, ushort, ulong)); -} - -private template indexOf(Args...) -{ - static foreach (i, Arg; Args[1 .. $]) - { - static if (!is(typeof(indexOf) == ptrdiff_t) && isEqual!(Args[0], Arg)) - { - enum ptrdiff_t indexOf = i; - } - } - static if (!is(typeof(indexOf) == ptrdiff_t)) - { - enum ptrdiff_t indexOf = -1; - } -} - -/** - * Returns the index of the first occurrence of $(D_PARAM T) in $(D_PARAM L). - * `-1` is returned if $(D_PARAM T) is not found. - * - * Params: - * T = The item to search for. - * L = Symbol sequence. - * - * Returns: The index of the first occurrence of $(D_PARAM T) in $(D_PARAM L). - */ -template staticIndexOf(T, L...) -{ - enum ptrdiff_t staticIndexOf = indexOf!(T, L); -} - -/// ditto -template staticIndexOf(alias T, L...) -{ - enum ptrdiff_t staticIndexOf = indexOf!(T, L); -} - -/// -@nogc nothrow pure @safe unittest -{ - static assert(staticIndexOf!(int) == -1); - static assert(staticIndexOf!(int, int) == 0); - static assert(staticIndexOf!(int, float, double, int, real) == 2); - static assert(staticIndexOf!(3, () {}, uint, 5, 3) == 3); -} - /** * Looks for $(D_PARAM T) in $(D_PARAM L) and returns $(D_KEYWORD true) if it * could be found and $(D_KEYWORD false) otherwise. @@ -916,7 +848,7 @@ enum bool canFind(alias T, L...) = staticIndexOf!(T, L) != -1; * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a template, * $(D_KEYWORD false) otherwise. */ -private enum bool isTemplate(alias T) = __traits(isTemplate, T); +enum bool isTemplate(alias T) = __traits(isTemplate, T); /// @nogc nothrow pure @safe unittest @@ -928,680 +860,6 @@ private enum bool isTemplate(alias T) = __traits(isTemplate, T); static assert(!isTemplate!(S!int)); } -/** - * Combines multiple templates with logical AND. So $(D_PSYMBOL templateAnd) - * evaluates to $(D_INLINECODE Preds[0] && Preds[1] && Preds[2]) and so on. - * - * Empty $(D_PARAM Preds) evaluates to $(D_KEYWORD true). - * - * Params: - * Preds = Template predicates. - * - * Returns: The constructed template. - */ -template templateAnd(Preds...) -if (allSatisfy!(isTemplate, Preds)) -{ - template templateAnd(T...) - { - static if (Preds.length == 0) - { - enum bool templateAnd = true; - } - else static if (Instantiate!(Preds[0], T)) - { - alias templateAnd = Instantiate!(.templateAnd!(Preds[1 .. $]), T); - } - else - { - enum bool templateAnd = false; - } - } -} - -/// -@nogc nothrow pure @safe unittest -{ - alias isMutableInt = templateAnd!(isIntegral, isMutable); - static assert(isMutableInt!int); - static assert(!isMutableInt!(const int)); - static assert(!isMutableInt!float); - - alias alwaysTrue = templateAnd!(); - static assert(alwaysTrue!int); - - alias isIntegral = templateAnd!(.isIntegral); - static assert(isIntegral!int); - static assert(isIntegral!(const int)); - static assert(!isIntegral!float); -} - -/** - * Combines multiple templates with logical OR. So $(D_PSYMBOL templateOr) - * evaluates to $(D_INLINECODE Preds[0] || Preds[1] || Preds[2]) and so on. - * - * Empty $(D_PARAM Preds) evaluates to $(D_KEYWORD false). - * - * Params: - * Preds = Template predicates. - * - * Returns: The constructed template. - */ -template templateOr(Preds...) -if (allSatisfy!(isTemplate, Preds)) -{ - template templateOr(T...) - { - static if (Preds.length == 0) - { - enum bool templateOr = false; - } - else static if (Instantiate!(Preds[0], T)) - { - enum bool templateOr = true; - } - else - { - alias templateOr = Instantiate!(.templateOr!(Preds[1 .. $]), T); - } - } -} - -/// -@nogc nothrow pure @safe unittest -{ - alias isMutableOrInt = templateOr!(isIntegral, isMutable); - static assert(isMutableOrInt!int); - static assert(isMutableOrInt!(const int)); - static assert(isMutableOrInt!float); - static assert(!isMutableOrInt!(const float)); - - alias alwaysFalse = templateOr!(); - static assert(!alwaysFalse!int); - - alias isIntegral = templateOr!(.isIntegral); - static assert(isIntegral!int); - static assert(isIntegral!(const int)); - static assert(!isIntegral!float); -} - -/** - * Params: - * pred = Template predicate. - * - * Returns: Negated $(D_PARAM pred). - */ -template templateNot(alias pred) -if (__traits(isTemplate, pred)) -{ - enum bool templateNot(T...) = !pred!T; -} - -/// -@nogc nothrow pure @safe unittest -{ - alias isNotIntegral = templateNot!isIntegral; - static assert(!isNotIntegral!int); - static assert(isNotIntegral!(char[])); -} - -/** - * Tests whether $(D_PARAM L) is sorted in ascending order according to - * $(D_PARAM cmp). - * - * $(D_PARAM cmp) can evaluate to: - * $(UL - * $(LI $(D_KEYWORD bool): $(D_KEYWORD true) means - * $(D_INLINECODE a[i] < a[i + 1]).) - * $(LI $(D_KEYWORD int): a negative number means that - * $(D_INLINECODE a[i] < a[i + 1]), a positive number that - * $(D_INLINECODE a[i] > a[i + 1]), `0` if they equal.) - * ) - * - * Params: - * cmp = Sorting template predicate. - * L = Elements to be tested. - * - * Returns: $(D_KEYWORD true) if $(D_PARAM L) is sorted, $(D_KEYWORD false) - * if not. - */ -template isSorted(alias cmp, L...) -if (__traits(isTemplate, cmp)) -{ - static if (L.length <= 1) - { - enum bool isSorted = true; - } - else - { - // `L` is sorted if the both halves and the boundary values are sorted. - enum bool isSorted = isLessEqual!(cmp, L[$ / 2 - 1], L[$ / 2]) - && isSorted!(cmp, L[0 .. $ / 2]) - && isSorted!(cmp, L[$ / 2 .. $]); - } -} - -/// -@nogc nothrow pure @safe unittest -{ - enum cmp(T, U) = T.sizeof < U.sizeof; - static assert(isSorted!(cmp)); - static assert(isSorted!(cmp, byte)); - static assert(isSorted!(cmp, byte, ubyte, short, uint)); - static assert(!isSorted!(cmp, long, byte, ubyte, short, uint)); -} - -/** - * Params: - * T = A template. - * Args = The first arguments for $(D_PARAM T). - * - * Returns: $(D_PARAM T) with $(D_PARAM Args) applied to it as its first - * arguments. - */ -template ApplyLeft(alias T, Args...) -{ - alias ApplyLeft(U...) = T!(Args, U); -} - -/// -@nogc nothrow pure @safe unittest -{ - alias allAreIntegral = ApplyLeft!(allSatisfy, isIntegral); - static assert(allAreIntegral!(int, uint)); - static assert(!allAreIntegral!(int, float, uint)); -} - -/** - * Params: - * T = A template. - * Args = The last arguments for $(D_PARAM T). - * - * Returns: $(D_PARAM T) with $(D_PARAM Args) applied to it as itslast - * arguments. - */ -template ApplyRight(alias T, Args...) -{ - alias ApplyRight(U...) = T!(U, Args); -} - -/// -@nogc nothrow pure @safe unittest -{ - alias intIs = ApplyRight!(allSatisfy, int); - static assert(intIs!(isIntegral)); - static assert(!intIs!(isUnsigned)); -} - -/** - * Params: - * n = The number of times to repeat $(D_PARAM L). - * L = The sequence to be repeated. - * - * Returns: $(D_PARAM L) repeated $(D_PARAM n) times. - */ -template Repeat(size_t n, L...) -if (n > 0) -{ - static if (n == 1) - { - alias Repeat = L; - } - else - { - alias Repeat = AliasSeq!(L, Repeat!(n - 1, L)); - } -} - -/// -@nogc nothrow pure @safe unittest -{ - static assert(is(Repeat!(1, uint, int) == AliasSeq!(uint, int))); - static assert(is(Repeat!(2, uint, int) == AliasSeq!(uint, int, uint, int))); - static assert(is(Repeat!(3) == AliasSeq!())); -} - -private template ReplaceOne(L...) -{ - static if (L.length == 2) - { - alias ReplaceOne = AliasSeq!(); - } - else static if (isEqual!(L[0], L[2])) - { - alias ReplaceOne = AliasSeq!(L[1], L[3 .. $]); - } - else - { - alias ReplaceOne = AliasSeq!(L[2], ReplaceOne!(L[0], L[1], L[3 .. $])); - } -} - -/** - * Replaces the first occurrence of $(D_PARAM T) in $(D_PARAM L) with - * $(D_PARAM U). - * - * Params: - * T = The symbol to be replaced. - * U = Replacement. - * L = List of symbols. - * - * Returns: $(D_PARAM L) with the first occurrence of $(D_PARAM T) replaced. - */ -template Replace(T, U, L...) -{ - alias Replace = ReplaceOne!(T, U, L); -} - -/// ditto -template Replace(alias T, U, L...) -{ - alias Replace = ReplaceOne!(T, U, L); -} - -/// ditto -template Replace(T, alias U, L...) -{ - alias Replace = ReplaceOne!(T, U, L); -} - -/// ditto -template Replace(alias T, alias U, L...) -{ - alias Replace = ReplaceOne!(T, U, L); -} - -/// -@nogc nothrow pure @safe unittest -{ - static assert(is(Replace!(int, uint, int) == AliasSeq!(uint))); - static assert(is(Replace!(int, uint, short, int, int, ushort) - == AliasSeq!(short, uint, int, ushort))); - - static assert(Replace!(5, 8, 1, 2, 5, 5) == AliasSeq!(1, 2, 8, 5)); -} - -private template ReplaceAllImpl(L...) -{ - static if (L.length == 2) - { - alias ReplaceAllImpl = AliasSeq!(); - } - else - { - private alias Rest = ReplaceAllImpl!(L[0], L[1], L[3 .. $]); - static if (isEqual!(L[0], L[2])) - { - alias ReplaceAllImpl = AliasSeq!(L[1], Rest); - } - else - { - alias ReplaceAllImpl = AliasSeq!(L[2], Rest); - } - } -} - -/** - * Replaces all occurrences of $(D_PARAM T) in $(D_PARAM L) with $(D_PARAM U). - * - * Params: - * T = The symbol to be replaced. - * U = Replacement. - * L = List of symbols. - * - * Returns: $(D_PARAM L) with all occurrences of $(D_PARAM T) replaced. - */ -template ReplaceAll(T, U, L...) -{ - alias ReplaceAll = ReplaceAllImpl!(T, U, L); -} - -/// ditto -template ReplaceAll(alias T, U, L...) -{ - alias ReplaceAll = ReplaceAllImpl!(T, U, L); -} - -/// ditto -template ReplaceAll(T, alias U, L...) -{ - alias ReplaceAll = ReplaceAllImpl!(T, U, L); -} - -/// ditto -template ReplaceAll(alias T, alias U, L...) -{ - alias ReplaceAll = ReplaceAllImpl!(T, U, L); -} - -/// -@nogc nothrow pure @safe unittest -{ - static assert(is(ReplaceAll!(int, uint, int) == AliasSeq!(uint))); - static assert(is(ReplaceAll!(int, uint, short, int, int, ushort) - == AliasSeq!(short, uint, uint, ushort))); - - static assert(ReplaceAll!(5, 8, 1, 2, 5, 5) == AliasSeq!(1, 2, 8, 8)); -} - -/** - * Params: - * L = List of symbols. - * - * Returns: $(D_PARAM L) with elements in reversed order. - */ -template Reverse(L...) -{ - static if (L.length == 0) - { - alias Reverse = AliasSeq!(); - } - else - { - alias Reverse = AliasSeq!(L[$ - 1], Reverse!(L[0 .. $ - 1])); - } -} - -/// -@nogc nothrow pure @safe unittest -{ - static assert(is(Reverse!(byte, short, int) == AliasSeq!(int, short, byte))); -} - -/** - * Applies $(D_PARAM F) to all elements of $(D_PARAM T). - * - * Params: - * F = Template predicate. - * T = List of symbols. - * - * Returns: Elements $(D_PARAM T) after applying $(D_PARAM F) to them. - */ -template Map(alias F, T...) -if (__traits(isTemplate, F)) -{ - static if (T.length == 0) - { - alias Map = AliasSeq!(); - } - else - { - alias Map = AliasSeq!(F!(T[0]), Map!(F, T[1 .. $])); - } -} - -/// -@nogc nothrow pure @safe unittest -{ - static assert(is(Map!(Unqual, const int, immutable short) - == AliasSeq!(int, short))); -} - -/** - * Sorts $(D_PARAM L) in ascending order according to $(D_PARAM cmp). - * - * $(D_PARAM cmp) can evaluate to: - * $(UL - * $(LI $(D_KEYWORD bool): $(D_KEYWORD true) means - * $(D_INLINECODE a[i] < a[i + 1]).) - * $(LI $(D_KEYWORD int): a negative number means that - * $(D_INLINECODE a[i] < a[i + 1]), a positive number that - * $(D_INLINECODE a[i] > a[i + 1]), `0` if they equal.) - * ) - * - * Merge sort is used to sort the arguments. - * - * Params: - * cmp = Sorting template predicate. - * L = Elements to be sorted. - * - * Returns: Elements of $(D_PARAM L) in ascending order. - * - * See_Also: $(LINK2 https://en.wikipedia.org/wiki/Merge_sort, Merge sort). - */ -template Sort(alias cmp, L...) -if (__traits(isTemplate, cmp)) -{ - private template merge(size_t A, size_t B) - { - static if (A + B == L.length) - { - alias merge = AliasSeq!(); - } - else static if (B >= Right.length - || (A < Left.length && isLessEqual!(cmp, Left[A], Right[B]))) - { - alias merge = AliasSeq!(Left[A], merge!(A + 1, B)); - } - else - { - alias merge = AliasSeq!(Right[B], merge!(A, B + 1)); - } - } - - static if (L.length <= 1) - { - alias Sort = L; - } - else - { - private alias Left = Sort!(cmp, L[0 .. $ / 2]); - private alias Right = Sort!(cmp, L[$ / 2 .. $]); - alias Sort = merge!(0, 0); - } -} - -/// -@nogc nothrow pure @safe unittest -{ - enum cmp(T, U) = T.sizeof < U.sizeof; - static assert(is(Sort!(cmp, long, short, byte, int) - == AliasSeq!(byte, short, int, long))); -} - -@nogc nothrow pure @safe unittest -{ - enum cmp(int T, int U) = T - U; - static assert(Sort!(cmp, 5, 17, 9, 12, 2, 10, 14) - == AliasSeq!(2, 5, 9, 10, 12, 14, 17)); -} - -private enum bool DerivedToFrontCmp(A, B) = is(A : B); - -/** - * Returns $(D_PARAM L) sorted in such a way that the most derived types come - * first. - * - * Params: - * L = Type tuple. - * - * Returns: Sorted $(D_PARAM L). - */ -template DerivedToFront(L...) -{ - alias DerivedToFront = Sort!(DerivedToFrontCmp, L); -} - -/// -@nogc nothrow pure @safe unittest -{ - class A - { - } - class B : A - { - } - class C : B - { - } - static assert(is(DerivedToFront!(B, A, C) == AliasSeq!(C, B, A))); -} - -/** - * Returns the type from the type tuple $(D_PARAM L) that is most derived from - * $(D_PARAM T). - * - * Params: - * T = The type to compare to. - * L = Type tuple. - * - * Returns: The type most derived from $(D_PARAM T). - */ -template MostDerived(T, L...) -{ - static if (L.length == 0) - { - alias MostDerived = T; - } - else static if (is(T : L[0])) - { - alias MostDerived = MostDerived!(T, L[1 .. $]); - } - else - { - alias MostDerived = MostDerived!(L[0], L[1 .. $]); - } -} - -/// -@nogc nothrow pure @safe unittest -{ - class A - { - } - class B : A - { - } - class C : B - { - } - static assert(is(MostDerived!(A, C, B) == C)); -} - -private template EraseOne(L...) -if (L.length > 0) -{ - static if (L.length == 1) - { - alias EraseOne = AliasSeq!(); - } - else static if (isEqual!(L[0 .. 2])) - { - alias EraseOne = AliasSeq!(L[2 .. $]); - } - else - { - alias EraseOne = AliasSeq!(L[1], EraseOne!(L[0], L[2 .. $])); - } -} - -/** - * Removes the first occurrence of $(D_PARAM T) from the alias sequence - * $(D_PARAL L). - * - * Params: - * T = The item to be removed. - * L = Alias sequence. - * - * Returns: $(D_PARAM L) with the first occurrence of $(D_PARAM T) removed. - */ -template Erase(T, L...) -{ - alias Erase = EraseOne!(T, L); -} - -/// ditto -template Erase(alias T, L...) -{ - alias Erase = EraseOne!(T, L); -} - -/// -@nogc nothrow pure @safe unittest -{ - static assert(is(Erase!(int, short, int, int, uint) == AliasSeq!(short, int, uint))); - static assert(is(Erase!(int, short, uint) == AliasSeq!(short, uint))); -} - -private template EraseAllImpl(L...) -{ - static if (L.length == 1) - { - alias EraseAllImpl = AliasSeq!(); - } - else static if (isEqual!(L[0 .. 2])) - { - alias EraseAllImpl = EraseAllImpl!(L[0], L[2 .. $]); - } - else - { - alias EraseAllImpl = AliasSeq!(L[1], EraseAllImpl!(L[0], L[2 .. $])); - } -} - -/** - * Removes all occurrences of $(D_PARAM T) from the alias sequence $(D_PARAL L). - * - * Params: - * T = The item to be removed. - * L = Alias sequence. - * - * Returns: $(D_PARAM L) with all occurrences of $(D_PARAM T) removed. - */ -template EraseAll(T, L...) -{ - alias EraseAll = EraseAllImpl!(T, L); -} - -/// ditto -template EraseAll(alias T, L...) -{ - alias EraseAll = EraseAllImpl!(T, L); -} - -/// -@nogc nothrow pure @safe unittest -{ - static assert(is(EraseAll!(int, short, int, int, uint) == AliasSeq!(short, uint))); - static assert(is(EraseAll!(int, short, uint) == AliasSeq!(short, uint))); - static assert(is(EraseAll!(int, int, int) == AliasSeq!())); -} - -/** - * Returns an alias sequence which contains only items that satisfy the - * condition $(D_PARAM pred). - * - * Params: - * pred = Template predicate. - * L = Alias sequence. - * - * Returns: $(D_PARAM L) filtered so that it contains only items that satisfy - * $(D_PARAM pred). - */ -template Filter(alias pred, L...) -if (__traits(isTemplate, pred)) -{ - static if (L.length == 0) - { - alias Filter = AliasSeq!(); - } - else static if (pred!(L[0])) - { - alias Filter = AliasSeq!(L[0], Filter!(pred, L[1 .. $])); - } - else - { - alias Filter = Filter!(pred, L[1 .. $]); - } -} - -/// -@nogc nothrow pure @safe unittest -{ - alias Given = AliasSeq!(real, int, bool, uint); - static assert(is(Filter!(isIntegral, Given) == AliasSeq!(int, uint))); -} - /** * Attaches a numeric index to each element from $(D_PARAM Args). * diff --git a/os/tanya/os/error.d b/middle/tanya/os/error.d similarity index 99% rename from os/tanya/os/error.d rename to middle/tanya/os/error.d index 3268a8a..733ff46 100644 --- a/os/tanya/os/error.d +++ b/middle/tanya/os/error.d @@ -14,7 +14,7 @@ */ module tanya.os.error; -import tanya.meta.trait; +import tanya.meta; // Socket API error. private template SAError(int posix, int wsa = posix) diff --git a/os/tanya/os/package.d b/middle/tanya/os/package.d similarity index 100% rename from os/tanya/os/package.d rename to middle/tanya/os/package.d diff --git a/os/dub.json b/os/dub.json deleted file mode 100644 index 18fe17a..0000000 --- a/os/dub.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "os", - "description": "Platform-independent interfaces to operating system functionality", - "targetType": "library", - - "dependencies": { - "tanya:meta": "*" - }, - - "sourcePaths": [ - "." - ], - "importPaths": [ - "." - ], - "dflags-dmd": ["-dip1000"] -} diff --git a/source/tanya/algorithm/iteration.d b/source/tanya/algorithm/iteration.d index 41c5f8b..df1027d 100644 --- a/source/tanya/algorithm/iteration.d +++ b/source/tanya/algorithm/iteration.d @@ -20,10 +20,10 @@ */ module tanya.algorithm.iteration; -import std.traits : Unqual, isMutable; +import std.traits; import std.typecons; import tanya.memory.lifetime; -import tanya.meta.trait; +import tanya.meta; import tanya.range; private struct SingletonByValue(E) diff --git a/source/tanya/algorithm/mutation.d b/source/tanya/algorithm/mutation.d index e1e7c22..1a1bb56 100644 --- a/source/tanya/algorithm/mutation.d +++ b/source/tanya/algorithm/mutation.d @@ -14,11 +14,10 @@ */ module tanya.algorithm.mutation; -import std.traits : Unqual, hasElaborateAssign, hasElaborateCopyConstructor, hasElaborateDestructor, isAssignable, - isDynamicArray; +import std.traits; static import tanya.memory.lifetime; static import tanya.memory.op; -import tanya.meta.trait; +import tanya.meta; import tanya.range; /** diff --git a/source/tanya/container/array.d b/source/tanya/container/array.d index b3b3455..b6c9c5d 100644 --- a/source/tanya/container/array.d +++ b/source/tanya/container/array.d @@ -18,11 +18,11 @@ import core.checkedint; import std.algorithm.comparison; import std.algorithm.iteration; import std.algorithm.mutation : bringToFront; -import std.traits : PointerTarget, Unqual, hasElaborateDestructor, isImplicitlyConvertible, isCopyable; +import std.traits; import tanya.algorithm.mutation; import tanya.memory.allocator; import tanya.memory.lifetime; -import tanya.meta.trait; +import tanya.meta; import tanya.range; /** diff --git a/source/tanya/container/buffer.d b/source/tanya/container/buffer.d index 35d83a5..ec8cbf0 100644 --- a/source/tanya/container/buffer.d +++ b/source/tanya/container/buffer.d @@ -16,7 +16,7 @@ module tanya.container.buffer; import std.traits : isScalarType; import tanya.memory.allocator; -import tanya.meta.trait; +import tanya.meta; version (unittest) { diff --git a/source/tanya/container/entry.d b/source/tanya/container/entry.d index 52b3e6a..c4d74c2 100644 --- a/source/tanya/container/entry.d +++ b/source/tanya/container/entry.d @@ -14,11 +14,11 @@ */ module tanya.container.entry; -import std.traits : Unqual, hasElaborateDestructor; +import std.traits; import tanya.container.array; import tanya.memory.allocator; import tanya.memory.lifetime; -import tanya.meta.trait; +import tanya.meta; package struct SEntry(T) { diff --git a/source/tanya/container/hashtable.d b/source/tanya/container/hashtable.d index d74783c..5e9a4e4 100644 --- a/source/tanya/container/hashtable.d +++ b/source/tanya/container/hashtable.d @@ -15,14 +15,14 @@ module tanya.container.hashtable; import std.algorithm.iteration; -import std.traits : CopyConstness, Unqual, ifTestable, isMutable; +import std.traits; import tanya.algorithm.mutation; import tanya.container.array; import tanya.container.entry; import tanya.hash.lookup; import tanya.memory.allocator; import tanya.memory.lifetime; -import tanya.meta.trait; +import tanya.meta; import tanya.range.primitive; /** diff --git a/source/tanya/container/list.d b/source/tanya/container/list.d index 23af88d..ddef391 100644 --- a/source/tanya/container/list.d +++ b/source/tanya/container/list.d @@ -17,11 +17,11 @@ module tanya.container.list; import std.algorithm.comparison; import std.algorithm.iteration; -import std.traits : Unqual, isImplicitlyConvertible, isCopyable; +import std.traits; import tanya.container.entry; import tanya.memory.allocator; import tanya.memory.lifetime; -import tanya.meta.trait; +import tanya.meta; import tanya.range.array; import tanya.range.primitive; diff --git a/source/tanya/container/set.d b/source/tanya/container/set.d index 67fc66a..5a4f64c 100644 --- a/source/tanya/container/set.d +++ b/source/tanya/container/set.d @@ -15,13 +15,13 @@ */ module tanya.container.set; -import std.traits : CopyConstness, Unqual, ifTestable, isImplicitlyConvertible, isMutable; +import std.traits; import tanya.container.array; import tanya.container.entry; import tanya.hash.lookup; import tanya.memory.allocator; import tanya.memory.lifetime; -import tanya.meta.trait; +import tanya.meta; import tanya.range.primitive; /** diff --git a/source/tanya/container/string.d b/source/tanya/container/string.d index 71328f2..10db553 100644 --- a/source/tanya/container/string.d +++ b/source/tanya/container/string.d @@ -28,12 +28,12 @@ module tanya.container.string; import std.algorithm.comparison; import std.algorithm.mutation : bringToFront; -import std.traits : CopyConstness, Unqual, isInstanceOf, isSomeChar, isNarrowString; +import std.traits; import tanya.algorithm.mutation; import tanya.hash.lookup; import tanya.memory.allocator; import tanya.memory.lifetime; -import tanya.meta.trait; +import tanya.meta; import tanya.range.array; import tanya.range.primitive; diff --git a/source/tanya/conv.d b/source/tanya/conv.d index 8f46bd3..3a75d62 100644 --- a/source/tanya/conv.d +++ b/source/tanya/conv.d @@ -14,11 +14,10 @@ */ module tanya.conv; -import std.traits : Unsigned, isNumeric, Largest, Unqual, EnumMembers, isFloatingPoint, isSomeChar, isSigned, - isUnsigned, isIntegral, isSomeString; +import std.traits; import tanya.container.string; import tanya.memory.allocator; -import tanya.meta.trait; +import tanya.meta; import tanya.range; /** diff --git a/source/tanya/format.d b/source/tanya/format.d index 0b031d1..089ed49 100644 --- a/source/tanya/format.d +++ b/source/tanya/format.d @@ -49,12 +49,13 @@ module tanya.format; import std.algorithm.comparison; import std.ascii; -import std.traits : Unqual, isPointer, isSomeChar, isFloatingPoint, isSomeFunction, isIntegral, isSomeString; +import std.math : signbit; +import std.meta; +import std.traits; import tanya.container.string; import tanya.math; static import tanya.memory.op; -import tanya.meta.metafunction; -import tanya.meta.trait; +import tanya.meta; import tanya.range; // Returns the last part of buffer with converted number. @@ -1952,7 +1953,7 @@ private const(char)[] real2String(double value, const FloatBits!double bits = { value }; exponent = (bits.integral >> 52) & 0x7ff; - sign = signBit(value); + sign = !!signbit(value); if (sign) { value = -value; diff --git a/source/tanya/hash/lookup.d b/source/tanya/hash/lookup.d index 706cca5..eb26caa 100644 --- a/source/tanya/hash/lookup.d +++ b/source/tanya/hash/lookup.d @@ -14,8 +14,8 @@ */ module tanya.hash.lookup; -import std.traits : isScalarType, isPointer, isSomeChar, isArray, isIntegral, isBoolean; -import tanya.meta.trait; +import std.traits; +import tanya.meta; import tanya.range.primitive; private struct Hasher diff --git a/source/tanya/math/package.d b/source/tanya/math/package.d index ef0592e..66923b6 100644 --- a/source/tanya/math/package.d +++ b/source/tanya/math/package.d @@ -22,8 +22,8 @@ module tanya.math; import std.math; -import std.traits : Unqual, isFloatingPoint; -import tanya.meta.trait; +import std.traits; +import tanya.meta; /// Floating-point number precisions according to IEEE-754. enum IEEEPrecision : ubyte @@ -113,433 +113,3 @@ package(tanya) union FloatBits(F) static assert(false, "Unsupported IEEE 754 floating point precision"); } } - -/** - * Floating-point number classifications. - */ -enum FloatingPointClass : ubyte -{ - /** - * Not a Number. - * - * See_Also: $(D_PSYMBOL isNaN). - */ - nan, - - /// Zero. - zero, - - /** - * Infinity. - * - * See_Also: $(D_PSYMBOL isInfinity). - */ - infinite, - - /** - * Denormalized number. - * - * See_Also: $(D_PSYMBOL isSubnormal). - */ - subnormal, - - /** - * Normalized number. - * - * See_Also: $(D_PSYMBOL isNormal). - */ - normal, -} - -/** - * Returns whether $(D_PARAM x) is a NaN, zero, infinity, subnormal or - * normalized number. - * - * This function doesn't distinguish between negative and positive infinity, - * negative and positive NaN or negative and positive zero. - * - * Params: - * F = Type of the floating point number. - * x = Floating point number. - * - * Returns: Classification of $(D_PARAM x). - */ -FloatingPointClass classify(F)(F x) -if (isFloatingPoint!F) -{ - if (x == 0) - { - return FloatingPointClass.zero; - } - FloatBits!F bits; - bits.floating = abs(x); - - static if (ieeePrecision!F == IEEEPrecision.single) - { - if (bits.integral > bits.expMask) - { - return FloatingPointClass.nan; - } - else if (bits.integral == bits.expMask) - { - return FloatingPointClass.infinite; - } - else if (bits.integral < (1 << 23)) - { - return FloatingPointClass.subnormal; - } - } - else static if (ieeePrecision!F == IEEEPrecision.double_) - { - if (bits.integral > bits.expMask) - { - return FloatingPointClass.nan; - } - else if (bits.integral == bits.expMask) - { - return FloatingPointClass.infinite; - } - else if (bits.integral < (1L << 52)) - { - return FloatingPointClass.subnormal; - } - } - else static if (ieeePrecision!F == IEEEPrecision.doubleExtended) - { - if (bits.exp == bits.expMask) - { - if ((bits.mantissa & bits.mantissaMask) == 0) - { - return FloatingPointClass.infinite; - } - else - { - return FloatingPointClass.nan; - } - } - else if (bits.exp == 0) - { - return FloatingPointClass.subnormal; - } - else if (bits.mantissa < (1L << 63)) // "Unnormal". - { - return FloatingPointClass.nan; - } - } - - return FloatingPointClass.normal; -} - -/// -@nogc nothrow pure @safe unittest -{ - assert(classify(0.0) == FloatingPointClass.zero); - assert(classify(double.nan) == FloatingPointClass.nan); - assert(classify(double.infinity) == FloatingPointClass.infinite); - assert(classify(-double.infinity) == FloatingPointClass.infinite); - assert(classify(1.4) == FloatingPointClass.normal); - assert(classify(1.11254e-307 / 10) == FloatingPointClass.subnormal); - - assert(classify(0.0f) == FloatingPointClass.zero); - assert(classify(float.nan) == FloatingPointClass.nan); - assert(classify(float.infinity) == FloatingPointClass.infinite); - assert(classify(-float.infinity) == FloatingPointClass.infinite); - assert(classify(0.3) == FloatingPointClass.normal); - assert(classify(5.87747e-38f / 10) == FloatingPointClass.subnormal); - - assert(classify(0.0L) == FloatingPointClass.zero); - assert(classify(real.nan) == FloatingPointClass.nan); - assert(classify(real.infinity) == FloatingPointClass.infinite); - assert(classify(-real.infinity) == FloatingPointClass.infinite); -} - -/** - * Determines whether $(D_PARAM x) is a finite number. - * - * Params: - * F = Type of the floating point number. - * x = Floating point number. - * - * Returns: $(D_KEYWORD true) if $(D_PARAM x) is a finite number, - * $(D_KEYWORD false) otherwise. - * - * See_Also: $(D_PSYMBOL isInfinity). - */ -bool isFinite(F)(F x) -if (isFloatingPoint!F) -{ - FloatBits!F bits; - static if (ieeePrecision!F == IEEEPrecision.single - || ieeePrecision!F == IEEEPrecision.double_) - { - bits.floating = x; - bits.integral &= bits.expMask; - return bits.integral != bits.expMask; - } - else static if (ieeePrecision!F == IEEEPrecision.doubleExtended) - { - bits.floating = abs(x); - return (bits.exp != bits.expMask) - && (bits.exp == 0 || bits.mantissa >= (1L << 63)); - } -} - -/// -@nogc nothrow pure @safe unittest -{ - assert(!isFinite(float.infinity)); - assert(!isFinite(-double.infinity)); - assert(isFinite(0.0)); - assert(!isFinite(float.nan)); - assert(isFinite(5.87747e-38f / 10)); - assert(isFinite(1.11254e-307 / 10)); - assert(isFinite(0.5)); -} - -/** - * Determines whether $(D_PARAM x) is $(B n)ot $(B a) $(B n)umber (NaN). - * - * Params: - * F = Type of the floating point number. - * x = Floating point number. - * - * Returns: $(D_KEYWORD true) if $(D_PARAM x) is not a number, - * $(D_KEYWORD false) otherwise. - */ -bool isNaN(F)(F x) -if (isFloatingPoint!F) -{ - FloatBits!F bits; - bits.floating = abs(x); - - static if (ieeePrecision!F == IEEEPrecision.single - || ieeePrecision!F == IEEEPrecision.double_) - { - return bits.integral > bits.expMask; - } - else static if (ieeePrecision!F == IEEEPrecision.doubleExtended) - { - const maskedMantissa = bits.mantissa & bits.mantissaMask; - if ((bits.exp == bits.expMask && maskedMantissa != 0) - || ((bits.exp != 0) && (bits.mantissa < (1L << 63)))) - { - return true; - } - return false; - } -} - -/// -@nogc nothrow pure @safe unittest -{ - assert(isNaN(float.init)); - assert(isNaN(double.init)); - assert(isNaN(real.init)); -} - -/** - * Determines whether $(D_PARAM x) is a positive or negative infinity. - * - * Params: - * F = Type of the floating point number. - * x = Floating point number. - * - * Returns: $(D_KEYWORD true) if $(D_PARAM x) is infinity, $(D_KEYWORD false) - * otherwise. - * - * See_Also: $(D_PSYMBOL isFinite). - */ -bool isInfinity(F)(F x) -if (isFloatingPoint!F) -{ - FloatBits!F bits; - bits.floating = abs(x); - static if (ieeePrecision!F == IEEEPrecision.single - || ieeePrecision!F == IEEEPrecision.double_) - { - return bits.integral == bits.expMask; - } - else static if (ieeePrecision!F == IEEEPrecision.doubleExtended) - { - return (bits.exp == bits.expMask) - && ((bits.mantissa & bits.mantissaMask) == 0); - } -} - -/// -@nogc nothrow pure @safe unittest -{ - assert(isInfinity(float.infinity)); - assert(isInfinity(-float.infinity)); - assert(isInfinity(double.infinity)); - assert(isInfinity(-double.infinity)); - assert(isInfinity(real.infinity)); - assert(isInfinity(-real.infinity)); -} - -/** - * Determines whether $(D_PARAM x) is a denormilized number or not. - * - * Denormalized number is a number between `0` and `1` that cannot be - * represented as - * - *
- * m*2e
- * 
- * - * where $(I m) is the mantissa and $(I e) is an exponent that fits into the - * exponent field of the type $(D_PARAM F). - * - * `0` is neither normalized nor denormalized. - * - * Params: - * F = Type of the floating point number. - * x = Floating point number. - * - * Returns: $(D_KEYWORD true) if $(D_PARAM x) is a denormilized number, - * $(D_KEYWORD false) otherwise. - * - * See_Also: $(D_PSYMBOL isNormal). - */ -bool isSubnormal(F)(F x) -if (isFloatingPoint!F) -{ - FloatBits!F bits; - bits.floating = abs(x); - static if (ieeePrecision!F == IEEEPrecision.single) - { - return bits.integral < (1 << 23) && bits.integral > 0; - } - else static if (ieeePrecision!F == IEEEPrecision.double_) - { - return bits.integral < (1L << 52) && bits.integral > 0; - } - else static if (ieeePrecision!F == IEEEPrecision.doubleExtended) - { - return bits.exp == 0 && bits.mantissa != 0; - } -} - -/// -@nogc nothrow pure @safe unittest -{ - assert(!isSubnormal(0.0f)); - assert(!isSubnormal(float.nan)); - assert(!isSubnormal(float.infinity)); - assert(!isSubnormal(0.3f)); - assert(isSubnormal(5.87747e-38f / 10)); - - assert(!isSubnormal(0.0)); - assert(!isSubnormal(double.nan)); - assert(!isSubnormal(double.infinity)); - assert(!isSubnormal(1.4)); - assert(isSubnormal(1.11254e-307 / 10)); - - assert(!isSubnormal(0.0L)); - assert(!isSubnormal(real.nan)); - assert(!isSubnormal(real.infinity)); -} - -/** - * Determines whether $(D_PARAM x) is a normilized number or not. - * - * Normalized number is a number that can be represented as - * - *
- * m*2e
- * 
- * - * where $(I m) is the mantissa and $(I e) is an exponent that fits into the - * exponent field of the type $(D_PARAM F). - * - * `0` is neither normalized nor denormalized. - * - * Params: - * F = Type of the floating point number. - * x = Floating point number. - * - * Returns: $(D_KEYWORD true) if $(D_PARAM x) is a normilized number, - * $(D_KEYWORD false) otherwise. - * - * See_Also: $(D_PSYMBOL isSubnormal). - */ -bool isNormal(F)(F x) -if (isFloatingPoint!F) -{ - static if (ieeePrecision!F == IEEEPrecision.single - || ieeePrecision!F == IEEEPrecision.double_) - { - FloatBits!F bits; - bits.floating = x; - bits.integral &= bits.expMask; - return bits.integral != 0 && bits.integral != bits.expMask; - } - else static if (ieeePrecision!F == IEEEPrecision.doubleExtended) - { - return classify(x) == FloatingPointClass.normal; - } -} - -/// -@nogc nothrow pure @safe unittest -{ - assert(!isNormal(0.0f)); - assert(!isNormal(float.nan)); - assert(!isNormal(float.infinity)); - assert(isNormal(0.3f)); - assert(!isNormal(5.87747e-38f / 10)); - - assert(!isNormal(0.0)); - assert(!isNormal(double.nan)); - assert(!isNormal(double.infinity)); - assert(isNormal(1.4)); - assert(!isNormal(1.11254e-307 / 10)); - - assert(!isNormal(0.0L)); - assert(!isNormal(real.nan)); - assert(!isNormal(real.infinity)); -} - -/** - * Determines whether the sign bit of $(D_PARAM x) is set or not. - * - * If the sign bit, $(D_PARAM x) is a negative number, otherwise positive. - * - * Params: - * F = Type of the floating point number. - * x = Floating point number. - * - * Returns: $(D_KEYWORD true) if the sign bit of $(D_PARAM x) is set, - * $(D_KEYWORD false) otherwise. - */ -bool signBit(F)(F x) -if (isFloatingPoint!F) -{ - FloatBits!F bits; - bits.floating = x; - static if (ieeePrecision!F == IEEEPrecision.single) - { - return (bits.integral & (1 << 31)) != 0; - } - else static if (ieeePrecision!F == IEEEPrecision.double_) - { - return (bits.integral & (1L << 63)) != 0; - } - else static if (ieeePrecision!F == IEEEPrecision.doubleExtended) - { - return (bits.exp & (1 << 15)) != 0; - } -} - -/// -@nogc nothrow pure @safe unittest -{ - assert(signBit(-1.0f)); - assert(!signBit(1.0f)); - - assert(signBit(-1.0)); - assert(!signBit(1.0)); - - assert(signBit(-1.0L)); - assert(!signBit(1.0L)); -} diff --git a/source/tanya/net/iface.d b/source/tanya/net/iface.d index 8443cb4..c910b29 100644 --- a/source/tanya/net/iface.d +++ b/source/tanya/net/iface.d @@ -14,10 +14,10 @@ */ module tanya.net.iface; -import std.traits : Unqual; +import std.traits; import tanya.algorithm.mutation; import tanya.container.string; -import tanya.meta.trait; +import tanya.meta; import tanya.range; version (Windows) diff --git a/source/tanya/net/inet.d b/source/tanya/net/inet.d index 314a90c..141fd77 100644 --- a/source/tanya/net/inet.d +++ b/source/tanya/net/inet.d @@ -14,8 +14,8 @@ */ module tanya.net.inet; -import std.traits : Unqual, isUnsigned; -import tanya.meta.trait; +import std.traits; +import tanya.meta; import tanya.range; /** diff --git a/source/tanya/net/ip.d b/source/tanya/net/ip.d index 73ef23d..87268bd 100644 --- a/source/tanya/net/ip.d +++ b/source/tanya/net/ip.d @@ -18,14 +18,14 @@ import std.algorithm.comparison; import std.ascii; import std.sumtype; import std.typecons; -import std.traits : Unqual; +import std.traits; import tanya.algorithm.iteration; import tanya.algorithm.mutation; import tanya.container.string; import tanya.conv; import tanya.format; import tanya.memory.lifetime; -import tanya.meta.trait; +import tanya.meta; import tanya.net.iface; import tanya.net.inet; import tanya.range; diff --git a/source/tanya/range/adapter.d b/source/tanya/range/adapter.d index d30b24c..287e868 100644 --- a/source/tanya/range/adapter.d +++ b/source/tanya/range/adapter.d @@ -14,10 +14,10 @@ */ module tanya.range.adapter; -import std.traits : hasMember, isArray; +import std.traits; import tanya.algorithm.mutation; import tanya.memory.lifetime; -import tanya.meta.trait; +import tanya.meta; import tanya.range; private mixin template InserterCtor() diff --git a/source/tanya/range/primitive.d b/source/tanya/range/primitive.d index aa8c0cf..d8abe3d 100644 --- a/source/tanya/range/primitive.d +++ b/source/tanya/range/primitive.d @@ -15,9 +15,9 @@ module tanya.range.primitive; import std.algorithm.comparison; -import std.traits : FunctionAttribute, ReturnType, hasElaborateCopyConstructor, functionAttributes; +import std.traits; import tanya.memory.lifetime; -import tanya.meta.trait; +import tanya.meta; import tanya.range.array; /** diff --git a/test/tanya/test/assertion.d b/source/tanya/test/assertion.d similarity index 98% rename from test/tanya/test/assertion.d rename to source/tanya/test/assertion.d index 919194f..9b146c8 100644 --- a/test/tanya/test/assertion.d +++ b/source/tanya/test/assertion.d @@ -22,9 +22,9 @@ */ module tanya.test.assertion; -import std.traits : isSomeFunction; +import std.traits; import tanya.memory.allocator; -import tanya.meta.trait; +import tanya.meta; /** * Asserts whether the function $(D_PARAM expr) throws an exception of type diff --git a/test/tanya/test/package.d b/source/tanya/test/package.d similarity index 100% rename from test/tanya/test/package.d rename to source/tanya/test/package.d diff --git a/test/tanya/test/stub.d b/source/tanya/test/stub.d similarity index 99% rename from test/tanya/test/stub.d rename to source/tanya/test/stub.d index fca2d96..1741bbb 100644 --- a/test/tanya/test/stub.d +++ b/source/tanya/test/stub.d @@ -91,7 +91,7 @@ struct WithLvalueElements mixin template InputRangeStub(E = int) { import std.traits : hasUDA, getUDAs; - import tanya.meta.metafunction : Alias; + import std.meta : Alias; /* * Aliases for the attribute lookups to access them faster diff --git a/test/dub.json b/test/dub.json deleted file mode 100644 index c988bd0..0000000 --- a/test/dub.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "test", - "description": "Test suite for unittest-blocks", - "targetType": "library", - - "dependencies": { - "tanya:middle": "*" - }, - - "sourcePaths": [ - "." - ], - "importPaths": [ - "." - ], - "dflags-dmd": ["-dip1000"] -} diff --git a/tests/tanya/math/tests/package.d b/tests/tanya/math/tests/package.d index fe10efd..2fc47ef 100644 --- a/tests/tanya/math/tests/package.d +++ b/tests/tanya/math/tests/package.d @@ -4,16 +4,3 @@ module tanya.math.tests; import tanya.math; - -static if (ieeePrecision!float == IEEEPrecision.doubleExtended) -@nogc nothrow pure @safe unittest -{ - assert(classify(1.68105e-10) == FloatingPointClass.normal); - assert(classify(1.68105e-4932L) == FloatingPointClass.subnormal); - - // Emulate unnormals, because they aren't generated anymore since i386 - FloatBits!real unnormal; - unnormal.exp = 0x123; - unnormal.mantissa = 0x1; - assert(classify(unnormal) == FloatingPointClass.subnormal); -} diff --git a/tests/tanya/memory/tests/smartref.d b/tests/tanya/memory/tests/smartref.d index 25d7d8f..52d4904 100644 --- a/tests/tanya/memory/tests/smartref.d +++ b/tests/tanya/memory/tests/smartref.d @@ -3,10 +3,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ module tanya.memory.tests.smartref; -import std.traits : ReturnType; +import std.traits; import tanya.memory.allocator; import tanya.memory.smartref; -import tanya.meta.trait; +import tanya.meta; import tanya.test.stub; @nogc @system unittest diff --git a/tests/tanya/meta/tests/metafunction.d b/tests/tanya/meta/tests/metafunction.d deleted file mode 100644 index 586e60d..0000000 --- a/tests/tanya/meta/tests/metafunction.d +++ /dev/null @@ -1,30 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -module tanya.meta.tests.metafunction; - -import tanya.meta.metafunction; - -@nogc nothrow pure @safe unittest -{ - enum cmp(int x, int y) = x - y; - static assert(isSorted!(cmp)); - static assert(isSorted!(cmp, 1)); - static assert(isSorted!(cmp, 1, 2, 2)); - static assert(isSorted!(cmp, 1, 2, 2, 4)); - static assert(isSorted!(cmp, 1, 2, 2, 4, 8)); - static assert(!isSorted!(cmp, 32, 2, 2, 4, 8)); - static assert(isSorted!(cmp, 32, 32)); -} - -@nogc nothrow pure @safe unittest -{ - enum cmp(int x, int y) = x < y; - static assert(isSorted!(cmp)); - static assert(isSorted!(cmp, 1)); - static assert(isSorted!(cmp, 1, 2, 2)); - static assert(isSorted!(cmp, 1, 2, 2, 4)); - static assert(isSorted!(cmp, 1, 2, 2, 4, 8)); - static assert(!isSorted!(cmp, 32, 2, 2, 4, 8)); - static assert(isSorted!(cmp, 32, 32)); -}