1 2 module witchcraft.mixins.constructors; 3 4 mixin template WitchcraftConstructor() 5 { 6 import witchcraft; 7 8 import std.algorithm; 9 import std.conv; 10 import std.meta; 11 import std.range; 12 import std..string; 13 import std.traits; 14 import std.variant; 15 16 static class ConstructorMixin(alias T, size_t overload) : Constructor 17 { 18 private: 19 alias method = Alias!(__traits(getOverloads, T, "__ctor")[overload]); 20 alias Return = ReturnType!method; 21 22 public: 23 const(Attribute)[] getAttributes() const 24 { 25 alias attributes = AliasSeq!(__traits(getAttributes, method)); 26 auto values = new Attribute[attributes.length]; 27 28 foreach(index, attribute; attributes) 29 { 30 values[index] = new AttributeImpl!attribute; 31 } 32 33 return values; 34 } 35 36 const(Type) getDeclaringType() const 37 { 38 alias Parent = Alias!(__traits(parent, method)); 39 40 return inspect!Parent; 41 } 42 43 const(TypeInfo) getDeclaringTypeInfo() const 44 { 45 alias Parent = Alias!(__traits(parent, method)); 46 47 static if(__traits(compiles, typeid(Parent))) 48 { 49 return typeid(Parent); 50 } 51 else 52 { 53 return null; 54 } 55 } 56 57 string getFullName() const 58 { 59 return fullyQualifiedName!method; 60 } 61 62 const(Type)[] getParameterTypes() const 63 { 64 auto parameterTypes = new Type[Parameters!method.length]; 65 66 foreach(index, Parameter; Parameters!method) 67 { 68 parameterTypes[index] = inspect!Parameter; 69 } 70 71 return parameterTypes; 72 } 73 74 const(TypeInfo)[] getParameterTypeInfos() const 75 { 76 auto parameterTypeInfos = new TypeInfo[Parameters!method.length]; 77 78 foreach(index, Parameter; Parameters!method) 79 { 80 static if(__traits(compiles, typeid(Parameter))) 81 { 82 parameterTypeInfos[index] = typeid(Parameter); 83 } 84 } 85 86 return parameterTypeInfos; 87 } 88 89 string getProtection() const 90 { 91 return __traits(getProtection, method); 92 } 93 94 const(Type) getReturnType() const 95 { 96 return inspect!Return; 97 } 98 99 @property 100 const(TypeInfo) getReturnTypeInfo() const 101 { 102 static if(__traits(compiles, typeid(Return))) 103 { 104 return typeid(Return); 105 } 106 else 107 { 108 return null; 109 } 110 } 111 112 static if(isAbstractClass!T) 113 { 114 Variant invoke(Variant instance, Variant[] arguments...) const 115 { 116 assert(0, T.stringof ~ " is abstract."); 117 } 118 } 119 else 120 { 121 Variant invoke(Variant instance, Variant[] arguments...) const 122 { 123 import std.algorithm, std.conv, std.range, std..string; 124 125 alias Params = Parameters!method; 126 127 enum variables = iota(0, Params.length) 128 .map!(i => "auto v%1$s = arguments[%1$s].get!(Params[%1$s]);".format(i)) 129 .joiner.text; 130 131 enum invokeString = iota(0, Params.length) 132 .map!(i => "v%s".format(i)) 133 .joiner(", ").text; 134 135 mixin(variables); 136 mixin("Params args = AliasSeq!(" ~ invokeString ~ ");"); 137 138 static if(is(T == class)) 139 { 140 return Variant(new T(args)); 141 } 142 else 143 { 144 return Variant(T(args)); 145 } 146 } 147 } 148 149 @property 150 final bool isAccessible() const 151 { 152 return true; 153 } 154 155 @property 156 bool isVarArgs() const 157 { 158 return variadicFunctionStyle!method != Variadic.no; 159 } 160 } 161 }