digitalmars.D - shared and getParameterStorageClasses bug?
- Jean-Louis Leroy (5/5) Aug 22 2020 void foo(lazy shared Object);
- Meta (5/10) Aug 22 2020 I'm not sure why the documentation says that, but I believe
- Petar Kirov [ZombineDev] (30/35) Aug 22 2020 From a grammar point of view, type qualifiers (`const`,
- Jean-Louis Leroy (16/33) Aug 23 2020 Thanks. Then my follow-up question is: how do I retrieve the
- Jean-Louis Leroy (5/24) Aug 23 2020 OK since the `shared` has migrated to the type, isSharedParameter
- Paul Backus (7/11) Aug 23 2020 An even simpler way is to use the pattern-matching feature of
- Steven Schveighoffer (6/21) Aug 23 2020 is(Parameters!fun[param] == shared);
- Andrei Alexandrescu (3/18) Aug 23 2020 This would have problems if shared is combined with other qualifiers
- Timon Gehr (2/21) Aug 24 2020 (Which is a compiler bug.)
- Petar Kirov [ZombineDev] (14/53) Aug 23 2020 Hmm, why do you need to extract them in the same fashion? For use
- Jean-Louis Leroy (8/12) Aug 24 2020 Yeah, it is related to my attempt to support all the language in
- Petar Kirov [ZombineDev] (4/16) Aug 25 2020 Interesting, so essentially, you need a good solution for your
- Jean-Louis Leroy (27/30) Aug 25 2020 Actually it already works as is:
- Petar Kirov [ZombineDev] (14/44) Aug 25 2020 Nice!
void foo(lazy shared Object); pragma(msg, __traits(getParameterStorageClasses, foo, 0)); // tuple("lazy") Shouldn't this return a tuple("lazy", "shared)? Given that `shared` is documented as a parameter storage class?
Aug 22 2020
On Saturday, 22 August 2020 at 18:34:21 UTC, Jean-Louis Leroy wrote:void foo(lazy shared Object); pragma(msg, __traits(getParameterStorageClasses, foo, 0)); // tuple("lazy") Shouldn't this return a tuple("lazy", "shared)? Given that `shared` is documented as a parameter storage class?I'm not sure why the documentation says that, but I believe shared is considered a "type constructor", not a storage class. It's in the same class as const, immutable, etc.
Aug 22 2020
On Saturday, 22 August 2020 at 18:34:21 UTC, Jean-Louis Leroy wrote:void foo(lazy shared Object); pragma(msg, __traits(getParameterStorageClasses, foo, 0)); // tuple("lazy") Shouldn't this return a tuple("lazy", "shared)? Given that `shared` is documented as a parameter storage class?From a grammar point of view, type qualifiers (`const`, `immutable`, `inout` and `shared`) can appear as 4 different entities: 1. Type constructors [0] 2. Variable storage classes [1] 3. Parameter attributes [2] 4. Member function attributes [3] Parameter attributes grammatically include both UDAs and parameter storage classes (confusingly named `InOut` in the spec), so we can actually collapse the grammatical entities related to variables (which include parameters) to just 2 kinds: type constructors and storage classes. Semantically: Q T x; // A) storage class syntax Q(T) x; // B) type constructor syntax A) and B) are equivalent (where `Q` is some type qualifier and `T` is some type). During semantic processing the compiler erases the difference between two by converting qualifiers appearing as storage classes to type constructors (IIRC described via `mtype.d`). Which leaves `lazy`, `in`, `out`, `ref`, `return` and `scope` as the only actual parameter storage classes that you can query. (`auto ref` is resolved to either `ref` or no storage class during IFTI semantic processing). [0]: https://dlang.org/spec/grammar.html#TypeCtor [1]: https://dlang.org/spec/grammar.html#StorageClass [2]: https://dlang.org/spec/grammar.html#Parameters [3]: https://dlang.org/spec/grammar.html#MemberFunctionAttributes
Aug 22 2020
On Sunday, 23 August 2020 at 06:42:02 UTC, Petar Kirov [ZombineDev] wrote:From a grammar point of view, type qualifiers (`const`, `immutable`, `inout` and `shared`) can appear as 4 different entities: 1. Type constructors [0] 2. Variable storage classes [1] 3. Parameter attributes [2] 4. Member function attributes [3] Parameter attributes grammatically include both UDAs and parameter storage classes (confusingly named `InOut` in the spec), so we can actually collapse the grammatical entities related to variables (which include parameters) to just 2 kinds: type constructors and storage classes. Semantically: Q T x; // A) storage class syntax Q(T) x; // B) type constructor syntax A) and B) are equivalent (where `Q` is some type qualifier and `T` is some type).Thanks. Then my follow-up question is: how do I retrieve the parameter type constructors? Without resorting on scanning the stringified parameter like here: enum isSharedParameter(alias fun, uint param) = Parameters!fun[param..param+1].stringof.indexOf("shared") != -1; (of course this is not robust: it would give false positives with types that contain the substring "shared"). My actual goal is to extract them in the same fashion as the storage classes, e.g.: void foo(lazy const shared Object); static assert(parameterTypeConstructors!foo == tuple("const", "shared")); Do I really have to parse a string like "(lazy shared(const(Object)))"? And, how reliable would this solution be?
Aug 23 2020
On Sunday, 23 August 2020 at 13:44:30 UTC, Jean-Louis Leroy wrote:On Sunday, 23 August 2020 at 06:42:02 UTC, Petar Kirov [ZombineDev] wrote:OK since the `shared` has migrated to the type, isSharedParameter can be written like this: enum isSharedParameter(alias fun, uint param) = is(Parameters!fun[param] == SharedOf!(Parameters!fun[param]));[...]Thanks. Then my follow-up question is: how do I retrieve the parameter type constructors? Without resorting on scanning the stringified parameter like here: enum isSharedParameter(alias fun, uint param) = Parameters!fun[param..param+1].stringof.indexOf("shared") != -1; (of course this is not robust: it would give false positives with types that contain the substring "shared"). My actual goal is to extract them in the same fashion as the storage classes, e.g.: void foo(lazy const shared Object); static assert(parameterTypeConstructors!foo == tuple("const", "shared")); Do I really have to parse a string like "(lazy shared(const(Object)))"? And, how reliable would this solution be?
Aug 23 2020
On Sunday, 23 August 2020 at 14:11:21 UTC, Jean-Louis Leroy wrote:OK since the `shared` has migrated to the type, isSharedParameter can be written like this: enum isSharedParameter(alias fun, uint param) = is(Parameters!fun[param] == SharedOf!(Parameters!fun[param]));An even simpler way is to use the pattern-matching feature of `is(...)`: enum isSharedParameter(alias fun, size_t param) = is(Parameters!fun[param] == shared(T), T); You can read this as, "there exists some T such that Parameters!fun[param] is shared(T)".
Aug 23 2020
On 8/23/20 10:21 AM, Paul Backus wrote:On Sunday, 23 August 2020 at 14:11:21 UTC, Jean-Louis Leroy wrote:is(Parameters!fun[param] == shared); This works for all type constructors. I think there's no way to get this as a nice string list though like a __traits might do (though it could be done). -SteveOK since the `shared` has migrated to the type, isSharedParameter can be written like this: enum isSharedParameter(alias fun, uint param) = is(Parameters!fun[param] == SharedOf!(Parameters!fun[param]));An even simpler way is to use the pattern-matching feature of `is(...)`: enum isSharedParameter(alias fun, size_t param) = is(Parameters!fun[param] == shared(T), T); You can read this as, "there exists some T such that Parameters!fun[param] is shared(T)".
Aug 23 2020
On 8/23/20 10:21 AM, Paul Backus wrote:On Sunday, 23 August 2020 at 14:11:21 UTC, Jean-Louis Leroy wrote:This would have problems if shared is combined with other qualifiers (const and my nemesis inout).OK since the `shared` has migrated to the type, isSharedParameter can be written like this: enum isSharedParameter(alias fun, uint param) = is(Parameters!fun[param] == SharedOf!(Parameters!fun[param]));An even simpler way is to use the pattern-matching feature of `is(...)`: enum isSharedParameter(alias fun, size_t param) = is(Parameters!fun[param] == shared(T), T); You can read this as, "there exists some T such that Parameters!fun[param] is shared(T)".
Aug 23 2020
On 23.08.20 21:15, Andrei Alexandrescu wrote:On 8/23/20 10:21 AM, Paul Backus wrote:(Which is a compiler bug.)On Sunday, 23 August 2020 at 14:11:21 UTC, Jean-Louis Leroy wrote:This would have problems if shared is combined with other qualifiers (const and my nemesis inout).OK since the `shared` has migrated to the type, isSharedParameter can be written like this: enum isSharedParameter(alias fun, uint param) = is(Parameters!fun[param] == SharedOf!(Parameters!fun[param]));An even simpler way is to use the pattern-matching feature of `is(...)`: enum isSharedParameter(alias fun, size_t param) = is(Parameters!fun[param] == shared(T), T); You can read this as, "there exists some T such that Parameters!fun[param] is shared(T)".
Aug 24 2020
On Sunday, 23 August 2020 at 13:44:30 UTC, Jean-Louis Leroy wrote:On Sunday, 23 August 2020 at 06:42:02 UTC, Petar Kirov [ZombineDev] wrote:Hmm, why do you need to extract them in the same fashion? For use in string mixins? If you just want to create a proxy function then simply using std.traits.Parameters should do the trick. If you're writing a meta programming library, then perhaps you can consider representing function types as: 1. AliasSeq of the types 2. AliasSeq of the types 3. AliasSeq of the default values 4. AliasSeq of ints, each representing a bitset of the parameter storage classes that we're set. Or alternatively string[][]. Another way would be to create a Parameter struct template that contains the relevant information and then have an AliasSeq of Parameter types for each function type.From a grammar point of view, type qualifiers (`const`, `immutable`, `inout` and `shared`) can appear as 4 different entities: 1. Type constructors [0] 2. Variable storage classes [1] 3. Parameter attributes [2] 4. Member function attributes [3] Parameter attributes grammatically include both UDAs and parameter storage classes (confusingly named `InOut` in the spec), so we can actually collapse the grammatical entities related to variables (which include parameters) to just 2 kinds: type constructors and storage classes. Semantically: Q T x; // A) storage class syntax Q(T) x; // B) type constructor syntax A) and B) are equivalent (where `Q` is some type qualifier and `T` is some type).Thanks. Then my follow-up question is: how do I retrieve the parameter type constructors? Without resorting on scanning the stringified parameter like here: enum isSharedParameter(alias fun, uint param) = Parameters!fun[param..param+1].stringof.indexOf("shared") != -1; (of course this is not robust: it would give false positives with types that contain the substring "shared"). My actual goal is to extract them in the same fashion as the storage classes, e.g.: void foo(lazy const shared Object); static assert(parameterTypeConstructors!foo == tuple("const", "shared")); Do I really have to parse a string like "(lazy shared(const(Object)))"? And, how reliable would this solution be?
Aug 23 2020
On Sunday, 23 August 2020 at 21:14:38 UTC, Petar Kirov [ZombineDev] wrote:Hmm, why do you need to extract them in the same fashion? For use in string mixins?Yeah, it is related to my attempt to support all the language in my openmethods library.If you just want to create a proxy function then simply using std.traits.Parameters should do the trick.That's a whole can of worms ;-) I am trying to handle that as well as possible in a part of openmethods that I spun off and donated to bolts (see here https://github.com/aliak00/bolts/blob/master/source/bolts/experimental/refraction.d).
Aug 24 2020
On Monday, 24 August 2020 at 21:01:30 UTC, Jean-Louis Leroy wrote:On Sunday, 23 August 2020 at 21:14:38 UTC, Petar Kirov [ZombineDev] wrote:Interesting, so essentially, you need a good solution for your refractParameter function, right? I'll try to check the code in more detail later and think about it.Hmm, why do you need to extract them in the same fashion? For use in string mixins?Yeah, it is related to my attempt to support all the language in my openmethods library.If you just want to create a proxy function then simply using std.traits.Parameters should do the trick.That's a whole can of worms ;-) I am trying to handle that as well as possible in a part of openmethods that I spun off and donated to bolts (see here https://github.com/aliak00/bolts/blob/master/source/bolts/experimental/refraction.d).
Aug 25 2020
On Tuesday, 25 August 2020 at 07:16:39 UTC, Petar Kirov [ZombineDev] wrote:Interesting, so essentially, you need a good solution for your refractParameter function, right? I'll try to check the code in more detail later and think about it.Actually it already works as is: void original(lazy const Object); enum edited = refract!(original, "original") .withName("copy") .withParametersAt(0, Parameter("foo", "int")); mixin(edited.mixture); void expected(int, lazy const Object); static assert(is(typeof(©) == typeof(&expected))); The generated mixin is: pragma(msg, edited.mixture); // system bolts.experimental.refraction.ReturnType!(original) // copy(int foo, lazy bolts.experimental.refraction.Parameters!(original)[0] _0); (In this case, Parameters!(original)[0..1] (note the ..) would have worked as well - and it would have looker better too. I'll implement that soon.) Let's look at the function types: pragma(msg, typeof(&original).stringof); // void function(lazy const(Object)) pragma(msg, typeof(©).stringof); // void function(int foo, lazy const(Object) _0) system It looks like it is impossible to tell the difference between 'const object' and 'const(Object)' - the substitution happens too early. So I guess it doesn't matter...
Aug 25 2020
On Tuesday, 25 August 2020 at 12:52:14 UTC, Jean-Louis Leroy wrote:On Tuesday, 25 August 2020 at 07:16:39 UTC, Petar Kirov [ZombineDev] wrote:Nice!Interesting, so essentially, you need a good solution for your refractParameter function, right? I'll try to check the code in more detail later and think about it.Actually it already works as is: void original(lazy const Object); enum edited = refract!(original, "original") .withName("copy") .withParametersAt(0, Parameter("foo", "int")); mixin(edited.mixture); void expected(int, lazy const Object); static assert(is(typeof(©) == typeof(&expected))); The generated mixin is: pragma(msg, edited.mixture); // system bolts.experimental.refraction.ReturnType!(original) // copy(int foo, lazy bolts.experimental.refraction.Parameters!(original)[0] _0); (In this case, Parameters!(original)[0..1] (note the ..) would have worked as well - and it would have looker better too. I'll implement that soon.) Let's look at the function types: pragma(msg, typeof(&original).stringof); // void function(lazy const(Object)) pragma(msg, typeof(©).stringof); // void function(int foo, lazy const(Object) _0) systemIt looks like it is impossible to tell the difference between 'const object' and 'const(Object)' - the substitution happens too early. So I guess it doesn't matter...Yes, `Q T` and `Q(T)` is exactly the same type (for Q ∈ { const, immutable, shared, inout } ), so you shouldn't try to differentiate between the two. (And `Q(T)` is the canonical notation.) BTW, 2-3 years ago I played with a similar task (meta programming utility library), and one difference in the approach I took was to avoid thick abstractions. In some cases, this works well, though since I didn't have use cases involving heavy function type processing recently I didn't push much in that direction. You can find some of the code here: https://gist.github.com/PetarKirov/a808c94857de84858accfb094c19bf77#file-rxd-meta2-d-L65-L123
Aug 25 2020