Mercurial > projects > ldc
annotate dmd/cond.c @ 813:2eaefe4a550b
Forgot to add AnonDeclaration::toObjFile for D2
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Mon, 01 Dec 2008 14:54:06 +0100 |
parents | eef8ac26c66c |
children | 330f999ade44 |
rev | line source |
---|---|
1 | 1 |
2 // Compiler implementation of the D programming language | |
3 // Copyright (c) 1999-2006 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 <assert.h> | |
13 | |
14 #include "id.h" | |
15 #include "init.h" | |
16 #include "declaration.h" | |
17 #include "identifier.h" | |
18 #include "expression.h" | |
19 #include "cond.h" | |
20 #include "module.h" | |
21 #include "template.h" | |
22 #include "lexer.h" | |
23 #ifdef _DH | |
24 #include "mtype.h" | |
25 #include "scope.h" | |
26 #endif | |
27 | |
28 int findCondition(Array *ids, Identifier *ident) | |
29 { | |
30 if (ids) | |
31 { | |
32 for (int i = 0; i < ids->dim; i++) | |
33 { | |
34 char *id = (char *)ids->data[i]; | |
35 | |
36 if (strcmp(id, ident->toChars()) == 0) | |
37 return TRUE; | |
38 } | |
39 } | |
40 | |
41 return FALSE; | |
42 } | |
43 | |
44 /* ============================================================ */ | |
45 | |
46 Condition::Condition(Loc loc) | |
47 { | |
48 this->loc = loc; | |
49 inc = 0; | |
50 } | |
51 | |
52 /* ============================================================ */ | |
53 | |
54 DVCondition::DVCondition(Module *mod, unsigned level, Identifier *ident) | |
55 : Condition(0) | |
56 { | |
57 this->mod = mod; | |
58 this->level = level; | |
59 this->ident = ident; | |
60 } | |
61 | |
62 Condition *DVCondition::syntaxCopy() | |
63 { | |
64 return this; // don't need to copy | |
65 } | |
66 | |
67 /* ============================================================ */ | |
68 | |
69 void DebugCondition::setGlobalLevel(unsigned level) | |
70 { | |
71 global.params.debuglevel = level; | |
72 } | |
73 | |
74 void DebugCondition::addGlobalIdent(char *ident) | |
75 { | |
76 if (!global.params.debugids) | |
77 global.params.debugids = new Array(); | |
78 global.params.debugids->push(ident); | |
79 } | |
80 | |
81 | |
82 DebugCondition::DebugCondition(Module *mod, unsigned level, Identifier *ident) | |
83 : DVCondition(mod, level, ident) | |
84 { | |
85 } | |
86 | |
87 int DebugCondition::include(Scope *sc, ScopeDsymbol *s) | |
88 { | |
89 //printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel); | |
90 if (inc == 0) | |
91 { | |
92 inc = 2; | |
93 if (ident) | |
94 { | |
95 if (findCondition(mod->debugids, ident)) | |
96 inc = 1; | |
97 else if (findCondition(global.params.debugids, ident)) | |
98 inc = 1; | |
99 else | |
100 { if (!mod->debugidsNot) | |
101 mod->debugidsNot = new Array(); | |
102 mod->debugidsNot->push(ident->toChars()); | |
103 } | |
104 } | |
105 else if (level <= global.params.debuglevel || level <= mod->debuglevel) | |
106 inc = 1; | |
107 } | |
108 return (inc == 1); | |
109 } | |
110 | |
111 void DebugCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
112 { | |
113 if (ident) | |
114 buf->printf("debug (%s)", ident->toChars()); | |
115 else | |
116 buf->printf("debug (%u)", level); | |
117 } | |
118 | |
119 /* ============================================================ */ | |
120 | |
121 void VersionCondition::setGlobalLevel(unsigned level) | |
122 { | |
123 global.params.versionlevel = level; | |
124 } | |
125 | |
126 void VersionCondition::checkPredefined(Loc loc, char *ident) | |
127 { | |
128 static char* reserved[] = | |
129 { | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
587
diff
changeset
|
130 "DigitalMars", "LLVM", "LDC", "LLVM64", |
275
665b81613475
[svn r296] Removed: the 'suite' dir, it never took off!
lindquist
parents:
1
diff
changeset
|
131 "X86", "X86_64", "PPC", "PPC64", |
1 | 132 "Windows", "Win32", "Win64", |
587
23538d0f0d5b
Fixed a few mini tests issues.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
445
diff
changeset
|
133 "linux", "darwin", "Posix", |
1 | 134 "LittleEndian", "BigEndian", |
135 "all", | |
136 "none", | |
137 }; | |
138 | |
139 for (unsigned i = 0; i < sizeof(reserved) / sizeof(reserved[0]); i++) | |
140 { | |
141 if (strcmp(ident, reserved[i]) == 0) | |
142 goto Lerror; | |
143 } | |
144 | |
145 if (ident[0] == 'D' && ident[1] == '_') | |
146 goto Lerror; | |
147 | |
148 return; | |
149 | |
150 Lerror: | |
151 error(loc, "version identifier '%s' is reserved and cannot be set", ident); | |
152 } | |
153 | |
154 void VersionCondition::addGlobalIdent(char *ident) | |
155 { | |
156 checkPredefined(0, ident); | |
157 addPredefinedGlobalIdent(ident); | |
158 } | |
159 | |
160 void VersionCondition::addPredefinedGlobalIdent(char *ident) | |
161 { | |
162 if (!global.params.versionids) | |
163 global.params.versionids = new Array(); | |
164 global.params.versionids->push(ident); | |
165 } | |
166 | |
167 | |
168 VersionCondition::VersionCondition(Module *mod, unsigned level, Identifier *ident) | |
169 : DVCondition(mod, level, ident) | |
170 { | |
171 } | |
172 | |
173 int VersionCondition::include(Scope *sc, ScopeDsymbol *s) | |
174 { | |
175 //printf("VersionCondition::include() level = %d, versionlevel = %d\n", level, global.params.versionlevel); | |
176 //if (ident) printf("\tident = '%s'\n", ident->toChars()); | |
177 if (inc == 0) | |
178 { | |
179 inc = 2; | |
180 if (ident) | |
181 { | |
182 if (findCondition(mod->versionids, ident)) | |
183 inc = 1; | |
184 else if (findCondition(global.params.versionids, ident)) | |
185 inc = 1; | |
186 else | |
187 { | |
188 if (!mod->versionidsNot) | |
189 mod->versionidsNot = new Array(); | |
190 mod->versionidsNot->push(ident->toChars()); | |
191 } | |
192 } | |
193 else if (level <= global.params.versionlevel || level <= mod->versionlevel) | |
194 inc = 1; | |
195 } | |
196 return (inc == 1); | |
197 } | |
198 | |
199 void VersionCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
200 { | |
201 if (ident) | |
202 buf->printf("version (%s)", ident->toChars()); | |
203 else | |
204 buf->printf("version (%u)", level); | |
205 } | |
206 | |
207 | |
208 /**************************** StaticIfCondition *******************************/ | |
209 | |
210 StaticIfCondition::StaticIfCondition(Loc loc, Expression *exp) | |
211 : Condition(loc) | |
212 { | |
213 this->exp = exp; | |
214 } | |
215 | |
216 Condition *StaticIfCondition::syntaxCopy() | |
217 { | |
218 return new StaticIfCondition(loc, exp->syntaxCopy()); | |
219 } | |
220 | |
221 int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s) | |
222 { | |
223 #if 0 | |
224 printf("StaticIfCondition::include(sc = %p, s = %p)\n", sc, s); | |
225 if (s) | |
226 { | |
227 printf("\ts = '%s', kind = %s\n", s->toChars(), s->kind()); | |
228 } | |
229 #endif | |
230 if (inc == 0) | |
231 { | |
232 if (!sc) | |
233 { | |
234 error(loc, "static if conditional cannot be at global scope"); | |
235 inc = 2; | |
236 return 0; | |
237 } | |
238 | |
239 sc = sc->push(sc->scopesym); | |
240 sc->sd = s; // s gets any addMember() | |
241 sc->flags |= SCOPEstaticif; | |
242 Expression *e = exp->semantic(sc); | |
243 sc->pop(); | |
244 e = e->optimize(WANTvalue | WANTinterpret); | |
245 if (e->isBool(TRUE)) | |
246 inc = 1; | |
247 else if (e->isBool(FALSE)) | |
248 inc = 2; | |
249 else | |
250 { | |
251 e->error("expression %s is not constant or does not evaluate to a bool", e->toChars()); | |
252 inc = 2; | |
253 } | |
254 } | |
255 return (inc == 1); | |
256 } | |
257 | |
258 void StaticIfCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
259 { | |
260 buf->writestring("static if("); | |
261 exp->toCBuffer(buf, hgs); | |
262 buf->writeByte(')'); | |
263 } | |
264 | |
265 | |
266 /**************************** IftypeCondition *******************************/ | |
267 | |
268 IftypeCondition::IftypeCondition(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec) | |
269 : Condition(loc) | |
270 { | |
271 this->targ = targ; | |
272 this->id = id; | |
273 this->tok = tok; | |
274 this->tspec = tspec; | |
275 } | |
276 | |
277 Condition *IftypeCondition::syntaxCopy() | |
278 { | |
279 return new IftypeCondition(loc, | |
280 targ->syntaxCopy(), | |
281 id, | |
282 tok, | |
283 tspec ? tspec->syntaxCopy() : NULL); | |
284 } | |
285 | |
286 int IftypeCondition::include(Scope *sc, ScopeDsymbol *sd) | |
287 { | |
288 //printf("IftypeCondition::include()\n"); | |
289 if (inc == 0) | |
290 { | |
291 if (!sc) | |
292 { | |
293 error(loc, "iftype conditional cannot be at global scope"); | |
294 inc = 2; | |
295 return 0; | |
296 } | |
297 unsigned errors = global.errors; | |
298 global.gag++; // suppress printing of error messages | |
299 targ = targ->semantic(loc, sc); | |
300 global.gag--; | |
301 if (errors != global.errors) // if any errors happened | |
302 { inc = 2; // then condition is false | |
303 global.errors = errors; | |
304 } | |
305 else if (id && tspec) | |
306 { | |
307 /* Evaluate to TRUE if targ matches tspec. | |
308 * If TRUE, declare id as an alias for the specialized type. | |
309 */ | |
310 | |
311 MATCH m; | |
312 TemplateTypeParameter tp(loc, id, NULL, NULL); | |
313 | |
314 TemplateParameters parameters; | |
315 parameters.setDim(1); | |
316 parameters.data[0] = (void *)&tp; | |
317 | |
318 Objects dedtypes; | |
319 dedtypes.setDim(1); | |
320 | |
321 m = targ->deduceType(NULL, tspec, ¶meters, &dedtypes); | |
322 if (m == MATCHnomatch || | |
323 (m != MATCHexact && tok == TOKequal)) | |
324 inc = 2; | |
325 else | |
326 { | |
327 inc = 1; | |
328 Type *tded = (Type *)dedtypes.data[0]; | |
329 if (!tded) | |
330 tded = targ; | |
331 Dsymbol *s = new AliasDeclaration(loc, id, tded); | |
332 s->semantic(sc); | |
333 sc->insert(s); | |
334 if (sd) | |
335 s->addMember(sc, sd, 1); | |
336 } | |
337 } | |
338 else if (id) | |
339 { | |
340 /* Declare id as an alias for type targ. Evaluate to TRUE | |
341 */ | |
342 Dsymbol *s = new AliasDeclaration(loc, id, targ); | |
343 s->semantic(sc); | |
344 sc->insert(s); | |
345 if (sd) | |
346 s->addMember(sc, sd, 1); | |
347 inc = 1; | |
348 } | |
349 else if (tspec) | |
350 { | |
351 /* Evaluate to TRUE if targ matches tspec | |
352 */ | |
353 tspec = tspec->semantic(loc, sc); | |
354 //printf("targ = %s\n", targ->toChars()); | |
355 //printf("tspec = %s\n", tspec->toChars()); | |
356 if (tok == TOKcolon) | |
357 { if (targ->implicitConvTo(tspec)) | |
358 inc = 1; | |
359 else | |
360 inc = 2; | |
361 } | |
362 else /* == */ | |
363 { if (targ->equals(tspec)) | |
364 inc = 1; | |
365 else | |
366 inc = 2; | |
367 } | |
368 } | |
369 else | |
370 inc = 1; | |
371 //printf("inc = %d\n", inc); | |
372 } | |
373 return (inc == 1); | |
374 } | |
375 | |
376 void IftypeCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
377 { | |
378 buf->writestring("iftype("); | |
379 targ->toCBuffer(buf, id, hgs); | |
380 if (tspec) | |
381 { | |
382 if (tok == TOKcolon) | |
383 buf->writestring(" : "); | |
384 else | |
385 buf->writestring(" == "); | |
386 tspec->toCBuffer(buf, NULL, hgs); | |
387 } | |
388 buf->writeByte(')'); | |
389 } | |
390 | |
391 |