Mercurial > projects > ddmd
annotate dmd/TraitsExp.d @ 178:e3afd1303184
Many small bugs fixed
Made all classes derive from TObject to detect memory leaks (functionality is disabled for now)
Began work on overriding backend memory allocations (to avoid memory leaks)
author | korDen |
---|---|
date | Sun, 17 Oct 2010 07:42:00 +0400 |
parents | 80f4806ffa13 |
children | cd48cb899aee |
rev | line source |
---|---|
72 | 1 module dmd.TraitsExp; |
2 | |
114 | 3 import dmd.common; |
72 | 4 import dmd.Expression; |
5 import dmd.Identifier; | |
6 import dmd.ArrayTypes; | |
7 import dmd.OutBuffer; | |
8 import dmd.Loc; | |
9 import dmd.Scope; | |
10 import dmd.HdrGenState; | |
11 import dmd.TOK; | |
12 import dmd.TY; | |
13 import dmd.STC; | |
14 import dmd.WANT; | |
15 import dmd.Id; | |
16 import dmd.Global; | |
17 import dmd.Lexer; | |
18 import dmd.ArrayLiteralExp; | |
19 import dmd.VarExp; | |
20 import dmd.StringExp; | |
21 import dmd.DotIdExp; | |
22 import dmd.DotVarExp; | |
23 import dmd.IntegerExp; | |
24 import dmd.TupleExp; | |
25 import dmd.Type; | |
26 import dmd.Dsymbol; | |
27 import dmd.DsymbolExp; | |
28 import dmd.ScopeDsymbol; | |
29 import dmd.FuncDeclaration; | |
30 import dmd.ClassDeclaration; | |
31 import dmd.TemplateDeclaration; | |
32 import dmd.TemplateInstance; | |
33 import dmd.TypeClass; | |
135 | 34 import dmd.Declaration; |
72 | 35 import dmd.Util; |
36 import dmd.expression.Util; | |
37 | |
38 import core.stdc.string : strcmp; | |
39 | |
40 /************************************************ | |
41 * Delegate to be passed to overloadApply() that looks | |
42 * for virtual functions. | |
43 */ | |
44 | |
45 struct Pvirtuals | |
46 { | |
47 Expression e1; | |
48 Expressions exps; | |
158 | 49 |
50 bool visit(FuncDeclaration f) | |
51 { | |
52 Pvirtuals* p = &this; | |
72 | 53 |
54 if (f.isVirtual()) | |
158 | 55 { |
56 Expression e; | |
72 | 57 |
158 | 58 if (p.e1.op == TOKdotvar) |
59 { | |
60 DotVarExp dve = cast(DotVarExp)p.e1; | |
72 | 61 e = new DotVarExp(Loc(0), dve.e1, f); |
62 } | |
63 else | |
64 e = new DsymbolExp(Loc(0), f); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
65 p.exps.push(e); |
72 | 66 } |
158 | 67 return false; |
72 | 68 } |
69 } | |
70 | |
71 | |
72 | |
73 class TraitsExp : Expression | |
74 { | |
75 Identifier ident; | |
76 | |
77 Objects args; | |
78 | |
79 this(Loc loc, Identifier ident, Objects args) | |
80 { | |
178 | 81 register(); |
72 | 82 super(loc, TOK.TOKtraits, this.sizeof); |
83 this.ident = ident; | |
84 this.args = args; | |
85 } | |
86 | |
87 override Expression syntaxCopy() | |
88 { | |
89 return new TraitsExp(loc, ident, TemplateInstance.arraySyntaxCopy(args)); | |
90 } | |
91 | |
92 override Expression semantic(Scope sc) | |
93 { | |
94 version (LOGSEMANTIC) { | |
95 printf("TraitsExp.semantic() %s\n", toChars()); | |
96 } | |
97 if (ident != Id.compiles && ident != Id.isSame) | |
98 TemplateInstance.semanticTiargs(loc, sc, args, 1); | |
99 size_t dim = args ? args.dim : 0; | |
100 Object o; | |
135 | 101 Declaration d; |
72 | 102 FuncDeclaration f; |
103 | |
104 string ISTYPE(string cond) | |
105 { | |
106 return ` | |
107 for (size_t i = 0; i < dim; i++) | |
113
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
95
diff
changeset
|
108 { Type t = getType(args[i]); |
72 | 109 if (!t) |
110 goto Lfalse; | |
111 if (!(`~cond~`)) | |
112 goto Lfalse; | |
113 } | |
114 if (!dim) | |
115 goto Lfalse; | |
116 goto Ltrue; | |
117 `; | |
118 } | |
119 | |
120 string ISDSYMBOL(string cond) | |
121 { | |
122 return `for (size_t i = 0; i < dim; i++) | |
113
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
95
diff
changeset
|
123 { Dsymbol s = getDsymbol(args[i]); |
72 | 124 if (!s) |
125 goto Lfalse; | |
126 if (!(`~cond~`)) | |
127 goto Lfalse; | |
128 } | |
129 if (!dim) | |
130 goto Lfalse; | |
131 goto Ltrue;`; | |
132 } | |
133 | |
134 if (ident == Id.isArithmetic) | |
135 { | |
136 mixin(ISTYPE(`t.isintegral() || t.isfloating()`)); | |
137 } | |
138 else if (ident == Id.isFloating) | |
139 { | |
140 mixin(ISTYPE(q{t.isfloating()})); | |
141 } | |
142 else if (ident == Id.isIntegral) | |
143 { | |
144 mixin(ISTYPE(q{t.isintegral()})); | |
145 } | |
146 else if (ident == Id.isScalar) | |
147 { | |
148 mixin(ISTYPE(q{t.isscalar()})); | |
149 } | |
150 else if (ident == Id.isUnsigned) | |
151 { | |
152 mixin(ISTYPE(q{t.isunsigned()})); | |
153 } | |
154 else if (ident == Id.isAssociativeArray) | |
155 { | |
156 mixin(ISTYPE(q{t.toBasetype().ty == TY.Taarray})); | |
157 } | |
158 else if (ident == Id.isStaticArray) | |
159 { | |
160 mixin(ISTYPE(q{t.toBasetype().ty == TY.Tsarray})); | |
161 } | |
162 else if (ident == Id.isAbstractClass) | |
163 { | |
164 mixin(ISTYPE(q{t.toBasetype().ty == TY.Tclass && (cast(TypeClass)t.toBasetype()).sym.isAbstract()})); | |
165 } | |
166 else if (ident == Id.isFinalClass) | |
167 { | |
168 mixin(ISTYPE(q{t.toBasetype().ty == TY.Tclass && (cast(TypeClass)t.toBasetype()).sym.storage_class & STC.STCfinal})); | |
169 } | |
170 else if (ident == Id.isAbstractFunction) | |
171 { | |
172 mixin(ISDSYMBOL(q{(f = s.isFuncDeclaration()) !is null && f.isAbstract()})); | |
173 } | |
174 else if (ident == Id.isVirtualFunction) | |
175 { | |
176 mixin(ISDSYMBOL(q{(f = s.isFuncDeclaration()) !is null && f.isVirtual()})); | |
177 } | |
178 else if (ident == Id.isFinalFunction) | |
179 { | |
180 mixin(ISDSYMBOL(q{(f = s.isFuncDeclaration()) !is null && f.isFinal()})); | |
181 } | |
135 | 182 //version(DMDV2) { |
183 else if (ident == Id.isRef) | |
184 { | |
185 mixin(ISDSYMBOL(q{(d = s.isDeclaration()) !is null && d.isRef()})); | |
186 } | |
187 else if (ident == Id.isOut) | |
188 { | |
189 mixin(ISDSYMBOL(q{(d = s.isDeclaration()) !is null && d.isOut()})); | |
190 } | |
191 else if (ident == Id.isLazy) | |
192 { | |
193 mixin(ISDSYMBOL(q{(d = s.isDeclaration()) !is null && d.storage_class & STClazy})); | |
194 } | |
195 //} | |
72 | 196 else if (ident == Id.hasMember || |
197 ident == Id.getMember || | |
198 ident == Id.getVirtualFunctions) | |
199 { | |
200 if (dim != 2) | |
201 goto Ldimerror; | |
113
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
95
diff
changeset
|
202 auto o_ = args[0]; |
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
95
diff
changeset
|
203 Expression e = isExpression(args[1]); |
72 | 204 if (!e) |
205 { error("expression expected as second argument of __traits %s", ident.toChars()); | |
206 goto Lfalse; | |
207 } | |
208 e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret); | |
209 if (e.op != TOKstring) | |
210 { error("string expected as second argument of __traits %s instead of %s", ident.toChars(), e.toChars()); | |
211 goto Lfalse; | |
212 } | |
113
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
95
diff
changeset
|
213 auto se = cast(StringExp)e; |
72 | 214 se = se.toUTF8(sc); |
215 if (se.sz != 1) | |
216 { error("string must be chars"); | |
217 goto Lfalse; | |
218 } | |
219 Identifier id = Lexer.idPool(fromStringz(cast(char*)se.string_)); | |
220 | |
221 Type t = isType(o_); | |
222 e = isExpression(o_); | |
223 Dsymbol s = isDsymbol(o_); | |
224 if (t) | |
225 e = typeDotIdExp(loc, t, id); | |
226 else if (e) | |
227 e = new DotIdExp(loc, e, id); | |
228 else if (s) | |
229 { e = new DsymbolExp(loc, s); | |
230 e = new DotIdExp(loc, e, id); | |
231 } | |
232 else | |
233 { error("invalid first argument"); | |
234 goto Lfalse; | |
235 } | |
236 | |
237 if (ident == Id.hasMember) | |
238 { /* Take any errors as meaning it wasn't found | |
239 */ | |
240 e = e.trySemantic(sc); | |
241 if (!e) | |
242 { if (global.gag) | |
243 global.errors++; | |
244 goto Lfalse; | |
245 } | |
246 else | |
247 goto Ltrue; | |
248 } | |
249 else if (ident == Id.getMember) | |
250 { | |
251 e = e.semantic(sc); | |
252 return e; | |
253 } | |
254 else if (ident == Id.getVirtualFunctions) | |
255 { | |
256 uint errors = global.errors; | |
257 Expression ex = e; | |
258 e = e.semantic(sc); | |
259 if (errors < global.errors) | |
260 error("%s cannot be resolved", ex.toChars()); | |
261 | |
262 /* Create tuple of virtual function overloads of e | |
263 */ | |
264 //e.dump(0); | |
265 Expressions exps = new Expressions(); | |
266 FuncDeclaration f_; | |
267 if (e.op == TOKvar) | |
158 | 268 { |
269 VarExp ve = cast(VarExp)e; | |
72 | 270 f_ = ve.var.isFuncDeclaration(); |
271 } | |
272 else if (e.op == TOKdotvar) | |
158 | 273 { |
274 DotVarExp dve = cast(DotVarExp)e; | |
72 | 275 f_ = dve.var.isFuncDeclaration(); |
276 } | |
277 else | |
278 f_ = null; | |
158 | 279 |
72 | 280 Pvirtuals p; |
281 p.exps = exps; | |
282 p.e1 = e; | |
158 | 283 overloadApply(f_, p); |
72 | 284 |
285 TupleExp tup = new TupleExp(loc, exps); | |
286 return tup.semantic(sc); | |
287 } | |
288 else | |
289 assert(0); | |
290 } | |
291 else if (ident == Id.classInstanceSize) | |
292 { | |
293 if (dim != 1) | |
294 goto Ldimerror; | |
113
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
95
diff
changeset
|
295 Object o_ = args[0]; |
72 | 296 Dsymbol s = getDsymbol(o_); |
297 ClassDeclaration cd; | |
298 if (!s || (cd = s.isClassDeclaration()) is null) | |
299 { | |
300 error("first argument is not a class"); | |
301 goto Lfalse; | |
302 } | |
303 return new IntegerExp(loc, cd.structsize, Type.tsize_t); | |
304 } | |
305 else if (ident == Id.allMembers || ident == Id.derivedMembers) | |
306 { | |
307 if (dim != 1) | |
308 goto Ldimerror; | |
113
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
95
diff
changeset
|
309 Object o_ = args[0]; |
72 | 310 Dsymbol s = getDsymbol(o_); |
311 ScopeDsymbol sd; | |
312 if (!s) | |
313 { | |
314 error("argument has no members"); | |
315 goto Lfalse; | |
316 } | |
317 if ((sd = s.isScopeDsymbol()) is null) | |
318 { | |
319 error("%s %s has no members", s.kind(), s.toChars()); | |
320 goto Lfalse; | |
321 } | |
322 Expressions exps = new Expressions; | |
323 while (1) | |
324 { size_t dim_ = ScopeDsymbol.dim(sd.members); | |
325 for (size_t i = 0; i < dim_; i++) | |
326 { | |
327 Dsymbol sm = ScopeDsymbol.getNth(sd.members, i); | |
328 //printf("\t[%i] %s %s\n", i, sm.kind(), sm.toChars()); | |
329 if (sm.ident) | |
330 { | |
331 //printf("\t%s\n", sm.ident.toChars()); | |
332 auto str = sm.ident.toChars(); | |
333 | |
334 /* Skip if already present in exps[] | |
335 */ | |
336 for (size_t j = 0; j < exps.dim; j++) | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
337 { auto se2 = cast(StringExp)exps[j]; |
72 | 338 if (strcmp(toStringz(str), cast(char*)se2.string_) == 0) |
339 goto Lnext; | |
340 } | |
341 | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
342 auto se = new StringExp(loc, str); |
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
343 exps.push(se); |
72 | 344 } |
345 Lnext: | |
346 ; | |
347 } | |
348 ClassDeclaration cd = sd.isClassDeclaration(); | |
349 if (cd && cd.baseClass && ident == Id.allMembers) | |
350 sd = cd.baseClass; // do again with base class | |
351 else | |
352 break; | |
353 } | |
354 Expression e = new ArrayLiteralExp(loc, exps); | |
355 e = e.semantic(sc); | |
356 return e; | |
357 } | |
358 else if (ident == Id.compiles) | |
359 { | |
360 /* Determine if all the objects - types, expressions, or symbols - | |
361 * compile without error | |
362 */ | |
363 if (!dim) | |
364 goto Lfalse; | |
365 | |
366 for (size_t i = 0; i < dim; i++) | |
113
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
95
diff
changeset
|
367 { Object o_ = args[i]; |
72 | 368 Expression e; |
369 | |
370 uint errors = global.errors; | |
371 global.gag++; | |
372 | |
373 Type t = isType(o_); | |
374 if (t) | |
375 { Dsymbol s; | |
376 t.resolve(loc, sc, &e, &t, &s); | |
377 if (t) | |
378 t.semantic(loc, sc); | |
379 else if (e) | |
380 e.semantic(sc); | |
381 } | |
382 else | |
383 { e = isExpression(o); | |
384 if (e) | |
385 e.semantic(sc); | |
386 } | |
387 | |
388 global.gag--; | |
389 if (errors != global.errors) | |
390 { if (global.gag == 0) | |
391 global.errors = errors; | |
392 goto Lfalse; | |
393 } | |
394 } | |
395 goto Ltrue; | |
396 } | |
397 else if (ident == Id.isSame) | |
398 { /* Determine if two symbols are the same | |
399 */ | |
400 if (dim != 2) | |
401 goto Ldimerror; | |
402 TemplateInstance.semanticTiargs(loc, sc, args, 0); | |
113
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
95
diff
changeset
|
403 Object o1 = args[0]; |
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
95
diff
changeset
|
404 Object o2 = args[1]; |
72 | 405 Dsymbol s1 = getDsymbol(o1); |
406 Dsymbol s2 = getDsymbol(o2); | |
407 | |
95 | 408 // writef("isSame: %s, %s\n", o1.toChars(), o2.toChars()); |
409 static if (0) | |
410 { | |
411 writef("o1: %p\n", o1); | |
412 writef("o2: %p\n", o2); | |
72 | 413 if (!s1) |
414 { Expression ea = isExpression(o1); | |
415 if (ea) | |
416 printf("%s\n", ea.toChars()); | |
417 Type ta = isType(o1); | |
418 if (ta) | |
419 printf("%s\n", ta.toChars()); | |
420 goto Lfalse; | |
421 } | |
422 else | |
423 printf("%s %s\n", s1.kind(), s1.toChars()); | |
424 } | |
425 if (!s1 && !s2) | |
426 { Expression ea1 = isExpression(o1); | |
427 Expression ea2 = isExpression(o2); | |
428 if (ea1 && ea2 && ea1.equals(ea2)) | |
429 goto Ltrue; | |
430 } | |
431 | |
432 if (!s1 || !s2) | |
433 goto Lfalse; | |
434 | |
435 s1 = s1.toAlias(); | |
436 s2 = s2.toAlias(); | |
437 | |
438 if (s1 == s2) | |
439 goto Ltrue; | |
440 else | |
441 goto Lfalse; | |
442 } | |
443 else | |
444 { error("unrecognized trait %s", ident.toChars()); | |
445 goto Lfalse; | |
446 } | |
447 | |
448 return null; | |
449 | |
450 Lnottype: | |
451 error("%s is not a type", o/*.toChars()*/); // BUG: o is Object, no member toChars() | |
452 goto Lfalse; | |
453 | |
454 Ldimerror: | |
455 error("wrong number of arguments %d", dim); | |
456 goto Lfalse; | |
457 | |
458 | |
459 Lfalse: | |
460 return new IntegerExp(loc, 0, Type.tbool); | |
461 | |
462 Ltrue: | |
463 return new IntegerExp(loc, 1, Type.tbool); | |
464 } | |
465 | |
466 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) | |
467 { | |
468 buf.writestring("__traits("); | |
469 buf.writestring(ident.toChars()); | |
470 if (args) | |
471 { | |
472 for (int i = 0; i < args.dim; i++) | |
473 { | |
474 buf.writeByte(','); | |
113
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
95
diff
changeset
|
475 Object oarg = args[i]; |
72 | 476 ObjectToCBuffer(buf, hgs, oarg); |
477 } | |
478 } | |
479 buf.writeByte(')'); | |
480 } | |
481 } |