New Upstream Release - mir-core
Ready changes
Summary
Merged new upstream version: 1.5.5 (was: 1.3.15).
Resulting package
Built on 2023-05-01T09:53 (took 11m12s)
The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:
apt install -t fresh-releases libmir-core-devapt install -t fresh-releases libmir-core1-dbgsymapt install -t fresh-releases libmir-core1
Lintian Result
Diff
diff --git a/debian/changelog b/debian/changelog
index bb16b98..7bea90e 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+mir-core (1.5.5-1) UNRELEASED; urgency=low
+
+ * New upstream release.
+ * Drop patch 01_fix-gdc-build.patch, present upstream.
+ * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk> Mon, 01 May 2023 09:43:22 -0000
+
mir-core (1.1.111-2) unstable; urgency=medium
* Add fix-gdc-build.patch: Fix build with GDC (Closes: #1018796)
diff --git a/debian/patches/01_fix-gdc-build.patch b/debian/patches/01_fix-gdc-build.patch
deleted file mode 100644
index d8ed8fa..0000000
--- a/debian/patches/01_fix-gdc-build.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-From 2d4aa33510403023d75eecd81c9ba0eaaf996f00 Mon Sep 17 00:00:00 2001
-From: Matthias Klumpp <matthias@tenstral.net>
-Date: Fri, 2 Sep 2022 18:28:53 +0200
-Subject: [PATCH] meson: Allow building with gdc
-
----
- meson.build | 16 ++++++++++++----
- 1 file changed, 12 insertions(+), 4 deletions(-)
-
-diff --git a/meson.build b/meson.build
-index facbfaa..8030ecc 100644
---- a/meson.build
-+++ b/meson.build
-@@ -6,6 +6,8 @@ subprojects = []
-
- has_cpp_headers = false
-
-+dc = meson.get_compiler('d')
-+
- sources_list = [
- 'mir/algebraic',
- 'mir/bitmanip',
-@@ -36,10 +38,16 @@ foreach s : sources_list
- sources += 'source/' + s + '.d'
- endforeach
-
--add_project_arguments([
-- '-preview=dip1008',
-- '-lowmem',
--], language: 'd')
-+if dc.get_id() == 'gcc'
-+ add_project_arguments([
-+ '-fpreview=dip1008',
-+ ], language: 'd')
-+else
-+ add_project_arguments([
-+ '-preview=dip1008',
-+ '-lowmem',
-+ ], language: 'd')
-+endif
-
- required_deps = []
-
diff --git a/debian/patches/series b/debian/patches/series
index dc1c406..e69de29 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1 +0,0 @@
-01_fix-gdc-build.patch
diff --git a/dub.sdl b/dub.sdl
index 7bed9ba..27f2f7d 100644
--- a/dub.sdl
+++ b/dub.sdl
@@ -8,11 +8,22 @@ license "Apache-2.0"
buildType "unittest" {
buildOptions "unittests" "debugMode" "debugInfo"
versions "mir_core_test"
+}
+
+buildType "unittest-verbose" {
+ buildOptions "unittests" "debugMode" "debugInfo"
+ versions "mir_core_test"
dflags "-checkaction=context" "-allinst"
}
buildType "unittest-dip1008" {
buildOptions "unittests" "debugMode" "debugInfo"
versions "mir_core_test"
- dflags "-lowmem" "-preview=dip1008" "-checkaction=context" "-allinst"
+ dflags "-lowmem" "-preview=dip1008"
+}
+
+buildType "unittest-dip1000" {
+ buildOptions "unittests" "debugMode" "debugInfo"
+ versions "mir_core_test"
+ dflags "-lowmem" "-preview=dip1000"
}
diff --git a/meson.build b/meson.build
index facbfaa..8030ecc 100644
--- a/meson.build
+++ b/meson.build
@@ -6,6 +6,8 @@ subprojects = []
has_cpp_headers = false
+dc = meson.get_compiler('d')
+
sources_list = [
'mir/algebraic',
'mir/bitmanip',
@@ -36,10 +38,16 @@ foreach s : sources_list
sources += 'source/' + s + '.d'
endforeach
-add_project_arguments([
- '-preview=dip1008',
- '-lowmem',
-], language: 'd')
+if dc.get_id() == 'gcc'
+ add_project_arguments([
+ '-fpreview=dip1008',
+ ], language: 'd')
+else
+ add_project_arguments([
+ '-preview=dip1008',
+ '-lowmem',
+ ], language: 'd')
+endif
required_deps = []
diff --git a/source/mir/algebraic.d b/source/mir/algebraic.d
index b63ab3e..a0d9c9a 100644
--- a/source/mir/algebraic.d
+++ b/source/mir/algebraic.d
@@ -57,7 +57,6 @@ $(T2plain `void`, It is usefull to indicate a possible return type of the visito
$(T2plain `typeof(null)`, It is usefull for nullable types. Also, it is used to indicate that a visitor can't match the current value of the algebraic. Can't be accesed by reference. )
$(T2 This, Dummy structure that is used to construct self-referencing algebraic types. Example: `Variant!(int, double, string, This*[2])`)
$(T2plain $(LREF SetAlias)`!setId`, Dummy structure that is used to construct cyclic-referencing lists of algebraic types. )
-$(T2 TaggedType, Dummy type used to associate tags with type. )
$(T2 Err, Wrapper to denote an error value type. )
$(T2 reflectErr, Attribute that denotes that the type is an error value type. )
)
@@ -66,7 +65,6 @@ $(BOOKTABLE $(H3 $(LREF Algebraic) Traits),
$(TR $(TH Name) $(TH Description))
$(T2 isVariant, Checks if the type is instance of $(LREF Algebraic).)
$(T2 isNullable, Checks if the type is instance of $(LREF Algebraic) with a self $(LREF TypeSet) that contains `typeof(null)`. )
-$(T2 isTaggedVariant, Checks if the type is instance of tagged $(LREF Algebraic).)
$(T2 isTypeSet, Checks if the types are the same as $(LREF TypeSet) of them. )
$(T2 ValueTypeOfNullable, Gets type of $(LI $(LREF .Algebraic.get.2)) method. )
$(T2 SomeVariant, Gets subtype of algebraic without types for which $(LREF isErr) is true.)
@@ -78,8 +76,7 @@ $(T2 isResultVariant, Checks if T is a Variant with at least one allowed type th
$(H3 Type Set)
-$(UL
-$(LI $(LREF TaggedTypeSet) is supported. Example:`TargetTypeSet!(["integer", "floating"], int, double)`).
+$(UL
$(LI Type set is unordered. Example:`TypeSet!(int, double)` and `TypeSet!(double, int)` are the same. )
$(LI Duplicats are ignored. Example: `TypeSet!(float, int, float)` and `TypeSet!(int, float)` are the same. )
$(LI Types are automatically unqualified if this operation can be performed implicitly. Example: `TypeSet!(const int) and `TypeSet!int` are the same. )
@@ -89,7 +86,7 @@ $(LI Empty `TypeSet!()` is allowed.)
)
$(H3 Visitors)
-$(UL
+$(UL
$(LI Visitors are allowed to return values of different types If there are more then one return type then the an $(LREF Algebraic) type is returned. )
$(LI Visitors are allowed to accept additional arguments. The arguments can be passed to the visitor handler. )
$(LI Multiple visitors can be passes to the visitor handler. )
@@ -100,7 +97,7 @@ $(LI If the visitors arguments has known types, then such visitors should be pas
)
$(H3 Implementation Features)
-$(UL
+$(UL
$(LI BetterC support. Runtime `TypeInfo` is not used.)
$(LI Copy-constructors and postblit constructors are supported. )
$(LI `toHash`, `opCmp`. `opEquals`, and `toString` support. )
@@ -126,6 +123,23 @@ module mir.algebraic;
import mir.internal.meta;
import mir.functional: naryFun;
+/++
+The attribute is used to define a permanent member field in an anlgebraic type.
+Should applied to a field of the union passed to $(LREF TaggedVariant).
++/
+enum algMeta;
+/++
+The attribute is used in pair with $(LREF algMeta) to exclude the field
+from compression in `toHash`, `opEquals`, and `opCmp` methods.
++/
+enum algTransp;
+/++
+The attribute is used in pair with $(LREF algMeta) to use the field
+as an error infomration. Usually it is a position marker in a file.
+The type should have `scope const` `toString` method.
++/
+enum algVerbose;
+
private static immutable variantExceptionMsg = "mir.algebraic: the algebraic stores other type then requested.";
private static immutable variantNullExceptionMsg = "mir.algebraic: the algebraic is empty and doesn't store any value.";
private static immutable variantMemberExceptionMsg = "mir.algebraic: the algebraic stores a type that isn't compatible with the user provided visitor and arguments.";
@@ -179,7 +193,7 @@ static if (__VERSION__ >= 2_100)
///
@safe pure version(mir_core_test) unittest
{
- struct CustomVariant
+ static struct CustomVariant
{
Variant!(int, string) data;
alias data this;
@@ -190,15 +204,15 @@ static if (__VERSION__ >= 2_100)
return this;
}
}
-
+
static assert(isLikeVariant!(Variant!(int, string)));
static assert(isLikeVariant!(const Variant!(int[], string)));
static assert(isLikeVariant!(Nullable!(int, string)));
static assert(!isLikeVariant!int);
-
+
static assert(!isVariant!CustomVariant);
static assert(isLikeVariant!CustomVariant);
-
+
CustomVariant customVariant = 5;
assert(customVariant.match!(
(string s) => false,
@@ -212,14 +226,22 @@ Checks if the type is instance of tagged $(LREF Algebraic).
Tagged algebraics can be defined with $(LREF TaggedVariant).
+/
-enum bool isTaggedVariant(T) = isVariant!T && is(T.Kind == enum);
+enum bool isTaggedVariant(T) = is(immutable T == immutable Algebraic!U, U) && is(U == union);
///
@safe pure version(mir_core_test) unittest
{
+ static union MyUnion
+ {
+ int integer;
+ immutable(char)[] string;
+ }
+
+ alias MyAlgebraic = Algebraic!MyUnion;
+ static assert(isTaggedVariant!MyAlgebraic);
+
static assert(!isTaggedVariant!int);
static assert(!isTaggedVariant!(Variant!(int, string)));
- static assert(isTaggedVariant!(TaggedVariant!(["integer", "string"], int, string)));
}
/++
@@ -279,41 +301,22 @@ Dummy type for $(LREF Variant) and $(LREF Nullable) self-referencing.
+/
struct This
{
-@safe pure nothrow @nogc const:
+@safe pure nothrow @nogc scope const:
int opCmp(typeof(this)) { return 0; }
string toString() { return typeof(this).stringof; }
}
-/++
-Dummy type used to associate tags with a type.
-+/
-struct TaggedType(T, string name)
- if (name.length)
+private template TagInfo(T, string name, udas...)
+ if (udas.length <= 3)
{
- private enum tag = name;
- private alias Type = T;
- static if (!is(T == void) && !is(T == typeof(null)))
- private T payload;
-@safe pure nothrow @nogc const:
- int opCmp(ref typeof(this)) { return 0; }
- string toString() { return typeof(this).stringof; }
+ import std.meta: staticIndexOf;
+ alias Type = T;
+ enum tag = name;
+ enum meta = staticIndexOf!(algMeta, udas) >= 0;
+ enum transparent = staticIndexOf!(algTransp, udas) >= 0;
+ enum verbose = staticIndexOf!(algVerbose, udas) >= 0;
}
-/++
-Checks if `T` is $(LREF TaggedType) instance.
-+/
-enum isTaggedType(T) = is(T == TaggedType!(I, name), I, string name);
-
-/++
-Gets $(LREF TaggedType) underlying type.
-+/
-alias getTaggedTypeUnderlying(T : TaggedType!(I, name), I, string name) = I;
-
-/++
-Gets $(LREF TaggedType) tag name.
-+/
-enum getTaggedTypeName(T : TaggedType!(I, name), I, string name) = name;
-
// example from std.variant
/++
$(H4 Self-Referential Types)
@@ -322,7 +325,7 @@ $(LUCKY self-referential data structures), i.e. structures that embed references
values of their own type within.
This is achieved with $(LREF Variant) by using $(LREF This) as a placeholder whenever a
reference to the type being defined is needed. The $(LREF Variant) instantiation
-will perform
+will perform
$(LINK2 https://en.wikipedia.org/wiki/Name_resolution_(programming_languages)#Alpha_renaming_to_make_name_resolution_trivial,
alpha renaming) on its constituent types, replacing $(LREF This)
with the self-referenced type. The structure of the type involving $(LREF This) may
@@ -330,7 +333,7 @@ be arbitrarily complex.
+/
@safe pure version(mir_core_test) unittest
{
- import mir.functional: Tuple = RefTuple;
+ import mir.functional: Tuple;
// A tree is either a leaf or a branch of two others
alias Tree(Leaf) = Variant!(Leaf, Tuple!(This*, This*));
@@ -357,19 +360,6 @@ be arbitrarily complex.
assert(obj.get!Map["customer"] == "John");
}
-version(mir_core_test) unittest
-{
- static struct Foo
- {
- ~this() @system
- {
- }
- }
- alias TFoo = TaggedType!(Foo, "foo");
- TFoo foo;
-}
-
-
/++
Type set resolution template used to construct $(LREF Algebraic) .
+/
@@ -382,13 +372,6 @@ template TypeSet(T...)
static if (is(NoDuplicates!T == T))
static if (staticIsSorted!(TypeCmp, T))
{
- static if (anySatisfy!(isTaggedType, T))
- {
- import std.meta: Filter, templateNot;
- static assert(Filter!(templateNot!isTaggedType, T).length == 0,
- "Either all or none types must be tagged. Types that doesn't have tags: " ~
- Filter!(templateNot!isTaggedType, T).stringof);
- }
alias TypeSet = T;
}
else
@@ -402,7 +385,7 @@ template TypeSet(T...)
// IonNull goes first as well
private template isIonNull(T)
{
- static if (is(T == TaggedType!(U, name), U, string name))
+ static if (is(T == TagInfo!(U, name), U, string name))
enum isIonNull = .isIonNull!U;
else
enum isIonNull = T.stringof == "IonNull";
@@ -411,12 +394,12 @@ private template isIonNull(T)
private template TypeCmp(A, B)
{
enum bool TypeCmp = is(A == B) ? false:
- is(A == typeof(null)) || is(A == TaggedType!(typeof(null), aname), string aname) ? true:
- is(B == typeof(null)) || is(B == TaggedType!(typeof(null), bname), string bname) ? false:
+ is(A == typeof(null)) ? true:
+ is(B == typeof(null)) ? false:
isIonNull!A ? true:
isIonNull!B ? false:
- is(A == void) || is(A == TaggedType!(void, vaname), string vaname) ? true:
- is(B == void) || is(A == TaggedType!(void, vbname), string vbname) ? false:
+ is(A == void) || is(A == TagInfo!(void, vaname), string vaname) ? true:
+ is(B == void) || is(A == TagInfo!(void, vbname), string vbname) ? false:
A.sizeof < B.sizeof ? true:
A.sizeof > B.sizeof ? false:
A.mangleof < B.mangleof;
@@ -440,14 +423,9 @@ private template applyTags(string[] tagNames, T...)
static if (tagNames.length == 0)
alias applyTags = AliasSeq!();
else
- alias applyTags = AliasSeq!(TaggedType!(T[0], tagNames[0]), .applyTags!(tagNames[1 .. $], T[1 .. $]));
+ alias applyTags = AliasSeq!(TagInfo!(T[0], tagNames[0]), .applyTags!(tagNames[1 .. $], T[1 .. $]));
}
-/++
-Type set for tagged $(LREF Variants) self-referencing.
-+/
-alias TaggedTypeSet(string[] tagNames, T...) = TypeSet!(applyTags!(tagNames, T));
-
/++
Checks if the type list is $(LREF TypeSet).
+/
@@ -464,7 +442,7 @@ enum bool isTypeSet(T...) = is(T == TypeSet!T);
/++
Variant Type (aka Algebraic Type).
-The impllementation is defined as
+The implementation is defined as
----
alias Variant(T...) = Algebraic!(TypeSet!T);
----
@@ -474,7 +452,7 @@ Compatible with BetterC mode.
alias Variant(T...) = Algebraic!(TypeSet!T);
///
-@safe pure @nogc
+@safe pure @nogc
version(mir_core_test) unittest
{
Variant!(int, double, string) v = 5;
@@ -487,8 +465,8 @@ version(mir_core_test) unittest
/// Single argument Variant
// and Type with copy constructor
-@safe pure nothrow @nogc
-version(mir_core_test) unittest
+@safe pure nothrow @nogc
+version(mir_core_test) unittest
{
static struct S
{
@@ -508,7 +486,7 @@ version(mir_core_test) unittest
}
/// Empty type set
-@safe pure nothrow @nogc version(mir_core_test) unittest
+@safe pure nothrow @nogc version(mir_core_test) unittest
{
Variant!() a;
auto b = a;
@@ -519,13 +497,13 @@ version(mir_core_test) unittest
}
/// Small types
-@safe pure nothrow @nogc version(mir_core_test) unittest
+@safe pure nothrow @nogc version(mir_core_test) unittest
{
static struct S { ubyte d; }
static assert(Nullable!(byte, char, S).sizeof == 2);
}
-@safe pure nothrow @nogc version(mir_core_test) unittest
+@safe pure nothrow @nogc version(mir_core_test) unittest
{
static struct S { ubyte[3] d; }
static assert(Nullable!(ushort, wchar, S).sizeof == 6);
@@ -560,7 +538,6 @@ Compatible with BetterC mode.
Template has two declarations:
----
-alias TaggedVariant(string[] tags, T...) = Variant!(applyTags!(tags, T));
// and
template TaggedVariant(T)
if (is(T == union))
@@ -571,104 +548,161 @@ template TaggedVariant(T)
See_also: $(LREF Variant), $(LREF isTaggedVariant).
+/
-alias TaggedVariant(string[] tags, T...) = Variant!(applyTags!(tags, T));
-
-/// ditto
+deprecated ("Use Algebraic!Union instead")
template TaggedVariant(T)
if (is(T == union))
{
- import std.meta: staticMap;
- enum names = __traits(allMembers, T);
- alias TypeOf(string member) = typeof(__traits(getMember, T, member));
- alias Types = staticMap!(TypeOf, names);
- alias TaggedVariant = .TaggedVariant!([names], Types);
+ alias TaggedVariant = Algebraic!T;
}
-/// Json Value
-@safe pure
+/// Json Value with styles
+@safe pure
version(mir_core_test) unittest
{
- static union JsonUnion
+ enum Style { block, flow }
+
+ static struct SomeMetadata {
+ int a;
+ @safe pure nothrow @nogc scope
+ int opCmp(scope const SomeMetadata rhs) const { return a - rhs.a; }
+ }
+
+ static struct ParsePosition
{
+ string file, line, column;
+
+ void toString()(scope ref W w) scope const
+ {
+ w.put(file);
+ if (line) {
+ w.put("("); w.put(line);
+ if (column) { w.put(","); w.put(column); }
+ w.put(")");
+ }
+ }
+ }
+
+ static union Json_
+ {
+ typeof(null) null_;
+ bool boolean;
long integer;
double floating;
- bool boolean;
- typeof(null) null_;
+ // Not, that `string` is't builtin type but an alias in `object.d`
+ // So we can use `string` as a name of the string field
immutable(char)[] string;
This[] array;
- This[immutable(char)[]] object;
+ // commented out to test `opCmp` primitive
+ // This[immutable(char)[]] object;
+
+ @algMeta:
+ bool active;
+ SomeMetadata metadata;
+ @algTransp:
+ Style style;
+ @algVerbose ParsePosition position;
}
- alias JsonValue = TaggedVariant!JsonUnion;
+ alias JsonAlgebraic = Algebraic!Json_;
// typeof(null) has priority
- static assert(JsonValue.Kind.init == JsonValue.Kind.null_);
- static assert(JsonValue.Kind.null_ == 0);
-
+ static assert(JsonAlgebraic.Kind.init == JsonAlgebraic.Kind.null_);
+ static assert(JsonAlgebraic.Kind.null_ == 0);
+
// Kind and AllowedTypes has the same order
- static assert (is(JsonValue.AllowedTypes[JsonValue.Kind.array] == JsonValue[]));
- static assert (is(JsonValue.AllowedTypes[JsonValue.Kind.boolean] == bool));
- static assert (is(JsonValue.AllowedTypes[JsonValue.Kind.floating] == double));
- static assert (is(JsonValue.AllowedTypes[JsonValue.Kind.integer] == long));
- static assert (is(JsonValue.AllowedTypes[JsonValue.Kind.null_] == typeof(null)));
- static assert (is(JsonValue.AllowedTypes[JsonValue.Kind.object] == JsonValue[string]));
+ static assert (is(JsonAlgebraic.AllowedTypes[JsonAlgebraic.Kind.array] == JsonAlgebraic[]));
+ static assert (is(JsonAlgebraic.AllowedTypes[JsonAlgebraic.Kind.boolean] == bool));
+ static assert (is(JsonAlgebraic.AllowedTypes[JsonAlgebraic.Kind.floating] == double));
+ static assert (is(JsonAlgebraic.AllowedTypes[JsonAlgebraic.Kind.integer] == long));
+ static assert (is(JsonAlgebraic.AllowedTypes[JsonAlgebraic.Kind.null_] == typeof(null)));
+ // static assert (is(JsonAlgebraic.AllowedTypes[JsonAlgebraic.Kind.object] == JsonAlgebraic[string]));
- JsonValue v;
- assert(v.kind == JsonValue.Kind.null_);
+ JsonAlgebraic v;
+ assert(v.kind == JsonAlgebraic.Kind.null_);
v = 1;
- assert(v.kind == JsonValue.Kind.integer);
+ assert(v.kind == JsonAlgebraic.Kind.integer);
assert(v == 1);
- v = JsonValue(1);
+ v = JsonAlgebraic(1);
assert(v == 1);
v = v.get!(long, double);
v = "Tagged!";
- assert(v.get !string == "Tagged!");
- assert(v.trustedGet!string == "Tagged!");
+ // member-based access. Simple!
+ assert(v.string == "Tagged!");
+ // type-based access
+ assert(v.get!string == "Tagged!");
+ assert(v.trustedGet!string == "Tagged!");
- assert(v.kind == JsonValue.Kind.string);
+ assert(v.kind == JsonAlgebraic.Kind.string);
assert(v.get!"string" == "Tagged!"); // string-based get
assert(v.trustedGet!"string" == "Tagged!"); // string-based trustedGet
- assert(v.get!(JsonValue.Kind.string) == "Tagged!"); // Kind-based get
- assert(v.trustedGet!(JsonValue.Kind.string) == "Tagged!"); // Kind-based trustedGet
+ assert(v.get!(JsonAlgebraic.Kind.string) == "Tagged!"); // Kind-based get
+ assert(v.trustedGet!(JsonAlgebraic.Kind.string) == "Tagged!"); // Kind-based trustedGet
- v = [JsonValue("str"), JsonValue(4.3)];
-
- assert(v.kind == JsonValue.Kind.array);
- assert(v.trustedGet!(JsonValue[])[1].kind == JsonValue.Kind.floating);
+ // checks
+ assert(v._is!string); // type based
+ assert(v._is!"string"); // string based
+ assert(v._is!(JsonAlgebraic.Kind.string)); //
v = null;
- assert(v.kind == JsonValue.Kind.null_);
+ assert(v.kind == JsonAlgebraic.Kind.null_);
+
+ v = [JsonAlgebraic("str"), JsonAlgebraic(4.3)];
+
+ assert(v.kind == JsonAlgebraic.Kind.array);
+ assert(v.trustedGet!(JsonAlgebraic[])[1].kind == JsonAlgebraic.Kind.floating);
+
+ JsonAlgebraic w = v;
+ w.style = Style.flow;
+ assert(v.style != w.style);
+ assert(v == w);
+ assert(v <= w);
+ assert(v >= w);
+ assert(v.toHash == w.toHash);
+ w.active = true;
+ assert(v != w);
+ assert(v.toHash != w.toHash);
+ assert(v.get!"array" == w.get!"array");
+ assert(v < w);
+
+ // test equality with self-referencing allowed type
+ auto arr = [JsonAlgebraic("str"), JsonAlgebraic(120)];
+ v = arr;
+ assert(v == arr);
+ assert(v == [JsonAlgebraic("str"), JsonAlgebraic(120)]);
}
/// Wrapped algebraic with propogated primitives
-@safe pure
+@safe pure
version(mir_core_test) unittest
{
static struct Response
{
- alias Union = TaggedVariant!(
- ["double_", "string", "array", "table"],
- double,
- string,
- Response[],
- Response[string],
- );
+ private union Response_
+ {
+ double float_;
+ immutable(char)[] string;
+ Response[] array;
+ Response[immutable(char)[]] table;
+ }
+
+ alias ResponseAlgebraic = Algebraic!Response_;
+
+ ResponseAlgebraic data;
+ alias Tag = ResponseAlgebraic.Kind;
- Union data;
- alias Tag = Union.Kind;
// propogates opEquals, opAssign, and other primitives
alias data this;
- static foreach (T; Union.AllowedTypes)
+ static foreach (T; ResponseAlgebraic.AllowedTypes)
this(T v) @safe pure nothrow @nogc { data = v; }
}
Response v = 3.0;
- assert(v.kind == Response.Tag.double_);
+ assert(v.kind == Response.Tag.float_);
v = "str";
assert(v == "str");
}
@@ -676,13 +710,13 @@ version(mir_core_test) unittest
/++
Nullable $(LREF Variant) Type (aka Algebraic Type).
-The impllementation is defined as
+The implementation is defined as
----
alias Nullable(T...) = Variant!(typeof(null), T);
----
In additional to common algebraic API the following members can be accesssed:
-$(UL
+$(UL
$(LI $(LREF .Algebraic.isNull))
$(LI $(LREF .Algebraic.nullify))
$(LI $(LREF .Algebraic.get.2))
@@ -706,7 +740,7 @@ Single type `Nullable`
version(mir_core_test) unittest
{
static assert(is(Nullable!int == Variant!(typeof(null), int)));
-
+
Nullable!int a = 5;
assert(a.get!int == 5);
@@ -724,7 +758,7 @@ version(mir_core_test) unittest
}
/// Empty nullable type set support
-@safe pure nothrow @nogc version(mir_core_test) unittest
+@safe pure nothrow @nogc version(mir_core_test) unittest
{
Nullable!() a;
auto b = a;
@@ -734,22 +768,35 @@ version(mir_core_test) unittest
static assert(typeof(a).sizeof == 1);
}
+private bool contains(scope const char[][] names, scope const char[] member)
+@safe pure nothrow @nogc
+{
+ foreach (name; names)
+ if (name == member)
+ return true;
+ return false;
+}
+
/++
Algebraic implementation.
For more portable code, it is higly recommeded to don't use this template directly.
Instead, please use of $(LREF Variant) and $(LREF Nullable), which sort types.
+/
-struct Algebraic(_Types...)
+struct Algebraic(T__...)
{
+ import mir.internal.meta: getUDAs;
import core.lifetime: moveEmplace;
import mir.conv: emplaceRef;
import mir.reflection: isPublic, hasField, isProperty;
- import std.meta: Filter, AliasSeq, ApplyRight, anySatisfy, allSatisfy, staticMap, templateOr, templateNot;
+ import std.meta: Filter, AliasSeq, ApplyRight, anySatisfy, allSatisfy, staticMap, templateOr, templateNot, templateAnd;
import std.traits:
hasElaborateAssign,
hasElaborateCopyConstructor,
hasElaborateDestructor,
hasMember,
+ hasUDA,
+ isAggregateType,
+ isAssociativeArray,
isDynamicArray,
isEqualityComparable,
isOrderingComparable,
@@ -757,25 +804,60 @@ struct Algebraic(_Types...)
Unqual
;
- private enum bool _variant_test_ = is(_Types == AliasSeq!(typeof(null), double));
-
- static if (anySatisfy!(isTaggedType, _Types))
+ static if (T__.length == 1 && is(T__[0] == union))
{
- private alias _UntaggedThisTypeSetList = staticMap!(getTaggedTypeUnderlying, _Types);
+ private alias UMTypeInfoOf__(immutable(char)[] member) = TagInfo!(
+ typeof(__traits(getMember, T__[0], member)),
+ member,
+ getUDAs!(T__[0], member, algMeta),
+ getUDAs!(T__[0], member, algTransp),
+ getUDAs!(T__[0], member, algVerbose),
+ );
+
+ private alias UMGetType__(alias TI) = TI.Type;
+ private enum bool UMGetMeta(alias TI) = TI.meta;
+
+ private alias AllInfo__ = staticMap!(UMTypeInfoOf__, __traits(allMembers, T__[0]));
+ private alias TypesInfo__ = Filter!(templateNot!UMGetMeta, AllInfo__);
+ private alias MetaInfo__ = Filter!(UMGetMeta, AllInfo__);
+ alias Types__ = staticMap!(UMGetType__, TypesInfo__);
+
+ /++
+ +/
+ static immutable char[][] metaFieldNames__ = () {
+ immutable(char)[][] ret;
+ foreach (T; MetaInfo__)
+ ret ~= T.tag;
+ return ret;
+ } ();
+
+ /++
+ +/
+ static immutable char[][] typeFieldNames__ = () {
+ immutable(char)[][] ret;
+ foreach (T; TypesInfo__)
+ ret ~= T.tag;
+ return ret;
+ } ();
}
else
{
- private alias _UntaggedThisTypeSetList = _Types;
+ alias Types__ = T__;
+ private alias MetaInfo__ = T__[0 .. 0];
+ enum immutable(char[][]) metaFieldNames__ = null;
+ enum immutable(char[][]) typeFieldNames__ = null;
}
+ private enum bool variant_test__ = is(Types__ == AliasSeq!(typeof(null), double));
+
/++
Allowed types list
See_also: $(LREF TypeSet)
+/
- alias AllowedTypes = AliasSeq!(ReplaceTypeUnless!(isVariant, This, Algebraic!_Types, _UntaggedThisTypeSetList));
+ alias AllowedTypes = AliasSeq!(ReplaceTypeUnless!(.isVariant, .This, Algebraic!T__, Types__));
version(mir_core_test)
- static if (_variant_test_)
+ static if (variant_test__)
///
unittest
{
@@ -797,9 +879,12 @@ struct Algebraic(_Types...)
V*)));
}
+ static foreach (i, T; MetaInfo__)
+ mixin ("MetaInfo__[" ~ i.stringof ~ "].Type " ~ T.tag ~";");
+
private alias _Payload = Replace!(void, _Void!(), Replace!(typeof(null), _Null!(), AllowedTypes));
- private static union _Storage_
+ private static union Storage__
{
_Payload payload;
@@ -812,27 +897,27 @@ struct Algebraic(_Types...)
ubyte[Largest!_Payload.sizeof] bytes;
}
- private _Storage_ _storage_;
+ private Storage__ storage__;
static if (AllowedTypes.length > 1)
{
- static if ((_Storage_.alignof & 1) && _Payload.length <= ubyte.max)
- private alias _ID_ = ubyte;
+ static if ((Storage__.alignof & 1) && _Payload.length <= ubyte.max)
+ private alias ID__ = ubyte;
else
- static if ((_Storage_.alignof & 2) && _Payload.length <= ushort.max)
- private alias _ID_ = ushort;
+ static if ((Storage__.alignof & 2) && _Payload.length <= ushort.max)
+ private alias ID__ = ushort;
else
- static if (_Storage_.alignof & 3)
- private alias _ID_ = uint;
- else
- private alias _ID_ = ulong;
-
- _ID_ _identifier_;
+ // static if (Storage__.alignof & 3)
+ private alias ID__ = uint;
+ // else
+ // private alias ID__ = ulong;
+
+ ID__ identifier__;
}
else
{
- alias _ID_ = uint;
- enum _ID_ _identifier_ = 0;
+ private alias ID__ = uint;
+ enum ID__ identifier__ = 0;
}
version (D_Ddoc)
@@ -851,12 +936,12 @@ struct Algebraic(_Types...)
enum Kind { _not_me_but_tags_name_list_ }
}
- static if (anySatisfy!(isTaggedType, _Types))
+ static if (typeFieldNames__.length)
{
version (D_Ddoc){}
else
{
- mixin(enumKindText([staticMap!(getTaggedTypeName, _Types)]));
+ mixin(enumKindText(typeFieldNames__));
}
}
@@ -865,7 +950,7 @@ struct Algebraic(_Types...)
version (D_Ddoc){}
else
{
- alias Kind = _ID_;
+ alias Kind = ID__;
}
}
@@ -877,38 +962,38 @@ struct Algebraic(_Types...)
+/
Kind kind() const @safe pure nothrow @nogc @property
{
- assert(_identifier_ <= Kind.max);
- return cast(Kind) _identifier_;
+ assert(identifier__ <= Kind.max);
+ return cast(Kind) identifier__;
}
static if (anySatisfy!(hasElaborateDestructor, _Payload))
~this() @trusted
{
- S: switch (_identifier_)
+ S: switch (identifier__)
{
static foreach (i, T; AllowedTypes)
static if (hasElaborateDestructor!T)
{
case i:
- (*cast(Unqual!(_Payload[i])*)&_storage_.payload[i]).__xdtor;
+ (*cast(Unqual!(_Payload[i])*)&storage__.payload[i]).__xdtor;
break S;
}
default:
}
version(mir_secure_memory)
- _storage_.bytes = 0xCC;
+ storage__.bytes = 0xCC;
}
// static if (anySatisfy!(hasOpPostMove, _Payload))
// void opPostMove(const ref typeof(this) old)
// {
- // S: switch (_identifier_)
+ // S: switch (identifier__)
// {
// static foreach (i, T; AllowedTypes)
// static if (hasOpPostMove!T)
// {
// case i:
- // this._storage_.payload[i].opPostMove(old._storage_.payload[i]);
+ // this.storage__.payload[i].opPostMove(old.storage__.payload[i]);
// return;
// }
// default: return;
@@ -926,7 +1011,7 @@ struct Algebraic(_Types...)
{
auto length()() const @property
{
- switch (_identifier_)
+ switch (identifier__)
{
static foreach (i, T; AllowedTypes)
{
@@ -939,7 +1024,7 @@ struct Algebraic(_Types...)
auto length()(size_t length) @property
{
- switch (_identifier_)
+ switch (identifier__)
{
static foreach (i, T; AllowedTypes)
{
@@ -973,7 +1058,7 @@ struct Algebraic(_Types...)
auto opIndex()(size_t[2] index)
{
auto ret = this;
- S: switch (_identifier_)
+ S: switch (identifier__)
{
static foreach (i, T; AllowedTypes)
{
@@ -995,14 +1080,18 @@ struct Algebraic(_Types...)
/// Construct an algebraic type from its subset.
this(RhsTypes...)(Algebraic!RhsTypes rhs)
- if (allSatisfy!(Contains!AllowedTypes, Algebraic!RhsTypes.AllowedTypes))
+ if (!(hasElaborateCopyConstructor!(Algebraic!T__) && is(Algebraic!RhsTypes == typeof(this))) && allSatisfy!(Contains!AllowedTypes, Algebraic!RhsTypes.AllowedTypes))
{
import core.lifetime: move;
- static if (is(RhsTypes == _Types))
+ static if (is(RhsTypes == Types__))
this = move(rhs);
else
{
- switch (rhs._identifier_)
+ static foreach (member; metaFieldNames__)
+ static if (Algebraic!RhsTypes.metaFieldNames__.contains(member))
+ __traits(getMember, this, member) = move(__traits(getMember, rhs, member));
+
+ switch (rhs.identifier__)
{
static foreach (i, T; Algebraic!RhsTypes.AllowedTypes)
{
@@ -1020,7 +1109,7 @@ struct Algebraic(_Types...)
}
version(mir_core_test)
- static if (_variant_test_)
+ static if (variant_test__)
///
unittest
{
@@ -1052,21 +1141,24 @@ struct Algebraic(_Types...)
private static union _StorageI(uint i)
{
_Payload[i] payload;
- ubyte[_Storage_.bytes.length] bytes;
+ ubyte[Storage__.bytes.length] bytes;
}
static if (allSatisfy!(hasInoutConstruction, CC_AllowedTypes))
this(return ref scope inout Algebraic rhs) inout
{
- static if (AllowedTypes.length > 1) this._identifier_ = rhs._identifier_;
+ static foreach (member; metaFieldNames__)
+ __traits(getMember, this, member) = __traits(getMember, rhs, member);
+
+ static if (AllowedTypes.length > 1) this.identifier__ = rhs.identifier__;
static foreach (int i, T; AllowedTypes)
static if (!is(T == typeof(null)) && !is(T == void))
{
- if (_identifier_ == i)
+ if (identifier__ == i)
{
static if (__VERSION__ < 2094)
{
- _storage_.bytes = () inout @trusted {
+ storage__.bytes = () inout @trusted {
auto ret = inout _StorageI!i(rhs.trustedGet!T);
return ret.bytes;
} ();
@@ -1074,8 +1166,8 @@ struct Algebraic(_Types...)
}
else
{
- _storage_ = () inout {
- mixin(`inout _Storage_ ret = { _member_` ~ i.stringof ~ ` : rhs.trustedGet!T };`);
+ storage__ = () inout @trusted {
+ mixin(`inout Storage__ ret = { _member_` ~ i.stringof ~ ` : rhs.trustedGet!T };`);
return ret;
} ();
return;
@@ -1088,14 +1180,17 @@ struct Algebraic(_Types...)
static if (allSatisfy!(hasMutableConstruction, CC_AllowedTypes))
this(return ref scope Algebraic rhs)
{
- static if (AllowedTypes.length > 1) this._identifier_ = rhs._identifier_;
+ static foreach (member; metaFieldNames__)
+ __traits(getMember, this, member) = __traits(getMember, rhs, member);
+
+ static if (AllowedTypes.length > 1) this.identifier__ = rhs.identifier__;
static foreach (int i, T; AllowedTypes)
static if (!is(T == typeof(null)) && !is(T == void))
{
- if (_identifier_ == i)
+ if (identifier__ == i)
{
- _storage_ = () {
- mixin(`_Storage_ ret = { _member_` ~ i.stringof ~ ` : rhs.trustedGet!T };`);
+ storage__ = () {
+ mixin(`Storage__ ret = { _member_` ~ i.stringof ~ ` : rhs.trustedGet!T };`);
return ret;
} ();
return;
@@ -1106,14 +1201,17 @@ struct Algebraic(_Types...)
static if (allSatisfy!(hasConstConstruction, CC_AllowedTypes))
this(return ref scope const Algebraic rhs) const
{
- static if (AllowedTypes.length > 1) this._identifier_ = rhs._identifier_;
+ static foreach (member; metaFieldNames__)
+ __traits(getMember, this, member) = __traits(getMember, rhs, member);
+
+ static if (AllowedTypes.length > 1) this.identifier__ = rhs.identifier__;
static foreach (int i, T; AllowedTypes)
static if (!is(T == typeof(null)) && !is(T == void))
{
- if (_identifier_ == i)
+ if (identifier__ == i)
{
- _storage_ = () const {
- mixin(`const _Storage_ ret = { _member_` ~ i.stringof ~ ` : rhs.trustedGet!T };`);
+ storage__ = () const {
+ mixin(`const Storage__ ret = { _member_` ~ i.stringof ~ ` : rhs.trustedGet!T };`);
return ret;
} ();
return;
@@ -1124,14 +1222,17 @@ struct Algebraic(_Types...)
static if (allSatisfy!(hasImmutableConstruction, CC_AllowedTypes))
this(return ref scope immutable Algebraic rhs) immutable
{
- static if (AllowedTypes.length > 1) this._identifier_ = rhs._identifier_;
+ static foreach (member; metaFieldNames__)
+ __traits(getMember, this, member) = __traits(getMember, rhs, member);
+
+ static if (AllowedTypes.length > 1) this.identifier__ = rhs.identifier__;
static foreach (int i, T; AllowedTypes)
static if (!is(T == typeof(null)) && !is(T == void))
{
- if (_identifier_ == i)
+ if (identifier__ == i)
{
- _storage_ = () immutable {
- mixin(`immutable _Storage_ ret = { _member_` ~ i.stringof ~ ` : rhs.trustedGet!T };`);
+ storage__ = () immutable {
+ mixin(`immutable Storage__ ret = { _member_` ~ i.stringof ~ ` : rhs.trustedGet!T };`);
return ret;
} ();
return;
@@ -1142,14 +1243,17 @@ struct Algebraic(_Types...)
static if (allSatisfy!(hasSemiImmutableConstruction, CC_AllowedTypes))
this(return ref scope const Algebraic rhs) immutable
{
- static if (AllowedTypes.length > 1) this._identifier_ = rhs._identifier_;
+ static foreach (member; metaFieldNames__)
+ __traits(getMember, this, member) = __traits(getMember, rhs, member);
+
+ static if (AllowedTypes.length > 1) this.identifier__ = rhs.identifier__;
static foreach (int i, T; AllowedTypes)
static if (!is(T == typeof(null)) && !is(T == void))
{
- if (_identifier_ == i)
+ if (identifier__ == i)
{
- _storage_ = () const {
- mixin(`immutable _Storage_ ret = { _member_` ~ i.stringof ~ ` : rhs.trustedGet!T };`);
+ storage__ = () const {
+ mixin(`immutable Storage__ ret = { _member_` ~ i.stringof ~ ` : rhs.trustedGet!T };`);
return ret;
} ();
return;
@@ -1160,14 +1264,17 @@ struct Algebraic(_Types...)
static if (allSatisfy!(hasSemiMutableConstruction, CC_AllowedTypes))
this(return ref scope const Algebraic rhs)
{
- static if (AllowedTypes.length > 1) this._identifier_ = rhs._identifier_;
+ static foreach (member; metaFieldNames__)
+ __traits(getMember, this, member) = __traits(getMember, rhs, member);
+
+ static if (AllowedTypes.length > 1) this.identifier__ = rhs.identifier__;
static foreach (int i, T; AllowedTypes)
static if (!is(T == typeof(null)) && !is(T == void))
{
- if (_identifier_ == i)
+ if (identifier__ == i)
{
- _storage_ = () const {
- mixin(`const _Storage_ ret = { _member_` ~ i.stringof ~ ` : rhs.trustedGet!T };`);
+ storage__ = () const {
+ mixin(`const Storage__ ret = { _member_` ~ i.stringof ~ ` : rhs.trustedGet!T };`);
return ret;
} ();
return;
@@ -1179,55 +1286,189 @@ struct Algebraic(_Types...)
/++
+/
- size_t toHash() @trusted nothrow const
+ static if (typeFieldNames__.length)
+ size_t toHash() scope @trusted const pure nothrow @nogc
{
+ size_t hash;
+
+
static if (AllowedTypes.length == 0 || is(AllowedTypes == AliasSeq!(typeof(null))))
{
- return 0;
}
- else
- switch (_identifier_)
+ else{S:
+ switch (identifier__)
{
+ import std.traits: isArray;
static foreach (i, T; AllowedTypes)
{
- case i:
+ case i: {
static if (is(T == void))
- return i;
+ hash = i;
else
static if (is(T == typeof(null)))
- return i;
+ hash = i;
+ else
+ static if (typeFieldNames__.length) // force for tagged types
+ {
+ static if (__traits(hasMember, T, "toHash"))
+ hash = trustedGet!T.toHash;
+ else
+ static if (isArray!T)
+ foreach (ref e; trustedGet!T)
+ static if (__traits(hasMember, typeof(e), "toHash"))
+ hash = hashOf(e.toHash, hash);
+ else
+ hash = hashOf(e, hash);
+ else
+ hash = hashOf(trustedGet!T);
+ }
else
- static if (__traits(compiles, hashOf(trustedGet!T, cast(size_t)i)))
- return hashOf(trustedGet!T, cast(size_t)i);
+ static if (__traits(compiles, hashOf(trustedGet!T.hashOf, i ^ hash)))
+ hash = hashOf(trustedGet!T.hashOf, i ^ hash);
else
{
- debug pragma(msg, "Mir warning: can't compute hash of " ~ (const T).stringof);
- return i;
+ debug pragma(msg, "Mir warning: couldn't compute hash. Expected a `size_t toHash() scope @safe const pure nothrow @nogc` method for " ~ T.stringof);
+ hash = i;
}
+ break S;
+ }
}
default: assert(0);
+ }}
+
+ static foreach (i, T; MetaInfo__)
+ static if (!T.transparent)
+ {
+ static if (is(MetaFieldsTypes[i] == class) || is(MetaFieldsTypes[i] == interface))
+ {{
+ scope eqfun = delegate() {
+ hash = hashOf(__traits(getMember, this, T.tag), hash);
+ };
+ trustedAllAttr(eqfun)();
+ }}
+ else
+ hash = hashOf(__traits(getMember, this, T.tag), hash);
}
+ return hash;
}
+ else
+ size_t toHash() const scope @trusted nothrow
+ {
+ size_t hash;
- /++
- +/
- bool opEquals()(auto ref const typeof(this) rhs) const @trusted
+
+ static if (AllowedTypes.length == 0 || is(AllowedTypes == AliasSeq!(typeof(null))))
+ {
+ }
+ else{S:
+ switch (identifier__)
+ {
+ import std.traits: isArray;
+ static foreach (i, T; AllowedTypes)
+ {
+ case i: {
+ static if (is(T == void))
+ hash = i;
+ else
+ static if (is(T == typeof(null)))
+ hash = i;
+ else
+ static if (typeFieldNames__.length) // force for tagged types
+ {
+ static if (__traits(hasMember, T, "toHash"))
+ hash = trustedGet!T.toHash;
+ else
+ static if (isArray!T)
+ foreach (ref e; trustedGet!T)
+ static if (__traits(hasMember, typeof(e), "toHash"))
+ hash = hashOf(e.toHash, hash);
+ else
+ hash = hashOf(e, hash);
+ else
+ hash = hashOf(trustedGet!T);
+ }
+ else
+ static if (__traits(compiles, hashOf(trustedGet!T.hashOf, i ^ hash)))
+ hash = hashOf(trustedGet!T.hashOf, i ^ hash);
+ else
+ {
+ debug pragma(msg, "Mir warning: can't compute hash. Expexted `size_t toHash() scope @safe const pure nothrow @nogc` method for " ~ T.stringof);
+ hash = i;
+ }
+ break S;
+ }
+ }
+ default: assert(0);
+ }}
+
+ static foreach (i, T; MetaInfo__)
+ static if (!T.transparent)
+ {
+ static if (is(MetaFieldsTypes[i] == class) || is(MetaFieldsTypes[i] == interface))
+ {{
+ scope eqfun = delegate() {
+ hash = hashOf(__traits(getMember, this, T.tag), hash);
+ };
+ trustedAllAttr(eqfun)();
+ }}
+ else
+ hash = hashOf(__traits(getMember, this, T.tag), hash);
+ }
+ return hash;
+ }
+
+
+ ///
+ bool opEquals()(scope const Algebraic rhs) scope @trusted const pure nothrow @nogc
+ {
+ return opEquals(rhs);
+ }
+
+ /// ditto
+ bool opEquals()(scope ref const Algebraic rhs) scope @trusted const pure nothrow @nogc
{
+ static foreach (i, T; MetaInfo__)
+ static if (!T.transparent)
+ {
+ static if (is(MetaFieldsTypes[i] == class) || is(MetaFieldsTypes[i] == interface))
+ {{
+ scope eqfun = delegate() {
+ return __traits(getMember, this, T.tag) != __traits(getMember, rhs, T.tag);
+ };
+ if (trustedAllAttr(eqfun)())
+ return false;
+ }}
+ else
+ if (__traits(getMember, this, T.tag) != __traits(getMember, rhs, T.tag))
+ return false;
+ }
+
static if (AllowedTypes.length == 0)
{
return true;
}
else
{
- if (this._identifier_ != rhs._identifier_)
+ if (this.identifier__ != rhs.identifier__)
return false;
- switch (_identifier_)
+ switch (identifier__)
{
static foreach (i, T; AllowedTypes)
{
case i:
static if (is(T == void))
return rhs._is!void;
+ else
+ static if (is(T == class) || is(T == interface))
+ {{
+ scope eqfun = delegate() {
+ return this.trustedGet!T == rhs.trustedGet!T;
+ };
+ return trustedAllAttr(eqfun)();
+ }}
+ else
+ static if (__traits(isFloating, T))
+ return this.trustedGet!T == rhs.trustedGet!T || (this.trustedGet!T != this.trustedGet!T && rhs.trustedGet!T != rhs.trustedGet!T);
else
return this.trustedGet!T == rhs.trustedGet!T;
}
@@ -1238,42 +1479,130 @@ struct Algebraic(_Types...)
/++
+/
- static if (is(AllowedTypes == _Types))
- auto opCmp()(auto ref const typeof(this) rhs) const @trusted
+ static if (!anySatisfy!(templateOr!(isAssociativeArray, templateAnd!(isAggregateType, templateNot!hasOpCmp)), staticMap!(basicElementType, AllowedTypes)))
+ {
+ static if (typeFieldNames__.length)
+ int opCmp()(auto ref scope const typeof(this) rhs) scope @trusted const pure nothrow @nogc
{
+ static foreach (i, T; MetaInfo__)
+ static if (!T.transparent)
+ {
+ static if (__traits(compiles, __cmp(__traits(getMember, this, T.tag), __traits(getMember, rhs, T.tag))))
+ {
+ if (auto d = __cmp(__traits(getMember, this, T.tag), __traits(getMember, rhs, T.tag)))
+ return d;
+ }
+ else
+ static if (__traits(hasMember, __traits(getMember, this, T.tag), "opCmp") && !is(MetaFieldsTypes[i] == U*, U))
+ {
+ if (auto d = __traits(getMember, this, T.tag).opCmp(__traits(getMember, rhs, T.tag)))
+ return d;
+ }
+ else
+ {
+ if (auto d = __traits(getMember, this, T.tag) < __traits(getMember, rhs, T.tag) ? -1 : __traits(getMember, this, T.tag) > __traits(getMember, rhs, T.tag) ? +1 : 0)
+ return d;
+ }
+ }
+
+
static if (AllowedTypes.length == 0)
{
return 0;
}
else
{
- import mir.internal.utility: isFloatingPoint;
- if (auto d = int(this._identifier_) - int(rhs._identifier_))
+ import std.traits: isArray;
+ if (auto d = int(this.identifier__) - int(rhs.identifier__))
return d;
- switch (_identifier_)
+ import std.traits: isArray, isPointer;
+ switch (identifier__)
{
static foreach (i, T; AllowedTypes)
{
case i:
- static if (__traits(compiles, __cmp(trustedGet!T, rhs.trustedGet!T)))
- return __cmp(trustedGet!T, rhs.trustedGet!T);
+ static if (__traits(hasMember, T, "opCmp") && !isPointer!T)
+ {{
+ auto ret = this.trustedGet!T.opCmp(rhs.trustedGet!T);
+ static if (is(typeof(ret) == int))
+ return ret;
+ else
+ return ret < 0 ? -1 : ret > 0 ? 1 : 0;
+ }}
+ else
+ static if (!isArray!T)
+ return this.trustedGet!T < rhs.trustedGet!T ? -1 :
+ this.trustedGet!T > rhs.trustedGet!T ? +1 : 0;
else
- static if (__traits(hasMember, T, "opCmp") && !is(T == U*, U))
- return this.trustedGet!T.opCmp(rhs.trustedGet!T);
+ return __cmp(trustedGet!T, rhs.trustedGet!T);
+ }
+ default: assert(0);
+ }
+ }
+ }
+ else
+ int opCmp()(auto ref scope const typeof(this) rhs) scope @trusted const //pure nothrow @nogc
+ {
+ static foreach (i, T; MetaInfo__)
+ static if (!T.transparent)
+ {
+ static if (__traits(compiles, __cmp(__traits(getMember, this, T.tag), __traits(getMember, rhs, T.tag))))
+ {
+ if (auto d = __cmp(__traits(getMember, this, T.tag), __traits(getMember, rhs, T.tag)))
+ return d;
+ }
+ else
+ static if (__traits(hasMember, __traits(getMember, this, T.tag), "opCmp") && !is(MetaFieldsTypes[i] == U*, U))
+ {
+ if (auto d = __traits(getMember, this, T.tag).opCmp(__traits(getMember, rhs, T.tag)))
+ return d;
+ }
+ else
+ {
+ if (auto d = __traits(getMember, this, T.tag) < __traits(getMember, rhs, T.tag) ? -1 : __traits(getMember, this, T.tag) > __traits(getMember, rhs, T.tag) ? +1 : 0)
+ return d;
+ }
+ }
+
+
+ static if (AllowedTypes.length == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ import std.traits: isArray;
+ if (auto d = int(this.identifier__) - int(rhs.identifier__))
+ return d;
+ import std.traits: isArray, isPointer;
+ switch (identifier__)
+ {
+ static foreach (i, T; AllowedTypes)
+ {
+ case i:
+ static if (__traits(hasMember, T, "opCmp") && !isPointer!T)
+ {{
+ auto ret = this.trustedGet!T.opCmp(rhs.trustedGet!T);
+ static if (is(typeof(ret) == int))
+ return ret;
+ else
+ return ret < 0 ? -1 : ret > 0 ? 1 : 0;
+ }}
else
- // static if (isFloatingPoint!T)
- // return trustedGet!T == rhs ? 0 : trustedGet!T - rhs.trustedGet!T;
- // else
+ static if (!isArray!T)
return this.trustedGet!T < rhs.trustedGet!T ? -1 :
this.trustedGet!T > rhs.trustedGet!T ? +1 : 0;
+ else
+ return __cmp(trustedGet!T, rhs.trustedGet!T);
}
default: assert(0);
}
}
}
+ }
/// Requires mir-algorithm package
- string toString()() const
+ immutable(char)[] toString()() @trusted scope const
{
static if (AllowedTypes.length == 0)
{
@@ -1282,22 +1611,34 @@ struct Algebraic(_Types...)
else
{
import mir.conv: to;
- switch (_identifier_)
+ immutable(char)[] ret;
+ static foreach (i, member; metaFieldNames__)
+ static if (!MetaInfo__[i].transparent)
+ {
+ static if (__traits(compiles, { auto s = to!(immutable(char)[])(__traits(getMember, this, member));}))
+ // should be passed by value to workaround compiler bug
+ ret ~= to!(immutable(char)[])(__traits(getMember, this, member));
+ else
+ ret ~= AllowedTypes[i].stringof;
+ ret ~= "::";
+ }
+ switch (identifier__)
{
static foreach (i, T; AllowedTypes)
{
case i:
static if (is(T == void))
- return "void";
+ ret ~= "void";
else
static if (is(T == typeof(null)))
- return "null";
+ ret ~= "null";
else
- static if (__traits(compiles, { auto s = to!string(trustedGet!T);}))
+ static if (__traits(compiles, { auto s = to!(immutable(char)[])(trustedGet!T);}))
// should be passed by value to workaround compiler bug
- return to!string((()=>trustedGet!T)());
+ ret ~= to!(immutable(char)[])(trustedGet!T);
else
- return AllowedTypes[i].stringof;
+ ret ~= AllowedTypes[i].stringof;
+ return ret;
}
default: assert(0);
}
@@ -1305,27 +1646,40 @@ struct Algebraic(_Types...)
}
///ditto
- void toString(W)(scope ref W w) const
+ void toString(W)(ref scope W w) scope const @trusted pure
+ if (__traits(compiles, ()pure{ w.put("Algebraic"); }))
{
+ if (false)
+ return w.put("Algebraic");
static if (AllowedTypes.length == 0)
{
return w.put("Algebraic");
}
else
{
- switch (_identifier_)
+ import mir.format: print;
+ static foreach (i, member; metaFieldNames__)
+ static if (!MetaInfo__[i].transparent)
+ {
+ static if (__traits(compiles, { import mir.format: print; print(w, __traits(getMember, this, member)); }))
+ { import mir.format: print; print(w, __traits(getMember, this, member)); }
+ else
+ w.put(AllowedTypes[i].stringof);
+ w.put("::");
+ }
+ switch (identifier__)
{
static foreach (i, T; AllowedTypes)
{
case i:
static if (is(T == void))
- return w.put("void");
+ w.put("void");
else
static if (is(T == typeof(null)))
- return w.put("null");
+ w.put("null");
else
static if (__traits(compiles, { import mir.format: print; print(w, trustedGet!T); }))
- { import mir.format: print; print(w, trustedGet!T); }
+ toStringImpl!T(w);
else
w.put(AllowedTypes[i].stringof);
return;
@@ -1335,13 +1689,55 @@ struct Algebraic(_Types...)
}
}
+ ///ditto
+ void toString(W)(ref scope W w) scope const @trusted
+ if (!__traits(compiles, ()pure{ w.put("Algebraic"); }))
+ {
+ if (false)
+ return w.put("Algebraic");
+ static if (AllowedTypes.length == 0)
+ {
+ return w.put("Algebraic");
+ }
+ else
+ {
+ switch (identifier__)
+ {
+ static foreach (i, T; AllowedTypes)
+ {
+ case i:
+ static if (is(T == void))
+ return w.put("void");
+ else
+ static if (is(T == typeof(null)))
+ return w.put("null");
+ else
+ static if (__traits(compiles, { import mir.format: print; print(w, trustedGet!T); }))
+ return toStringImpl!T(w);
+ else
+ return w.put(AllowedTypes[i].stringof);
+ }
+ default: assert(0);
+ }
+ }
+ }
+
+ private void toStringImpl(T, W)(ref scope W w) @safe scope const pure nothrow @nogc
+ {
+ import mir.format: print;
+ scope pfun = delegate() {
+ print(w, trustedGet!T);
+ };
+ trustedAllAttr(pfun)();
+ }
+
static if (is(AllowedTypes[0] == typeof(null)))
{
///
bool opCast(C)() const
if (is(C == bool))
{
- return _identifier_ != 0;
+ return identifier__ != 0;
}
///
@@ -1352,24 +1748,23 @@ struct Algebraic(_Types...)
}
/// Defined if the first type is `typeof(null)`
- bool isNull() const @property { return _identifier_ == 0; }
+ bool isNull() const @property { return identifier__ == 0; }
/// ditto
void nullify() { this = null; }
/// ditto
auto get()()
- if (allSatisfy!(isCopyable, AllowedTypes[1 .. $]) && AllowedTypes.length != 2)
+ if (allSatisfy!(isCopyable, AllowedTypes[1 .. $]) && AllowedTypes.length != 2 && is(AllowedTypes[0] == typeof(null)))
{
import mir.utility: _expect;
- if (_expect(!_identifier_, false))
+ if (_expect(!identifier__, false))
{
throw variantNullException;
}
static if (AllowedTypes.length != 2)
{
- Algebraic!(_Types[1 .. $]) ret;
-
- S: switch (_identifier_)
+ Algebraic!(AllowedTypes[1 .. $]) ret;
+ S: switch (identifier__)
{
static foreach (i, T; AllowedTypes[1 .. $])
{
@@ -1377,14 +1772,17 @@ struct Algebraic(_Types...)
case i + 1:
if (!hasElaborateCopyConstructor!T && !__ctfe)
goto default;
- ret = this.trustedGet!T;
+ static if (is(T == void))
+ ret = ret._void;
+ else
+ ret = this.trustedGet!T;
break S;
}
}
default:
- ret._storage_.bytes = this._storage_.bytes;
+ ret.storage__.bytes = this.storage__.bytes;
static if (ret.AllowedTypes.length > 1)
- ret._identifier_ = cast(typeof(ret._identifier_))(this._identifier_ - 1);
+ ret.identifier__ = cast(typeof(ret.identifier__))(this.identifier__ - 1);
}
return ret;
}
@@ -1396,24 +1794,24 @@ struct Algebraic(_Types...)
Gets the value if not null. If `this` is in the null state, and the optional
parameter `fallback` was provided, it will be returned. Without `fallback`,
calling `get` with a null state is invalid.
-
+
When the fallback type is different from the Nullable type, `get(T)` returns
the common type.
-
+
Params:
fallback = the value to return in case the `Nullable` is null.
-
+
Returns:
The value held internally by this `Nullable`.
+/
auto ref inout(AllowedTypes[1]) get() return inout
{
- assert(_identifier_, "Called `get' on null Nullable!(" ~ AllowedTypes[1].stringof ~ ").");
+ assert(identifier__, "Called `get' on null Nullable!(" ~ AllowedTypes[1].stringof ~ ").");
return trustedGet!(AllowedTypes[1]);
}
version(mir_core_test)
- static if (_variant_test_)
+ static if (variant_test__)
///
@safe pure nothrow @nogc
unittest
@@ -1444,7 +1842,7 @@ struct Algebraic(_Types...)
bool _is(R : Algebraic!RetTypes, RetTypes...)() @safe pure nothrow @nogc const @property
if (allSatisfy!(Contains!AllowedTypes, Algebraic!RetTypes.AllowedTypes))
{
- static if (is(RetTypes == _Types))
+ static if (is(RetTypes == Types__))
return true;
else
{
@@ -1453,7 +1851,7 @@ struct Algebraic(_Types...)
alias RhsAllowedTypes = Algebraic!RetTypes.AllowedTypes;
alias Ret = CopyTypeQualifiers!(This, Algebraic!RetTypes);
// uint rhsTypeId;
- switch (_identifier_)
+ switch (identifier__)
{
foreach (i, T; AllowedTypes)
static if (staticIndexOf!(T, RhsAllowedTypes) >= 0)
@@ -1480,7 +1878,7 @@ struct Algebraic(_Types...)
auto ref trustedGet(R : Algebraic!RetTypes, this This, RetTypes...)() return @property
if (allSatisfy!(Contains!AllowedTypes, Algebraic!RetTypes.AllowedTypes))
{
- static if (is(RetTypes == _Types))
+ static if (is(RetTypes == Types__))
return this;
else
{
@@ -1489,7 +1887,7 @@ struct Algebraic(_Types...)
alias RhsAllowedTypes = Algebraic!RetTypes.AllowedTypes;
alias Ret = CopyTypeQualifiers!(This, Algebraic!RetTypes);
// uint rhsTypeId;
- switch (_identifier_)
+ switch (identifier__)
{
foreach (i, T; AllowedTypes)
static if (staticIndexOf!(T, RhsAllowedTypes) >= 0)
@@ -1518,7 +1916,7 @@ struct Algebraic(_Types...)
}
version(mir_core_test)
- static if (_variant_test_)
+ static if (variant_test__)
///
@safe pure nothrow @nogc
unittest
@@ -1541,12 +1939,12 @@ struct Algebraic(_Types...)
assert(integer == 12L);
}
- static if (anySatisfy!(isTaggedType, _Types))
+ static if (typeFieldNames__.length)
{
/// `trustedGet` overload that accept $(LREF .Algebraic.Kind).
alias trustedGet(Kind kind) = trustedGet!(AllowedTypes[kind]);
/// ditto
- alias trustedGet(string kind) = trustedGet!(__traits(getMember, Kind, kind));
+ alias trustedGet(immutable(char)[] kind) = trustedGet!(__traits(getMember, Kind, kind));
}
/++
@@ -1557,7 +1955,7 @@ struct Algebraic(_Types...)
auto ref get(R : Algebraic!RetTypes, this This, RetTypes...)() return @property
if (allSatisfy!(Contains!AllowedTypes, Algebraic!RetTypes.AllowedTypes))
{
- static if (is(RetTypes == _Types))
+ static if (is(RetTypes == Types__))
return this;
else
{
@@ -1566,7 +1964,7 @@ struct Algebraic(_Types...)
alias RhsAllowedTypes = Algebraic!RetTypes.AllowedTypes;
alias Ret = CopyTypeQualifiers!(This, Algebraic!RetTypes);
// uint rhsTypeId;
- switch (_identifier_)
+ switch (identifier__)
{
foreach (i, T; AllowedTypes)
static if (staticIndexOf!(T, RhsAllowedTypes) >= 0)
@@ -1595,7 +1993,7 @@ struct Algebraic(_Types...)
}
version(mir_core_test)
- static if (_variant_test_)
+ static if (variant_test__)
///
@safe pure @nogc
unittest
@@ -1616,12 +2014,20 @@ struct Algebraic(_Types...)
assert(integer == 12L);
}
- static if (anySatisfy!(isTaggedType, _Types))
+ static if (typeFieldNames__.length)
{
/// `get` overload that accept $(LREF .Algebraic.Kind).
alias get(Kind kind) = get!(AllowedTypes[kind]);
/// ditto
- alias get(string kind) = get!(__traits(getMember, Kind, kind));
+ alias get(immutable(char)[] kind) = get!(__traits(getMember, Kind, kind));
+
+ /// `_is` overload that accept $(LREF .Algebraic.Kind).
+ alias _is(Kind kind) = _is!(AllowedTypes[kind]);
+ /// ditto
+ alias _is(immutable(char)[] kind) = _is!(__traits(getMember, Kind, kind));
+
+ static foreach (member; typeFieldNames__)
+ mixin ("alias " ~ member ~ `() = get!"` ~ member ~ `";`);
}
private alias _ReflectionTypes = AllowedTypes[is(AllowedTypes[0] == typeof(null)) .. $];
@@ -1654,30 +2060,10 @@ struct Algebraic(_Types...)
{
static foreach (member; AllMembersRec!(_ReflectionTypes[0]))
static if (
- member != "_ID_" &&
- member != "_identifier_" &&
- member != "_is" &&
- member != "_storage_" &&
- member != "_Storage_" &&
- member != "_variant_test_" &&
- member != "_void" &&
- member != "AllowedTypes" &&
- member != "get" &&
- member != "isNull" &&
- member != "kind" &&
- member != "Kind" &&
- member != "nullify" &&
- member != "opAssign" &&
- member != "opCast" &&
- member != "opCmp" &&
- member != "opEquals" &&
- member != "opPostMove" &&
- member != "toHash" &&
- member != "toString" &&
- member != "trustedGet" &&
- member != "deserializeFromAsdf" &&
- member != "deserializeFromIon" &&
- !(member.length >= 2 && member[0 .. 2] == "__"))
+ !.algebraicMembers.contains(member) &&
+ !metaFieldNames__.contains(member) &&
+ !typeFieldNames__.contains(member) &&
+ !(member.length >= 2 && (member[0 .. 2] == "__" || member[$ - 2 .. $] == "__")))
static if (allSatisfy!(ApplyRight!(hasMember, member), _ReflectionTypes))
static if (!anySatisfy!(ApplyRight!(isMemberType, member), _ReflectionTypes))
static if (allSatisfy!(ApplyRight!(isSingleMember, member), _ReflectionTypes))
@@ -1701,29 +2087,30 @@ struct Algebraic(_Types...)
///
ref opAssign(RhsTypes...)(Algebraic!RhsTypes rhs) return @trusted
- if (RhsTypes.length < AllowedTypes.length && allSatisfy!(Contains!AllowedTypes, Algebraic!RhsTypes.AllowedTypes))
+ if (allSatisfy!(Contains!AllowedTypes, Algebraic!RhsTypes.AllowedTypes) && !is(Algebraic == Algebraic!RhsTypes))
{
import core.lifetime: forward;
- static if (anySatisfy!(hasElaborateDestructor, AllowedTypes))
- this.__dtor();
+ this = this.init;
__ctor(forward!rhs);
return this;
}
+ // pragma(msg, AllowedTypes);
+
static foreach (int i, T; AllowedTypes)
{
/// Zero cost always nothrow `get` alternative
auto ref trustedGet(E)() @trusted @property return inout nothrow
if (is(E == T))
{
- assert (i == _identifier_);
+ assert (i == identifier__);
static if (is(T == typeof(null)))
return null;
else
static if (is(T == void))
return;
else
- return _storage_.payload[i];
+ return storage__.payload[i];
}
/++
@@ -1735,7 +2122,7 @@ struct Algebraic(_Types...)
import mir.utility: _expect;
static if (AllowedTypes.length > 1)
{
- if (_expect(i != _identifier_, false))
+ if (_expect(i != identifier__, false))
{
throw variantException;
}
@@ -1749,7 +2136,7 @@ struct Algebraic(_Types...)
bool _is(E)() const @property nothrow @nogc
if (is(E == T))
{
- return _identifier_ == i;
+ return identifier__ == i;
}
static if (is(T == void))
@@ -1758,12 +2145,12 @@ struct Algebraic(_Types...)
static Algebraic _void()
{
Algebraic ret;
- ret._storage_ = () {
+ ret.storage__ = () {
import core.lifetime: forward;
- mixin(`_Storage_ ret = { _member_` ~ i.stringof ~ ` : _Void!().init };`);
+ mixin(`Storage__ ret = { _member_` ~ i.stringof ~ ` : _Void!().init };`);
return ret;
} ();
- ret._identifier_ = i;
+ ret.identifier__ = i;
return ret;
}
}
@@ -1781,20 +2168,20 @@ struct Algebraic(_Types...)
static if (__VERSION__ < 2094 && anySatisfy!(hasElaborateCopyConstructor, AllowedTypes))
{
- _storage_.bytes = () @trusted {
+ storage__.bytes = () @trusted {
auto ret = _StorageI!i(rhs);
return ret.bytes;
} ();
}
else
{
- _storage_ = () {
- mixin(`_Storage_ ret = { _member_` ~ i.stringof ~ ` : rhs };`);
+ storage__ = () {
+ mixin(`Storage__ ret = { _member_` ~ i.stringof ~ ` : rhs };`);
return ret;
} ();
}
static if (_Payload.length > 1)
- _identifier_ = i;
+ identifier__ = i;
}
/// ditto
@@ -1807,20 +2194,20 @@ struct Algebraic(_Types...)
alias rhs = value;
static if (__VERSION__ < 2094 && anySatisfy!(hasElaborateCopyConstructor, AllowedTypes))
{
- _storage_.bytes = () const @trusted {
+ storage__.bytes = () const @trusted {
auto ret = const _StorageI!i(rhs);
return ret.bytes;
} ();
}
else
{
- _storage_ = () {
- mixin(`const _Storage_ ret = { _member_` ~ i.stringof ~ ` : rhs };`);
+ storage__ = () {
+ mixin(`const Storage__ ret = { _member_` ~ i.stringof ~ ` : rhs };`);
return ret;
} ();
}
static if (_Payload.length > 1)
- _identifier_ = i;
+ identifier__ = i;
}
/// ditto
@@ -1833,50 +2220,57 @@ struct Algebraic(_Types...)
alias rhs = value;
static if (__VERSION__ < 2094 && anySatisfy!(hasElaborateCopyConstructor, AllowedTypes))
{
- _storage_.bytes = () const @trusted {
+ storage__.bytes = () const @trusted {
auto ret = immutable _StorageI!i(rhs);
return ret.bytes;
} ();
}
else
{
- _storage_ = () {
- mixin(`immutable _Storage_ ret = { _member_` ~ i.stringof ~ ` : rhs };`);
+ storage__ = () {
+ mixin(`immutable Storage__ ret = { _member_` ~ i.stringof ~ ` : rhs };`);
return ret;
} ();
}
static if (_Payload.length > 1)
- _identifier_ = i;
+ identifier__ = i;
}
static if (__traits(compiles, (ref T a, ref T b) { moveEmplace(a, b); }))
///
ref opAssign(T rhs) return @trusted
{
+ static foreach (T; MetaInfo__)
+ __traits(getMember, this, T.tag) = T.Type.init;
+
import core.lifetime: forward;
- static if (anySatisfy!(hasElaborateDestructor, AllowedTypes))
- this.__dtor();
+ this = this.init;
__ctor(forward!rhs);
return this;
}
/++
+/
- auto opEquals()(auto ref const T rhs) const
+ bool opEquals()(scope ref const UnqualRec!T rhs) scope @trusted const //pure nothrow @nogc
{
static if (AllowedTypes.length > 1)
- if (_identifier_ != i)
+ if (identifier__ != i)
return false;
return trustedGet!T == rhs;
- }
+ }
+
+ ///ditto
+ bool opEquals()(scope const UnqualRec!T rhs) scope @trusted const //pure nothrow @nogc
+ {
+ return opEquals(rhs);
+ }
/++
+/
- auto opCmp()(auto ref const T rhs) const
+ auto opCmp()(auto ref scope const UnqualRec!T rhs) scope @trusted const pure nothrow @nogc
{
- import mir.internal.utility: isFloatingPoint;
static if (AllowedTypes.length > 1)
- if (auto d = int(_identifier_) - int(i))
+ if (auto d = int(identifier__) - int(i))
return d;
static if (__traits(compiles, __cmp(trustedGet!T, rhs)))
return __cmp(trustedGet!T, rhs);
@@ -1884,11 +2278,7 @@ struct Algebraic(_Types...)
static if (__traits(hasMember, T, "opCmp") && !is(T == U*, U))
return trustedGet!T.opCmp(rhs);
else
- static if (isFloatingPoint!T)
- return trustedGet!T == rhs ? 0 : trustedGet!T - rhs;
- else
- return trustedGet!T < rhs ? -1 :
- trustedGet!T > rhs ? +1 : 0;
+ return trustedGet!T < rhs ? -1 : trustedGet!T > rhs ? +1 : 0;
}
static if (is(Unqual!T == bool))
@@ -1919,7 +2309,7 @@ struct Algebraic(_Types...)
auto opEquals()(int rhs) const
{
return opEquals(long(rhs));
- }
+ }
auto opCmp()(int rhs) const
{
@@ -1952,7 +2342,7 @@ struct Algebraic(_Types...)
auto opEquals()(uint rhs) const
{
return opEquals(ulong(rhs));
- }
+ }
auto opCmp()(uint rhs) const
{
@@ -1963,7 +2353,7 @@ struct Algebraic(_Types...)
}
}
- static if (anySatisfy!(isErr, _Types))
+ static if (anySatisfy!(isErr, AllowedTypes))
{
/++
Determines if the variant holds value of some none-$(LREF isVariant) type.
@@ -1971,7 +2361,7 @@ struct Algebraic(_Types...)
+/
bool isOk() @safe pure nothrow @nogc const @property
{
- switch (_identifier_)
+ switch (identifier__)
{
static foreach (i, T; AllowedTypes)
{
@@ -1995,9 +2385,9 @@ unittest
double d;
}
- static class C
+ static class Cc
{
- // alias this members are supported
+ // alias this members are supported
Base base;
alias base this;
@@ -2006,6 +2396,8 @@ unittest
@safe pure nothrow @nogc:
+ override size_t toHash() scope const { return hashOf(_b) ^ a; }
+
string b() const @property { return _b; }
void b(string b) @property { _b = b; }
@@ -2027,17 +2419,17 @@ unittest
double retArg(double v) { return v; }
double retArgT(TArgs...)(int v) { return v * TArgs.length; }
- // alias this members are supported
+ // alias this members are supported
Base base;
alias base this;
}
static void inc(ref int a) { a++; }
- alias V = Nullable!(C, S); // or Variant!
+ alias V = Nullable!(Cc, S); // or Variant!
auto v = V(2, "str");
- assert(v._is!C);
+ assert(v._is!Cc);
assert(v.a == 2);
assert(v.b == "str");
// members are returned by reference if possible
@@ -2045,7 +2437,7 @@ unittest
assert(v.a == 3);
v.b = "s";
assert(v.b == "s");
- // alias this members are supported
+ // alias this members are supported
v.d = 10;
assert(v.d == 10);
// method call support
@@ -2065,13 +2457,12 @@ unittest
assert(v.a == 6);
v.b = "s";
assert(v.b == "s");
- // alias this members are supported
+ // alias this members are supported
v.d = 15;
assert(v.d == 15);
// method call support
assert(v.retArg(300)._is!double);
assert(v.retArg(300) == 300.0);
-
}
// test CTFE
@@ -2131,11 +2522,11 @@ version(mir_core_test) unittest
static if (hasToHash)
- size_t toHash() { return hashOf(_payload); }
+ size_t toHash() scope { return hashOf(_payload); }
static if (hasOpEquals)
- auto opEquals(ref const typeof(this) rhs) @trusted { return memcmp(_payload.ptr, rhs._payload.ptr, _payload.length); }
- auto opCmp(ref const typeof(this) rhs) { return _payload == rhs._payload; }
+ auto opEquals(ref const scope typeof(this) rhs) scope { return _payload == rhs._payload; }
+ auto opCmp(ref const scope typeof(this) rhs) @trusted scope { return memcmp(_payload.ptr, rhs._payload.ptr, _payload.length); }
}
static foreach (size1; [1, 2, 4, 8, 10, 16, 20])
@@ -2313,14 +2704,14 @@ version(mir_core_test) unittest
this(this) @safe pure nothrow @nogc {}
// void opAssign(typeof(this) rhs) {}
}
- static struct C { const(uint)* value; }
+ static struct C1 { const(uint)* value; }
S s;
S r = s;
r = s;
r = S.init;
- alias V = Variant!(S, C);
+ alias V = Variant!(S, C1);
V v = S();
V w = v;
w = S();
@@ -2388,7 +2779,7 @@ version(mir_core_test) unittest
assert(array[2] == 100);
array.length = 4;
assert(array == [0L, 0, 100, 0]);
- array = array[2 .. 3];
+ array = array[2 .. 3];
assert(array.length == 1);
assert(array[0] == 100);
array[0] = 10.Variant!(long, double);
@@ -2421,20 +2812,20 @@ $(LREF Algerbraic)`.toString` requries `mir-algorithm` package
V variant;
assert(secondOrderVisitorHandler(visitorHandler(variant)) == "NULL");
- assert(variant.to!string == "null");
+ assert(variant.toString == "null");
variant = V._void;
assert(variant._is!void);
assert(is(typeof(variant.get!void()) == void));
assert(secondOrderVisitorHandler(visitorHandler(variant)) == "VOID");
- assert(variant.to!string == "void");
+ assert(variant.toString == "void");
variant = 5;
assert(secondOrderVisitorHandler(visitorHandler(variant)) == "SO VOID");
assert(variant == 6);
- assert(variant.to!string == (MIR_ALGORITHM ? "6" : "int"));
+ assert(variant.toString == (MIR_ALGORITHM ? "6" : "int"));
}
version(mir_core_test)
@@ -2585,7 +2976,7 @@ unittest
alias collideWith = tryMatch!(
(Asteroid x, Asteroid y) => "a/a",
- // No visitor for A/S pair
+ // No visitor for A/S pair
// (Asteroid x, Spaceship y) => "a/s",
(Spaceship x, Asteroid y) => "s/a",
(Spaceship x, Spaceship y) => "s/s",
@@ -2661,7 +3052,7 @@ unittest
alias collideWith = optionalMatch!(
(Asteroid x, Asteroid y) => "a/a",
- // No visitor for A/S pair
+ // No visitor for A/S pair
// (Asteroid x, Spaceship y) => "a/s",
(Spaceship x, Asteroid y) => "s/a",
(Spaceship x, Spaceship y) => "s/s",
@@ -2704,7 +3095,7 @@ unittest
assert(collide(os, es) == "big-boom");
assert(collide(os, os) == "big-boom");
- // check types
+ // check types
static assert(!__traits(compiles, collide(Asteroid.init, Spaceship.init)));
static assert(is(typeof(collideWith(Asteroid.init, Spaceship.init)) == Nullable!()));
@@ -2737,7 +3128,7 @@ unittest
alias collideWith = autoMatch!(
(Asteroid x, Asteroid y) => "a/a",
- // No visitor for A/S pair
+ // No visitor for A/S pair
// (Asteroid x, Spaceship y) => "a/s",
(Spaceship x, Asteroid y) => "s/a",
(Spaceship x, Spaceship y) => "s/s",
@@ -2780,7 +3171,7 @@ unittest
assert(collide(os, es) == "big-boom");
assert(collide(os, os) == "big-boom");
- // check types
+ // check types
static assert(!__traits(compiles, collide(Asteroid.init, Spaceship.init)));
static assert(is(typeof(collideWith(Asteroid.init, Spaceship.init)) == Nullable!()));
@@ -2807,12 +3198,12 @@ alias getMember(string member, TArgs...) = visitImpl!(getMemberHandler!(member,
version(mir_core_test) unittest
{
static struct S { auto bar(int a) { return a; } enum boolean = true; }
- static struct C { alias bar = (double a) => a * 2; enum boolean = false; }
+ static struct C2 { alias bar = (double a) => a * 2; enum boolean = false; }
- alias V = Variant!(S, C);
+ alias V = Variant!(S, C2);
V x = S();
- V y = C();
+ V y = C2();
static assert(is(typeof(x.getMember!"bar"(2)) == Variant!(int, double)));
assert(x.getMember!"bar"(2) == 2);
@@ -2844,17 +3235,17 @@ version(mir_core_test) unittest
Nullable!int m;
}
- static struct C
+ static struct C1
{
Variant!(float, double) m;
}
- alias V = Variant!(S, C);
+ alias V = Variant!(S, C1);
V x = S(2.nullable);
- V y = C(Variant!(float, double)(4.0));
+ V y = C1(Variant!(float, double)(4.0));
- // getMember returns an algebraic of algebaics
+ // getMember returns an algebraic of algebraics
static assert(is(typeof(x.getMember!"m") == Variant!(Variant!(float, double), Nullable!int)));
// matchMember returns a fused algebraic
static assert(is(typeof(x.matchMember!"m") == Nullable!(int, float, double)));
@@ -2874,12 +3265,12 @@ alias tryGetMember(string member) = visitImpl!(getMemberHandler!member, Exhausti
version(mir_core_test) unittest
{
static struct S { int bar(int a) { return a; }}
- static struct C { alias Bar = (double a) => a * 2; }
+ static struct C3 { alias Bar = (double a) => a * 2; }
- alias V = Variant!(S, C);
+ alias V = Variant!(S, C3);
V x = S();
- V y = C();
+ V y = C3();
static assert(is(typeof(x.tryGetMember!"bar"(2)) == int));
static assert(is(typeof(y.tryGetMember!"Bar"(2)) == double));
@@ -3146,7 +3537,7 @@ template visitImpl(alias visitor, Exhaustive exhaustive, bool fused, alias Filte
else
alias AllReturnTypes = NoDuplicates!(staticMap!(VariantReturnTypesImpl, Args[0].AllowedTypes));
- switch (args[0]._identifier_)
+ switch (args[0].identifier__)
{
static foreach (i, T; Args[0].AllowedTypes)
{
@@ -3194,7 +3585,7 @@ template visitImpl(alias visitor, Exhaustive exhaustive, bool fused, alias Filte
}
}
-private string enumKindText()(string[] strs)
+private string enumKindText()(scope const char[][] strs)
{
auto r = "enum Kind {";
foreach (s; strs)
@@ -3357,8 +3748,8 @@ version(mir_core_test)
alias V = Variant!(long, int, string, long[], int[]);
alias autoGetElementType = match!(
(string s) => "string", // we override the suit handler below for string
- suit!(isDynamicArray, a => Unqual!(typeof(a[0])).stringof),
- suit!(templateNot!isDynamicArray, a => Unqual!(typeof(a)).stringof),
+ suit!(isDynamicArray, a => Unqual!(typeof(a[0])).stringof),
+ suit!(templateNot!isDynamicArray, a => Unqual!(typeof(a)).stringof),
);
assert(autoGetElementType(V(string.init)) == "string");
assert(autoGetElementType(V((long[]).init)) == "long");
@@ -3529,11 +3920,6 @@ template isErr(T)
import std.traits: isAggregateType, hasUDA;
static if (is(T == enum) || isAggregateType!T)
{
- static if (isTaggedType!T)
- {
- enum isErr = .isErr!(getTaggedTypeUnderlying!T);
- }
- else
static if (is(immutable T == immutable Err!V, V))
{
enum isErr = true;
@@ -3629,9 +4015,9 @@ private template withNewLine(alias arg)
alias withNewLine = AliasSeq!("\n", arg);
}
-private noreturn throwMe(Args...)(auto ref Args args) {
- static if (Args.length == 1)
- enum simpleThrow = is(immutable Args[0] : immutable Throwable);
+private noreturn throwMe(T...)(auto ref T args) {
+ static if (T.length == 1)
+ enum simpleThrow = is(immutable T[0] : immutable Throwable);
else
enum simpleThrow = false;
static if (simpleThrow)
@@ -3644,7 +4030,7 @@ private noreturn throwMe(Args...)(auto ref Args args) {
static if (__traits(compiles, { import mir.format: print; }))
{
import std.meta: staticMap;
- throw new MirException("assumeOk failure:", staticMap!(withNewLine, args));
+ throw new MirException("assumeOk failure:", staticMap!(withNewLine, args));
}
else
{
@@ -3732,7 +4118,7 @@ unittest
version(mir_core_test)
unittest
{
- struct RequestToken
+ static struct RequestToken
{
Variant!(long, string) value;
alias value this;
@@ -3754,3 +4140,45 @@ unittest
static assert(is(typeof(r) == Variant!(long, string)));
}
+
+package auto trustedAllAttr(T)(scope T t) @trusted
+{
+ import std.traits;
+ enum attrs = (functionAttributes!T & ~FunctionAttribute.system)
+ | FunctionAttribute.pure_
+ | FunctionAttribute.safe
+ | FunctionAttribute.nogc
+ | FunctionAttribute.nothrow_;
+ return cast(SetFunctionAttributes!(T, functionLinkage!T, attrs)) t;
+}
+
+private static immutable algebraicMembers = [
+ "_is",
+ "_void",
+ "AllowedTypes",
+ "MetaFieldsTypes",
+ "get",
+ "isNull",
+ "kind",
+ "Kind",
+ "nullify",
+ "opAssign",
+ "opCast",
+ "opCmp",
+ "opEquals",
+ "opPostMove",
+ "toHash",
+ "toString",
+ "trustedGet",
+ "deserializeFromAsdf",
+ "deserializeFromIon",
+];
+
+private template UnqualRec(T)
+{
+ import std.traits: Unqual, isDynamicArray, ForeachType;
+ static if (isDynamicArray!T)
+ alias UnqualRec = UnqualRec!(ForeachType!T)[];
+ else
+ alias UnqualRec = Unqual!T;
+}
diff --git a/source/mir/complex/package.d b/source/mir/complex/package.d
index 94f8c1e..5861333 100644
--- a/source/mir/complex/package.d
+++ b/source/mir/complex/package.d
@@ -105,7 +105,7 @@ struct Complex(T)
return this;
}
-const:
+scope const:
///
bool opEquals(const Complex rhs)
@@ -120,8 +120,6 @@ const:
return hashOf(val) ;
}
-scope:
-
///
bool opEquals(R)(Complex!R rhs)
if (!is(R == T))
diff --git a/source/mir/conv.d b/source/mir/conv.d
index 34b4ee6..5d6b199 100644
--- a/source/mir/conv.d
+++ b/source/mir/conv.d
@@ -136,7 +136,7 @@ template to(T)
{
import mir.appender: UnsafeArrayBuffer;
alias C = Unqual!(ForeachType!T);
- C[64] array = '\0';
+ C[64] array = void;
auto buffer = UnsafeArrayBuffer!C(array);
}
else
diff --git a/source/mir/exception.d b/source/mir/exception.d
index 2cc52ec..c69cbf1 100644
--- a/source/mir/exception.d
+++ b/source/mir/exception.d
@@ -65,7 +65,20 @@ unittest
{
import mir.exception;
try throw new MirException("Hi D", 2, "!");
- catch(Exception e) assert(e.msg == "Hi D2!");
+ catch(MirException e) assert(e.scopeMessage == "Hi D2!");
+ }
+}
+
+/// Generic style, GC allocated MSG
+version (mir_test) static if (NOGCEXP && HASFORMAT)
+@safe pure nothrow @nogc
+unittest
+{
+ static if (__traits(compiles, (()@nogc {import mir.format;})()))
+ {
+ import mir.exception;
+ try throw new MirException("Hi D", 2, "!");
+ catch(Exception e) assert(e.message == "Hi D2!");
}
}
@@ -79,7 +92,7 @@ unittest
import mir.exception;
import mir.format;
try throw new MirException(stringBuf() << "Hi D" << 2 << "!" << getData);
- catch(Exception e) assert(e.msg == "Hi D2!");
+ catch(Exception e) assert(e.scopeMessage == "Hi D2!");
}
}
@@ -221,6 +234,18 @@ mixin template MirThrowableImpl()
private char[maxMirExceptionMsgLen] _payload = void;
import mir.exception: maxMirExceptionMsgLen, mirExceptionInitilizePayloadImpl;
+ const(char)[] _msg;
+
+ override string message() const @safe pure nothrow
+ {
+ return _msg ? _msg.idup : msg;
+ }
+
+ const(char)[] scopeMessage() scope const @safe pure nothrow @nogc
+ {
+ return _msg ? _msg : msg;
+ }
+
/++
Params:
msg = message. No-scope `msg` is assumed to have the same lifetime as the throwable. scope strings are copied to internal buffer.
@@ -228,15 +253,17 @@ mixin template MirThrowableImpl()
line = line number
nextInChain = next exception in the chain (optional)
+/
- @nogc @safe pure nothrow this(scope const(char)[] msg, string file = __FILE__, size_t line = __LINE__, Throwable nextInChain = null)
+ @nogc @trusted pure nothrow this(scope const(char)[] msg, string file = __FILE__, size_t line = __LINE__, Throwable nextInChain = null)
{
- super((() @trusted => cast(immutable) mirExceptionInitilizePayloadImpl(_payload, msg))(), file, line, nextInChain);
+ this._msg = mirExceptionInitilizePayloadImpl(_payload, msg);
+ super(cast(immutable)this._msg, file, line, nextInChain);
}
/// ditto
- @nogc @safe pure nothrow this(scope const(char)[] msg, Throwable nextInChain, string file = __FILE__, size_t line = __LINE__)
+ @nogc @trusted pure nothrow this(scope const(char)[] msg, Throwable nextInChain, string file = __FILE__, size_t line = __LINE__)
{
- super((() @trusted => cast(immutable) mirExceptionInitilizePayloadImpl(_payload, msg))(), file, line, nextInChain);
+ this._msg = mirExceptionInitilizePayloadImpl(_payload, msg);
+ super(cast(immutable)this._msg, file, line, nextInChain);
}
/// ditto
@@ -265,13 +292,26 @@ mixin template MirThrowableImpl()
Generic multiargument overload.
Constructs a string using the `print` function.
+/
- this(Args...)(scope auto ref Args args, string file = __FILE__, size_t line = __LINE__, Throwable nextInChain = null)
- if (Args.length > 1)
+ this(Args...)(auto ref scope const Args args, string file = __FILE__, size_t line = __LINE__, Throwable nextInChain = null) pure
+ if (Args.length > 1 && !is(Args[$ - 1] == Throwable))
+ {
+ static assert (__traits(compiles, {import mir.format;}), "MirThrowableImpl needs mir-algorithm for mir.format and exception formatting.");
+ import mir.format;
+ auto buf = stringBuf();
+ foreach(ref arg; args)
+ buf.print(arg);
+ this(buf.data, file, line, nextInChain);
+ }
+
+ this(Args...)(auto ref scope const Args args) pure @trusted
+ if (Args.length > 4 && is(Args[$ - 1] == Throwable))
{
static assert (__traits(compiles, {import mir.format;}), "MirThrowableImpl needs mir-algorithm for mir.format and exception formatting.");
import mir.format;
auto buf = stringBuf();
- this(buf.print(args).data, file, line, nextInChain);
+ foreach(ref arg; args[0 .. $ - 3])
+ buf.print(arg);
+ this(buf.data, args[$ - 3 .. $ - 1], cast() args[$ - 1]);
}
}
diff --git a/source/mir/functional.d b/source/mir/functional.d
index 733c380..ddb7fb9 100644
--- a/source/mir/functional.d
+++ b/source/mir/functional.d
@@ -23,11 +23,11 @@ $(TR $(TH Function Name) $(TH Description))
$(TR $(TD $(LREF forward))
$(TD Forwards function arguments with saving ref-ness.
))
- $(TR $(TD $(LREF refTuple))
+ $(TR $(TD $(LREF tuple))
$(TD Removes $(LREF Ref) shell.
))
$(TR $(TD $(LREF unref))
- $(TD Creates a $(LREF RefTuple) structure.
+ $(TD Creates a $(LREF Tuple) structure.
))
$(TR $(TD $(LREF __ref))
$(TD Creates a $(LREF Ref) structure.
@@ -52,9 +52,21 @@ public import core.lifetime : forward;
/++
Constructs static array.
+/
-T[N] staticArray(T, size_t N)(T[N] a...)
+T[N] staticArray(T, size_t N)(return scope T[N] a...) {
+ import std.traits: isDynamicArray;
+ static if (isDynamicArray!T) {
+ T[N] ret;
+ static foreach(i; 0..a.length) ret[i] = a[i];
+ return ret;
+ }
+ else return a;
+}
+
+@safe version(mir_core_test) unittest
{
- return a;
+ string[2] v = ["AA", "BB"];
+ auto res = staticArray(v);
+ assert(res == v);
}
/++
@@ -123,7 +135,7 @@ private mixin template _RefTupleMixin(T...)
Simplified tuple structure. Some fields may be type of $(LREF Ref).
Ref stores a pointer to a values.
+/
-struct RefTuple(T...)
+struct Tuple(T...)
{
@optmath:
T expand;
@@ -131,26 +143,32 @@ struct RefTuple(T...)
mixin _RefTupleMixin!T;
}
+deprecated("Use 'Tuple' instead")
+alias RefTuple = Tuple;
+
/// Removes $(LREF Ref) shell.
alias Unref(V : Ref!T, T) = T;
/// ditto
-template Unref(V : RefTuple!T, T...)
+template Unref(V : Tuple!T, T...)
{
import std.meta: staticMap;
- alias Unref = RefTuple!(staticMap!(.Unref, T));
+ alias Unref = Tuple!(staticMap!(.Unref, T));
}
/// ditto
alias Unref(V) = V;
/++
-Returns: a $(LREF RefTuple) structure.
+Returns: a $(LREF Tuple) structure.
+/
-RefTuple!Args refTuple(Args...)(auto ref Args args)
+Tuple!Args tuple(Args...)(auto ref Args args)
{
- return RefTuple!Args(args);
+ return Tuple!Args(args);
}
+deprecated("Use 'tuple' instead")
+alias refTuple = tuple;
+
/// Removes $(LREF Ref) shell.
ref T unref(V : Ref!T, T)(scope return V value)
{
@@ -158,7 +176,7 @@ ref T unref(V : Ref!T, T)(scope return V value)
}
/// ditto
-Unref!(RefTuple!T) unref(V : RefTuple!T, T...)(V value)
+Unref!(Tuple!T) unref(V : Tuple!T, T...)(V value)
{
typeof(return) ret;
foreach(i, ref elem; ret.expand)
@@ -191,7 +209,7 @@ private template autoExpandAndForwardElem(alias value)
}
template autoExpandAndForward(alias value)
- if (is(typeof(value) : RefTuple!Types, Types...))
+ if (is(typeof(value) : Tuple!Types, Types...))
{
import core.lifetime: move;
@@ -226,7 +244,7 @@ template autoExpandAndForward(alias value)
version(mir_core_test) unittest
{
long v;
- auto tup = refTuple(v._ref, 2.3);
+ auto tup = tuple(v._ref, 2.3);
auto f(ref long a, double b)
{
@@ -257,7 +275,7 @@ private auto copyArg(alias a)()
/++
Takes multiple functions and adjoins them together. The result is a
-$(LREF RefTuple) with one element per passed-in function. Upon
+$(LREF Tuple) with one element per passed-in function. Upon
invocation, the returned tuple is the adjoined results of all
functions.
Note: In the special case where only a single function is provided
@@ -283,7 +301,7 @@ template adjoin(fun...) if (fun.length && fun.length <= 26)
}
import mir.internal.utility;
- mixin("return refTuple(" ~ [staticMap!(_adjoin, Iota!(fun.length))].joinStrings ~ ");");
+ mixin("return tuple(" ~ [staticMap!(_adjoin, Iota!(fun.length))].joinStrings ~ ");");
}
}
else alias adjoin = .adjoin!(staticMap!(naryFun, fun));
@@ -297,7 +315,7 @@ template adjoin(fun...) if (fun.length && fun.length <= 26)
static bool f1(int a) { return a != 0; }
static int f2(int a) { return a / 2; }
auto x = adjoin!(f1, f2)(5);
- assert(is(typeof(x) == RefTuple!(bool, int)));
+ assert(is(typeof(x) == Tuple!(bool, int)));
assert(x.a == true && x.b == 2);
}
@@ -315,10 +333,10 @@ template adjoin(fun...) if (fun.length && fun.length <= 26)
auto x1 = adjoin!(F1)(5);
static int F2(int a) { return a / 2; }
auto x2 = adjoin!(F1, F2)(5);
- assert(is(typeof(x2) == RefTuple!(bool, int)));
+ assert(is(typeof(x2) == Tuple!(bool, int)));
assert(x2.a && x2.b == 2);
auto x3 = adjoin!(F1, F2, F2)(5);
- assert(is(typeof(x3) == RefTuple!(bool, int, int)));
+ assert(is(typeof(x3) == Tuple!(bool, int, int)));
assert(x3.a && x3.b == 2 && x3.c == 2);
bool F4(int a) { return a != x1; }
@@ -341,18 +359,18 @@ version(mir_core_test) unittest
alias funs = staticMap!(naryFun, "a", "a * 2", "a * 3", "a * a", "-a");
alias afun = adjoin!funs;
int a = 5, b = 5;
- assert(afun(a) == refTuple(Ref!int(a), 10, 15, 25, -5));
- assert(afun(a) == refTuple(Ref!int(b), 10, 15, 25, -5));
+ assert(afun(a) == tuple(Ref!int(a), 10, 15, 25, -5));
+ assert(afun(a) == tuple(Ref!int(b), 10, 15, 25, -5));
static class C{}
alias IC = immutable(C);
IC foo(){return typeof(return).init;}
- RefTuple!(IC, IC, IC, IC) ret1 = adjoin!(foo, foo, foo, foo)();
+ Tuple!(IC, IC, IC, IC) ret1 = adjoin!(foo, foo, foo, foo)();
static struct S{int* p;}
alias IS = immutable(S);
IS bar(){return typeof(return).init;}
- enum RefTuple!(IS, IS, IS, IS) ret2 = adjoin!(bar, bar, bar, bar)();
+ enum Tuple!(IS, IS, IS, IS) ret2 = adjoin!(bar, bar, bar, bar)();
}
private template needOpCallAlias(alias fun)
diff --git a/source/mir/internal/meta.d b/source/mir/internal/meta.d
index a7e6cdd..ac976fa 100644
--- a/source/mir/internal/meta.d
+++ b/source/mir/internal/meta.d
@@ -13,7 +13,7 @@ module mir.internal.meta;
template getUDAs(T, string member, alias attribute)
{
import std.meta : Filter, AliasSeq;
- T* aggregate;
+ private __gshared T* aggregate;
static if (__traits(compiles, __traits(getAttributes, __traits(getMember, *aggregate, member))))
alias getUDAs = Filter!(isDesiredUDA!attribute, __traits(getAttributes, __traits(getMember, *aggregate, member)));
else
@@ -56,7 +56,7 @@ private template isDesiredUDA(alias attribute)
template memberTypeOf(T, string member)
{
- T* aggregate;
+ private __gshared T* aggregate;
alias memberTypeOf = typeof(__traits(getMember, aggregate, member));
}
@@ -77,7 +77,7 @@ template AllMembersRec(T)
{
static if (__traits(getAliasThis, T).length)
{
- T* aggregate;
+ private __gshared T* aggregate;
static if (is(typeof(__traits(getMember, aggregate, __traits(getAliasThis, T)))))
{
import std.meta: Filter, AliasSeq;
@@ -109,6 +109,7 @@ enum canImplicitlyRemoveConst(T) = __traits(compiles, {static T _function_(ref c
enum canRemoveConst(T) = canConstructWith!(const T, T);
enum canRemoveImmutable(T) = canConstructWith!(immutable T, T);
enum hasOpPostMove(T) = __traits(hasMember, T, "opPostMove");
+enum hasOpCmp(T) = __traits(hasMember, T, "opCmp");
enum hasToHash(T) = __traits(hasMember, T, "toHash");
static if (__VERSION__ < 2094)
enum isCopyable(S) = is(typeof({ S foo = S.init; S copy = foo; }));
@@ -649,3 +650,12 @@ version(mir_core_test) @safe unittest
class C : I!int {}
static assert(is(ReplaceType!(int, string, C) == C));
}
+
+template basicElementType(T)
+{
+ import std.traits: isArray, ForeachType;
+ static if (isArray!T)
+ alias basicElementType = ForeachType!T;
+ else
+ alias basicElementType = T;
+}
diff --git a/source/mir/math/common.d b/source/mir/math/common.d
index f68990f..64c06cb 100644
--- a/source/mir/math/common.d
+++ b/source/mir/math/common.d
@@ -281,7 +281,7 @@ else version(GNU)
///
T nearbyint(T)(in T x) if (isFloatingPoint!T) { mixin(mixinGCCBuiltin!`nearbyint`); }
///
- T copysign(T)(in T mag, in T sgn) if (isFloatingPoint!T) { alias y = sgn; mixin(mixinGCCBuiltin2!`copysign`); }
+ T copysign(T)(in T x, in T sgn) if (isFloatingPoint!T) { alias y = sgn; mixin(mixinGCCBuiltin2!`copysign`); }
///
T round(T)(in T x) if (isFloatingPoint!T) { mixin(mixinGCCBuiltin!`round`); }
///
diff --git a/source/mir/primitives.d b/source/mir/primitives.d
index 245d07c..e128418 100644
--- a/source/mir/primitives.d
+++ b/source/mir/primitives.d
@@ -116,8 +116,8 @@ package(mir) bool anyEmptyShape(size_t N)(scope const auto ref size_t[N] shape)
}
///
-bool anyEmpty(Range)(scope const auto ref Range range) @property
- if (hasShape!Range || __traits(hasMember, Range, "anyEmpty"))
+bool anyEmpty(Range)(scope auto ref Range range) @property
+ if (hasShape!Range || __traits(hasMember, Range, "anyEmpty") || is(ReturnType!((Range r) => r.empty) == bool))
{
static if (__traits(hasMember, Range, "anyEmpty"))
{
diff --git a/source/mir/qualifier.d b/source/mir/qualifier.d
index ce66536..cbf4c7f 100644
--- a/source/mir/qualifier.d
+++ b/source/mir/qualifier.d
@@ -69,7 +69,7 @@ This funciton should be used only when the result never skips the current scope.
This function is used by some algorithms to optimise work with reference counted types.
+/
-auto ref lightScope(T)(auto ref return T v)
+auto ref lightScope(T)(auto ref return scope T v)
if (!is(T : P*, P) && __traits(hasMember, T, "lightScope"))
{
return v.lightScope;
@@ -77,7 +77,7 @@ auto ref lightScope(T)(auto ref return T v)
/// ditto
auto ref lightScope(T)(auto return ref T v)
- if (is(T : P*, P) || !__traits(hasMember, T, "lightScope"))
+ if (!is(T : P*, P) && !__traits(hasMember, T, "lightScope"))
{
static if (is(T == immutable))
return lightImmutable(v);
@@ -88,6 +88,13 @@ auto ref lightScope(T)(auto return ref T v)
return v;
}
+/// ditto
+auto lightScope(T)(return T v)
+ if (is(T : P*, P))
+{
+ return cast(typeof(*v)*) v;
+}
+
///
auto lightImmutable(T)(auto ref immutable T v)
if (!is(T : P*, P) && __traits(hasMember, immutable T, "lightImmutable"))
diff --git a/source/mir/reflection.d b/source/mir/reflection.d
index bcdd111..1f77f77 100644
--- a/source/mir/reflection.d
+++ b/source/mir/reflection.d
@@ -2,7 +2,7 @@
Base reflection utilities.
License: $(HTTP www.apache.org/licenses/LICENSE-2.0, Apache-2.0)
-Authors: Ilia Ki
+Authors: Ilia Ki
Macros:
+/
module mir.reflection;
@@ -10,6 +10,7 @@ module mir.reflection;
import std.meta;
import std.traits: hasUDA, getUDAs, Parameters, isSomeFunction, FunctionAttribute, functionAttributes, EnumMembers, isAggregateType;
import mir.internal.meta: hasUDA;
+import mir.functional: Tuple;
deprecated
package alias isSomeStruct = isAggregateType;
@@ -26,7 +27,7 @@ template isStdNullable(T)
{
import std.traits : hasMember;
- T* aggregate;
+ private __gshared T* aggregate;
enum bool isStdNullable =
hasMember!(T, "isNull") &&
@@ -524,7 +525,7 @@ Checks if member is property.
+/
template isProperty(T, string member)
{
- T* aggregate;
+ private __gshared T* aggregate;
static if (__traits(compiles, isSomeFunction!(__traits(getMember, *aggregate, member))))
{
@@ -759,10 +760,41 @@ private template Deserializable(T, string member)
private enum SerdeFieldsAndProperties(T) = Reverse!(NoDuplicates!(Reverse!(SerdeFieldsAndPropertiesImpl!T)));
+
+private static immutable exlMembers = [
+ "opAssign",
+ "opCast",
+ "opCmp",
+ "opEquals",
+ "opPostMove",
+ "toHash",
+ "toString",
+ "trustedGet",
+ "deserializeFromAsdf",
+ "deserializeFromIon",
+];
+
+private auto filterMembers(string[] members)
+{
+ string[] ret;
+
+ L: foreach(member; members)
+ {
+ if (member.length >= 2 && (member[0 .. 2] == "__" || member[$ - 2 .. $] == "__"))
+ continue;
+ foreach(exlMember; exlMembers)
+ if (exlMember == member)
+ continue L;
+ ret ~= member;
+ }
+ return ret;
+};
+
private template allMembers(T)
{
+ import std.meta: aliasSeqOf;
static if (isAggregateType!T)
- alias allMembers = __traits(allMembers, T);
+ alias allMembers = aliasSeqOf!(filterMembers([__traits(allMembers, T)]));
else
alias allMembers = AliasSeq!();
}
@@ -772,7 +804,7 @@ private template SerdeFieldsAndPropertiesImpl(T)
alias isProperty = ApplyLeft!(.isProperty, T);
alias hasField = ApplyLeft!(.hasField, T);
alias isOriginalMember = ApplyLeft!(.isOriginalMember, T);
- T* aggregate;
+ private __gshared T* aggregate;
template hasReflectSerde(string member)
{
static if (is(typeof(__traits(getMember, *aggregate, member))))
@@ -781,7 +813,7 @@ private template SerdeFieldsAndPropertiesImpl(T)
enum hasReflectSerde = false;
}
alias isMember = templateAnd!(templateOr!(hasField, isProperty, hasReflectSerde), isOriginalMember);
- static if (__traits(getAliasThis, T).length)
+ static if (!is(immutable T == Tuple!Types, Types...) && __traits(getAliasThis, T).length)
{
alias A = typeof(__traits(getMember, aggregate, __traits(getAliasThis, T)));
static if (isAggregateType!T)
@@ -805,27 +837,44 @@ private template SerdeFieldsAndPropertiesImpl(T)
// check if the member is readable
private template isReadable(T, string member)
{
- T* aggregate;
+ private __gshared T* aggregate;
enum bool isReadable = __traits(compiles, { static fun(T)(auto ref T t) {} fun(__traits(getMember, *aggregate, member)); });
}
// check if the member is readable/writeble?
private template isReadableAndWritable(T, string member)
{
- T* aggregate;
+ private __gshared T* aggregate;
enum bool isReadableAndWritable = __traits(compiles, __traits(getMember, *aggregate, member) = __traits(getMember, *aggregate, member));
}
package template isPublic(T, string member)
{
- T* aggregate;
- enum bool isPublic = !__traits(getProtection, __traits(getMember, *aggregate, member)).privateOrPackage;
+ private __gshared T* aggregate;
+ static if (__traits(compiles, { auto _ = __traits(getProtection, __traits(getMember, *aggregate, member)); }))
+ enum bool isPublic = !__traits(getProtection, __traits(getMember, *aggregate, member)).privateOrPackage;
+ else
+ enum bool isPublic = false;
+}
+
+version(unittest)
+{
+ final class ZipArchive
+ {
+ public:
+ static const ushort zip64ExtractVersion = 45;
+ }
+}
+
+version (mir_core_test) @nogc nothrow pure @safe unittest
+{
+ static assert(!isPublic!(ZipArchive, "zip64ExtractVersion"));
}
// check if the member is property
private template isSetter(T, string member)
{
- T* aggregate;
+ private __gshared T* aggregate;
static if (__traits(compiles, isSomeFunction!(__traits(getMember, *aggregate, member))))
{
static if (isSomeFunction!(__traits(getMember, *aggregate, member)))
@@ -843,7 +892,7 @@ private template isSetter(T, string member)
private template isGetter(T, string member)
{
- T* aggregate;
+ private __gshared T* aggregate;
static if (__traits(compiles, isSomeFunction!(__traits(getMember, *aggregate, member))))
{
static if (isSomeFunction!(__traits(getMember, *aggregate, member)))
Debdiff
[The following lists of changes regard files as different if they have different names, permissions or owners.]
Files in second set of .debs but not in first
-rw-r--r-- root/root /usr/lib/debug/.build-id/7c/476ca546cb20e7cd7b15d3b52de14401813e77.debug
Files in first set of .debs but not in second
-rw-r--r-- root/root /usr/lib/debug/.build-id/e5/175b9be8c912712603b2009b1553d8a9805493.debug
No differences were encountered between the control files of package libmir-core-dev
No differences were encountered between the control files of package libmir-core1
Control files of package libmir-core1-dbgsym: lines which differ (wdiff format)
Build-Ids: e5175b9be8c912712603b2009b1553d8a9805493 7c476ca546cb20e7cd7b15d3b52de14401813e77