Thread overview
Fun determining the number of parameters using core reflect
Sep 11, 2021
Stefan Koch
Sep 11, 2021
Stefan Koch
Sep 11, 2021
Stefan Koch
September 11, 2021

Hi there,

I've just been wanted to know if a particular local variable has is pointer taken inside a function.
i.e. whether it's aliased.

In order to reflect on that I would have to look at where it is defined i.e. reflect on the lexical parent which is possible but is currently disabled by default since it's expensive.

So I wondered if I could just get the parent function node inside my reflection function, which works since I can get the string of the function I am in.

After a bit of tinkering I arrived at the following code.

Enjoy!

And please feel free to ask questions and suggest improvements!

import core.reflect.reflect;
int f()
{
    int x;
    static assert(nParameters == 0);
    g(&x);
    return x;
}
int f2(int x, float y)
{
    static assert(nParameters == 2);
    return x;
}

void g(int* x) {}

@(core.reflect) uint nParameters(immutable string fName = __FUNCTION__, immutable Scope _scope = currentScope())
{
    auto F = cast(const FunctionDeclaration)
        nodeFromName(fName, ReflectFlags.NoParent | ReflectFlags.NoFunctionbody, _scope);
    uint params = cast(uint)F.type.parameterTypes.length;
    return params;
}
September 11, 2021

On Saturday, 11 September 2021 at 08:48:34 UTC, Stefan Koch wrote:

>

Hi there,

Ah one more think I forgot to mention.
If you want to play with this be advised that my core_reflect branch is currently trying to be somewhat stable.
The cutting edge changes you need for this example to work are in the.
core_reflect_newCTFE branch.

September 11, 2021

On Saturday, 11 September 2021 at 08:48:34 UTC, Stefan Koch wrote:

>

Hi there,

import core.reflect.reflect;
@(core.reflect) uint nParameters(immutable string fName = __FUNCTION__, immutable Scope _scope = currentScope())
{
    auto F = cast(const FunctionDeclaration)
        nodeFromName(fName, ReflectFlags.NoParent | ReflectFlags.NoFunctionbody, _scope);
    uint params = cast(uint)F.type.parameterTypes.length;
    return params;
}

I can already hear you ask if that supports eponymous templates.
The answers is ... yes it does.

As of a few minutes ago :)

string nArgs(T...)(T args)
{
    static assert(nParameters == 4, "template has to be called with 4 arguments excat>
    return "reflection is cool";
}

pragma(msg, nArgs(1, 2, "trythis", 4.0));

// pragma(msg, nArgs(1, 2, "trythis", 4.0, 1)); // won't compile static assert fails

You can determine the type and names of the parameters passed in.
You can determine how they are used in the function body if there is a body.
I just realized a few minutes ago what interesting things allows you to do.