Metaprogramming without templates

Stefan Koch uplink.coder at googlemail.com
Tue Jun 29 14:26:10 UTC 2021


On Friday, 25 June 2021 at 15:07:54 UTC, Stefan Koch wrote:
> 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]

Hi there, I have just been able to do the first thing I wanted to 
use core reflect for.
dynamically loading function pointers for debugging functions.
In case the function cannot be loaded because it's not running in 
the debug environment I want the function pointers to be 
initialized to dummy functions which do nothing.

Let's have a look at the code:
```D
import core.reflect.reflect;
static immutable decls = declarationsFromTokenString(
q{
//  extern (C) @nogc pure nothrow __gshared {
      void __itt_sync_create (void *addr, const char *objtype, 
const char *objname, int attribute);
      void  __itt_sync_cancel (void* addr);
      void __itt_sync_acquired (void* addr);
      void  __itt_sync_releasing (void* addr);
      void __itt_sync_prepare (void* addr);
//  }
});
import core.reflect.nodeToSource;

pragma(msg, () {
     string result;

     foreach(d;decls)
     {
         if (auto fd = cast(FunctionDeclaration) d)
         {
             result ~= fd
                 .makeFunctionVariableWithDummyInit()
                 .nodeToSource()
             ;
         }
     }
     return result;
} ());

VariableDeclaration makeFunctionVariableWithDummyInit(const 
FunctionDeclaration fd) {
   auto type = new TypePointer();
   type.nextOf = cast()fd.type;
   auto name = fd.name;

   auto result = new VariableDeclaration();
   result.type = type;
   result.name = name;
   auto func = new FunctionLiteral();
   func.parameters = cast()fd.parameters;
   func.fbody = makeDummyBody(fd.type.returnType);
   result._init = func;
   return result;
}

BlockStatement makeDummyBody(const Type returnType)
{
     BlockStatement stmt = new BlockStatement();

     if (cast(TypeBasic) returnType && returnType.identifier == 
"void")
     {
         stmt.statements ~= new ReturnStatement();
     }
     else
         assert(0, "non void return not supported as of now");

     return stmt;
}
```

and the output of this will be

```D
void function (void* addr, char* objtype, char* objname, int 
attribute) __itt_sync_create = () {
     return ;
};
void function (void* addr) __itt_sync_cancel = () {
     return ;
};
void function (void* addr) __itt_sync_acquired = () {
     return ;
};
void function (void* addr) __itt_sync_releasing = () {
     return ;
};
void function (void* addr) __itt_sync_prepare = () {
     return ;
};
```

which does exactly what I want it declares function pointers with 
the same name as the functions extracted from the intel header.
and initializes them to dummy functions be default.
yay.

Creating a string is not how it's supposed to be spliced in 
though!
rather I will special case `mixin` to splice in `core.reflect` 
directly nodes when it is used on them.
Or maybe something more clever :)


More information about the Digitalmars-d mailing list