Mercurial > projects > qtd
comparison d2/qtd/MOC.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 | 12cec2d14e1c |
comparison
equal
deleted
inserted
replaced
349:925386e0e780 | 350:31520b2c0b3c |
---|---|
1 module qtd.MOC; | 1 module qtd.MOC; |
2 | 2 |
3 import std.typetuple; | 3 import |
4 | 4 std.typetuple, |
5 import qt.QGlobal; | 5 std.traits, |
6 import qtd.Signal; | 6 std.typetuple, |
7 import qtd.Marshal; | 7 std.conv, |
8 import qtd.Meta; | 8 qt.QGlobal, |
9 import qtd.ctfe.Format; | 9 qtd.Signal, |
10 | 10 qtd.Marshal, |
11 public import qt.core.QString; | 11 qtd.Array, |
12 | 12 qtd.Str, |
13 public import std.traits; | 13 qtd.meta.Compiletime, |
14 qtd.ctfe.Format; | |
15 | |
16 import qt.core.QString; | |
17 | |
14 /** | 18 /** |
15 Utils. | 19 Utils. |
16 */ | 20 */ |
17 | |
18 bool is_digit_char(const char s) | |
19 { | |
20 return (s >= '0' && s <= '9'); | |
21 } | |
22 | |
23 bool is_octal_char(const char s) | |
24 { | |
25 return (s >= '0' && s <= '7'); | |
26 } | |
27 | |
28 bool is_hex_char(const char s) | |
29 { | |
30 return ((s >= 'a' && s <= 'f') | |
31 || (s >= 'A' && s <= 'F') | |
32 || (s >= '0' && s <= '9') | |
33 ); | |
34 } | |
35 | |
36 int lastIndexOf(T)(T[] haystack, T[] needle, int from = -1) | 21 int lastIndexOf(T)(T[] haystack, T[] needle, int from = -1) |
37 { | 22 { |
38 auto l = haystack.length; | 23 auto l = haystack.length; |
39 auto ol = needle.length; | 24 auto ol = needle.length; |
40 int delta = l - ol; | 25 int delta = l - ol; |
42 from = delta; | 27 from = delta; |
43 if (from < 0 || from > l) | 28 if (from < 0 || from > l) |
44 return -1; | 29 return -1; |
45 if (from > delta) | 30 if (from > delta) |
46 from = delta; | 31 from = delta; |
47 | 32 |
48 while(from >= 0) | 33 while(from >= 0) |
49 { | 34 { |
50 if (haystack[from..from+ol] == needle) | 35 if (haystack[from..from+ol] == needle) |
51 return from; | 36 return from; |
52 from--; | 37 from--; |
53 } | 38 } |
54 return -1; | 39 return -1; |
55 } | |
56 | |
57 | |
58 T[] newArray(T)(size_t len, T[] from = []) | |
59 { | |
60 if (len == from.length) | |
61 return from; | |
62 | |
63 if (!from.length) | |
64 from = [T.init]; | |
65 | |
66 if (from.length < len) | |
67 return newArray!T(len, from ~ from); | |
68 | |
69 return from[0..len]; | |
70 } | 40 } |
71 | 41 |
72 string replicate(int n, char value) | 42 string replicate(int n, char value) |
73 { | 43 { |
74 char[] ret = "".dup; | 44 char[] ret = "".dup; |
111 // string normalizedType; | 81 // string normalizedType; |
112 // string tag; | 82 // string tag; |
113 // string name; | 83 // string name; |
114 string sig; | 84 string sig; |
115 string arguments; | 85 string arguments; |
116 Access access; | 86 Access access; |
117 /* bool returnTypeIsVolatile; | 87 /* bool returnTypeIsVolatile; |
118 | 88 |
119 QList<ArgumentDef> arguments; | 89 QList<ArgumentDef> arguments; |
120 | 90 |
121 enum Access { Private, Protected, Public }; | 91 enum Access { Private, Protected, Public }; |
161 const int startPos = i; | 131 const int startPos = i; |
162 ++i; | 132 ++i; |
163 auto ch = s[i]; | 133 auto ch = s[i]; |
164 if (ch == 'x') { | 134 if (ch == 'x') { |
165 ++i; | 135 ++i; |
166 while (i < s.length && is_hex_char(s[i])) | 136 while (i < s.length && isHexChar(s[i])) |
167 ++i; | 137 ++i; |
168 } else if (is_octal_char(ch)) { | 138 } else if (isOctalChar(ch)) { |
169 while (i < startPos + 4 | 139 while (i < startPos + 4 |
170 && i < s.length | 140 && i < s.length |
171 && is_octal_char(s[i])) { | 141 && isOctalChar(s[i])) { |
172 ++i; | 142 ++i; |
173 } | 143 } |
174 } else { // single character escape sequence | 144 } else { // single character escape sequence |
175 i = qMin(i + 1, s.length); | 145 i = qMin(i + 1, s.length); |
176 } | 146 } |
251 | 221 |
252 QByteArray qualifiedClassNameIdentifier = cdef->qualified; | 222 QByteArray qualifiedClassNameIdentifier = cdef->qualified; |
253 qualifiedClassNameIdentifier.replace(':', '_'); | 223 qualifiedClassNameIdentifier.replace(':', '_'); |
254 */ | 224 */ |
255 bool isConstructible = false; | 225 bool isConstructible = false; |
256 | 226 |
257 FunctionDef[] propertyList, enumList, constructorList; | 227 FunctionDef[] propertyList, enumList, constructorList; |
258 int index = 12; | 228 int index = 12; |
259 gen.output ~= format_ctfe("static const uint[] qt_meta_data_${} = [\n", className); | 229 gen.output ~= "private static const uint[] qt_meta_data = [\n"; |
260 gen.output ~= format_ctfe("\n // content:\n"); | 230 gen.output ~= format_ctfe("\n // content:\n"); |
261 gen.output ~= format_ctfe(" ${}, // revision\n", 2); | 231 gen.output ~= format_ctfe(" ${}, // revision\n", 2); |
262 gen.output ~= format_ctfe(" ${}, // classname\n", strreg(gen, className)); | 232 gen.output ~= format_ctfe(" ${}, // classname\n", strreg(gen, className)); |
263 gen.output ~= format_ctfe(" ${}, ${}, // classinfo\n", 0, 0); | 233 gen.output ~= format_ctfe(" ${}, ${}, // classinfo\n", 0, 0); |
264 // index += cdef->classInfoList.count() * 2; | 234 // index += cdef->classInfoList.count() * 2; |
321 gen.output ~= format_ctfe("\n 0 // eod\n];\n\n"); | 291 gen.output ~= format_ctfe("\n 0 // eod\n];\n\n"); |
322 | 292 |
323 // | 293 // |
324 // Build stringdata array | 294 // Build stringdata array |
325 // | 295 // |
326 gen.output ~= format_ctfe("static const string qt_meta_stringdata_${} = \n", className); | 296 gen.output ~= "private static const string qt_meta_stringdata = \n"; |
327 gen.output ~= format_ctfe(" \""); | 297 gen.output ~= format_ctfe(" \""); |
328 int col = 0; | 298 int col = 0; |
329 int len = 0; | 299 int len = 0; |
330 foreach (i, s; gen.strings) { | 300 foreach (i, s; gen.strings) { |
331 len = s.length; | 301 len = s.length; |
356 | 326 |
357 gen.output ~= "\\0"; | 327 gen.output ~= "\\0"; |
358 col += len + 2; | 328 col += len + 2; |
359 } | 329 } |
360 gen.output ~= "\";\n\n"; | 330 gen.output ~= "\";\n\n"; |
361 | 331 |
362 return gen.output; | 332 return gen.output; |
363 } | |
364 | |
365 string metaCallArgs(Args...)() | |
366 { | |
367 string res; | |
368 foreach(i, _; Args) { | |
369 if (i > 0) | |
370 res ~= ","; | |
371 res ~= metaCallArgument!(Args[i])("_a[" ~ __toString(i+1) ~ "]"); | |
372 } | |
373 return res; | |
374 } | 333 } |
375 | 334 |
376 string qtDeclArgs(Args...)() | 335 string qtDeclArgs(Args...)() |
377 { | 336 { |
378 string ret; | 337 string ret; |
383 ret ~= qtDeclArg!(Args[i]); | 342 ret ~= qtDeclArg!(Args[i]); |
384 } | 343 } |
385 return ret; | 344 return ret; |
386 } | 345 } |
387 | 346 |
388 string generate_qt_metacall(alias Signals, alias Slots)() | |
389 { | |
390 string res = " | |
391 protected int qt_metacall(QMetaObject.Call _c, int _id, void **_a) | |
392 { | |
393 _id = super.qt_metacall(_c, _id, _a); | |
394 if (_id < 0) | |
395 return _id;\n"; | |
396 | |
397 alias TypeTuple!(Signals.at, Slots.at) Methods; | |
398 enum methodCount = Methods.length; | |
399 if(methodCount) | |
400 { | |
401 res ~= " | |
402 if (_c == QMetaObject.Call.InvokeMetaMethod) { | |
403 switch (_id) {"; | |
404 foreach(i, _; Repeat!(void, methodCount)) { | |
405 res ~= " | |
406 case " ~ __toString(i) ~ ": " ~ MetaEntryName!(Methods[i].at) ~ "(" ~ metaCallArgs!(MetaEntryArgs!(Methods[i].at))() ~ "); break;"; | |
407 } | |
408 res ~= "\n default: ;\n }\n"; | |
409 res ~= " _id -= " ~ __toString(methodCount) ~ ";"; | |
410 res ~= "\n }"; | |
411 } | |
412 | |
413 res ~= "\n return _id; | |
414 }"; | |
415 return res; | |
416 } | |
417 | |
418 string dDeclArgs(Args...)() | 347 string dDeclArgs(Args...)() |
419 { | 348 { |
420 string ret; | 349 string ret; |
421 foreach(i, _; Args) | 350 foreach(i, _; Args) |
422 { | 351 { |
423 if (i > 0) | 352 if (i > 0) |
424 ret ~= ", "; | 353 ret ~= ", "; |
425 ret ~= fullDName!(Args[i]); | 354 ret ~= fullName!(Args[i]); |
426 } | 355 } |
427 return ret; | 356 return ret; |
428 } | |
429 string genMetaMethodsConstr(alias Funcs)(string className) | |
430 { | |
431 string res; | |
432 enum funcsCount = Funcs.at.length; | |
433 foreach(i, bogus; Repeat!(void, funcsCount)) | |
434 { | |
435 res ~= " index++;\n" ~ | |
436 " _staticMetaObject.addMethod(new " ~ className ~ "(signature!(" ~ dDeclArgs!(MetaEntryArgs!(Funcs.at[i].at))()~ ")(\"" ~ MetaEntryName!(Funcs.at[i].at) ~ "\"), index));\n\n"; | |
437 } | |
438 return res; | |
439 } | |
440 string generateMetaObjectConstruction(alias Signals, alias Slots)() | |
441 { | |
442 string res; | |
443 res ~= "\n | |
444 private static void _populateMetaInfo() { | |
445 alias BaseClassesTuple!(typeof(this))[0] BaseClass; | |
446 int index = BaseClass.staticMetaObject().methodCount() - 1;\n\n"; | |
447 | |
448 res ~= genMetaMethodsConstr!(Signals)("QMetaSignal"); | |
449 res ~= genMetaMethodsConstr!(Slots)("QMetaSlot"); | |
450 | |
451 res ~= " | |
452 }\n"; | |
453 return res; | |
454 } | |
455 | |
456 string generateQMetaObject(string className) | |
457 { | |
458 string res; | |
459 res ~= " | |
460 public QMetaObject metaObject() { return staticMetaObject(); } | |
461 private static __gshared QMetaObject _staticMetaObject; | |
462 private static __gshared QMetaObjectNative _nativeStaticMetaObject; | |
463 public static QMetaObject staticMetaObject() | |
464 { | |
465 if(!_staticMetaObject) | |
466 createStaticMetaObject(); | |
467 return _staticMetaObject; | |
468 } | |
469 protected static void createStaticMetaObject() { | |
470 assert(!_staticMetaObject); | |
471 alias BaseClassesTuple!(typeof(this))[0] BaseClass; | |
472 if (!BaseClass._staticMetaObject) | |
473 BaseClass.createStaticMetaObject; | |
474 auto base = BaseClass._staticMetaObject; | |
475 _nativeStaticMetaObject = QMetaObjectNative(base.nativeId, qt_meta_stringdata_" ~ className ~ ".ptr, | |
476 qt_meta_data_" ~ className ~ ".ptr, null ); | |
477 | |
478 _staticMetaObject = new QMetaObject(&_nativeStaticMetaObject, base); | |
479 // _staticMetaObject.construct!(typeof(this)); | |
480 _populateMetaInfo(); | |
481 }\n\n"; | |
482 return res; | |
483 } | 357 } |
484 | 358 |
485 size_t commaCount(int argCount) | 359 size_t commaCount(int argCount) |
486 { | 360 { |
487 size_t ret = 0; | 361 size_t ret = 0; |
488 if(argCount > 1) | 362 if(argCount > 1) |
489 ret = argCount - 1; | 363 ret = argCount - 1; |
490 return ret; | 364 return ret; |
491 } | 365 } |
492 | 366 |
493 FunctionDef[] genFuncDefs(alias Funcs, alias newFunc)() | 367 FunctionDef[] generateFuncDefs(alias newFunc, Funcs...)() |
494 { | 368 { |
495 typeof(return) res; | 369 typeof(return) res; |
496 enum funcsCount = Funcs.at.length; | 370 enum funcsCount = Funcs.length; |
497 foreach(i, bogus; Repeat!(void, funcsCount)) | 371 foreach(i, bogus; Repeat!(void, funcsCount)) |
498 { | 372 { |
499 string args = replicate(commaCount((MetaEntryArgs!(Funcs.at[i].at)).length), ','); | 373 alias ParameterTypeTuple!(Funcs[i]) Args; |
500 string funcSig = MetaEntryName!(Funcs.at[i].at) ~ "(" ~ qtDeclArgs!(MetaEntryArgs!(Funcs.at[i].at))() ~ ")"; | 374 string args = replicate(commaCount(Args.length), ','); |
375 string funcSig = methodName!(Funcs[i]) ~ "(" ~ qtDeclArgs!(Args)() ~ ")"; | |
501 res ~= newFunc(funcSig, args); | 376 res ~= newFunc(funcSig, args); |
502 } | 377 } |
503 return res; | 378 return res; |
504 } | 379 } |
505 | 380 |
507 { | 382 { |
508 } | 383 } |
509 | 384 |
510 // ------------------------------------------------------------------------------------------ | 385 // ------------------------------------------------------------------------------------------ |
511 | 386 |
512 string generateSignalEmitters(alias Funcs)() | 387 string generateSignalEmitters(uint signalCount) |
513 { | 388 { |
514 string res; | 389 string res = ""; |
515 enum funcsCount = Funcs.at.length; | 390 foreach (i; 0..signalCount) |
516 foreach(i, bogus; Repeat!(void, funcsCount)) | 391 { |
517 { | 392 auto iStr = to!string(i); |
518 res ~= SignalEmitter!(MetaEntryArgs!(Funcs.at[i].at))(SignalType.NewSignal, MetaEntryName!(Funcs.at[i].at), cast(string[])[], i); | 393 res ~= "mixin SignalEmitter!(SignalKind.NewSignal, " ~ iStr ~ ");\n"; |
519 } | 394 } |
520 return res; | 395 return res; |
521 } | 396 } |
522 | 397 |
523 string generateSlotAliases(alias Funcs)() | 398 private mixin template SlotAlias(alias slot) |
524 { | 399 { |
525 string res; | 400 mixin ("alias slot " ~ methodName!slot ~ ";"); |
526 enum funcsCount = Funcs.at.length; | 401 } |
527 foreach(i, bogus; Repeat!(void, funcsCount)) | 402 |
528 { | 403 string generateSlotAliases(uint slotCount) |
529 string name = MetaEntryName!(Funcs.at[i].at); | 404 { |
530 res ~= format_ctfe(" alias slot_${} ${};\n", name, name); | 405 string res = ""; |
406 foreach(i; 0..slotCount) | |
407 { | |
408 auto iStr = to!string(i); | |
409 res ~= "mixin SlotAlias!(slots[" ~ iStr ~ "]);\n"; | |
531 } | 410 } |
532 return res; | 411 return res; |
533 } | 412 } |
534 | 413 |
535 | 414 string generateMetaCall(string methodName, size_t argCount) |
536 string generateMetaInfo(T, alias Signals, alias Slots)() | |
537 { | 415 { |
538 string res = ""; | 416 string res = ""; |
539 auto signalList = genFuncDefs!(Signals, newSignal)(); | 417 foreach (i; 1..argCount) |
540 auto slotList = genFuncDefs!(Slots, newSlot)(); | 418 res ~= generateConvToD(i); |
541 res ~= generateSignalEmitters!(Signals)(); | 419 |
542 res ~= generateSlotAliases!(Slots)(); | 420 res ~= methodName ~ "("; |
543 res ~= generateCode(T.stringof, signalList, slotList); | 421 foreach (i; 1..argCount) |
544 res ~= generate_qt_metacall!(Signals, Slots); | 422 { |
545 res ~= generateMetaObjectConstruction!(Signals, Slots); | 423 if (i > 1) |
546 res ~= generateQMetaObject(T.stringof); | 424 res ~= ", "; |
547 return res; | 425 res ~= "_out" ~ to!string(i); |
548 } | 426 } |
549 | 427 return res ~ ");\n"; |
550 template Q_OBJECT() | 428 } |
551 { | 429 |
552 alias findSignals!(typeof(this)) SignalFuncs; | 430 string generateDispatchSwitch(size_t methodCount) |
553 alias toMetaEntries!(SignalFuncs) SignalMetaEntries; | 431 { |
554 alias findSlots!(typeof(this)) SlotFuncs; | 432 string res = "switch(_id) {\n"; |
555 alias toMetaEntries!(SlotFuncs) SlotMetaEntries; | 433 |
556 | 434 foreach(i; 0..methodCount) |
557 mixin(generateMetaInfo!(typeof(this), SignalMetaEntries, SlotMetaEntries)()); | 435 { |
558 // debug output | 436 string iStr = to!string(i); |
559 // pragma(msg, generateMetaInfo!(typeof(this), SignalMetaEntries, SlotMetaEntries)()); | 437 res ~= " case " ~ iStr ~ ":\n"; |
560 } | 438 res ~= " alias methods[" ~ iStr ~ "] method;\n"; |
439 res ~= " alias TypeTuple!(void, ParameterTypeTuple!method) Args;\n"; | |
440 res ~= " mixin(generateMetaCall(methodName!method, Args.length));\n"; | |
441 res ~= " break;\n"; | |
442 } | |
443 | |
444 res ~= " default:\n"; | |
445 | |
446 return res ~ "}\n"; | |
447 } | |
448 | |
449 mixin template Q_OBJECT() | |
450 { | |
451 import std.typetuple; | |
452 import qtd.Marshal; | |
453 import qt.core.QString; // for QStringUtil.toNative | |
454 | |
455 public: // required to override the outside scope protection. | |
456 | |
457 alias typeof(this) This; | |
458 | |
459 alias findSignals!(This) signals; | |
460 alias findSlots!(This) slots; | |
461 alias TypeTuple!(signals, slots) methods; | |
462 | |
463 | |
464 mixin (generateSignalEmitters(signals.length)); | |
465 mixin (generateSlotAliases(slots.length)); | |
466 | |
467 auto signalList = generateFuncDefs!(newSignal, signals)(); | |
468 auto slotList = generateFuncDefs!(newSlot, slots)(); | |
469 mixin (generateCode(typeof(this).stringof, signalList, slotList)); | |
470 | |
471 protected int qt_metacall(QMetaObject.Call _c, int _id, void **_a) | |
472 { | |
473 _id = super.qt_metacall(_c, _id, _a); | |
474 | |
475 static if (methods.length) | |
476 { | |
477 if (_id < 0) | |
478 return _id; | |
479 | |
480 if (_c == QMetaObject.Call.InvokeMetaMethod) { | |
481 //pragma(msg, generateDispatchSwitch(methods.length)); | |
482 mixin (generateDispatchSwitch(methods.length)); | |
483 } | |
484 _id -= methods.length; | |
485 } | |
486 | |
487 return _id; | |
488 } | |
489 | |
490 @property | |
491 override QMetaObject metaObject() const { return staticMetaObject(); } | |
492 | |
493 private static __gshared QMetaObject _staticMetaObject; | |
494 private static __gshared QMetaObjectNative _nativeStaticMetaObject; | |
495 | |
496 @property | |
497 static QMetaObject staticMetaObject() | |
498 { | |
499 // TODO: synchronize or enable static constructors in circular modules | |
500 if(!_staticMetaObject) | |
501 { | |
502 alias BaseClassesTuple!(This)[0] Base; | |
503 | |
504 _nativeStaticMetaObject = QMetaObjectNative( | |
505 Base.staticMetaObject.nativeId, | |
506 qt_meta_stringdata.ptr, | |
507 qt_meta_data.ptr, null); | |
508 | |
509 QMetaObject.create!This(&_nativeStaticMetaObject); | |
510 } | |
511 return _staticMetaObject; | |
512 } | |
513 | |
514 /*internal*/ static void setStaticMetaObject(QMetaObject m) | |
515 { | |
516 _staticMetaObject = m; | |
517 } | |
518 } | |
519 |