digitalmars.D - [core.reflect] TemplateInstance reflection
- Stefan Koch (211/211) Sep 30 2021 Good Evening everyone.
- russhy (3/3) Sep 30 2021 Playing with traits is often very tedious, i can already see the
- rikki cattermole (3/6) Oct 01 2021 All heil the linear O(n)!
- Elronnd (7/9) Oct 03 2021 I feel like all I ever do when you show off your incredible work
- Stefan Koch (14/24) Oct 04 2021 I am not sure what you mean with impractical changes.
- Stefan Koch (5/19) Oct 04 2021 ahhh you said; _you_ are proposing impractical changes,
- bauss (6/8) Oct 04 2021 That would also help when it comes to user code, as users
- Stefan Koch (4/12) Oct 04 2021 That is exactly what I meant.
- bauss (3/17) Oct 04 2021 That's great!
- jmh530 (19/20) Oct 04 2021 In the code below you can only get the target of the alias, such
- Stefan Koch (7/28) Oct 04 2021 You can get Foo by asking for the name "Foo"
- jmh530 (2/9) Oct 04 2021 Tanks. I was thinking getting the name of `Foo` from `x` or `y`.
- Stefan Koch (3/13) Oct 04 2021 That isn't currently possible.
- jmh530 (5/8) Oct 04 2021 Yeah, I figured. I keep thinking about DIP 1021 (resolution of
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: ```D 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); } ()); ``` ```JSON 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
Sep 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
Sep 30 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!
Oct 01 2021
On Thursday, 30 September 2021 at 22:19:33 UTC, Stefan Koch wrote:preliminary tests show that the reflection data-creation scales linearlyI 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?
Oct 03 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: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.preliminary tests show that the reflection data-creation scales linearlyI 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?
Oct 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: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.On Thursday, 30 September 2021 at 22:19:33 UTC, Stefan Koch wrote:I am not sure what you mean with impractical changes.preliminary tests show that the reflection data-creation scales linearlyI 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?
Oct 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
Oct 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: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.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
Oct 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:That's great! I'm really looking forward to this addition tbh.On Monday, 4 October 2021 at 07:26:30 UTC, Stefan Koch wrote: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.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
Oct 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? ```d 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)); } ```
Oct 04 2021
On Monday, 4 October 2021 at 11:54:09 UTC, jmh530 wrote:On Thursday, 30 September 2021 at 22:19:33 UTC, Stefan Koch wrote:You can get Foo by asking for the name "Foo" but it won't tell you much, right now as reflecting template declarations is a really tricky thing, they can have hidden errors in them, which puts the reflector in a bad state. Therefore I don't touch the bodies of template declarations right now.[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? ```d 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)); } ```
Oct 04 2021
On Monday, 4 October 2021 at 12:07:36 UTC, Stefan Koch wrote:[snip] You can get Foo by asking for the name "Foo" but it won't tell you much, right now as reflecting template declarations is a really tricky thing, they can have hidden errors in them, which puts the reflector in a bad state. Therefore I don't touch the bodies of template declarations right now.Tanks. I was thinking getting the name of `Foo` from `x` or `y`.
Oct 04 2021
On Monday, 4 October 2021 at 14:00:49 UTC, jmh530 wrote:On Monday, 4 October 2021 at 12:07:36 UTC, Stefan Koch wrote:That isn't currently possible. DMD rewrites that before core.reflect sees the function body.[snip] You can get Foo by asking for the name "Foo" but it won't tell you much, right now as reflecting template declarations is a really tricky thing, they can have hidden errors in them, which puts the reflector in a bad state. Therefore I don't touch the bodies of template declarations right now.Tanks. I was thinking getting the name of `Foo` from `x` or `y`.
Oct 04 2021
On Monday, 4 October 2021 at 16:04:32 UTC, Stefan Koch wrote:[snip] That isn't currently possible. DMD rewrites that before core.reflect sees the function body.Yeah, I figured. I keep thinking about DIP 1021 (resolution of alias template parameters) and keeping that information around somehow (pragma?) seems like it would be needed in the more general case.
Oct 04 2021