2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2006 by Digital Mars
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.
16 #include "declaration.h"
17 #include "identifier.h"
18 #include "expression.h"
28 int findCondition(Array
*ids
, Identifier
*ident
)
32 for (int i
= 0; i
< ids
->dim
; i
++)
34 char *id
= (char *)ids
->data
[i
];
36 if (strcmp(id
, ident
->toChars()) == 0)
44 /* ============================================================ */
46 Condition::Condition(Loc loc
)
52 /* ============================================================ */
54 DVCondition::DVCondition(Module
*mod
, unsigned level
, Identifier
*ident
)
62 Condition
*DVCondition::syntaxCopy()
64 return this; // don't need to copy
67 /* ============================================================ */
69 void DebugCondition::setGlobalLevel(unsigned level
)
71 global
.params
.debuglevel
= level
;
74 void DebugCondition::addGlobalIdent(char *ident
)
76 if (!global
.params
.debugids
)
77 global
.params
.debugids
= new Array();
78 global
.params
.debugids
->push(ident
);
82 DebugCondition::DebugCondition(Module
*mod
, unsigned level
, Identifier
*ident
)
83 : DVCondition(mod
, level
, ident
)
87 int DebugCondition::include(Scope
*sc
, ScopeDsymbol
*s
)
89 //printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel);
95 if (findCondition(mod
->debugids
, ident
))
97 else if (findCondition(global
.params
.debugids
, ident
))
100 { if (!mod
->debugidsNot
)
101 mod
->debugidsNot
= new Array();
102 mod
->debugidsNot
->push(ident
->toChars());
105 else if (level
<= global
.params
.debuglevel
|| level
<= mod
->debuglevel
)
111 void DebugCondition::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
114 buf
->printf("debug (%s)", ident
->toChars());
116 buf
->printf("debug (%u)", level
);
119 /* ============================================================ */
121 void VersionCondition::setGlobalLevel(unsigned level
)
123 global
.params
.versionlevel
= level
;
126 void VersionCondition::checkPredefined(Loc loc
, char *ident
)
128 static char* reserved
[] =
130 "DigitalMars", "X86", "X86_64",
131 "Windows", "Win32", "Win64",
133 "LittleEndian", "BigEndian",
138 for (unsigned i
= 0; i
< sizeof(reserved
) / sizeof(reserved
[0]); i
++)
140 if (strcmp(ident
, reserved
[i
]) == 0)
144 if (ident
[0] == 'D' && ident
[1] == '_')
150 error(loc
, "version identifier '%s' is reserved and cannot be set", ident
);
153 void VersionCondition::addGlobalIdent(char *ident
)
155 checkPredefined(0, ident
);
156 addPredefinedGlobalIdent(ident
);
159 void VersionCondition::addPredefinedGlobalIdent(char *ident
)
161 if (!global
.params
.versionids
)
162 global
.params
.versionids
= new Array();
163 global
.params
.versionids
->push(ident
);
167 VersionCondition::VersionCondition(Module
*mod
, unsigned level
, Identifier
*ident
)
168 : DVCondition(mod
, level
, ident
)
172 int VersionCondition::include(Scope
*sc
, ScopeDsymbol
*s
)
174 //printf("VersionCondition::include() level = %d, versionlevel = %d\n", level, global.params.versionlevel);
175 //if (ident) printf("\tident = '%s'\n", ident->toChars());
181 if (findCondition(mod
->versionids
, ident
))
183 else if (findCondition(global
.params
.versionids
, ident
))
187 if (!mod
->versionidsNot
)
188 mod
->versionidsNot
= new Array();
189 mod
->versionidsNot
->push(ident
->toChars());
192 else if (level
<= global
.params
.versionlevel
|| level
<= mod
->versionlevel
)
198 void VersionCondition::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
201 buf
->printf("version (%s)", ident
->toChars());
203 buf
->printf("version (%u)", level
);
207 /**************************** StaticIfCondition *******************************/
209 StaticIfCondition::StaticIfCondition(Loc loc
, Expression
*exp
)
215 Condition
*StaticIfCondition::syntaxCopy()
217 return new StaticIfCondition(loc
, exp
->syntaxCopy());
220 int StaticIfCondition::include(Scope
*sc
, ScopeDsymbol
*s
)
223 printf("StaticIfCondition::include(sc = %p, s = %p)\n", sc
, s
);
226 printf("\ts = '%s', kind = %s\n", s
->toChars(), s
->kind());
233 error(loc
, "static if conditional cannot be at global scope");
238 sc
= sc
->push(sc
->scopesym
);
239 sc
->sd
= s
; // s gets any addMember()
240 sc
->flags
|= SCOPEstaticif
;
241 Expression
*e
= exp
->semantic(sc
);
243 e
= e
->optimize(WANTvalue
| WANTinterpret
);
246 else if (e
->isBool(FALSE
))
250 e
->error("expression %s is not constant or does not evaluate to a bool", e
->toChars());
257 void StaticIfCondition::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
259 buf
->writestring("static if(");
260 exp
->toCBuffer(buf
, hgs
);
265 /**************************** IftypeCondition *******************************/
267 IftypeCondition::IftypeCondition(Loc loc
, Type
*targ
, Identifier
*id
, enum TOK tok
, Type
*tspec
)
276 Condition
*IftypeCondition::syntaxCopy()
278 return new IftypeCondition(loc
,
282 tspec
? tspec
->syntaxCopy() : NULL
);
285 int IftypeCondition::include(Scope
*sc
, ScopeDsymbol
*sd
)
287 //printf("IftypeCondition::include()\n");
292 error(loc
, "iftype conditional cannot be at global scope");
296 unsigned errors
= global
.errors
;
297 global
.gag
++; // suppress printing of error messages
298 targ
= targ
->semantic(loc
, sc
);
300 if (errors
!= global
.errors
) // if any errors happened
301 { inc
= 2; // then condition is false
302 global
.errors
= errors
;
304 else if (id
&& tspec
)
306 /* Evaluate to TRUE if targ matches tspec.
307 * If TRUE, declare id as an alias for the specialized type.
311 TemplateTypeParameter
tp(loc
, id
, NULL
, NULL
);
313 TemplateParameters parameters
;
314 parameters
.setDim(1);
315 parameters
.data
[0] = (void *)&tp
;
320 m
= targ
->deduceType(NULL
, tspec
, ¶meters
, &dedtypes
);
321 if (m
== MATCHnomatch
||
322 (m
!= MATCHexact
&& tok
== TOKequal
))
327 Type
*tded
= (Type
*)dedtypes
.data
[0];
330 Dsymbol
*s
= new AliasDeclaration(loc
, id
, tded
);
334 s
->addMember(sc
, sd
, 1);
339 /* Declare id as an alias for type targ. Evaluate to TRUE
341 Dsymbol
*s
= new AliasDeclaration(loc
, id
, targ
);
345 s
->addMember(sc
, sd
, 1);
350 /* Evaluate to TRUE if targ matches tspec
352 tspec
= tspec
->semantic(loc
, sc
);
353 //printf("targ = %s\n", targ->toChars());
354 //printf("tspec = %s\n", tspec->toChars());
356 { if (targ
->implicitConvTo(tspec
))
362 { if (targ
->equals(tspec
))
370 //printf("inc = %d\n", inc);
375 void IftypeCondition::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
377 buf
->writestring("iftype(");
378 targ
->toCBuffer(buf
, id
, hgs
);
382 buf
->writestring(" : ");
384 buf
->writestring(" == ");
385 tspec
->toCBuffer(buf
, NULL
, hgs
);