Getting the names of all the top-level functions in module

Stefan Koch uplink.coder at googlemail.com
Tue Sep 21 13:29:44 UTC 2021


Hello there,

I was just working on an example for my upcoming library 
`core.reflect`
and I wanted to contrast it with the current template way of 
doing things.
The issue at hand here is getting all the names of top-level 
(free)function in a module in a string[].

The way that I found to do this with templates involves a bit of 
knowledge of is expressions here it is

```d
template functionNames (alias M)
{
     static const functionNames = ()
     {
         string[] names;
         foreach(m;__traits(derivedMembers, M))
         {
             alias sym = __traits(getMember, M, m);
             static if (is(typeof(sym) T) && is(T F == function))
             {
                 names ~= __traits(identifier, sym);
             }
         }
         return names;
     } ();
}
```

Note that on the "callsite" you have to instantiate the helper 
template as:
`static const fNames = functionNames!(mixin(__MODULE__))`;
the parens around the mixin are not optional it will not parse 
without them.

now comes the way do that with core.reflect.

```d
@(core.reflect) // annotation prevents code-gen since the 
`nodeFromName` builtin which is called in there is not a real 
function and therefore has no body for the codegenerator to look 
at.
const(FunctionDeclaration)[] getFreeFunctionNamesFromModule(
     string module_ = __MODULE__,
     ReflectFlags flags = ReflectFlags.NoMemberRecursion,
     immutable Scope _scope = currentScope()
)
{
     string[] result;
     auto mod_ = nodeFromName(module_, flags, _scope);
     if (auto mod = cast(Module) mod_)
     foreach(member;mod.members)
     {
         if (auto fd = cast(const FunctionDeclaration) member)
         {
             result ~= fd.name;
         }
     }

     return result;
}
```

and you use it like this.
`static const functionNames = getFreeFunctionNamesFromModule;`
I am using a parenthesis less call to make it look like it's a 
magic builtin but in reality the only bits of magic that are used 
are the two builtins `nodeFromName` and `currentScope`

whereas the template above used 5 magic constructs.
  - 2 different types of pattern matching is expressions.
    and
  - 3 different __traits expressions.


More information about the Digitalmars-d mailing list