comparison dmd/TraitsExp.d @ 23:460959608115

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