Jump to page: 1 2
Thread overview
[core.reflect] TemplateInstance reflection
Sep 30, 2021
Stefan Koch
Sep 30, 2021
russhy
Oct 01, 2021
rikki cattermole
Oct 04, 2021
Elronnd
Oct 04, 2021
Stefan Koch
Oct 04, 2021
Stefan Koch
Oct 04, 2021
bauss
Oct 04, 2021
Stefan Koch
Oct 04, 2021
bauss
Oct 04, 2021
jmh530
Oct 04, 2021
Stefan Koch
Oct 04, 2021
jmh530
Oct 04, 2021
Stefan Koch
Oct 04, 2021
jmh530
September 30, 2021

Good Evening everyone.

Today I have made progress with reflecting over template instances.

TLDR. core.reflect can almost replace __traits now and preliminary tests show that the reflection data-creation scales linearly.
Meaning 10 times as much code takes 10 times as much time to reflect.

The following code:

import core.reflect.reflect;

template TypeDef(string name, T)
{
    struct TypeDef
    {
        T value;
        alias value this;
    }
}

alias myInt = TypeDef!("myInt", int);

pragma(msg, () {
    auto n = nodeFromName("myInt", ReflectFlags.Everything);
    string[immutable(ulong)] cmap;
    return nodeToString(n, &cmap);
} ());
AliasDeclaration = {
    internalPointer: unhandled,
    serial: 599,
    astTypeName: "AliasDeclaration",
    name: "myInt",
    attributes: [],
    linkage: Default,
    comment: "",
    mangledName: "",
    location: Location = {
        filename: "testTemplateReflection.d",
        line: 12,
        column: 1,
    },
    parent: Module = {
        internalPointer: unhandled,
        serial: 580,
        astTypeName: "Module",
        _scope: Scope = {
            internalPointer: unhandled,
            serial: 0,
            astTypeName: "Scope",
        },
        identifier: "testTemplateReflection",
        parent: null,
        members: [
            DeclarationRef to 'myInt',
        ],
        packages: [],
        source_filename: "testTemplateReflection.d",
        string_import_filenames: [],
        declDefs: [],
    },
    storageClasses: [],
    type: TypeStruct = {
        internalPointer: unhandled,
        serial: 31545,
        astTypeName: "TypeStruct",
        kind: "struct",
        alignSize: 4,
        size: 4,
        identifier: "TypeDef!("myInt", int)",
        _unqualified: null,
        sym: StructDeclaration = {
            internalPointer: unhandled,
            serial: 31544,
            astTypeName: "StructDeclaration",
            name: "TypeDef",
            attributes: [],
            linkage: D,
            comment: "",
            mangledName: "22testTemplateReflection__T7TypeDefVAyaa5_6d79496e74TiZQBc",
            location: Location = {
                filename: "testTemplateReflection.d",
                line: 5,
                column: 5,
            },
            parent: TemplateInstance = {
                internalPointer: unhandled,
                serial: 597,
                astTypeName: "TemplateInstance",
                _scope: null,
                identifier: "",
                parent: Module = {
                    internalPointer: unhandled,
                    serial: 580,
                    astTypeName: "Module",
                    _scope: Scope = {
                        internalPointer: unhandled,
                        serial: 0,
                        astTypeName: "Scope",
                    },
                    identifier: "testTemplateReflection",
                    parent: null,
                    members: [
                        DeclarationRef to 'myInt',
                    ],
                    packages: [],
                    source_filename: "testTemplateReflection.d",
                    string_import_filenames: [],
                    declDefs: [],
                },
                members: [
                    DeclarationRef to 'TypeDef',
                ],
                name: "TypeDef",
                decl: TemplateDeclaration = {
                    internalPointer: unhandled,
                    serial: 594,
                    astTypeName: "TemplateDeclaration",
                    name: "TypeDef",
                    attributes: [],
                    linkage: Default,
                    comment: "",
                    mangledName: "22testTemplateReflection7TypeDef",
                    location: Location = {
                        filename: "testTemplateReflection.d",
                        line: 3,
                        column: 1,
                    },
                    parent: Module = {
                        internalPointer: unhandled,
                        serial: 580,
                        astTypeName: "Module",
                        _scope: Scope = {
                            internalPointer: unhandled,
                            serial: 0,
                            astTypeName: "Scope",
                        },
                        identifier: "testTemplateReflection",
                        parent: null,
                        members: [
                            DeclarationRef to 'myInt',
                        ],
                        packages: [],
                        source_filename: "testTemplateReflection.d",
                        string_import_filenames: [],
                        declDefs: [],
                    },
                    storageClasses: [],
                    isEponymous: true,
                    constraint: null,
                },
            },
            storageClasses: [],
            type: TypeRef to 'TypeDef!("myInt", int)',
            fields: [
                VariableDeclaration = {
                    internalPointer: unhandled,
                    serial: 31547,
                    astTypeName: "VarDeclaration",
                    name: "value",
                    attributes: [],
                    linkage: D,
                    comment: "",
                    mangledName: "_D22testTemplateReflection__T7TypeDefVAyaa5_6d79496e74TiZQBc5valuei",
                    location: Location = {
                        filename: "testTemplateReflection.d",
                        line: 7,
                        column: 11,
                    },
                    parent: DeclarationRef to 'TypeDef',
                    storageClasses: [
                        Field,
                        Ctorinit,
                    ],
                    type: TypeBasic = {
                        internalPointer: unhandled,
                        serial: 138,
                        astTypeName: "TypeBasic",
                        kind: "int",
                        alignSize: 4,
                        size: 4,
                        identifier: "int",
                        _unqualified: null,
                    },
                    _init: null,
                    offset: unhandled,
                },
            ],
            members: [
                DeclarationRef to 'value',
            ],
        },
    },
    decl: null,
}

As you can see it is possible to look through the type alias myInt Into the template-instance TypeDef!("myInt", int) and through there into the eponymous struct Declaration.

I am aware that the produced tree is fairly big however I've thought that a more faithful representation of the Tree inside the compiler would be useful to more people than a cut down version which is tailored to specific use-cases that I know of.

As always I would be very happy about positive feedback or constructive criticism.

Have a very nice day/night/evening/morning.

Cheers,
Stefan

September 30, 2021

Playing with traits is often very tedious, i can already see the advantages of using core.reflect instead, and it's working with templates, impressive work

October 01, 2021
On 01/10/2021 11:19 AM, Stefan Koch wrote:
> TLDR. core.reflect can almost replace `__traits` now and preliminary tests show that the reflection data-creation scales linearly.
> Meaning 10 times as much code takes 10 times as much time to reflect.

All heil the linear O(n)!

May it ever get cheaper!
October 04, 2021
On Thursday, 30 September 2021 at 22:19:33 UTC, Stefan Koch wrote:
> preliminary tests show that the reflection data-creation scales linearly

I feel like all I ever do when you show off your incredible work on core.reflect or newctfe is propose completely impractical changes.  Well, let me propose another one :)

Have you considered using the same in-memory layout for the compiler's own structures as for the core.reflect ones, so it's not linear-time but constant-time?
October 04, 2021
On Monday, 4 October 2021 at 04:40:37 UTC, Elronnd wrote:
> On Thursday, 30 September 2021 at 22:19:33 UTC, Stefan Koch wrote:
>> preliminary tests show that the reflection data-creation scales linearly
>
> I feel like all I ever do when you show off your incredible work on core.reflect or newctfe is propose completely impractical changes.  Well, let me propose another one :)
>
> Have you considered using the same in-memory layout for the compiler's own structures as for the core.reflect ones, so it's not linear-time but constant-time?

I am not sure what you mean with impractical changes.
It's true that newCTFE turned out to be much bigger in scope and required work than anticipated.
Whereas core.reflect is actually manageable.
I have considered just exposing the compiler internal data-structures directly.
But that would be completely unmaintainable as the ABI would break on nearly every compiler release.
The reason core.reflect uses it's own class hierarchy is to have a buffer between what is exposed to the user and the compiler internals.
Such that there is at least the possibility of changing one without having to change the other at the same time.

October 04, 2021
On Monday, 4 October 2021 at 07:26:30 UTC, Stefan Koch wrote:
> On Monday, 4 October 2021 at 04:40:37 UTC, Elronnd wrote:
>> On Thursday, 30 September 2021 at 22:19:33 UTC, Stefan Koch wrote:
>>> preliminary tests show that the reflection data-creation scales linearly
>>
>> I feel like all I ever do when you show off your incredible work on core.reflect or newctfe is propose completely impractical changes.  Well, let me propose another one :)
>>
>> Have you considered using the same in-memory layout for the compiler's own structures as for the core.reflect ones, so it's not linear-time but constant-time?
>
> I am not sure what you mean with impractical changes.
ahhh you said; _you_ are proposing impractical changes,
not that I am proposing impractical changes .... :-)
My bad.
Yeah using the same structure is completely impractical.

October 04, 2021
On Monday, 4 October 2021 at 07:26:30 UTC, Stefan Koch wrote:
> Such that there is at least the possibility of changing one without having to change the other at the same time.

That would also help when it comes to user code, as users wouldn't have to change due to breaking changes, only core.reflect behind the scene would have to maintain breaking changes.

Unless that's what you meant
October 04, 2021
On Monday, 4 October 2021 at 09:31:45 UTC, bauss wrote:
> On Monday, 4 October 2021 at 07:26:30 UTC, Stefan Koch wrote:
>> Such that there is at least the possibility of changing one without having to change the other at the same time.
>
> That would also help when it comes to user code, as users wouldn't have to change due to breaking changes, only core.reflect behind the scene would have to maintain breaking changes.
>
> Unless that's what you meant

That is exactly what I meant.
The interface for the reflection consumer it supposed to be stable after it has shown that it is sufficient.
October 04, 2021
On Monday, 4 October 2021 at 09:46:03 UTC, Stefan Koch wrote:
> On Monday, 4 October 2021 at 09:31:45 UTC, bauss wrote:
>> On Monday, 4 October 2021 at 07:26:30 UTC, Stefan Koch wrote:
>>> Such that there is at least the possibility of changing one without having to change the other at the same time.
>>
>> That would also help when it comes to user code, as users wouldn't have to change due to breaking changes, only core.reflect behind the scene would have to maintain breaking changes.
>>
>> Unless that's what you meant
>
> That is exactly what I meant.
> The interface for the reflection consumer it supposed to be stable after it has shown that it is sufficient.

That's great!

I'm really looking forward to this addition tbh.
October 04, 2021

On Thursday, 30 September 2021 at 22:19:33 UTC, Stefan Koch wrote:

>

[snip]

In the code below you can only get the target of the alias, such as int and float. Would it be possible to use core.reflect or something similar, to be able to get back Foo or Foo!int?

template Foo(T)
{
    static if(is(T == int))
        alias Foo = int;
    else
        alias Foo = float;
}

void main() {
    Foo!int x;
    Foo!double y;
    static assert(is(typeof(x) == int));
    static assert(is(typeof(y) == float));
}
« First   ‹ Prev
1 2