Metaprogramming without templates

Stefan Koch uplink.coder at googlemail.com
Fri Jun 25 15:07:54 UTC 2021


On Thursday, 24 June 2021 at 11:53:00 UTC, Stefan Koch wrote:
> On Sunday, 20 June 2021 at 22:51:06 UTC, Stefan Koch wrote:
>> [snip]
>> And I assume I'll first have to make advances on dealing with 
>> complicated forward reference graphs before I can show 
>> anything neat.
>
> No more assumptions now I have proof :P
>
>
> I hope I can find a way to compute a schedule that will leave a 
> symbol in a stable state as reflection is not supposed to be 
> able to modify anything.

more news on this.
I am now forcing the resolution of types as part of the 
reflection.
That does get rid of the uncomplicated forward refs.

Also I checked that the data can be used at runtime without 
issues.

If you run to following program:

```D
     extern (C) void*** fnXXfn(void* p, void** pp);
     static immutable fn_x = cast(immutable FunctionDeclaration) 
nodeFromName("fnXXfn");
     void main()
     {
       import core.stdc.stdio;
       printf(StructToString(fn_x).ptr);
     }


     string StructToString(S)(S _struct, uint indent_level = 1)
     {
       import std.conv : to;

       char[] indent_m;
       indent_m.length = indent_level * 4;
       indent_m[] = ' ';
       string indent = cast(string) indent_m;

       string result = S.stringof ~ " = {\n";

       //TODO: if it's a class cast to base_type;

       foreach(i, e;_struct.tupleof)
       {
         auto name = __traits(identifier, _struct.tupleof[i]);
         result ~= indent ~ name ~ ": ";
         enum isAggregate(T) = is(T == class) || is(T == struct);
         if (e)
         {
             static if (is(typeof(e) : const(char)[]))
             {
                result ~= "\"" ~ e ~ "\"" ~ "\n";
             }
             else static if (is(typeof(e) : E[], E))
             {
                 if (!e.length)
                 {
                   result ~= "[]\n";
                 }
                 else
                 {
                     result ~= "[\n";
                     indent ~= "    ";
                     foreach(elem;e)
                     {
                         pragma(msg, "isArray: " , typeof(e));
                         static if (isAggregate!(typeof(elem)))
                         {
                             result ~= indent ~ 
StructToString(elem, indent_level + 2) ~ ",\n";
                         }
                         else
                         {
                            result ~= indent ~ to!string(elem) ~ 
"\n";
                         }
                     }
                     indent = indent[0 .. $ - 4];
                     result ~= indent ~ "]\n";
                 }
             }
             else static if (isAggregate!(typeof(e)))
             {
                 result ~= StructToString(e, indent_level + 1) ~ 
"\n";
             }
             else
             {
                result ~= to!string(e) ~ "\n";
             }
         }
         else
         {
             result ~= "null\n";
         }
       }
       result ~= indent[4 .. $] ~ "}";
       return result;
     }
```

it will give you the output:

```D
     immutable(FunctionDeclaration) = {
         type: immutable(FunctionType) = {
             returnType: immutable(Type) = {
                 kind: "pointer"
                 alignSize: 8
                 size: 8
                 identifier: "void***"
             }
             parameterTypes: [
                 immutable(FunctionParameter) = {
                     type: immutable(Type) = {
                         kind: "pointer"
                         alignSize: 8
                         size: 8
                         identifier: "void*"
                     }
                     identifier: "p"
                 },
                 immutable(FunctionParameter) = {
                     type: immutable(Type) = {
                         kind: "pointer"
                         alignSize: 8
                         size: 8
                         identifier: "void**"
                     }
                     identifier: "pp"
                 },
             ]
         }
         parameters: null
         fbody: null
     }
```

If you look closely you will see that it matches type of the 
function `fnXXfn`
Declared in the code up above.
If my printout code would recurse into super-classes you would 
also be able to see name of the declaration.
However I didn't do that yet ;)
This is just an example to show that these reflection classes can 
be used at runtime as well as at compile time.

Lastly you can play with this yourself if you do:
`git clone https://github.com/UplinkCoder/dmd -b core_reflect`
and
`git clone https://github.com/UplinkCoder/druntime -b 
core_reflect`
and
`git clone https://github.com/dlang/phobos -b v2.094.2`
then you go into build it
then you build phobos
you might have to remove '-transition=complex' from the makefiles 
in both druntime and phobos.

and now you should be able to run the exmaple posted above.

I am not quite sure why; but although this is based on ~master as 
of roughly 5 days ago
phobos only seems to compile if you checkout v2.094.2 ...




More information about the Digitalmars-d mailing list