Mercurial > projects > qtd
comparison d2/qtd/Signal.d @ 350:31520b2c0b3c
Removed dependency on parent trait and stringof
author | Max Samukha <maxter@spambox.com> |
---|---|
date | Thu, 20 May 2010 15:49:08 +0300 |
parents | 970332a88b72 |
children | da4235301224 |
comparison
equal
deleted
inserted
replaced
349:925386e0e780 | 350:31520b2c0b3c |
---|---|
9 * (See accompanying file boost-license-1.0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | 9 * (See accompanying file boost-license-1.0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
10 * | 10 * |
11 */ | 11 */ |
12 module qtd.Signal; | 12 module qtd.Signal; |
13 | 13 |
14 public import qt.QGlobal; | |
15 import qtd.Marshal; | |
16 import qtd.Meta; | |
17 | |
18 import core.stdc.stdlib : crealloc = realloc, cfree = free; | 14 import core.stdc.stdlib : crealloc = realloc, cfree = free; |
19 import core.stdc.string : memmove; | 15 import core.stdc.string : memmove; |
16 | |
20 import | 17 import |
21 core.thread, | 18 core.thread, |
22 core.exception, | 19 core.exception, |
23 std.algorithm; | 20 |
24 | 21 std.algorithm, |
25 public import | |
26 std.typetuple, | 22 std.typetuple, |
23 std.conv, | |
27 std.traits, | 24 std.traits, |
28 std.conv, | 25 std.string, |
29 std.metastrings; | 26 |
30 | 27 qt.QGlobal, |
31 public import std.string : strip, toStringz; | 28 qtd.Marshal, |
32 | 29 qtd.meta.Compiletime, |
30 qtd.ctfe.Format; | |
31 | |
33 /** The beast that takes string representation of function arguments | 32 /** The beast that takes string representation of function arguments |
34 * and returns an array of default values it doesn't check if arguments | 33 * and returns an array of default values it doesn't check if arguments |
35 * without default values follow the arguments with default values for | 34 * without default values follow the arguments with default values for |
36 * simplicity. It is done by mixing in an delegate alias. | 35 * simplicity. It is done by mixing in a delegate alias. |
37 */ | 36 */ |
38 string[] defaultValues(string signature) | 37 string[] defaultValues(string signature) |
39 { | 38 { |
40 int braces = 0; | 39 int braces = 0; |
41 bool inDefaultValue = false; | 40 bool inDefaultValue = false; |
42 bool inStringLiteral = false; | 41 bool inStringLiteral = false; |
43 string[] res; | 42 string[] res; |
44 int startValue = 0; | 43 int startValue = 0; |
45 | 44 |
46 if(strip(signature).length == 0) | 45 if(strip(signature).length == 0) |
47 return res; | 46 return res; |
48 | 47 |
49 foreach (i,c; signature) | 48 foreach (i,c; signature) |
50 { | 49 { |
66 else | 65 else |
67 { | 66 { |
68 inStringLiteral = true; | 67 inStringLiteral = true; |
69 } | 68 } |
70 } | 69 } |
71 | 70 |
72 if (!inStringLiteral && braces == 0) | 71 if (!inStringLiteral && braces == 0) |
73 { | 72 { |
74 if(c == '=') // found default value | 73 if(c == '=') // found default value |
75 { | 74 { |
76 inDefaultValue = true; | 75 inDefaultValue = true; |
84 inDefaultValue = false; | 83 inDefaultValue = false; |
85 } | 84 } |
86 } | 85 } |
87 } | 86 } |
88 } | 87 } |
89 | 88 |
90 if (inDefaultValue) | 89 if (inDefaultValue) |
91 res ~= signature[startValue..$]; | 90 res ~= signature[startValue..$]; |
92 | 91 |
93 return res; | 92 return res; |
94 } | 93 } |
95 | 94 |
96 int defaultValuesLength(string[] defVals) | 95 /** |
97 { | 96 Generates D-to-C++ conversion code for signals. |
98 return defVals.length; | 97 */ |
99 } | 98 string genConvToCpp(uint argIndex) |
100 | 99 { |
101 | 100 string res = format_ctfe(q{ |
102 // templates for extracting data from static meta-information of signals, slots or properties | 101 |
103 // public alias TypeTuple!("name", index, OwnerClass, ArgTypes) __signal | 102 static if (isStringType!(Args[${0}])) |
104 template MetaEntryName(source...) | 103 { |
105 { | 104 auto _tmp${0} = QString(_t${0}); |
106 enum MetaEntryName = source[0]; // name of the metaentry is the first element | 105 _a[${0}] = cast(void*)&_tmp${0}; |
107 } | 106 } |
108 | 107 else static if (isQObjectType!(Args[${0}]) || isObjectType!(Args[${0}])) |
109 template MetaEntryOwner(source...) | 108 _a[${0}] = _t${0} ? &(_t${0}.__nativeId) : cast(void*)&_t${0}; |
110 { | 109 else static if (isValueType!(Args[${0}])) |
111 alias TupleWrapper!(source[2]).at[0] MetaEntryOwner; // class that owns the property is the third | 110 _a[${0}] = _t${0}.__nativeId; |
112 // Compiler #BUG 3092 - evaluates MetaEntryOwner as a Tuple with one element | 111 else |
113 } | 112 _a[${0}] = cast(void*)&_t${0}; |
114 | 113 |
115 template MetaEntryArgs(source...) | 114 }, argIndex); |
116 { | 115 |
117 alias ParameterTypeTuple!(source[1]) MetaEntryArgs; // arguments-tuple starts from the fourth position | 116 return res; |
118 } | 117 } |
119 | 118 |
120 template TupleWrapper(A...) { alias A at; } | 119 string genSignalEmitter(SignalKind signalKind, string name, uint localIndex, uint argCount) |
121 | 120 { |
122 string convertSignalArguments(Args...)() | 121 string res; |
123 { | 122 |
124 // void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) }; | 123 // signature |
125 // at least for string argument need to construct a QString value | 124 // |
126 string res = prepareSignalArguments!(Args); | 125 if (signalKind != SignalKind.BindQtSignal) |
126 res ~= "protected "; | |
127 | |
128 res ~= "Args[0] " ~ name; | |
127 | 129 |
128 res ~= "void*[" ~ __toString(Args.length+1) ~ "] _a = [null"; | 130 if (signalKind == SignalKind.BindQtSignal) |
129 foreach(i, _; Args) | 131 res ~= "_emit"; |
130 res ~= ", " ~ "cast(void*) (" ~ convertSignalArgument!(Args[i])("_t" ~ __toString(i)) ~ ")"; | 132 |
131 res ~= "];\n"; | 133 res ~= "("; |
132 return res; | |
133 } | |
134 | |
135 public string SignalEmitter(A...)(SignalType signalType, string name, string[] defVals, int localIndex) | |
136 { | |
137 string fullArgs, args; | |
138 int defValsLength = defVals.length; | |
139 string argsConversion = ""; | |
140 string argsPtr = "null"; | |
141 static if (A.length) | |
142 { | |
143 while(A.length != defVals.length) | |
144 defVals = "" ~ defVals; | |
145 | |
146 fullArgs = A[0].stringof ~ " _t0"; | |
147 if (defVals[0].length) | |
148 fullArgs ~= " = " ~ defVals[0]; | |
149 args = "_t0"; | |
150 foreach(i, _; A[1..$]) | |
151 { | |
152 fullArgs ~= ", " ~ A[i+1].stringof ~ " _t" ~ __toString(i+1); | |
153 if (defVals[i+1].length) | |
154 fullArgs ~= " = " ~ defVals[i+1]; | |
155 args ~= ", _t" ~ __toString(i+1); | |
156 } | |
157 // build up conversion of signal args from D to C++ | |
158 argsPtr = "_a.ptr"; | |
159 argsConversion = convertSignalArguments!(A)(); | |
160 } | |
161 string attribute; | |
162 string sigName = name; | |
163 if (signalType == SignalType.BindQtSignal) | |
164 name ~= "_emit"; | |
165 else | |
166 attribute = "protected "; | |
167 | 134 |
168 string indexArgs = __toString(localIndex); | 135 foreach (i; 1..argCount) |
169 if(defValsLength > 0) | 136 { |
170 indexArgs ~= ", " ~ __toString(localIndex+defValsLength); | 137 auto iStr = to!string(i); |
171 string str = attribute ~ "final void " ~ name ~ "(" ~ fullArgs ~ ") {\n" ~ argsConversion ~ "\n" | 138 if (i > 1) |
172 ~ " QMetaObject.activate(this, typeof(this).staticMetaObject, " ~ indexArgs ~ ", " ~ argsPtr ~ ");\n" | 139 res ~= ", "; |
173 ~ "}\n"; // ~ | 140 res ~= "Args[" ~ iStr ~ "] _t" ~ iStr; |
174 return str; | 141 } |
142 | |
143 res ~= ") {\n"; | |
144 | |
145 // body | |
146 // | |
147 res ~= " void*[" ~ to!string(argCount) ~ "] _a;\n"; | |
148 foreach (i; 1..argCount) | |
149 res ~= genConvToCpp(i); | |
150 | |
151 res ~= " QMetaObject.activate(this, typeof(this).staticMetaObject, " | |
152 ~ to!string(localIndex) ~ ", _a.ptr);\n"; | |
153 | |
154 return res ~= "}\n"; | |
155 } | |
156 | |
157 // BUG: parameter storage classes are not supported yet | |
158 mixin template SignalEmitter(SignalKind signalKind, int localIndex) | |
159 { | |
160 alias signals[localIndex] signal; | |
161 alias TypeTuple!(ReturnType!(signal), ParameterTypeTuple!(signal)) Args; | |
162 | |
163 /+ | |
164 pragma(msg, genSignalEmitter(signalKind, | |
165 methodName!signal, | |
166 localIndex, | |
167 Args.length)); | |
168 +/ | |
169 | |
170 mixin (genSignalEmitter(signalKind, | |
171 methodName!signal, | |
172 localIndex, | |
173 Args.length)); | |
175 } | 174 } |
176 /** ---------------- */ | 175 /** ---------------- */ |
177 | 176 |
178 | 177 |
179 const string signalPrefix = "__signal"; | 178 enum SignalKind |
180 const string slotPrefix = "__slot"; | |
181 | |
182 enum SignalType | |
183 { | 179 { |
184 BindQtSignal, | 180 BindQtSignal, |
185 NewSignal, | 181 NewSignal, |
186 NewSlot | 182 NewSlot |
187 } | 183 } |
207 string[] getSymbols(C)(string prefix) | 203 string[] getSymbols(C)(string prefix) |
208 { | 204 { |
209 string[] result; | 205 string[] result; |
210 auto allSymbols = __traits(derivedMembers, C); | 206 auto allSymbols = __traits(derivedMembers, C); |
211 foreach(s; allSymbols) | 207 foreach(s; allSymbols) |
212 if(ctfeStartsWith(s, prefix)) | 208 { |
209 if(startsWith(s, prefix)) | |
213 result ~= s; | 210 result ~= s; |
211 } | |
214 return result; | 212 return result; |
215 } | 213 } |
216 | 214 |
217 string removePrefix(string source) | 215 string removePrefix(string source) |
218 { | 216 { |
219 foreach (i, c; source) | 217 foreach (i, c; source) |
218 { | |
220 if (c == '_') | 219 if (c == '_') |
221 return source[i+1..$]; | 220 return source[i+1..$]; |
221 } | |
222 return source; | 222 return source; |
223 } | |
224 | |
225 template Alias(T...) | |
226 { | |
227 alias T Alias; | |
228 } | 223 } |
229 | 224 |
230 // recursive search in the static meta-information | 225 // recursive search in the static meta-information |
231 template findSymbolsImpl2(C, alias signals, int id) | 226 template findSymbolsImpl2(C, alias signals, int id) |
232 { | 227 { |
233 alias Alias!(__traits(getOverloads, C, signals[id])) current; | 228 alias qtd.meta.Compiletime.Alias!(__traits(getOverloads, C, signals[id])) current; |
234 static if (signals.length - id - 1 > 0) | 229 static if (signals.length - id - 1 > 0) |
235 alias TypeTuple!(current, findSymbolsImpl2!(C, signals, id + 1).result) result; | 230 alias TypeTuple!(current, findSymbolsImpl2!(C, signals, id + 1).result) result; |
236 else | 231 else |
237 alias current result; | 232 alias TypeTuple!(current) result; |
238 } | 233 } |
239 | 234 |
240 template findSymbols2(C, string prefix) | 235 template findSymbols2(C, string prefix) |
241 { | 236 { |
242 enum signals = getSymbols!(C)(prefix); | 237 enum signals = getSymbols!(C)(prefix); |
254 template findSlots(C) | 249 template findSlots(C) |
255 { | 250 { |
256 alias findSymbols2!(C, "slot_").result findSlots; | 251 alias findSymbols2!(C, "slot_").result findSlots; |
257 } | 252 } |
258 | 253 |
259 /* commented out for future when we will implement default arguments | 254 template methodName(alias method) |
260 template metaMethods(alias func, int index, int defValsCount) | 255 { |
261 { | 256 enum methodName = removePrefix(__traits(identifier, method)); |
262 static if(defValsCount >= 0) { | 257 } |
263 alias TupleWrapper!(func, index) current; | |
264 // pragma(msg, __traits(identifier, (current.at)[0]) ~ " " ~ typeof(&(current.at)[0]).stringof); | |
265 alias metaMethods!(func, index+1, defValsCount-1).result next; | |
266 alias TypeTuple!(current, next) result; | |
267 } | |
268 else | |
269 { | |
270 alias TypeTuple!() result; | |
271 } | |
272 } | |
273 */ | |
274 | |
275 template toMetaEntriesImpl(int id, Methods...) | |
276 { | |
277 static if (Methods.length > id) | |
278 { | |
279 alias typeof(&Methods[id]) Fn; | |
280 // commented out for future when we will implement default arguments | |
281 // enum defValsLength = 0; //ParameterTypeTuple!(Fn).length - requiredArgCount!(Methods[id])(); | |
282 // pragma(msg, __traits(identifier, Methods[id]) ~ " " ~ typeof(&Methods[id]).stringof); | |
283 // alias metaMethods!(Methods[id], 0, defValsLength).result subres; | |
284 alias TupleWrapper!(removePrefix(__traits(identifier, Methods[id])), typeof(&Methods[id])) subres; | |
285 alias TypeTuple!(subres, toMetaEntriesImpl!(id+1, Methods).result) result; | |
286 } | |
287 else | |
288 { | |
289 alias TypeTuple!() result; | |
290 } | |
291 } | |
292 | |
293 template toMetaEntries(Methods...) | |
294 { | |
295 alias TupleWrapper!(toMetaEntriesImpl!(0, Methods).result) toMetaEntries; | |
296 } |