Thread overview
Get the code of any D-entity as string?
Dec 25, 2020
sighoya
Dec 25, 2020
Paul Backus
Dec 25, 2020
Ali Çehreli
Dec 26, 2020
sighoya
Dec 26, 2020
Basile B.
Dec 27, 2020
sighoya
Dec 27, 2020
Max Haughton
Dec 27, 2020
sighoya
Dec 27, 2020
Basile B.
Dec 27, 2020
sighoya
December 25, 2020
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.
December 25, 2020
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.
December 25, 2020
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

December 26, 2020
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.


December 26, 2020
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);
---
December 27, 2020
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)
December 27, 2020
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.
December 27, 2020
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.


December 27, 2020
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.
December 27, 2020
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.