comparison d2/qtd/meta/Runtime.d @ 368:185df9220ea7

Fixed startsWith. Implemented meta-object members as ranges. Freed QMetaObject from stuff that belongs to MetaClass
author Max Samukha <maxter@maxter.com>
date Mon, 28 Jun 2010 21:29:32 +0300
parents 958e8b9a89bd
children a032df77b6ab
comparison
equal deleted inserted replaced
367:f69341b40588 368:185df9220ea7
2 Copyright: Copyright Max Samukha, 2010 2 Copyright: Copyright Max Samukha, 2010
3 Authors: Max Samukha 3 Authors: Max Samukha
4 License: Boost Software License 1.0 4 License: Boost Software License 1.0
5 **************************************************************************/ 5 **************************************************************************/
6 module qtd.meta.Runtime; 6 module qtd.meta.Runtime;
7 //TODO: Probably replace switch dispatch with pointer dispatch
8 //and leave switch dispatch only in C interface
9 7
10 import 8 import
11 qtd.meta.Compiletime, 9 qtd.meta.Compiletime,
12 10
13 std.typetuple, 11 std.typetuple,
14 std.conv, 12 std.conv,
15 std.variant, 13 std.stdio,
16 core.sync.rwmutex; 14 std.traits,
17 15 std.variant;
18 private __gshared ReadWriteMutex lock; 16
17 import std.range : isForwardRange, isRandomAccessRange;
18
19 /**
20 Object to lock on when accessing thread-shared meta-objects.
21 */
22 immutable Object metaLock;
19 shared static this() 23 shared static this()
20 { 24 {
21 lock = new ReadWriteMutex; 25 metaLock = cast(immutable)new Object;
22 } 26 }
23 27
24 /** 28 /**
25 IDs of the built-in basic types. 29 IDs of the built-in basic types.
26 */ 30 */
85 { 89 {
86 super(msg); 90 super(msg);
87 } 91 }
88 } 92 }
89 93
90 abstract class Meta 94 abstract class MetaBase
91 { 95 {
92 alias typeof(this) This; 96 alias typeof(this) This;
93 97
94 string name; 98 string name;
95 MetaAttribute[] attributes; 99 MetaAttribute[] attributes;
96 Meta[] members; 100
101 protected MetaBase[] members_;
97 102
98 template createImpl(M : This) 103 template createImpl(M : This)
99 { 104 {
100 static M createImpl(alias symbol)() 105 static M createImpl(alias symbol)()
101 { 106 {
123 } 128 }
124 } 129 }
125 130
126 protected void construct(alias symbol)() 131 protected void construct(alias symbol)()
127 { 132 {
133 name = symbol.stringof;
128 createAttrs!symbol; 134 createAttrs!symbol;
129 } 135 }
130 } 136
131 137 static struct MembersRange
132 /** 138 {
133 Base class for run time attributes. 139 private MetaBase[] members_;
140
141 @property
142 MetaBase front()
143 {
144 return members_[0];
145 }
146
147 @property
148 bool empty()
149 {
150 return members_.length == 0;
151 }
152
153 @property
154 MembersRange save()
155 {
156 return this;
157 }
158
159 @property
160 MetaBase back()
161 {
162 return members_[$ - 1];
163 }
164
165 void popFront()
166 {
167 members_ = members_[1..$];
168 }
169
170 void popBack()
171 {
172 members_ = members_[0..$ - 1];
173 }
174
175 MetaBase opIndex(size_t i)
176 {
177 return members_[i];
178 }
179
180 @property
181 size_t length()
182 {
183 return members_.length;
184 }
185 }
186
187 /**
188 Returns a random access range of members of the class described by this meta-object.
189 */
190 @property
191 MembersRange members()
192 {
193 return MembersRange(members_);
194 }
195 }
196
197 version (QtdUnittest) unittest
198 {
199 static assert(isRandomAccessRange!(MetaBase.MembersRange));
200 }
201
202 /**
203 Base class for run-time attributes.
134 */ 204 */
135 abstract class MetaAttribute 205 abstract class MetaAttribute
136 { 206 {
137 alias typeof(this) This;
138
139 string name; 207 string name;
140 AttributeOptions options; 208 AttributeOptions options;
141 209
142 This create(string name, AttributeOptions opts, A...)() 210 this(string name, AttributeOptions opts)
143 {
144 auto ma = new This;
145 ma.construct!(name, opts, A)();
146 return ma;
147 }
148
149 void construct(string name, AttributeOptions opts)()
150 { 211 {
151 this.name = name; 212 this.name = name;
152 options = opts; 213 options = opts;
153 } 214 }
154 } 215 }
155 216
156 abstract class MetaType : Meta 217 abstract class MetaType : MetaBase
157 { 218 {
158 } 219 }
159 220
160 abstract class MetaAggregate : MetaType 221 abstract class MetaAggregate : MetaType
161 { 222 {
162 } 223 }
163 224
164 class MetaClass : MetaAggregate 225 class MetaClass : MetaAggregate
226 {
227 alias typeof(this) This;
228
229 private
230 {
231 This base_;
232 This firstDerived_;
233 This next_;
234 ClassInfo classInfo_;
235 }
236
237 alias createImpl!This create;
238
239 static struct AllMembersRange
240 {
241 public //private
242 {
243 This metaClass_;
244 MetaBase[] members_;
245
246 void skipEmpty()
247 {
248 while (!metaClass_.members_.length)
249 {
250 metaClass_ = metaClass_.base_;
251 if (!metaClass_)
252 {
253 members_ = null;
254 return;
255 }
256 }
257
258 members_ = metaClass_.members_;
259 }
260 }
261
262 this(This metaClass)
263 {
264 metaClass_ = metaClass;
265 skipEmpty();
266 }
267
268 @property
269 MetaBase front()
270 {
271 return members_[0];
272 }
273
274 @property
275 bool empty()
276 {
277 return members_.length == 0;
278 }
279
280 @property
281 AllMembersRange save()
282 {
283 return this;
284 }
285
286 void popFront()
287 {
288 members_ = members_[1..$];
289 if (!members_.length)
290 {
291 metaClass_ = metaClass_.base_;
292 if (metaClass_)
293 skipEmpty();
294 }
295 }
296 }
297
298 /**
299 Returns a forward range of members of the class described by this meta-object,
300 including base class members.
301 */
302 @property
303 AllMembersRange allMembers()
304 {
305 return AllMembersRange(this);
306 }
307
308 /**
309 Returns the meta-object of the base class.
310 */
311 @property
312 This base()
313 {
314 return base_;
315 }
316
317 /**
318 Returns the next meta-object on this level of the inheritance hierarchy.
319 */
320 @property
321 This next()
322 {
323 return next_;
324 }
325
326 /**
327 Returns the meta-object for the first derived class.
328 */
329 @property
330 This firstDerived()
331 {
332 return firstDerived_;
333 }
334
335 /**
336 D class info.
337 */
338 @property
339 ClassInfo classInfo()
340 {
341 return classInfo_;
342 }
343
344
345 /* internal */ void construct(T : Object)()
346 {
347 super.construct!T();
348 static if (!is(T == Object))
349 {
350 alias BaseClassesTuple!(T)[0] Base;
351 base_ = meta!Base;
352
353 next_ = base_.firstDerived_;
354 base_.firstDerived_ = this;
355 }
356 classInfo_ = T.classinfo;
357 }
358
359 /**
360 */
361 override string toString() const
362 {
363 return "MetaClass for " ~ classInfo_.name;
364 }
365 }
366
367 version (QtdUnittest) unittest
368 {
369 static assert (isForwardRange!(MetaClass.AllMembersRange));
370 }
371
372 class MetaStruct : MetaAggregate
165 { 373 {
166 alias typeof(this) This; 374 alias typeof(this) This;
167 alias createImpl!This create; 375 alias createImpl!This create;
168 } 376 }
169 377
170 class MetaStruct : MetaAggregate 378 /**
171 { 379 */
172 alias typeof(this) This;
173 alias createImpl!This create;
174 }
175
176 @property 380 @property
177 auto meta(alias symbol, M : Meta)() 381 M meta(alias symbol, M : MetaBase)()
178 { 382 {
179 __gshared static M m; 383 __gshared static M sharedM;
180 384 static M m;
181 {
182 lock.reader.lock;
183 scope(exit)
184 lock.reader.unlock;
185 if (m)
186 return m;
187 }
188
189 lock.writer.lock;
190 scope(exit)
191 lock.writer.unlock;
192 385
193 if (!m) 386 if (!m)
194 m = M.create!symbol; 387 {
388 synchronized(metaLock)
389 {
390 if (!sharedM)
391 sharedM = M.create!symbol;
392 }
393 m = sharedM;
394 }
395
396 assert (m is sharedM);
195 return m; 397 return m;
196 } 398 }
197 399
400 version (QtdUnittest) unittest
401 {
402 class A
403 {
404 }
405
406 auto m = meta!A;
407 assert(m is meta!A);
408 }
409
410 /**
411 */
198 // only classes and structs for now 412 // only classes and structs for now
199 @property 413 @property
200 auto meta(T)() 414 auto meta(T)()
201 { 415 {
202 static if (is(typeof(T.staticMetaObject))) 416 static if (is(T.Meta))
203 return T.staticMetaObject; 417 return meta!(T, T.Meta);
204 else static if (is(T == class)) 418 else static if (is(T == class))
205 return meta!(T, MetaClass); 419 return meta!(T, MetaClass);
206 else static if (is(T == struct)) 420 else static if (is(T == struct))
207 return meta!(T, MetaStruct); 421 return meta!(T, MetaStruct);
208 else 422 else
209 static assert(false, "No meta object for symbol " ~ T.stringof); 423 static assert(false, "No meta-object for symbol " ~ T.stringof);
210 } 424 }
211 425
212 /** 426 /**
213 A run time attribute implementation that stores the attribute data in an 427 A run-time attribute implementation that stores the attribute data in an
214 array of variants. 428 array of variants.
215 */ 429 */
216 class MetaVariantAttribute : MetaAttribute 430 class MetaVariantAttribute : MetaAttribute
217 { 431 {
432 alias typeof(this) This;
433
218 Variant[] values; 434 Variant[] values;
219 435
220 private this() 436 private this(string name, AttributeOptions opts)
221 { 437 {
222 } 438 super(name, opts);
223 439 }
224 static MetaVariantAttribute create(string category, AttributeOptions opts, A...)() 440
225 { 441 static MetaVariantAttribute create(string name, AttributeOptions opts, A...)()
226 auto ret = new MetaVariantAttribute; 442 {
227 ret.construct!(category, opts)(); 443 auto ret = new This(name, opts);
228 foreach(i, _; A) 444 foreach(i, _; A)
229 { 445 {
230 static if (__traits(compiles, { ret.values ~= Variant(A[i]); } )) 446 static if (__traits(compiles, { ret.values ~= Variant(A[i]); } ))
231 ret.values ~= Variant(A[i]); 447 ret.values ~= Variant(A[i]);
232 } 448 }
233 return ret; 449 return ret;
234 } 450 }
235 } 451 }
236 452
237 /** 453 /**
238 A run time attribute implementation that stores the attribute data in an 454 A run-time attribute implementation that stores the attribute data in an
239 assiciative array of variants. 455 assiciative array of variants.
240 */ 456 */
241 class MetaVariantDictAttribute : MetaAttribute 457 class MetaVariantDictAttribute : MetaAttribute
242 { 458 {
243 Variant[string] values; 459 Variant[string] values;
244 alias typeof(this) This; 460 alias typeof(this) This;
245 461
246 private this() 462 private this(string name, AttributeOptions opts)
247 { 463 {
248 } 464 super(name, opts);
249 465 }
250 static This create(string category, AttributeOptions opts, A...)() 466
251 { 467 static This create(string name, AttributeOptions opts, A...)()
252 auto ret = new This; 468 {
253 ret.construct!(category, opts)(); 469 auto ret = new This(name, opts);
254 foreach(i, _; A) 470 foreach(i, _; A)
255 { 471 {
256 static if (i % 2 == 0 && __traits(compiles, { ret.values[A[i]] = Variant(A[i + 1]); } )) 472 static if (i % 2 == 0 && __traits(compiles, { ret.values[A[i]] = Variant(A[i + 1]); } ))
257 ret.values[A[i]] = Variant(A[i + 1]); // PHOBOS BUG: phobos asserts on this 473 ret.values[A[i]] = Variant(A[i + 1]); // PHOBOS BUG: phobos asserts on this
258 } 474 }
259 return ret; 475 return ret;
260 } 476 }
261 } 477 }
262 478
263 version (QtdUnittest) 479 version(QtdUnittest) unittest
264 { 480 {
265 unittest 481 static void foo() {}
266 { 482
267 static void foo() {} 483 static class C
268 484 {
269 static class C 485 mixin InnerAttribute!("variantAttribute", MetaVariantAttribute, "22", foo, 33);
270 { 486 mixin InnerAttribute!("variantDictAttribute", MetaVariantDictAttribute,
271 mixin InnerAttribute!("variantAttribute", MetaVariantAttribute, "22", foo, 33); 487 //"a", "33", // PHOBOS BUG: variant is unusable with AAs
272 mixin InnerAttribute!("variantDictAttribute", MetaVariantDictAttribute, 488 "b", foo
273 //"a", "33", // PHOBOS BUG: variant is unusable with AAs 489 //"c", 44
274 "b", foo 490 );
275 //"c", 44 491 }
276 ); 492
277 } 493 auto attrs = meta!(C).attributes;
278 494 assert(attrs.length == 2);
279 auto attrs = meta!(C).attributes; 495 auto attr = cast(MetaVariantAttribute)attrs[0];
280 assert(attrs.length == 2); 496
281 auto attr = cast(MetaVariantAttribute)attrs[0]; 497 assert(attr.name == "variantAttribute");
282 498 assert(attr.values[0] == "22");
283 assert(attr.name == "variantAttribute"); 499 assert(attr.values[1] == 33);
284 assert(attr.values[0] == "22"); 500
285 assert(attr.values[1] == 33); 501 auto attr2 = cast(MetaVariantDictAttribute) attrs[1];
286 502 assert(attr2.name == "variantDictAttribute");
287 auto attr2 = cast(MetaVariantDictAttribute) attrs[1]; 503 //assert(attr2.values["a"] == "33");
288 assert(attr2.name == "variantDictAttribute"); 504 //assert(attr2.values["c"] == 44);
289 //assert(attr2.values["a"] == "33"); 505 }
290 //assert(attr2.values["c"] == 44);
291 }
292 }