www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Get the code of any D-entity as string?

reply sighoya <sighoya gmail.com> writes:
I've read a bit in Dlang traits.

It now has the ability to retrieve all method signatures of an 
overload set.
Big plus from me.

Is generally possible to get the declaration of a 
type/module/value as string in traits?

I didn't have any concrete use case for it, but it would 
essentially allow us to reflect over any code (we may have to 
respect privacy, of course).

On top of that, people could write their own token or ast 
frameworks as library solutions.

Further, most of the trait functionality given in the trait 
library could be simply implemented as a library solution.

I don't know D enough to be sure it isn't yet possible. 
Theoretically, we could read all files in a source folder, but I 
want also to read declarations from types outside my source 
folders, e.g. from those located in dyn libs.
Dec 25 2020
next sibling parent Paul Backus <snarwin gmail.com> writes:
On Friday, 25 December 2020 at 21:25:40 UTC, sighoya wrote:
 Is generally possible to get the declaration of a 
 type/module/value as string in traits?
No.
Dec 25 2020
prev sibling next sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 12/25/20 1:25 PM, sighoya wrote:

 Is generally possible to get the declaration of a type/module/value as
 string in traits?
I am probably misunderstanding it but there is the .stringof property for all types: T.stringof.
 I want also to read
 declarations from types outside my source folders, e.g. from those
 located in dyn libs.
I am probably stating the obvious but you normally import the interesting modules of that library anyway and the type information is available that way. Ali
Dec 25 2020
parent reply sighoya <sighoya gmail.com> writes:
On Friday, 25 December 2020 at 23:04:15 UTC, Ali Çehreli wrote:

 I am probably misunderstanding it but there is the .stringof 
 property for all types: T.stringof.
But does stringof really print the declaration as string and not the type name itself? I found: https://dlang.org/spec/property.html#stringof
 I am probably stating the obvious but you normally import the 
 interesting modules of that library anyway and the type 
 information is available that way.

 Ali
Well, certainly, yes. But only if `stringof` would do the job. The best thing would be to retrieve whole modules (abstract files) as string. On top of that we can retrieve any value/type declaration.
Dec 26 2020
parent reply Basile B. <b2.temp gmx.com> writes:
On Saturday, 26 December 2020 at 12:38:21 UTC, sighoya wrote:
 On Friday, 25 December 2020 at 23:04:15 UTC, Ali Çehreli wrote:

 I am probably misunderstanding it but there is the .stringof 
 property for all types: T.stringof.
But does stringof really print the declaration as string and not the type name itself? I found: https://dlang.org/spec/property.html#stringof
 I am probably stating the obvious but you normally import the 
 interesting modules of that library anyway and the type 
 information is available that way.

 Ali
Well, certainly, yes. But only if `stringof` would do the job. The best thing would be to retrieve whole modules (abstract files) as string. On top of that we can retrieve any value/type declaration.
with __traits(allMembers) you can rebuild the declaration. For a struct that works well. --- struct E {int a;} struct S { ulong[] a; E(0) const int b; void v() const {} void v(int) const {} } string getDeclaration(T)() if (is(T == struct)) { import std.traits, std.meta; string result = "struct " ~ T.stringof ~ " {\n"; static foreach (m; __traits(allMembers, T)) {{ static if (isCallable!(__traits(getMember, T, m))) alias sym = __traits(getOverloads, T, m); else alias sym = AliasSeq!(__traits(getMember, T, m)); static foreach (s; sym) { result ~= " "; static foreach (a; __traits(getAttributes, s)) result ~= " " ~ a.stringof ~ " "; static if (is(typeof(s))) result ~= typeof(s).stringof ~ " " ~ m ~ ";\n"; } }} result ~= "}"; return result; } pragma(msg, getDeclaration!S); ---
Dec 26 2020
parent sighoya <sighoya gmail.com> writes:
On Saturday, 26 December 2020 at 21:45:41 UTC, Basile B. wrote:
 struct E {int a;}
 struct S
 {
     ulong[] a;
      E(0) const int b;
     void v() const {}
     void v(int) const {}
 }

 string getDeclaration(T)()
 if (is(T == struct))
 {
     import std.traits, std.meta;
     string result = "struct " ~ T.stringof ~ " {\n";
     static foreach (m; __traits(allMembers, T))
     {{
         static if (isCallable!(__traits(getMember, T, m)))
             alias sym = __traits(getOverloads, T, m);
         else
             alias sym = AliasSeq!(__traits(getMember, T, m));
         static foreach (s; sym)
         {
             result ~= "    ";
             static foreach (a; __traits(getAttributes, s))
                 result ~= " " ~ a.stringof ~ " ";
             static if (is(typeof(s)))
                 result ~= typeof(s).stringof ~ " " ~ m ~ ";\n";
         }
     }}
     result ~= "}";
     return result;
 }

 pragma(msg, getDeclaration!S);
 ---
Thanks a lot, retrieving type declarations as string is better than nothing. But it is still not enough, for instance retrieving the expressions of struct fields as string and also recursively resolving the expressions of the variables in the string expression as string. This is also a limitation in Nim macros, I think, you can't capture values outside the input scope.
Dec 27 2020
prev sibling parent reply Max Haughton <maxhaton gmail.com> writes:
On Friday, 25 December 2020 at 21:25:40 UTC, sighoya wrote:
 I've read a bit in Dlang traits.

 It now has the ability to retrieve all method signatures of an 
 overload set.
 Big plus from me.

 Is generally possible to get the declaration of a 
 type/module/value as string in traits?

 I didn't have any concrete use case for it, but it would 
 essentially allow us to reflect over any code (we may have to 
 respect privacy, of course).

 On top of that, people could write their own token or ast 
 frameworks as library solutions.

 Further, most of the trait functionality given in the trait 
 library could be simply implemented as a library solution.

 I don't know D enough to be sure it isn't yet possible. 
 Theoretically, we could read all files in a source folder, but 
 I want also to read declarations from types outside my source 
 folders, e.g. from those located in dyn libs.
Not possible although implementing as a __trait would be about 15 lines I think. I think read only AST access in some form would actually be quite nice, if not for dmd's AST being fuckugly (the hierarchy is fine but it's more gcc than clang)
Dec 26 2020
parent reply sighoya <sighoya gmail.com> writes:
On Sunday, 27 December 2020 at 04:13:53 UTC, Max Haughton wrote:
 Not possible although implementing as a __trait would be about 
 15 lines I think.
I think that too, and it would nicely reuse the work of the compiler to parse the whole project.
 I think read only AST access in some form would actually be 
 quite nice, if not for dmd's AST being fuckugly (the hierarchy 
 is fine but it's more gcc than clang)
The point is, once we have that we can decide ourselves which framework is the best for meta modelling. Is it pure string manipulation or token stream manipulation à la Rust or an AST manipulation à la Nim/Scala. It can be all defined on top.
Dec 27 2020
parent reply Basile B. <b2.temp gmx.com> writes:
On Sunday, 27 December 2020 at 12:20:01 UTC, sighoya wrote:
 On Sunday, 27 December 2020 at 04:13:53 UTC, Max Haughton wrote:
 Not possible although implementing as a __trait would be about 
 15 lines I think.
I think that too, and it would nicely reuse the work of the compiler to parse the whole project.
 I think read only AST access in some form would actually be 
 quite nice, if not for dmd's AST being fuckugly (the hierarchy 
 is fine but it's more gcc than clang)
The point is, once we have that we can decide ourselves which framework is the best for meta modelling. Is it pure string manipulation or token stream manipulation à la Rust or an AST manipulation à la Nim/Scala. It can be all defined on top.
A more concrete example of what you are trying to achieve would allow to show the D way.
Dec 27 2020
parent sighoya <sighoya gmail.com> writes:
On Sunday, 27 December 2020 at 14:40:01 UTC, Basile B. wrote:

A more concrete example of what you are trying to achieve would
 allow to show the D way.
What happens with your code example for the struct: ``` struct S { ulong[] a; E(0) const int b=1; void v() const {return;} int v(int i) const {return i+1;} } ``` Did I get the value/function body? Even if get that some day, what about function/value declarations in the free scope (module scope)? A realistic scenario would be mocking, you read in the declaration of the type to test and create mock variables for the variables referenced in the function body to decouple it from other modules.
Dec 27 2020