Mercurial > projects > qtd
comparison d2/qtd/MOC.d @ 357:9784459f0750
An attempt (failed due to optlink) to improve locality of declarations exported from QtD executables
Q_CLASSINFO implementation
Now Qtd can be built on Windows
author | Max Samukha <maxter@spambox.com> |
---|---|
date | Wed, 02 Jun 2010 19:38:05 +0300 |
parents | 12cec2d14e1c |
children | a3f5c10414f3 |
comparison
equal
deleted
inserted
replaced
356:12cec2d14e1c | 357:9784459f0750 |
---|---|
104 bool isDestructor; | 104 bool isDestructor; |
105 bool isAbstract; | 105 bool isAbstract; |
106 */ | 106 */ |
107 } | 107 } |
108 | 108 |
109 struct ClassInfoDef | |
110 { | |
111 string name; | |
112 string value; | |
113 } | |
114 | |
109 FunctionDef newSlot(string sig, string args) | 115 FunctionDef newSlot(string sig, string args) |
110 { | 116 { |
111 return FunctionDef(sig, args, Access.Public); | 117 return FunctionDef(sig, args, Access.Public); |
112 } | 118 } |
113 | 119 |
114 FunctionDef newSignal(string sig, string args) | 120 FunctionDef newSignal(string sig, string args) |
115 { | 121 { |
116 return FunctionDef(sig, args, Access.Protected); | 122 return FunctionDef(sig, args, Access.Protected); |
123 } | |
124 | |
125 struct ClassDef | |
126 { | |
127 string classname; | |
128 FunctionDef[] signalList; | |
129 FunctionDef[] slotList; | |
130 ClassInfoDef[] classInfoList; | |
117 } | 131 } |
118 | 132 |
119 struct Generator | 133 struct Generator |
120 { | 134 { |
121 string output; | 135 string output; |
122 string[] strings; | 136 string[] strings; |
123 // QByteArray purestSuperClass; | 137 // QByteArray purestSuperClass; |
124 // QList<QByteArray> metaTypes; | 138 // QList<QByteArray> metaTypes; |
125 } | 139 |
140 ClassDef cdef; | |
141 } | |
142 | |
143 | |
126 | 144 |
127 int lengthOfEscapeSequence(string s, uint i) | 145 int lengthOfEscapeSequence(string s, uint i) |
128 { | 146 { |
129 if (s[i] != '\\' || i >= s.length - 1) | 147 if (s[i] != '\\' || i >= s.length - 1) |
130 return 1; | 148 return 1; |
185 gen.output ~= format_ctfe(" ${}, ${}, ${}, ${}, 0x${:x},\n", strreg(gen, f.sig), | 203 gen.output ~= format_ctfe(" ${}, ${}, ${}, ${}, 0x${:x},\n", strreg(gen, f.sig), |
186 strreg(gen, f.arguments), strreg(gen, ""/*f.normalizedType*/), strreg(gen, ""/*f.tag*/), flags); | 204 strreg(gen, f.arguments), strreg(gen, ""/*f.normalizedType*/), strreg(gen, ""/*f.tag*/), flags); |
187 } | 205 } |
188 } | 206 } |
189 | 207 |
190 string generateCode(string className, FunctionDef[] signalList, FunctionDef[] slotList) | 208 ClassInfoDef[] generateClassInfoDefs(T)() |
191 { | 209 { |
192 auto gen = Generator("", []); | 210 ClassInfoDef[] defs; |
193 | 211 alias GetAttributes!(T, "Q_CLASSINFO") classInfos; |
212 // COMPILER BUG: | |
213 enum len = classInfos.length; | |
214 foreach (i, _; Repeat!(void, len)) | |
215 defs ~= ClassInfoDef(classInfos[i].tuple[2], classInfos[i].tuple[3]); | |
216 | |
217 return defs; | |
218 } | |
219 | |
220 void generateClassInfos(ref Generator gen) | |
221 { | |
222 if (!gen.cdef.classInfoList.length) | |
223 return; | |
224 | |
225 gen.output ~= "\n // classinfo: key, value\n"; | |
226 | |
227 foreach (c; gen.cdef.classInfoList) | |
228 gen.output ~= format_ctfe(" ${}, ${},\n", strreg(gen, c.name), strreg(gen, c.value)); | |
229 } | |
230 | |
231 string generateCode(ref Generator gen) | |
232 { | |
194 /* bool isQt = (cdef->classname == "Qt"); | 233 /* bool isQt = (cdef->classname == "Qt"); |
195 bool isQObject = (cdef->classname == "QObject"); | 234 bool isQObject = (cdef->classname == "QObject"); |
196 bool isConstructible = !cdef->constructorList.isEmpty(); | 235 bool isConstructible = !cdef->constructorList.isEmpty(); |
197 | 236 |
198 // | 237 // |
227 FunctionDef[] propertyList, enumList, constructorList; | 266 FunctionDef[] propertyList, enumList, constructorList; |
228 int index = 12; | 267 int index = 12; |
229 gen.output ~= "private static const uint[] qt_meta_data = [\n"; | 268 gen.output ~= "private static const uint[] qt_meta_data = [\n"; |
230 gen.output ~= format_ctfe("\n // content:\n"); | 269 gen.output ~= format_ctfe("\n // content:\n"); |
231 gen.output ~= format_ctfe(" ${}, // revision\n", 2); | 270 gen.output ~= format_ctfe(" ${}, // revision\n", 2); |
232 gen.output ~= format_ctfe(" ${}, // classname\n", strreg(gen, className)); | 271 gen.output ~= format_ctfe(" ${}, // classname\n", strreg(gen, gen.cdef.classname)); |
233 gen.output ~= format_ctfe(" ${}, ${}, // classinfo\n", 0, 0); | 272 gen.output ~= format_ctfe(" ${}, ${}, // classinfo\n", gen.cdef.classInfoList.length, gen.cdef.classInfoList.length ? index : 0); |
234 // index += cdef->classInfoList.count() * 2; | 273 index += gen.cdef.classInfoList.length * 2; |
235 | 274 |
236 int methodCount = signalList.length + slotList.length;// + cdef->methodList.count(); | 275 int methodCount = gen.cdef.signalList.length + gen.cdef.slotList.length;// + cdef->methodList.count(); |
237 gen.output ~= format_ctfe(" ${}, ${}, // methods\n", methodCount, methodCount ? index : 0); | 276 gen.output ~= format_ctfe(" ${}, ${}, // methods\n", methodCount, methodCount ? index : 0); |
238 index += methodCount * 5; | 277 index += methodCount * 5; |
239 gen.output ~= format_ctfe(" ${}, ${}, // properties\n", propertyList.length, propertyList.length ? index : 0); | 278 gen.output ~= format_ctfe(" ${}, ${}, // properties\n", propertyList.length, propertyList.length ? index : 0); |
240 index += propertyList.length * 3; | 279 index += propertyList.length * 3; |
241 // if(cdef->notifyableProperties) | 280 // if(cdef->notifyableProperties) |
249 isConstructible ? index : 0); | 288 isConstructible ? index : 0); |
250 | 289 |
251 // | 290 // |
252 // Build classinfo array | 291 // Build classinfo array |
253 // | 292 // |
254 // generateClassInfos(); | 293 generateClassInfos(gen); |
255 | 294 |
256 // | 295 // |
257 // Build signals array first, otherwise the signal indices would be wrong | 296 // Build signals array first, otherwise the signal indices would be wrong |
258 // | 297 // |
259 generateFunctions(gen, signalList, "signal", MethodFlags.MethodSignal); | 298 generateFunctions(gen, gen.cdef.signalList, "signal", MethodFlags.MethodSignal); |
260 | 299 |
261 // | 300 // |
262 // Build slots array | 301 // Build slots array |
263 // | 302 // |
264 generateFunctions(gen, slotList, "slot", MethodFlags.MethodSlot); | 303 generateFunctions(gen, gen.cdef.slotList, "slot", MethodFlags.MethodSlot); |
265 | 304 |
266 // | 305 // |
267 // Build method array | 306 // Build method array |
268 // | 307 // |
269 // generateFunctions(cdef->methodList, "method", MethodMethod); | 308 // generateFunctions(cdef->methodList, "method", MethodMethod); |
342 ret ~= qtDeclArg!(Args[i]); | 381 ret ~= qtDeclArg!(Args[i]); |
343 } | 382 } |
344 return ret; | 383 return ret; |
345 } | 384 } |
346 | 385 |
347 string dDeclArgs(Args...)() | |
348 { | |
349 string ret; | |
350 foreach(i, _; Args) | |
351 { | |
352 if (i > 0) | |
353 ret ~= ", "; | |
354 ret ~= fullName!(Args[i]); | |
355 } | |
356 return ret; | |
357 } | |
358 | |
359 size_t commaCount(int argCount) | 386 size_t commaCount(int argCount) |
360 { | 387 { |
361 size_t ret = 0; | 388 size_t ret = 0; |
362 if(argCount > 1) | 389 if(argCount > 1) |
363 ret = argCount - 1; | 390 ret = argCount - 1; |
364 return ret; | 391 return ret; |
365 } | 392 } |
366 | 393 |
367 FunctionDef[] generateFuncDefs(alias newFunc, Funcs...)() | 394 FunctionDef[] genFuncDefs(alias newFunc, Funcs...)() |
368 { | 395 { |
369 typeof(return) res; | 396 typeof(return) res; |
370 enum funcsCount = Funcs.length; | 397 enum funcsCount = Funcs.length; |
371 foreach(i, bogus; Repeat!(void, funcsCount)) | 398 foreach(i, bogus; Repeat!(void, funcsCount)) |
372 { | 399 { |
444 res ~= " default:\n"; | 471 res ~= " default:\n"; |
445 | 472 |
446 return res ~ "}\n"; | 473 return res ~ "}\n"; |
447 } | 474 } |
448 | 475 |
476 string generateMetaInfo(T)() | |
477 { | |
478 Generator gen; | |
479 | |
480 gen.cdef.classname = T.stringof; | |
481 | |
482 gen.cdef.slotList = genFuncDefs!(newSignal, T.signals)(); | |
483 gen.cdef.signalList = genFuncDefs!(newSlot, T.slots)(); | |
484 gen.cdef.classInfoList = generateClassInfoDefs!T(); | |
485 | |
486 generateCode(gen); | |
487 | |
488 return gen.output; | |
489 } | |
490 | |
449 mixin template Q_OBJECT() | 491 mixin template Q_OBJECT() |
450 { | 492 { |
451 import std.typetuple; | 493 import std.typetuple; |
452 import qtd.Marshal; | 494 import qtd.Marshal; |
495 import std.stdio; | |
453 import qt.core.QString; // for QStringUtil.toNative | 496 import qt.core.QString; // for QStringUtil.toNative |
454 | 497 |
455 public: // required to override the outside scope protection. | 498 public: // required to override the outside scope protection. |
456 | 499 |
457 alias typeof(this) This; | 500 alias typeof(this) This; |
458 | 501 |
459 alias findSignals!(This) signals; | 502 alias findSignals!(This) signals; |
460 alias findSlots!(This) slots; | 503 alias findSlots!(This) slots; |
461 alias TypeTuple!(signals, slots) methods; | 504 alias TypeTuple!(signals, slots) methods; |
462 | 505 |
463 | |
464 mixin (generateSignalEmitters(signals.length)); | 506 mixin (generateSignalEmitters(signals.length)); |
465 mixin (generateSlotAliases(slots.length)); | 507 mixin (generateSlotAliases(slots.length)); |
466 | 508 //pragma(msg, generateMetaInfo!This()); |
467 auto signalList = generateFuncDefs!(newSignal, signals)(); | 509 mixin (generateMetaInfo!This()); |
468 auto slotList = generateFuncDefs!(newSlot, slots)(); | |
469 mixin (generateCode(typeof(this).stringof, signalList, slotList)); | |
470 | 510 |
471 protected int qt_metacall(QMetaObject.Call _c, int _id, void **_a) | 511 protected int qt_metacall(QMetaObject.Call _c, int _id, void **_a) |
472 { | 512 { |
473 _id = super.qt_metacall(_c, _id, _a); | 513 _id = super.qt_metacall(_c, _id, _a); |
474 | 514 |
488 } | 528 } |
489 | 529 |
490 @property | 530 @property |
491 override QMetaObject metaObject() const { return staticMetaObject(); } | 531 override QMetaObject metaObject() const { return staticMetaObject(); } |
492 | 532 |
493 private static __gshared QMetaObject _staticMetaObject; | 533 private static |
494 private static __gshared QMetaObjectNative _nativeStaticMetaObject; | 534 { |
535 __gshared QMetaObject staticMetaObject_; | |
536 __gshared QMetaObjectNative nativeStaticMetaObject_; | |
537 bool staticMoInited_; | |
538 } | |
495 | 539 |
496 @property | 540 @property |
497 static QMetaObject staticMetaObject() | 541 static QMetaObject staticMetaObject() |
498 { | 542 { |
499 // TODO: synchronize or enable static constructors in circular modules | 543 // using a thread-local flag to mitigate |
500 if(!_staticMetaObject) | 544 // the performance hit caused by lazy initialization |
545 if(!staticMoInited_) | |
501 { | 546 { |
502 alias BaseClassesTuple!(This)[0] Base; | 547 synchronized(qtdMoLock) |
503 | 548 { |
504 _nativeStaticMetaObject = QMetaObjectNative( | 549 if (!staticMetaObject_) |
505 Base.staticMetaObject.nativeId, | 550 { |
506 qt_meta_stringdata.ptr, | 551 alias BaseClassesTuple!(This)[0] Base; |
507 qt_meta_data.ptr, null); | 552 |
508 | 553 nativeStaticMetaObject_ = QMetaObjectNative( |
509 QMetaObject.create!This(&_nativeStaticMetaObject); | 554 Base.staticMetaObject.nativeId, |
510 } | 555 qt_meta_stringdata.ptr, |
511 return _staticMetaObject; | 556 qt_meta_data.ptr, null); |
557 | |
558 QMetaObject.create!This(&nativeStaticMetaObject_); | |
559 } | |
560 } | |
561 staticMoInited_ = true; | |
562 } | |
563 | |
564 return staticMetaObject_; | |
512 } | 565 } |
513 | 566 |
514 /*internal*/ static void setStaticMetaObject(QMetaObject m) | 567 /*internal*/ static void setStaticMetaObject(QMetaObject m) |
515 { | 568 { |
516 _staticMetaObject = m; | 569 _staticMetaObject = m; |