Mercurial > projects > dstep
comparison dstep/internal/Reflection.d @ 26:6825fcc47e39
Added dstep.internal.Reflection
author | Jacob Carlborg <doob@me.com> |
---|---|
date | Tue, 06 Apr 2010 11:38:08 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
25:b9de51448c6b | 26:6825fcc47e39 |
---|---|
1 /** | |
2 * Copyright: Copyright (c) 2010 Jacob Carlborg. | |
3 * Authors: Jacob Carlborg | |
4 * Version: Initial created: Mar 8, 2010 | |
5 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) | |
6 */ | |
7 module dstep.internal.Reflection; | |
8 | |
9 import dstep.objc.bridge.Bridge; | |
10 import dstep.internal.String; | |
11 | |
12 /** | |
13 * Returns the name of the given function | |
14 * | |
15 * Params: | |
16 * func = the function alias to get the name of | |
17 * | |
18 * Returns: the name of the function | |
19 */ | |
20 template functionNameOf (alias func) | |
21 { | |
22 version(LDC) | |
23 const functionNameOf = (&func).stringof[1 .. $]; | |
24 | |
25 else | |
26 const functionNameOf = (&func).stringof[2 .. $]; | |
27 } | |
28 | |
29 /** | |
30 * Returns the parameter names of the given function | |
31 * | |
32 * Params: | |
33 * func = the function alias to get the parameter names of | |
34 * | |
35 * Returns: an array of strings containing the parameter names | |
36 */ | |
37 template parameterNamesOf (alias func) | |
38 { | |
39 const parameterNamesOf = parameterNamesOfImpl!(func); | |
40 } | |
41 | |
42 private string[] parameterNamesOfImpl (alias func) () | |
43 { | |
44 string funcStr = typeof(&func).stringof; | |
45 | |
46 auto start = funcStr.indexOf('('); | |
47 auto end = funcStr.indexOf(')'); | |
48 | |
49 const firstPattern = ' '; | |
50 const secondPattern = ','; | |
51 | |
52 funcStr = funcStr[start + 1 .. end]; | |
53 | |
54 if (funcStr == "") | |
55 return null; | |
56 | |
57 funcStr ~= secondPattern; | |
58 | |
59 string token; | |
60 string[] arr; | |
61 | |
62 foreach (c ; funcStr) | |
63 { | |
64 if (c != firstPattern && c != secondPattern) | |
65 token ~= c; | |
66 | |
67 else | |
68 { | |
69 if (token) | |
70 arr ~= token; | |
71 | |
72 token = null; | |
73 } | |
74 } | |
75 | |
76 if (arr.length == 1) | |
77 return arr; | |
78 | |
79 string[] result; | |
80 bool skip = false; | |
81 | |
82 foreach (str ; arr) | |
83 { | |
84 skip = !skip; | |
85 | |
86 if (skip) | |
87 continue; | |
88 | |
89 result ~= str; | |
90 } | |
91 | |
92 return result; | |
93 } | |
94 | |
95 /** | |
96 * Compile-time function to get the index of the give element. | |
97 * | |
98 * Performs a linear scan, returning the index of the first occurrence | |
99 * of the specified element in the array, or U.max if the array does | |
100 * not contain the element. | |
101 * | |
102 * Params: | |
103 * arr = the array to get the index of the element from | |
104 * element = the element to find | |
105 * | |
106 * Returns: the index of the element or size_t.max if the element was not found. | |
107 */ | |
108 private size_t indexOf (T) (T[] arr, T element) | |
109 { | |
110 foreach (i, e ; arr) | |
111 if (e == element) | |
112 return i; | |
113 | |
114 return size_t.max; | |
115 } | |
116 | |
117 //FIXME fix this when http://d.puremagic.com/issues/show_bug.cgi?id=3512 is fixed | |
118 version (none) | |
119 { | |
120 | |
121 /** | |
122 * Compile-time function to get the index of the give element. | |
123 * | |
124 * Performs a linear scan, returning the index of the first occurrence | |
125 * of the specified element in the array, or U.max if the array does | |
126 * not contain the element. | |
127 * | |
128 * Params: | |
129 * arr = the array to get the index of the element from | |
130 * element = the element to find | |
131 * | |
132 * Returns: the index of the element or size_t.max if the element was not found. | |
133 */ | |
134 private size_t indexOf (T) (T[] arr, dchar element) | |
135 { | |
136 static assert(is(T == char) || is(T == wchar) || is(T == dchar), `dstep.internal.Traits.indexOf: The given type "` ~ T.stringof ~ `" is not valid, it has to be char, wchar or dchar`); | |
137 | |
138 foreach (i, dchar e ; arr) | |
139 if (e == element) | |
140 return i; | |
141 | |
142 return size_t.max; | |
143 } | |
144 } | |
145 | |
146 /** | |
147 * Evaluates to true if $(D_PARAM T) has a instance method with the given name | |
148 * | |
149 * Params: | |
150 * T = the type of the class/struct | |
151 * method = the name of the method | |
152 */ | |
153 template hasInstanceMethod (T, string method) | |
154 { | |
155 const hasInstanceMethod = is(typeof({ | |
156 T t; | |
157 mixin("auto f = &t." ~ method ~ ";"); | |
158 })); | |
159 } | |
160 | |
161 /** | |
162 * Evaluates to true if $(D_PARAM T) has a class method with the given name | |
163 * | |
164 * Params: | |
165 * T = the type of the class/struct | |
166 * method = the name of the method | |
167 */ | |
168 template hasClassMethod (T, string method) | |
169 { | |
170 const hasClassMethod = is(typeof({ | |
171 mixin("auto f = &T." ~ method ~ ";"); | |
172 })); | |
173 } | |
174 | |
175 /** | |
176 * Evaluates to true if $(D_PARAM T) has a either a class method or a instance method | |
177 * with the given name. | |
178 * | |
179 * Params: | |
180 * T = the type of the class/struct | |
181 * method = the name of the method | |
182 */ | |
183 template hasMethod (T, string method) | |
184 { | |
185 const hasMethod = hasClassMethod!(T, method) || hasInstanceMethod!(T, method); | |
186 } | |
187 | |
188 /** | |
189 * Evaluates to true if T has a field with the given name | |
190 * | |
191 * Params: | |
192 * T = the type of the class/struct | |
193 * field = the name of the field | |
194 */ | |
195 template hasField (T, string field) | |
196 { | |
197 const hasField = hasFieldImpl!(T, field, 0); | |
198 } | |
199 | |
200 private template hasFieldImpl (T, string field, size_t i) | |
201 { | |
202 static if (T.tupleof.length == i) | |
203 const hasFieldImpl = false; | |
204 | |
205 else static if (T.tupleof[i].stringof[1 + T.stringof.length + 2 .. $] == field) | |
206 const hasFieldImpl = true; | |
207 | |
208 else | |
209 const hasFieldImpl = hasFieldImpl!(T, field, i + 1); | |
210 } | |
211 | |
212 /// Evaluates to true if $(D_PARAM T) has binded methods | |
213 template hasBindedMethods (T) | |
214 { | |
215 const bool hasBindedMethods = hasField!(T, Bridge.objcClassMethodDeclarationVar) || hasField!(T, Bridge.objcMethodDeclarationVar); | |
216 } | |
217 | |
218 | |
219 | |
220 /** | |
221 * Sets the given value to the filed with the given name | |
222 * | |
223 * Params: | |
224 * t = an instance of the type that has the field | |
225 * value = the value to set | |
226 */ | |
227 void setValueOfField (string field, T, U) (ref T t, U value) | |
228 in | |
229 { | |
230 static assert(hasField!(T, field), "The given field \"" ~ field ~ "\" doesn't exist in the type \"" ~ T.stringof ~ "\""); | |
231 } | |
232 body | |
233 { | |
234 const len = T.stringof.length; | |
235 | |
236 foreach (i, dummy ; typeof(T.tupleof)) | |
237 { | |
238 const f = T.tupleof[i].stringof[1 + len + 2 .. $]; | |
239 | |
240 static if (f == field) | |
241 { | |
242 t.tupleof[i] = value; | |
243 break; | |
244 } | |
245 } | |
246 } | |
247 | |
248 /** | |
249 * Evaluates to the type of the field with the given name | |
250 * | |
251 * Params: | |
252 * T = the type of the class/struct | |
253 * field = the name of the field | |
254 */ | |
255 template TypeOfField (T, string field) | |
256 { | |
257 static assert(hasField!(T, field), "The given field \"" ~ field ~ "\" doesn't exist in the type \"" ~ T.stringof ~ "\""); | |
258 | |
259 alias TypeOfFieldImpl!(T, field, 0) TypeOfField; | |
260 } | |
261 | |
262 private template TypeOfFieldImpl (T, string field, size_t i) | |
263 { | |
264 static if (T.tupleof[i].stringof[1 + T.stringof.length + 2 .. $] == field) | |
265 alias typeof(T.tupleof[i]) TypeOfFieldImpl; | |
266 | |
267 else | |
268 alias TypeOfFieldImpl!(T, field, i + 1) TypeOfFieldImpl; | |
269 } | |
270 | |
271 /** | |
272 * Creates a new instance of class with the given name | |
273 * | |
274 * Params: | |
275 * name = the fully qualified name of the class | |
276 * args = the arguments to the constructor | |
277 * | |
278 * Returns: the newly created instance or null | |
279 */ | |
280 T factory (T : Object, ARGS...) (string name, ARGS args) | |
281 { | |
282 auto classInfo = ClassInfo.find(name); | |
283 | |
284 if (!classInfo) | |
285 return null; | |
286 | |
287 auto object = newInstance(classInfo); | |
288 | |
289 if (classInfo.flags & 8 && classInfo.defaultConstructor is null) | |
290 { | |
291 auto o = cast(T) object; | |
292 | |
293 static if (is(typeof(o._ctor(args)))) | |
294 return o._ctor(args); | |
295 | |
296 else | |
297 return null; | |
298 } | |
299 | |
300 else | |
301 { | |
302 if (classInfo.flags & 8 && classInfo.defaultConstructor !is null) | |
303 { | |
304 Object delegate () ctor; | |
305 ctor.ptr = cast(void*) object; | |
306 ctor.funcptr = cast(Object function()) classInfo.defaultConstructor; | |
307 | |
308 return cast(T) ctor(); | |
309 } | |
310 | |
311 else | |
312 return cast(T) object; | |
313 } | |
314 } | |
315 | |
316 private | |
317 { | |
318 version (LDC) | |
319 extern (C) Object _d_allocclass(ClassInfo); | |
320 | |
321 else | |
322 extern (C) Object _d_newclass(ClassInfo); | |
323 } | |
324 | |
325 /** | |
326 * Creates a new instance of the given ClassInfo | |
327 * | |
328 * Params: | |
329 * classInfo = the class to create a new instance of | |
330 * | |
331 * Returns: the new instance | |
332 */ | |
333 Object newInstance (ClassInfo classInfo) | |
334 { | |
335 version (LDC) | |
336 { | |
337 Object object = _d_allocclass(classInfo); | |
338 (cast(byte*) object)[0 .. classInfo.init.length] = classInfo.init[]; | |
339 | |
340 return object; | |
341 } | |
342 | |
343 else | |
344 return _d_newclass(classInfo); | |
345 } |