Mercurial > projects > qtd
annotate d2/qtd/meta/Runtime.d @ 365:958e8b9a89bd
Changeset a084e2df3776 is broken. Backing out.
author | Max Samukha <maxter@spambox.com> |
---|---|
date | Fri, 11 Jun 2010 20:09:25 +0300 |
parents | a084e2df3776 |
children | 185df9220ea7 |
rev | line source |
---|---|
351 | 1 /************************************************************************** |
2 Copyright: Copyright Max Samukha, 2010 | |
3 Authors: Max Samukha | |
4 License: Boost Software License 1.0 | |
5 **************************************************************************/ | |
6 module qtd.meta.Runtime; | |
7 //TODO: Probably replace switch dispatch with pointer dispatch | |
8 //and leave switch dispatch only in C interface | |
9 | |
10 import | |
11 qtd.meta.Compiletime, | |
12 | |
13 std.typetuple, | |
14 std.conv, | |
15 std.variant, | |
16 core.sync.rwmutex; | |
17 | |
18 private __gshared ReadWriteMutex lock; | |
19 shared static this() | |
20 { | |
21 lock = new ReadWriteMutex; | |
22 } | |
23 | |
24 /** | |
25 IDs of the built-in basic types. | |
26 */ | |
27 enum BasicTypeId | |
28 { | |
29 /// | |
30 void_, | |
31 /// | |
32 bool_, | |
33 /// | |
34 byte_, | |
35 /// | |
36 ubyte_, | |
37 /// | |
38 short_, | |
39 /// | |
40 ushort_, | |
41 /// | |
42 int_, | |
43 /// | |
44 uint_, | |
45 /// | |
46 long_, | |
47 /// | |
48 ulong_, | |
49 /// | |
50 cent_, | |
51 /// | |
52 ucent_, | |
53 /// | |
54 float_, | |
55 /// | |
56 double_, | |
57 /// | |
58 real_, | |
59 /// | |
60 ifloat_, | |
61 /// | |
62 idouble_, | |
63 /// | |
64 ireal_, | |
65 /// | |
66 cfloat_, | |
67 /// | |
68 cdouble_, | |
69 /// | |
70 creal_, | |
71 /// | |
72 char_, | |
73 /// | |
74 wchar_, | |
75 /// | |
76 dchar_ | |
77 } | |
78 | |
79 /** | |
80 Thrown on meta-system errors. | |
81 */ | |
82 class MetaException : Exception | |
83 { | |
84 this(string msg) | |
85 { | |
86 super(msg); | |
87 } | |
88 } | |
89 | |
365
958e8b9a89bd
Changeset a084e2df3776 is broken. Backing out.
Max Samukha <maxter@spambox.com>
parents:
364
diff
changeset
|
90 abstract class Meta |
351 | 91 { |
92 alias typeof(this) This; | |
93 | |
94 string name; | |
95 MetaAttribute[] attributes; | |
365
958e8b9a89bd
Changeset a084e2df3776 is broken. Backing out.
Max Samukha <maxter@spambox.com>
parents:
364
diff
changeset
|
96 Meta[] members; |
351 | 97 |
98 template createImpl(M : This) | |
99 { | |
100 static M createImpl(alias symbol)() | |
101 { | |
102 auto m = new M; | |
103 m.construct!symbol; | |
104 return m; | |
105 } | |
106 } | |
107 | |
108 private void createAttrs(alias symbol)() | |
109 { | |
110 alias GetAttributes!symbol attrs; | |
111 enum len = attrs.length; // COMPILER BUG | |
112 foreach (i, _; Repeat!(void, len)) | |
113 { | |
114 alias TypeTuple!(attrs[i].tuple) attr; | |
115 // if the third element of the attribute data is a MetaAttribute subclass, | |
116 // use that to create the attribute instance. | |
117 static if (attr.length > 2 && (is(attr[2] : MetaAttribute))) | |
118 { | |
119 alias attr[2] MA; | |
120 alias TypeTuple!(attr[0..2], attr[3..$]) args; | |
121 attributes ~= MA /*COMPILER BUG: tuple element as tuple*/[0].create!args(); | |
122 } | |
123 } | |
124 } | |
125 | |
126 protected void construct(alias symbol)() | |
127 { | |
128 createAttrs!symbol; | |
129 } | |
130 } | |
131 | |
132 /** | |
133 Base class for run time attributes. | |
134 */ | |
135 abstract class MetaAttribute | |
136 { | |
137 alias typeof(this) This; | |
138 | |
139 string name; | |
140 AttributeOptions options; | |
141 | |
142 This create(string name, AttributeOptions opts, A...)() | |
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 { | |
151 this.name = name; | |
152 options = opts; | |
153 } | |
154 } | |
155 | |
365
958e8b9a89bd
Changeset a084e2df3776 is broken. Backing out.
Max Samukha <maxter@spambox.com>
parents:
364
diff
changeset
|
156 abstract class MetaType : Meta |
351 | 157 { |
158 } | |
159 | |
160 abstract class MetaAggregate : MetaType | |
161 { | |
162 } | |
163 | |
164 class MetaClass : MetaAggregate | |
165 { | |
166 alias typeof(this) This; | |
365
958e8b9a89bd
Changeset a084e2df3776 is broken. Backing out.
Max Samukha <maxter@spambox.com>
parents:
364
diff
changeset
|
167 alias createImpl!This create; |
351 | 168 } |
169 | |
170 class MetaStruct : MetaAggregate | |
171 { | |
172 alias typeof(this) This; | |
173 alias createImpl!This create; | |
174 } | |
175 | |
176 @property | |
365
958e8b9a89bd
Changeset a084e2df3776 is broken. Backing out.
Max Samukha <maxter@spambox.com>
parents:
364
diff
changeset
|
177 auto meta(alias symbol, M : Meta)() |
351 | 178 { |
365
958e8b9a89bd
Changeset a084e2df3776 is broken. Backing out.
Max Samukha <maxter@spambox.com>
parents:
364
diff
changeset
|
179 __gshared static M m; |
958e8b9a89bd
Changeset a084e2df3776 is broken. Backing out.
Max Samukha <maxter@spambox.com>
parents:
364
diff
changeset
|
180 |
958e8b9a89bd
Changeset a084e2df3776 is broken. Backing out.
Max Samukha <maxter@spambox.com>
parents:
364
diff
changeset
|
181 { |
958e8b9a89bd
Changeset a084e2df3776 is broken. Backing out.
Max Samukha <maxter@spambox.com>
parents:
364
diff
changeset
|
182 lock.reader.lock; |
958e8b9a89bd
Changeset a084e2df3776 is broken. Backing out.
Max Samukha <maxter@spambox.com>
parents:
364
diff
changeset
|
183 scope(exit) |
958e8b9a89bd
Changeset a084e2df3776 is broken. Backing out.
Max Samukha <maxter@spambox.com>
parents:
364
diff
changeset
|
184 lock.reader.unlock; |
958e8b9a89bd
Changeset a084e2df3776 is broken. Backing out.
Max Samukha <maxter@spambox.com>
parents:
364
diff
changeset
|
185 if (m) |
958e8b9a89bd
Changeset a084e2df3776 is broken. Backing out.
Max Samukha <maxter@spambox.com>
parents:
364
diff
changeset
|
186 return m; |
958e8b9a89bd
Changeset a084e2df3776 is broken. Backing out.
Max Samukha <maxter@spambox.com>
parents:
364
diff
changeset
|
187 } |
958e8b9a89bd
Changeset a084e2df3776 is broken. Backing out.
Max Samukha <maxter@spambox.com>
parents:
364
diff
changeset
|
188 |
958e8b9a89bd
Changeset a084e2df3776 is broken. Backing out.
Max Samukha <maxter@spambox.com>
parents:
364
diff
changeset
|
189 lock.writer.lock; |
958e8b9a89bd
Changeset a084e2df3776 is broken. Backing out.
Max Samukha <maxter@spambox.com>
parents:
364
diff
changeset
|
190 scope(exit) |
958e8b9a89bd
Changeset a084e2df3776 is broken. Backing out.
Max Samukha <maxter@spambox.com>
parents:
364
diff
changeset
|
191 lock.writer.unlock; |
351 | 192 |
364
a084e2df3776
Preparing for non-QObject meta-objects. Now meta-objects for static types can be uniformly accessed using meta!T
Max Samukha <maxter@maxter.com>
parents:
351
diff
changeset
|
193 if (!m) |
365
958e8b9a89bd
Changeset a084e2df3776 is broken. Backing out.
Max Samukha <maxter@spambox.com>
parents:
364
diff
changeset
|
194 m = M.create!symbol; |
351 | 195 return m; |
196 } | |
197 | |
198 // only classes and structs for now | |
199 @property | |
200 auto meta(T)() | |
201 { | |
365
958e8b9a89bd
Changeset a084e2df3776 is broken. Backing out.
Max Samukha <maxter@spambox.com>
parents:
364
diff
changeset
|
202 static if (is(typeof(T.staticMetaObject))) |
958e8b9a89bd
Changeset a084e2df3776 is broken. Backing out.
Max Samukha <maxter@spambox.com>
parents:
364
diff
changeset
|
203 return T.staticMetaObject; |
351 | 204 else static if (is(T == class)) |
205 return meta!(T, MetaClass); | |
206 else static if (is(T == struct)) | |
207 return meta!(T, MetaStruct); | |
208 else | |
209 static assert(false, "No meta object for symbol " ~ T.stringof); | |
210 } | |
211 | |
212 /** | |
213 A run time attribute implementation that stores the attribute data in an | |
214 array of variants. | |
215 */ | |
216 class MetaVariantAttribute : MetaAttribute | |
217 { | |
218 Variant[] values; | |
219 | |
220 private this() | |
221 { | |
222 } | |
223 | |
224 static MetaVariantAttribute create(string category, AttributeOptions opts, A...)() | |
225 { | |
226 auto ret = new MetaVariantAttribute; | |
227 ret.construct!(category, opts)(); | |
228 foreach(i, _; A) | |
229 { | |
230 static if (__traits(compiles, { ret.values ~= Variant(A[i]); } )) | |
231 ret.values ~= Variant(A[i]); | |
232 } | |
233 return ret; | |
234 } | |
235 } | |
236 | |
237 /** | |
238 A run time attribute implementation that stores the attribute data in an | |
239 assiciative array of variants. | |
240 */ | |
241 class MetaVariantDictAttribute : MetaAttribute | |
242 { | |
243 Variant[string] values; | |
244 alias typeof(this) This; | |
245 | |
246 private this() | |
247 { | |
248 } | |
249 | |
250 static This create(string category, AttributeOptions opts, A...)() | |
251 { | |
252 auto ret = new This; | |
253 ret.construct!(category, opts)(); | |
254 foreach(i, _; A) | |
255 { | |
256 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 | |
258 } | |
259 return ret; | |
260 } | |
261 } | |
262 | |
263 version (QtdUnittest) | |
264 { | |
265 unittest | |
266 { | |
267 static void foo() {} | |
268 | |
269 static class C | |
270 { | |
271 mixin InnerAttribute!("variantAttribute", MetaVariantAttribute, "22", foo, 33); | |
272 mixin InnerAttribute!("variantDictAttribute", MetaVariantDictAttribute, | |
273 //"a", "33", // PHOBOS BUG: variant is unusable with AAs | |
274 "b", foo | |
275 //"c", 44 | |
276 ); | |
277 } | |
278 | |
279 auto attrs = meta!(C).attributes; | |
280 assert(attrs.length == 2); | |
281 auto attr = cast(MetaVariantAttribute)attrs[0]; | |
282 | |
283 assert(attr.name == "variantAttribute"); | |
284 assert(attr.values[0] == "22"); | |
285 assert(attr.values[1] == 33); | |
286 | |
287 auto attr2 = cast(MetaVariantDictAttribute) attrs[1]; | |
288 assert(attr2.name == "variantDictAttribute"); | |
289 //assert(attr2.values["a"] == "33"); | |
290 //assert(attr2.values["c"] == 44); | |
291 } | |
292 } |