October 06, 2021

Good Morning Everyone,

I have been working a little to present some real world example of where core.reflect might be used.

One of them is automatic wrapper generation.
(For example you might want to call D functions from C# or something).

There is a library called autowrap which does this using templates and string mixins.
Which tries to get the __traits reflection data into string form as soon as possible in order to avoid template overhead.

Here I am reimplemeting a very small part of their C# wrapper.

import core.reflect.reflect;
import core.reflect.utils;

string getDlangInterfaceType(const Type type)
{
    assert(isAggregateType(T));
    auto u = unqualType(type);
    auto slice_type = cast(TypeSlice) type;
    if (slice_type !is null)
    {
        u = unqualType(slice_type.nextOf);
    }

    string result;

    switch(u.serial)
    {
        case getType("Duration", ReflectFlags.Default, sc).serial :
            result = "Marshalled_Duration";
        break;
        case getType("DateTime", ReflectFlags.Default, sc).serial :
        case getType("Date", ReflectFlags.Default, sc).serial :
        case getType("TimeOfDay", ReflectFlags.Default, sc).serial :
            result = "Marshalled_std_datetime_date";
        break;
        case getType("SysTime", ReflectFlags.Default, sc).serial :
            result = "Marshalled_std_datetime_systime";
        break;
        default :
            result = getAggregate(u).fqn();
    }

    if (slice_type)
    {
        return result ~= "[]";
    }

    return result;
}

static assert(() {
        auto st = nodeFromName("SysTime");
        return st.getType().getDlangInterfaceType();
} () == "Marshalled_std_datetime_systime");
// works at compile time.

struct S
{
    DateTime[] dates;
}

static immutable s = nodeFromName("S", ReflectFlags.Members);
void main()
{
        string result;

        printf("%s\n", getType(s)
            .fields()[0]
            .getType()
            .getDlangInterfaceType().ptr
        );
        // works at runtime as well -- output: "Marshalled_std_datetime_date[]"
        // perhaps with some garbage at the end if you are unlucky and it's not a '\0'
}

Note the functions getType,getAggregate, fields fqn and unqualType are defined in the core.reflect utility module

As a comparison here is the version which exists in autowrap/csharp today:

private string getDLangInterfaceType(T)() {

    import core.time : Duration;
    import std.datetime.date : Date, DateTime, TimeOfDay;
    import std.datetime.systime : SysTime;
    import std.traits : fullyQualifiedName, Unqual;

    alias U = Unqual!T;

    // FIXME This code really should be reworked so that there's no need to
    // check for arrays of date/time types, but rather it's part of the general
    // array handling.
    static if(is(U == Duration))
        return "Marshalled_Duration";
    else static if(is(U == DateTime) || is(U == Date) || is(U == TimeOfDay))
        return "Marshalled_std_datetime_date";
    else static if(is(U == SysTime))
        return "Marshalled_std_datetime_systime";
    else static if(is(U == Duration[]))
        return "Marshalled_Duration[]";
    else static if(is(U == DateTime[]) || is(U == Date[]) || is(U == TimeOfDay[]))
        return "Marshalled_std_datetime_date[]";
    else static if(is(U == SysTime[]))
        return "Marshalled_std_datetime_systime[]";
    else
        return fullyQualifiedName!T;
}

As you can see the version in auto-wrap appears to be shorter.
mainly because there are no separate lines for the types DateTime Time and TimeOfDay.

Also note that you cannot use the getType which takes a string at runtime.
the only reason this works is because the cases are supposed to be constant expressions and at compile time it gets constant-folded into

        case 2658LU:
        {
            result = "Marshalled_Duration";
            break;
        }
        case 53134LU:
        case 55933LU:
        case 56951LU:
        {
            result = "Marshalled_std_datetime_date";
            break;
        }
        case 99806LU:
        {
            result = "Marshalled_std_datetime_systime";
            break;
        }
October 06, 2021

On Wednesday, 6 October 2021 at 11:43:46 UTC, Stefan Koch wrote:

>

Good Morning Everyone,

>
assert(isAggregateType(T));

this won't compile of course.
I shouldn't edit my examples after running them :)
just read the example without this line.