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