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 }