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

Alex AJ at gmail.com
Wed Apr 3 07:22:10 UTC 2019


The follow code is a reflection library that unifies all the junk 
in std.traits and __traits and makes it using reflection as if it 
were runtime and one can even keep the info around at runtime...

But D's type system is too screwed up. Fields and members are not 
treated as types in and have themselves so 1. Building a compact 
code base is impossible. 2. The type system sometimes requires 
using alias and sometimes a type yet there is no way to unify the 
two to reduce code bloat and everything must be duplicated. 3. 
The Type's do not carry their moodules and import automatically 
so the symbols can be used. This requires getting the module and 
importanting things. Further more certain _traits want a this 
object to work for fields and others don't but none of the 
methods seem sensical. 4. If a symbol is private CT __traits 
fails..., again non-sensical.

The following code works flawlessly for aggregates. I'm able to 
get all the proper info but I've spend 10x as long on this code 
just trying to make sense of fields and members and can't get 
anything to work properly in any way that makes sense.

I will stop working on this unless someone can tell me how I'm 
suppose to fill in the appropriate info for fields and members or 
fixes the compiler to work corretly.


The idea here is that instead of having to use D's terrible 
std.traits and __traits(which are hard to remember and nuanced)), 
the code simply wraps all the calls and get's all the meta info 
in to a oop class hierarchy(at CT using CTFE).

auto CR = Reflect!(cDerived!int);

CR is a class that we can then use to find out all the meta info. 
CR.TypeName, CR.MangledName, CR.DType, CR.ModuleName, 
CR.Attributes, etc...

Everything gets unified with standard oop and it's all their at 
compile time. Since it just wraps most of the std.traits and 
__traits, it only provides a common and uniform interface. It 
reduces a lot of the boil plate code of having to deal with this 
stuff(Which is why I attempted it). I got tired of having to do 
the same things over and over such as recurse through the type 
hierarchy to find something. Here one can use CTFE and runtime 
programming and avoid most of the CT code. (although since it 
collects all the information at once it probably is extremely 
inefficent).

Ideally D would have provided us with a simple Type that 
contained all this info from the get go.

I'd hate abandonding this since it is working quite well and 
virtually has no issues except the fields and members problem 
which is pretty much making the whole program useless(sure it 
works on functions and aggregates but fields and members are 
probaby even more important).

Hopefully someone can figure out how to make it work.



int main()
{
	pragma(msg, printModelHierarchy(Reflect!(cDerived!int)));
}

This is the output of the program, it shows the "complete"(if the 
issues didn't exist) reflection of cDerived.


	Id = cDerived
	TypeName = cDerived!int
	FullName = mModel.cDerived!(int)
	ModuleName = mModel
	MangledName = C6mModel__T8cDerivedTiZQm
	Protection = public
	Body =
	Uses = []
	Attributes = [
		sAttributeReflection("fdsa", "string"),
		sAttributeReflection("8", "int")
	]
	IsNested = false
	IsInnerClass = false
	HasUnsharedAliasing = true
	HasNested = false
	HasIndirections = true
	HasElaborateDestructor = false
	HasElaborateCopyConstructor = false
	HasElaborateAssign = false
	HasAliasing = true
	TypeParameters = []
	AliasThis = [sTypeReflection("type", "cType")]
	NestedAggregates = []
	DerivedClasses = []
	Fields = [
		Id = type
		TypeName = cDerived!int.type
		FullName = mModel.cDerived!(int).type
		ModuleName = mModel
		MangledName = C6mModel__T8cDerivedTiZQm
		Protection =
		Body =
		Uses = []
		Attributes = []
		DType = field
		,
		Id = testField1
		TypeName = cDerived!int.testField1
		FullName = mModel.cDerived!(int).testField1
		ModuleName = mModel
		MangledName = C6mModel__T8cDerivedTiZQm
		Protection =
		Body =
		Uses = []
		Attributes = []
		DType = field
		,
		Id = testField2
		TypeName = cDerived!int.testField2
		FullName = mModel.cDerived!(int).testField2
		ModuleName = mModel
		MangledName = C6mModel__T8cDerivedTiZQm
		Protection =
		Body =
		Uses = []
		Attributes = []
		DType = field
	]
	Methods = [
		Id = @property int()
		TypeName = cDerived!int.ValueProp
		FullName = mModel.cDerived!(int).ValueProp
		ModuleName = mModel
		MangledName = C6mModel__T8cDerivedTiZQm
		Protection =
		Body =
		Uses = []
		Attributes = []
		DType = delegate
		Overloads = [
			Id =
			TypeName =
			FullName =
			ModuleName =
			MangledName =
			Protection =
			Body =
			Uses = []
			Attributes = []
			DType = function
			Signature = @property int()
			NumArgs = 0
			Linkage = D
			Parameters = []
		]
	]
	InheritedInterfaces = [
		Id = iX
		TypeName = iX
		FullName = mModel.iX
		ModuleName = mModel
		MangledName = C6mModel2iX
		Protection = public
		Body =
		Uses = []
		Attributes = []
		IsNested = false
		IsInnerClass = false
		HasUnsharedAliasing = true
		HasNested = false
		HasIndirections = true
		HasElaborateDestructor = false
		HasElaborateCopyConstructor = false
		HasElaborateAssign = false
		HasAliasing = true
		TypeParameters = []
		AliasThis = []
		NestedAggregates = []
		DerivedClasses = []
		Fields = [
			Id =
			TypeName = iX.
			FullName = mModel.iX.
			ModuleName = mModel
			MangledName = C6mModel2iX
			Protection =
			Body =
			Uses = []
			Attributes = []
			DType = field
		]
		Methods = []
		DType = interface
		InheritedInterfaces = []
		,
		Id = iY
		TypeName = iY
		FullName = mModel.iY
		ModuleName = mModel
		MangledName = C6mModel2iY
		Protection = public
		Body =
		Uses = []
		Attributes = []
		IsNested = false
		IsInnerClass = false
		HasUnsharedAliasing = true
		HasNested = false
		HasIndirections = true
		HasElaborateDestructor = false
		HasElaborateCopyConstructor = false
		HasElaborateAssign = false
		HasAliasing = true
		TypeParameters = []
		AliasThis = []
		NestedAggregates = []
		DerivedClasses = []
		Fields = [
			Id =
			TypeName = iY.
			FullName = mModel.iY.
			ModuleName = mModel
			MangledName = C6mModel2iY
			Protection =
			Body =
			Uses = []
			Attributes = []
			DType = field
		]
		Methods = []
		DType = interface
		InheritedInterfaces = []
	]
	DType = class
	IsAbstract = false
	Alignment = 8
	InheritedClasses = [
		Id = cBase
		TypeName = cBase
		FullName = mModel.cBase
		ModuleName = mModel
		MangledName = C6mModel5cBase
		Protection = public
		Body =
		Uses = []
		Attributes = []
		IsNested = false
		IsInnerClass = false
		HasUnsharedAliasing = true
		HasNested = false
		HasIndirections = true
		HasElaborateDestructor = false
		HasElaborateCopyConstructor = false
		HasElaborateAssign = false
		HasAliasing = true
		TypeParameters = []
		AliasThis = []
		NestedAggregates = []
		DerivedClasses = []
		Fields = [
			Id = testField
			TypeName = cBase.testField
			FullName = mModel.cBase.testField
			ModuleName = mModel
			MangledName = C6mModel5cBase
			Protection =
			Body =
			Uses = []
			Attributes = []
			DType = field
		]
		Methods = [
			Id = cBase(iBase c)
			TypeName = cBase.fooBase
			FullName = mModel.cBase.fooBase
			ModuleName = mModel
			MangledName = C6mModel5cBase
			Protection =
			Body =
			Uses = []
			Attributes = []
			DType = delegate
			Overloads = [
				Id =
				TypeName =
				FullName =
				ModuleName =
				MangledName =
				Protection =
				Body =
				Uses = []
				Attributes = []
				DType = function
				Signature = cBase(iBase)
				NumArgs = 1
				Linkage = D
				Parameters = []
			]
		]
		InheritedInterfaces = [
			Id = iBase
			TypeName = iBase
			FullName = mModel.iBase
			ModuleName = mModel
			MangledName = C6mModel5iBase
			Protection = public
			Body =
			Uses = []
			Attributes = [
				sAttributeReflection("fdsa", "string"),
				sAttributeReflection("4", "int")
			]
			IsNested = false
			IsInnerClass = false
			HasUnsharedAliasing = true
			HasNested = false
			HasIndirections = true
			HasElaborateDestructor = false
			HasElaborateCopyConstructor = false
			HasElaborateAssign = false
			HasAliasing = true
			TypeParameters = []
			AliasThis = []
			NestedAggregates = []
			DerivedClasses = []
			Fields = [
				Id =
				TypeName = iBase.
				FullName = mModel.iBase.
				ModuleName = mModel
				MangledName = C6mModel5iBase
				Protection =
				Body =
				Uses = []
				Attributes = []
				DType = field
			]
			Methods = [
				Id = iBase(iBase)
				TypeName = iBase.fooBase
				FullName = mModel.iBase.fooBase
				ModuleName = mModel
				MangledName = C6mModel5iBase
				Protection =
				Body =
				Uses = []
				Attributes = []
				DType = delegate
				Overloads = [
					Id =
					TypeName =
					FullName =
					ModuleName =
					MangledName =
					Protection =
					Body =
					Uses = []
					Attributes = []
					DType = function
					Signature = iBase(iBase)
					NumArgs = 1
					Linkage = D
					Parameters = []
				]
			]
			DType = interface
			InheritedInterfaces = []
		]
		DType = class
		IsAbstract = false
		Alignment = 4
		InheritedClasses = [Object]
	]












module mReflect;

import mExTraits;
import std.meta, std.conv, std.typecons, std.typetuple, 
std.string, std.algorithm, std.range, std.variant;


struct sTypeReflection
{
	string Name;
	string Type;
	this(string n, string t) { Name = n; Type = t; }
}


struct sAttributeReflection
{
	string Value;
	string Type;
	this(string v, string t) { Value = v; Type = t; }
}



/*
	Encapsulation of basic reflection
*/
abstract class cBaseReflection
{
	// Declared in reverse order for proper output
	sAttributeReflection[] Attributes;			// Attributes on the type
	cBaseReflection[] Uses;						// Known types that use this type 
as a field, parameter, return type, etc
	string Body;								// D does not allow getting a body but this 
is included if it ever does
	string Protection;
	string MangledName;
	string ModuleName;							// The module name
	string FullName;							// The fully qualified name
	string TypeName;							// The type name
	string Id;									// The id  = __traits(identifier,T)
	
	string DType() { return "Unknown"; }

	auto Reflect(alias T)()
	{
		
		Id = __traits(identifier, T);	
		static if (__traits(compiles, T.stringof)) TypeName = 
T.stringof;
		static if (__traits(compiles, moduleName!T)) ModuleName = 
moduleName!(T);
		static if (__traits(compiles, fullyQualifiedName!T)) FullName = 
fullyQualifiedName!(T);
		static if (__traits(compiles, mangledName!T)) MangledName = 
mangledName!T;
		static if (__traits(compiles, __traits(getProtection, T))) 
Protection = __traits(getProtection, T);
		// Get the attributes for the type
		static if (__traits(compiles, __traits(getAttributes, T)))
			static foreach(a;  __traits(getAttributes, T)) Attributes ~= 
sAttributeReflection(to!string(a), typeof(a).stringof);

		return this;
	}
}

/*
Encapsulates an Enumeration Reflection
*/
class cEnumReflection : cBaseReflection
{
	static struct sValueReflection
	{
		string Name;
		string Value;		
		sAttributeReflection[] Attributes;			
		this(string n, string v) { Name = n; Value = v; }
	} sValueReflection[] Values;

	string BaseType;
	override string DType() { return "enum"; }

	auto Reflect(alias T)()
	{
		super.Reflect!T;
		
		//BaseType = TypeOf(T).stringof;
		static foreach(e; EnumMembers!T)
		{{
			Values ~= sValueReflection(to!string(e), e.stringof);
			mixin("alias E = __traits(getAttributes, 
T."~to!string(e)~");");			
			static foreach(a; E) 						
				Values[$-1].Attributes ~= sAttributeReflection(to!string(a), 
typeof(a).stringof);							
		}}

		return this;
	}
}







/*
	Encapsulates an Aggregate Type
*/
abstract class cAggregateReflection : cBaseReflection
{		

	
	
	cMethodReflection[] Methods;							// The methods
	cFieldReflection[] Fields;								// The fields
	cClassReflection[] DerivedClasses;						// Known immedate 
derived class that derive this type
	cAggregateReflection[] NestedAggregates;				// Any nested 
aggregates
	sTypeReflection[] AliasThis;							// The Alias This	
	sTypeReflection[] TypeParameters;						// Any type parameters 
used.
	bool HasAliasing;
	bool HasElaborateAssign;
	bool HasElaborateCopyConstructor;
	bool HasElaborateDestructor;
	bool HasIndirections;
	bool HasNested;
	bool HasUnsharedAliasing;
	bool IsInnerClass;
	bool IsNested;
	
	override string DType() { return "Unknown"; }

	auto Reflect(alias T)()
	{
		super.Reflect!T;

		// Get the Alias This
		static foreach(a;  __traits(getAliasThis, T))
		{{
			mixin("import "~moduleName!T~";");		
			mixin("AliasThis ~= sTypeReflection(to!string(a), 
typeof("~moduleName!T~"."~T.stringof~"."~to!string(a)~").stringof);");
		}}

		HasAliasing = hasAliasing!T;
		HasElaborateAssign = hasElaborateAssign!T;
		HasElaborateCopyConstructor = hasElaborateCopyConstructor!T;
		HasElaborateDestructor = hasElaborateDestructor!T;
		HasIndirections = hasIndirections!T;
		HasNested = hasNested!T;
		HasUnsharedAliasing = hasUnsharedAliasing!T;
		static if (__traits(compiles, isInnerClass!T)) IsInnerClass = 
isInnerClass!T;
		static if (__traits(compiles, isNested!T)) IsNested = 
isNested!T;
		
	
		// Get the fields
		alias n = FieldNameTuple!T;
		static foreach(k, f; std.traits.Fields!T)
		{{
			Fields ~= (new cFieldReflection()).Reflect!(Alias!T, n[k]);
		}}


		static foreach(k, m; __traits(derivedMembers, T))
		{{
			static if (__traits(compiles, __traits(getVirtualMethods, T, 
m)))
			static foreach(j, v; typeof(__traits(getVirtualMethods, T, 
m)))		
			{{
				//pragma(msg, T.stringof, " --- ", v.stringof);
				Methods ~= (new cMethodReflection()).Reflect!(T, m);

			}}
		}}
		return this;
	}
}


/*
Encapsulates a Field Reflection
*/
class cFieldReflection : cBaseReflection
{
	override string DType() { return "field"; }

	auto Reflect(alias T, string name)()
	{		
		// There is no field type so must manually construct and 
duplicate code, else we could reflect directly

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

		*/

		

		// Get the attributes for the field
		import mModel;
		static if (__traits(compiles, mixin(`static if 
(__traits(compiles, __traits(getAttributes, 
`~T.stringof~`.`~name~`)))`)))
		mixin(`static if (__traits(compiles, __traits(getAttributes, 
`~T.stringof~`.`~name~`))) pragma(msg, "fdadsf"); `);
		//static if (aFound) { mixin(`static foreach(a;  
__traits(getAttributes, `~T.stringof~`.`~name~`)) Attributes ~= 
sAttributeReflection(to!string(a), typeof(a).stringof);`);}

		//pragma(msg, T);
		//T t;
		//mixin("alias X = t."~name~";");
		//super.Reflect!X;

		return this;
	}
}


/*
Encapsulates a Method Reflection
*/
class cMethodReflection : cBaseReflection
{
	cFunctionReflection[] Overloads;

	override string DType() { return "delegate"; }

	auto Reflect(alias T, string name)()
	{
		
		// There is no method type so must manually construct and 
duplicate code, else we could reflect directly
		//super.Reflect!T;

		mixin(`import `~moduleName!T~`;`);	// Must import the type to 
be able to inspect it(fragile and bizzare and ridiculous)
		T t = T.init;


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

		static if (__traits(compiles, __traits(getOverloads, T, name)))
		{			
			static foreach (f; typeof(__traits(getOverloads, T, name)))
			{
				//pragma(msg, f, " --- ", f.stringof);
				Overloads ~= (new cFunctionReflection()).Reflect!(Alias!f);
				//pragma(msg, name, " --- ", (t.f).stringof);
				mixin(`Id = "`~f.stringof~`";`);
				/*

				mixin(`Signature = 
FunctionTypeOf!(`~T.stringof~`.`~name~`).stringof;`);
				pragma(msg, `Signature = 
FunctionTypeOf!(`~T.stringof~`.`~name~`).stringof;`);
				NumArgs = arity!T;
				Linkage = functionLinkage!T;
				VariadicFunctionStyle = variadicFunctionStyle!T;
				mixin(`Protection = __traits(getProtection, 
(`~T.stringof~`).`~name~`);`);
				*/
			}
		}

		return this;
	}
}


/*
	Encapsulates a Union Reflection
*/
class cUnionReflection : cAggregateReflection
{
	override string DType() { return "union"; }

	auto Reflect(alias T)()
	{
		super.Reflect!T;

		return this;
	}
}


/*
	Encapsulates a Struct Reflection
*/
class cStructReflection : cAggregateReflection
{
	override string DType() { return "struct"; }

	auto Reflect(alias T)()
	{
		super.Reflect!T;

		return this;

	}
}



/*
	Encapsulates a Interface Reflection
*/
class cInterfaceReflection : cAggregateReflection
{	
	cInterfaceReflection[] InheritedInterfaces;				// The inherited 
interfaces
	override string DType() { return "interface"; }

	auto Reflect(alias T)()
	{
		super.Reflect!T;
		
		// Reflect on inherited interfaces
		static foreach(t; BaseTypeTuple!T)
			static if (isInterface!t)
				InheritedInterfaces ~= (new 
cInterfaceReflection()).Reflect!(t);


		return this;
	}
}



/*
	Encapsulates a Class Reflection
*/
class cClassReflection : cInterfaceReflection
{


	
	cClassReflection[] InheritedClasses;					// Any Inherited 
class(D only allows single class inheritance, but we allow for 
possibly more for uniformity)	
	int Alignment;
	bool IsAbstract = false;
	override string DType() { return "class"; }
	auto Reflect(alias T)()
	{
		super.Reflect!T;

		IsAbstract = isAbstractClass!T;
		Alignment = classInstanceAlignment!T;

		// Reflect on inherited class
		static foreach(t; BaseTypeTuple!T)
			static if (isClass!t)
				InheritedClasses ~= (new cClassReflection()).Reflect!(t);


		return this;
	}
}






/*
	Encapsulates a Function Reflection
*/
class cFunctionReflection : cBaseReflection
{
	static struct sParameterReflection
	{
		string Name;
		string Type;
		string DefaultValue = "none";
		string DefaultValueType = "void";
		struct sStorageClass
		{
			static foreach(a; EnumMembers!ParameterStorageClass)
				mixin(`bool Is`~strip(capitalize(to!string(a)),"_")~";");
		} sStorageClass StorageClass;
		this(string n, string t, string dv, string dt) { Name = n; Type 
= t; DefaultValue = dv; DefaultValueType = dt; }
	}

	static struct sFunctionAttributes
	{
		static foreach(a; EnumMembers!FunctionAttribute)
			mixin(`bool Is`~strip(capitalize(to!string(a)),"_")~";");
	} sFunctionAttributes FunctionAttributes;
	sParameterReflection[] Parameters;
	sTypeReflection ReturnType;



	
	string Linkage;
	Variadic VariadicFunctionStyle;
	int NumArgs;
	string Signature;
	override string DType() { return "function"; }

	auto Reflect(T)()
	{
		Signature = FunctionTypeOf!T.stringof;
		NumArgs = arity!T;
		Linkage = functionLinkage!T;
		VariadicFunctionStyle = variadicFunctionStyle!T;

		return this;
	}

	auto Reflect(alias T)()
	{
		super.Reflect!T;

		Signature = FunctionTypeOf!T.stringof;
		NumArgs = arity!T;
		Linkage = functionLinkage!T;
		VariadicFunctionStyle = variadicFunctionStyle!T;
		
		
		static foreach(a; EnumMembers!FunctionAttribute)
			mixin(`FunctionAttributes.Is`~strip(capitalize(to!string(a)),"_")~" = (functionAttributes!T & FunctionAttribute."~to!string(a)~") != 0;");

		static foreach(k, a; std.traits.Parameters!T)
		{{
			static if (__traits(compiles, 
typeof(ParameterDefaults!T[k]).stringof))
				enum dt = typeof(ParameterDefaults!T[k]).stringof;
			else
				enum dt = "void";

			Parameters ~= 
sParameterReflection(ParameterIdentifierTuple!T[k], a.stringof, 
ParameterDefaults!T[k].stringof, dt);			
			static foreach(j, a; EnumMembers!ParameterStorageClass)
				mixin(`Parameters[k].StorageClass.Is`~strip(capitalize(to!string(a)),"_")~" = (ParameterStorageClassTuple!T[k] & ParameterStorageClass."~to!string(a)~") != 0;");
		}}

		ReturnType = sTypeReflection("", 
std.traits.ReturnType!T.stringof);

	}
}

/*
Encapsulates a Delegate Reflection
*/
class cDelegateReflection : cFunctionReflection
{
	override string DType() { return "delegate"; }

	auto Reflect(alias T)()
	{
		super.Reflect!T;

		return this;
	}
}








/*
	Takes a type and builds it's inheritance and uses hierarchy.
*/
auto Reflect(Ts...)()
{
	alias T = Ts[0];
	
	static foreach(t; ["class", "interface", "struct", "union", 
"function", "delegate", "enum"])
		mixin("static if (is"~capitalize(t)~"!(T)) { auto model = new 
c"~capitalize(t)~"Reflection(); model.Reflect!T(); } ");


	return model;
}




auto printModelHierarchy(T, int depth = 1)(T model)
{static if (depth > 20) return "ERROR"; else {
	auto res = "";
	auto tab = "\t".replicate(depth);
	if (model.TypeName == "Object") return "Object";
	
	// Print out basic info, allMembers returns funky as it returns 
the most derived first from top to bottom. Generally we want to 
display the least derived from top to bottom. Reversing gets us 
bottom to top though so we must declare them in reverse order in 
the types.
	static foreach(k, m; [Reverse!(__traits(allMembers, T))])
	{{
		static if (!canFind(["factory", "Monitor", "opEquals", "opCmp", 
"toHash", "toString", "Reflect"], m))		// Ignore these
		{
			mixin(`alias Q = TypeOf!(T.`~m~`);`);	
			
			static if (isPrimitive!Q || isString!Q)																	// 
Print primitives
				mixin(`res ~= tab~m~" = 
"~to!string(model.`~m.stringof[1..$-1]~`)~"\n";`);	
			else static if (__traits(compiles, is(ReturnType!Q == string)) 
&& is(ReturnType!Q == string))			// Print functions that return 
strings
			{			
				mixin(`res ~= tab~m~" = 
"~model.`~m.stringof[1..$-1]~`()~"\n";`);	
			}
			else																									// Print other types
			{				
				static if (is(Q U : U[]) && !is(U == Object))														// 
Print Arrays, handling recursion
				{{										
					mixin("auto arr = model."~m~";");
					if (arr.length > 0)
					{
						string[] r;
						foreach(a; arr)
						{
								static if (is(U : cBaseReflection))
									r ~= printModelHierarchy!(U, depth + 1)(a).strip("\t\n 
,");								
								else
									r ~= to!string(a).strip("\t\n ,");
						}

						// Prepare results
						auto q = r.join(",");
						if (q.length > 60 || r.canFind("\n") || r.canFind(","))
							static if (is(U : cBaseReflection))
								q = 
"\n"~tab~"\t"~r.join("\n"~tab~"\t,\n"~tab~"\t")~"\n"~tab;
							else
								q = "\n"~tab~"\t"~r.join(",\n"~tab~"\t")~"\n"~tab;
						res ~= tab~m~" = ["~q~"]\n";
					} else res ~= tab~m~" = []\n";
					
				}}
			}
		
		
		}
	}}

	return res;
}}






















module mExTraits;

public import std.traits;
public import std.meta;


enum isPrimitive(T) = is(T == bool) || is(T == byte) || is(T == 
cdouble) || is(T == creal) || is(T == cfloat) || is(T == char) || 
is(T == dchar) ||
						is(T == double) || is(T == float) || is(T == idouble) || 
is(T == ifloat) || is(T == int) || is(T == ireal) || is(T == 
long) || is(T == real) ||
						is(T == short) || is(T == ubyte)  || is(T == uint) || is(T 
== ulong) || is(T == ushort) || is(T == wchar);
enum isPrimitive(alias T) = is(T == bool) || is(T == byte) || 
is(T == cdouble) || is(T == creal) || is(T == cfloat) || is(T == 
char) || is(T == dchar) ||
						is(T == double) || is(T == float) || is(T == idouble) || 
is(T == ifloat) || is(T == int) || is(T == ireal) || is(T == 
long) || is(T == real) ||
						is(T == short) || is(T == ubyte) || is(T == uint) || is(T 
== ulong) || is(T == ushort) || is(T == wchar);
enum Is(A,B) = is(A == B);
enum isFloatingPoint(T) = is(T == float) || is(T == double) || 
is(T == real) || is(T == cfloat) || is(T == cdouble) || is(T == 
creal) || is(T == ifloat) || is(T == idouble) || is(T == ireal);
enum isClass(T) = is(T == class);
enum isClass(alias T) = is(T == class);
enum isInterface(T) = is(T == interface);
enum isInterface(alias T) = is(T == interface);
enum isObject(T) = isClass!(T) || isInterface!(T);
enum isStruct(T) = is(T == struct);
enum isStruct(alias T) = is(T == struct);
enum isUnion(T) = is(T == union);
enum isUnion(alias T) = is(T == union);
enum isArray(T) = is(T U : U[]);
enum isStaticArray(T) = is(T : U[n], U, size_t n);
enum isString(T) = is(T : string) || is(T : wstring) || is(T : 
dstring);
enum isString(alias T) = is(T : string) || is(T : wstring) || 
is(T : dstring);
enum isAssociativeArray(T) = 
is(typeof(T.init.values[0])[typeof(T.init.keys[0])] == T);
enum isPointer(T) = is(T U : U*);
enum isFunctionPointer(T) = is(typeof(*T) == function);
enum isEnum(T) = is(T == enum);
enum isEnum(alias T) = is(T == enum);
enum isReference(T) = isObject!(T) || isPointer!(T);
enum isVoid(T) = is(T == void);
enum isSymbol(alias arg) = __traits(compiles, 
__traits(getAttributes, arg));
enum isType(alias symbol) = __traits(compiles, 
expectType!(symbol)); private template expectType(T) {}
alias TypeOfDataType(T) = T.DataType;
alias ElementTypeOfArray(T : T[]) = T;
template BaseTypeOfPointer (T) { static if (is(T U : U*)) alias 
BaseTypeOfPointer!(U) BaseTypeOfPointer; else alias T 
BaseTypeOfPointer; }
template BaseTypeOfEnum (T) { static if (is(T U == enum)) alias 
BaseTypeOfEnum!(U) BaseTypeOfEnum; else alias T BaseTypeOfEnum; }
template KeyTypeOfAssociativeArray (T) { static 
assert(isAssociativeArray!(Unqual!(T)), "The type needs to be an 
associative array"); alias typeof(T.init.keys[0]) 
KeyTypeOfAssociativeArray; }
template ValueTypeOfAssociativeArray (T) { static 
assert(isAssociativeArray!(Unqual!(T)), "The type needs to be an 
associative array"); alias typeof(T.init.values[0]) 
ValueTypeOfAssociativeArray; }
template TypeOf(alias expr) { static if (isType!(expr)) alias 
expr TypeOf; else alias typeof(expr) TypeOf; }



template StringToType(alias s)
{
	mixin("alias T = "~s~";");
	alias StringToType = Alias!T;
}























module mModel;


struct sStruct
{
	int Y;

	int opIndex(int i)
	{
		return i;
	}
}

@(4) enum eEnum : long
{
	X,
	Y = 43,
	@("sdfdsa") @(3) Z = 4
}

@("fdsa", 4) interface iBase
{
	iBase fooBase(iBase);
}

union uUnion
{
	int X;
	long Y;
}

class cBase : iBase
{
	string testField;
	cBase fooBase(iBase c) { return cast(cBase)c; }
	//cType barBase(cDerived c) { return c.type; }

}

interface iX { };
interface iY { };


@("fdsa",8) class cDerived(Q) : cBase, iX, iY
{
	alias type this;
	cType type;

	@("XXXRRERES") int testField1;
	private double testField2;

	@property int ValueProp() { return 3; }
}

class cType
{

}







More information about the Digitalmars-d mailing list