root/trunk/rebuild/cond.c

Revision 915, 8.6 kB (checked in by Gregor, 3 months ago)

MERGE: dmdfe-2.0 r914 (DMD 2.019)

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