comparison dmd2/traits.c @ 758:f04dde6e882c

Added initial D2 support, D2 frontend and changes to codegen to make things compile.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Tue, 11 Nov 2008 01:38:48 +0100
parents
children 638d16625da2
comparison
equal deleted inserted replaced
757:2c730d530c98 758:f04dde6e882c
1
2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2007 by Digital Mars
4 // All Rights Reserved
5 // written by Walter Bright
6 // http://www.digitalmars.com
7 // License for redistribution is by either the Artistic License
8 // in artistic.txt, or the GNU General Public License in gnu.txt.
9 // See the included readme.txt for details.
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <ctype.h>
14 #include <assert.h>
15 #include <complex.h>
16 #include <math.h>
17
18 #if IN_GCC
19 // Issues with using -include total.h (defines integer_t) and then complex.h fails...
20 #undef integer_t
21 #endif
22
23 #ifdef __APPLE__
24 #define integer_t dmd_integer_t
25 #endif
26
27 #if IN_GCC || IN_LLVM
28 #include "mem.h"
29 #elif _WIN32
30 #include "..\root\mem.h"
31 #elif linux
32 #include "../root/mem.h"
33 #endif
34
35 //#include "port.h"
36 #include "mtype.h"
37 #include "init.h"
38 #include "expression.h"
39 #include "template.h"
40 #include "utf.h"
41 #include "enum.h"
42 #include "scope.h"
43 #include "statement.h"
44 #include "declaration.h"
45 #include "aggregate.h"
46 #include "import.h"
47 #include "id.h"
48 #include "dsymbol.h"
49 #include "module.h"
50 #include "attrib.h"
51 #include "hdrgen.h"
52 #include "parse.h"
53
54 #define LOGSEMANTIC 0
55
56 /************************************************
57 * Delegate to be passed to overloadApply() that looks
58 * for virtual functions.
59 */
60
61 struct Pvirtuals
62 {
63 Expression *e1;
64 Expressions *exps;
65 };
66
67 static int fpvirtuals(void *param, FuncDeclaration *f)
68 { Pvirtuals *p = (Pvirtuals *)param;
69
70 if (f->isVirtual())
71 { Expression *e;
72
73 if (p->e1->op == TOKdotvar)
74 { DotVarExp *dve = (DotVarExp *)p->e1;
75 e = new DotVarExp(0, dve->e1, f);
76 }
77 else
78 e = new DsymbolExp(0, f);
79 p->exps->push(e);
80 }
81 return 0;
82 }
83
84 /************************ TraitsExp ************************************/
85
86 Expression *TraitsExp::semantic(Scope *sc)
87 {
88 #if LOGSEMANTIC
89 printf("TraitsExp::semantic() %s\n", toChars());
90 #endif
91 if (ident != Id::compiles && ident != Id::isSame)
92 TemplateInstance::semanticTiargs(loc, sc, args, 1);
93 size_t dim = args ? args->dim : 0;
94 Object *o;
95 FuncDeclaration *f;
96
97 #define ISTYPE(cond) \
98 for (size_t i = 0; i < dim; i++) \
99 { Type *t = getType((Object *)args->data[i]); \
100 if (!t) \
101 goto Lfalse; \
102 if (!(cond)) \
103 goto Lfalse; \
104 } \
105 if (!dim) \
106 goto Lfalse; \
107 goto Ltrue;
108
109 #define ISDSYMBOL(cond) \
110 for (size_t i = 0; i < dim; i++) \
111 { Dsymbol *s = getDsymbol((Object *)args->data[i]); \
112 if (!s) \
113 goto Lfalse; \
114 if (!(cond)) \
115 goto Lfalse; \
116 } \
117 if (!dim) \
118 goto Lfalse; \
119 goto Ltrue;
120
121
122
123 if (ident == Id::isArithmetic)
124 {
125 ISTYPE(t->isintegral() || t->isfloating())
126 }
127 else if (ident == Id::isFloating)
128 {
129 ISTYPE(t->isfloating())
130 }
131 else if (ident == Id::isIntegral)
132 {
133 ISTYPE(t->isintegral())
134 }
135 else if (ident == Id::isScalar)
136 {
137 ISTYPE(t->isscalar())
138 }
139 else if (ident == Id::isUnsigned)
140 {
141 ISTYPE(t->isunsigned())
142 }
143 else if (ident == Id::isAssociativeArray)
144 {
145 ISTYPE(t->toBasetype()->ty == Taarray)
146 }
147 else if (ident == Id::isStaticArray)
148 {
149 ISTYPE(t->toBasetype()->ty == Tsarray)
150 }
151 else if (ident == Id::isAbstractClass)
152 {
153 ISTYPE(t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->isAbstract())
154 }
155 else if (ident == Id::isFinalClass)
156 {
157 ISTYPE(t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->storage_class & STCfinal)
158 }
159 else if (ident == Id::isAbstractFunction)
160 {
161 ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isAbstract())
162 }
163 else if (ident == Id::isVirtualFunction)
164 {
165 ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isVirtual())
166 }
167 else if (ident == Id::isFinalFunction)
168 {
169 ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isFinal())
170 }
171 else if (ident == Id::hasMember ||
172 ident == Id::getMember ||
173 ident == Id::getVirtualFunctions)
174 {
175 if (dim != 2)
176 goto Ldimerror;
177 Object *o = (Object *)args->data[0];
178 Expression *e = isExpression((Object *)args->data[1]);
179 if (!e)
180 { error("expression expected as second argument of __traits %s", ident->toChars());
181 goto Lfalse;
182 }
183 e = e->optimize(WANTvalue | WANTinterpret);
184 if (e->op != TOKstring)
185 { error("string expected as second argument of __traits %s instead of %s", ident->toChars(), e->toChars());
186 goto Lfalse;
187 }
188 StringExp *se = (StringExp *)e;
189 se = se->toUTF8(sc);
190 if (se->sz != 1)
191 { error("string must be chars");
192 goto Lfalse;
193 }
194 Identifier *id = Lexer::idPool((char *)se->string);
195
196 Type *t = isType(o);
197 e = isExpression(o);
198 Dsymbol *s = isDsymbol(o);
199 if (t)
200 e = new TypeDotIdExp(loc, t, id);
201 else if (e)
202 e = new DotIdExp(loc, e, id);
203 else if (s)
204 { e = new DsymbolExp(loc, s);
205 e = new DotIdExp(loc, e, id);
206 }
207 else
208 { error("invalid first argument");
209 goto Lfalse;
210 }
211
212 if (ident == Id::hasMember)
213 { /* Take any errors as meaning it wasn't found
214 */
215 unsigned errors = global.errors;
216 global.gag++;
217 e = e->semantic(sc);
218 global.gag--;
219 if (errors != global.errors)
220 { if (global.gag == 0)
221 global.errors = 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 unsigned 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 = (VarExp *)e;
247 f = ve->var->isFuncDeclaration();
248 }
249 else if (e->op == TOKdotvar)
250 { DotVarExp *dve = (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, 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 = (Object *)args->data[0];
271 Dsymbol *s = getDsymbol(o);
272 ClassDeclaration *cd;
273 if (!s || (cd = s->isClassDeclaration()) == 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 = (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()) == 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 char *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 = (StringExp *)exps->data[j];
313 if (strcmp(str, (char *)se2->string) == 0)
314 goto Lnext;
315 }
316
317 StringExp *se = new StringExp(loc, str);
318 exps->push(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 = (Object *)args->data[i];
343 Type *t;
344 Expression *e;
345 Dsymbol *s;
346
347 unsigned errors = global.errors;
348 global.gag++;
349
350 t = isType(o);
351 if (t)
352 { t->resolve(loc, sc, &e, &t, &s);
353 if (t)
354 t->semantic(loc, sc);
355 else if (e)
356 e->semantic(sc);
357 }
358 else
359 { e = isExpression(o);
360 if (e)
361 e->semantic(sc);
362 }
363
364 global.gag--;
365 if (errors != global.errors)
366 { if (global.gag == 0)
367 global.errors = errors;
368 goto Lfalse;
369 }
370 }
371 goto Ltrue;
372 }
373 else if (ident == Id::isSame)
374 { /* Determine if two symbols are the same
375 */
376 if (dim != 2)
377 goto Ldimerror;
378 TemplateInstance::semanticTiargs(loc, sc, args, 0);
379 Object *o1 = (Object *)args->data[0];
380 Object *o2 = (Object *)args->data[1];
381 Dsymbol *s1 = getDsymbol(o1);
382 Dsymbol *s2 = getDsymbol(o2);
383
384 #if 0
385 printf("o1: %p\n", o1);
386 printf("o2: %p\n", o2);
387 if (!s1)
388 { Expression *ea = isExpression(o1);
389 if (ea)
390 printf("%s\n", ea->toChars());
391 Type *ta = isType(o1);
392 if (ta)
393 printf("%s\n", ta->toChars());
394 goto Lfalse;
395 }
396 else
397 printf("%s %s\n", s1->kind(), s1->toChars());
398 #endif
399 if (!s1 && !s2)
400 { Expression *ea1 = isExpression(o1);
401 Expression *ea2 = isExpression(o2);
402 if (ea1 && ea2 && ea1->equals(ea2))
403 goto Ltrue;
404 }
405
406 if (!s1 || !s2)
407 goto Lfalse;
408
409 s1 = s1->toAlias();
410 s2 = s2->toAlias();
411
412 if (s1 == s2)
413 goto Ltrue;
414 else
415 goto Lfalse;
416 }
417 else
418 { error("unrecognized trait %s", ident->toChars());
419 goto Lfalse;
420 }
421
422 return NULL;
423
424 Lnottype:
425 error("%s is not a type", o->toChars());
426 goto Lfalse;
427
428 Ldimerror:
429 error("wrong number of arguments %d", dim);
430 goto Lfalse;
431
432
433 Lfalse:
434 return new IntegerExp(loc, 0, Type::tbool);
435
436 Ltrue:
437 return new IntegerExp(loc, 1, Type::tbool);
438 }
439
440