From a8859e95452541af6c64b3cd272e2f0d7907dbbc Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Tue, 18 Jul 2017 09:27:18 +0200 Subject: [PATCH 1/4] reimplement std.traits.ParameterStorageClassTuple() with __traits --- std/traits.d | 81 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 30 deletions(-) diff --git a/std/traits.d b/std/traits.d index 5b8700cca80..efa82d01ed0 100644 --- a/std/traits.d +++ b/std/traits.d @@ -1016,8 +1016,11 @@ template arity(alias func) } /** -Returns a tuple consisting of the storage classes of the parameters of a -function $(D func). +Get tuple, one per function parameter, of the storage classes of the parameters. +Params: + func = function symbol or type of function, delegate, or pointer to function +Returns: + a tuple of ParameterStorageClass bits */ enum ParameterStorageClass : uint { @@ -1037,39 +1040,28 @@ enum ParameterStorageClass : uint template ParameterStorageClassTuple(func...) if (func.length == 1 && isCallable!func) { - alias Func = Unqual!(FunctionTypeOf!func); - - /* - * TypeFuncion: - * CallConvention FuncAttrs Arguments ArgClose Type - */ - alias Params = Parameters!Func; - - // chop off CallConvention and FuncAttrs - enum margs = demangleFunctionAttributes(mangledName!Func[1 .. $]).rest; + alias Func = FunctionTypeOf!func; - // demangle Arguments and store parameter storage classes in a tuple - template demangleNextParameter(string margs, size_t i = 0) + static if (is(Func PT == __parameters)) { - static if (i < Params.length) + template StorageClass(size_t i) { - enum demang = demangleParameterStorageClass(margs); - enum skip = mangledName!(Params[i]).length; // for bypassing Type - enum rest = demang.rest; - - alias demangleNextParameter = - AliasSeq!( - demang.value + 0, // workaround: "not evaluatable at ..." - demangleNextParameter!(rest[skip .. $], i + 1) - ); - } - else // went thru all the parameters - { - alias demangleNextParameter = AliasSeq!(); + static if (i < PT.length) + { + alias StorageClass = AliasSeq!( + extractParameterStorageClassFlags!(__traits(getParameterStorageClasses, Func, i)), + StorageClass!(i + 1)); + } + else + alias StorageClass = AliasSeq!(); } + alias ParameterStorageClassTuple = StorageClass!0; + } + else + { + static assert(0, func[0].stringof ~ " is not a function"); + alias ParameterStorageClassTuple = AliasSeq!(); } - - alias ParameterStorageClassTuple = demangleNextParameter!margs; } /// @@ -1087,6 +1079,35 @@ template ParameterStorageClassTuple(func...) static assert(pstc[2] == STC.none); } +/***************** + * Convert string tuple Attribs to ParameterStorageClass bits + * Params: + * Attribs = string tuple + * Returns: + * ParameterStorageClass bits + */ +ParameterStorageClass extractParameterStorageClassFlags(Attribs...)() +{ + auto result = ParameterStorageClass.none; + foreach (attrib; Attribs) + { + final switch (attrib) with (ParameterStorageClass) + { + case "scope": result |= scope_; break; + case "out": result |= out_; break; + case "ref": result |= ref_; break; + case "lazy": result |= lazy_; break; + case "return": result |= return_; break; + } + } + /* Mimic behavor of original version of ParameterStorageClassTuple() + * to avoid breaking existing code. + */ + if (result == (ParameterStorageClass.ref_ | ParameterStorageClass.return_)) + result = ParameterStorageClass.return_; + return result; +} + @safe unittest { alias STC = ParameterStorageClass; From 102cd2da250412234206fa235e20ba0b2a4af312 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Tue, 18 Jul 2017 22:36:24 +0200 Subject: [PATCH 2/4] fix case in documentation --- std/traits.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/traits.d b/std/traits.d index efa82d01ed0..37f4f123110 100644 --- a/std/traits.d +++ b/std/traits.d @@ -1020,7 +1020,7 @@ Get tuple, one per function parameter, of the storage classes of the parameters. Params: func = function symbol or type of function, delegate, or pointer to function Returns: - a tuple of ParameterStorageClass bits + A tuple of ParameterStorageClass bits */ enum ParameterStorageClass : uint { From 2c0e2c7bd8fb2cdba04d171230a6066e0b9b21b6 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Wed, 19 Jul 2017 01:01:59 +0200 Subject: [PATCH 3/4] convert static loop into runtime/CTFE loop --- std/traits.d | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/std/traits.d b/std/traits.d index 37f4f123110..1a27ea86b3d 100644 --- a/std/traits.d +++ b/std/traits.d @@ -1089,22 +1089,25 @@ template ParameterStorageClassTuple(func...) ParameterStorageClass extractParameterStorageClassFlags(Attribs...)() { auto result = ParameterStorageClass.none; - foreach (attrib; Attribs) + static if (Attribs.length > 0) { - final switch (attrib) with (ParameterStorageClass) + foreach (attrib; [Attribs]) { - case "scope": result |= scope_; break; - case "out": result |= out_; break; - case "ref": result |= ref_; break; - case "lazy": result |= lazy_; break; - case "return": result |= return_; break; + final switch (attrib) with (ParameterStorageClass) + { + case "scope": result |= scope_; break; + case "out": result |= out_; break; + case "ref": result |= ref_; break; + case "lazy": result |= lazy_; break; + case "return": result |= return_; break; + } } + /* Mimic behavor of original version of ParameterStorageClassTuple() + * to avoid breaking existing code. + */ + if (result == (ParameterStorageClass.ref_ | ParameterStorageClass.return_)) + result = ParameterStorageClass.return_; } - /* Mimic behavor of original version of ParameterStorageClassTuple() - * to avoid breaking existing code. - */ - if (result == (ParameterStorageClass.ref_ | ParameterStorageClass.return_)) - result = ParameterStorageClass.return_; return result; } From 272722fc5bf56e2528c8d89e1fea7957d4e065b7 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Wed, 19 Jul 2017 08:09:37 +0200 Subject: [PATCH 4/4] avoid new CTFE function to be emitted to the object file --- std/traits.d | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/std/traits.d b/std/traits.d index 1a27ea86b3d..fecc8e36bfe 100644 --- a/std/traits.d +++ b/std/traits.d @@ -1086,29 +1086,32 @@ template ParameterStorageClassTuple(func...) * Returns: * ParameterStorageClass bits */ -ParameterStorageClass extractParameterStorageClassFlags(Attribs...)() +template extractParameterStorageClassFlags(Attribs...) { - auto result = ParameterStorageClass.none; - static if (Attribs.length > 0) + enum ParameterStorageClass extractParameterStorageClassFlags = () { - foreach (attrib; [Attribs]) + auto result = ParameterStorageClass.none; + static if (Attribs.length > 0) { - final switch (attrib) with (ParameterStorageClass) + foreach (attrib; [Attribs]) { - case "scope": result |= scope_; break; - case "out": result |= out_; break; - case "ref": result |= ref_; break; - case "lazy": result |= lazy_; break; - case "return": result |= return_; break; + final switch (attrib) with (ParameterStorageClass) + { + case "scope": result |= scope_; break; + case "out": result |= out_; break; + case "ref": result |= ref_; break; + case "lazy": result |= lazy_; break; + case "return": result |= return_; break; + } } + /* Mimic behavor of original version of ParameterStorageClassTuple() + * to avoid breaking existing code. + */ + if (result == (ParameterStorageClass.ref_ | ParameterStorageClass.return_)) + result = ParameterStorageClass.return_; } - /* Mimic behavor of original version of ParameterStorageClassTuple() - * to avoid breaking existing code. - */ - if (result == (ParameterStorageClass.ref_ | ParameterStorageClass.return_)) - result = ParameterStorageClass.return_; - } - return result; + return result; + }(); } @safe unittest