Mercurial > projects > ldc
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 |