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;