I give up! I tried to create a reflection library but D's traits are just too screwed up!

Alex AJ at gmail.com
Sat Apr 6 13:17:01 UTC 2019


On Friday, 5 April 2019 at 16:00:26 UTC, Adam D. Ruppe wrote:
> On Thursday, 4 April 2019 at 02:19:48 UTC, Alex wrote:
>> But because there is no `T` for fields we can't do it so easy, 
>> so we have to construct the name and use string mixins.
>
> You should pass fields as an alias more often than not. It is a 
> little tricky when you want to read/write it (the alias is not 
> a value, so you need to pass a pointer or something 
> separately), but for reflection you want to use the alias.
>
> UDAs do not exist on types per se, since they are tied to 
> symbols.
>
>> mixin(`static foreach(a;  __traits(getAttributes, 
>> `~T.stringof~`.`~name~`))
>
> This shouldn't use mixin at all, and even if you do use mixin, 
> it shouldn't be using stringof; .stringof is a code smell and 
> should almost never be used. This bypasses the local symbol. 
> That is actually the reason why you get a visibility error.
>
> Just use T. more info: 
> https://stackoverflow.com/questions/32615733/struct-composition-with-mixin-and-templates/32621854#32621854


Ok, I was able to remove all of them I believe. I got in the 
habit because I routinely switch the mixin to a pragma(msg and 
having the actual name their is far more informative than T, 
helps find out if the type if wrong).


I don't know why it is code smell, since it should ultimately end 
up the same.


Fixing this did not solve the `private` error.

// Get the attributes for the field
mixin(`Protection = __traits(getProtection, T.`~name~`);`);


In any case, the code seems to be fundamentally working now, as I 
mentioned in a previous thread. I just have to finish dealing 
with all the other types, which shouldn't be a huge problem.



-----------

As far as using an alias as fields,

The code is this:

	// Get the fields
	alias n = FieldNameTuple!T;
	static foreach(k, f; std.traits.Fields!T)
	{{
		Fields ~= (new cFieldReflection()).Reflect!(Alias!T, n[k]);
	}}

I am passing the base type and the name then building it inside 
Reflect, I've tried passing various things so I could simplify 
the code, but I am unable to get anything to work.



auto Reflect(alias T, string name)()
{		
	static if (name != "")
	{
		// There is no field type so must manually construct and 
duplicate code, else we could reflect directly
		mixin(`import `~moduleName!T~`;`);	
//		mixin(`super.Reflect!(T.`~name~`);`);

		Id = name;	
		static if (__traits(compiles, TypeName = T.stringof)) TypeName 
= T.stringof~"."~name;
		ModuleName = moduleName!(T);
		FullName = fullyQualifiedName!(T)~"."~name;
		MangledName = mangledName!T;

		// Get the attributes for the field
		mixin(`Protection = __traits(getProtection, T.`~name~`);`);
		mixin(`static if (__traits(compiles, __traits(getProtection, 
T.`~name~`)))				
			static foreach(a;  __traits(getAttributes, T.`~name~`)) 
Attributes ~= sAttributeReflection(to!string(a), 
typeof(a).stringof);`);
	}
	return this;
		
}

If I could call super.Reflect then it would fill in all the info 
and I could remove the Id = name ... MangledName lines and 
consolidate code. But I have not figure out how to get any of 
that code to work without constructing the symbols by hand.



More information about the Digitalmars-d mailing list