root/branches/dmdfe-2.0/cond.c

Revision 914, 8.4 kB (checked in by Gregor, 3 months ago)

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