2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2007 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.
19 // Issues with using -include total.h (defines integer_t) and then complex.h fails...
24 #define integer_t dmd_integer_t
30 #include "..\root\mem.h"
32 #include "../root/mem.h"
38 #include "expression.h"
43 #include "statement.h"
44 #include "declaration.h"
45 #include "aggregate.h"
56 /************************************************
57 * Delegate to be passed to overloadApply() that looks
58 * for virtual functions.
67 static int fpvirtuals(void *param
, FuncDeclaration
*f
)
68 { Pvirtuals
*p
= (Pvirtuals
*)param
;
73 if (p
->e1
->op
== TOKdotvar
)
74 { DotVarExp
*dve
= (DotVarExp
*)p
->e1
;
75 e
= new DotVarExp(0, dve
->e1
, f
);
78 e
= new DsymbolExp(0, f
);
84 /************************ TraitsExp ************************************/
86 Expression
*TraitsExp::semantic(Scope
*sc
)
89 printf("TraitsExp::semantic() %s\n", toChars());
91 if (ident
!= Id::compiles
&& ident
!= Id::isSame
)
92 TemplateInstance::semanticTiargs(loc
, sc
, args
, 1);
93 size_t dim
= args
? args
->dim
: 0;
97 #define ISTYPE(cond) \
98 for (size_t i = 0; i < dim; i++) \
99 { Type *t = getType((Object *)args->data[i]); \
109 #define ISDSYMBOL(cond) \
110 for (size_t i = 0; i < dim; i++) \
111 { Dsymbol *s = getDsymbol((Object *)args->data[i]); \
123 if (ident
== Id::isArithmetic
)
125 ISTYPE(t
->isintegral() || t
->isfloating())
127 else if (ident
== Id::isFloating
)
129 ISTYPE(t
->isfloating())
131 else if (ident
== Id::isIntegral
)
133 ISTYPE(t
->isintegral())
135 else if (ident
== Id::isScalar
)
137 ISTYPE(t
->isscalar())
139 else if (ident
== Id::isUnsigned
)
141 ISTYPE(t
->isunsigned())
143 else if (ident
== Id::isAssociativeArray
)
145 ISTYPE(t
->toBasetype()->ty
== Taarray
)
147 else if (ident
== Id::isStaticArray
)
149 ISTYPE(t
->toBasetype()->ty
== Tsarray
)
151 else if (ident
== Id::isAbstractClass
)
153 ISTYPE(t
->toBasetype()->ty
== Tclass
&& ((TypeClass
*)t
->toBasetype())->sym
->isAbstract())
155 else if (ident
== Id::isFinalClass
)
157 ISTYPE(t
->toBasetype()->ty
== Tclass
&& ((TypeClass
*)t
->toBasetype())->sym
->storage_class
& STCfinal
)
159 else if (ident
== Id::isAbstractFunction
)
161 ISDSYMBOL((f
= s
->isFuncDeclaration()) != NULL
&& f
->isAbstract())
163 else if (ident
== Id::isVirtualFunction
)
165 ISDSYMBOL((f
= s
->isFuncDeclaration()) != NULL
&& f
->isVirtual())
167 else if (ident
== Id::isFinalFunction
)
169 ISDSYMBOL((f
= s
->isFuncDeclaration()) != NULL
&& f
->isFinal())
171 else if (ident
== Id::hasMember
||
172 ident
== Id::getMember
||
173 ident
== Id::getVirtualFunctions
)
177 Object
*o
= (Object
*)args
->data
[0];
178 Expression
*e
= isExpression((Object
*)args
->data
[1]);
180 { error("expression expected as second argument of __traits %s", ident
->toChars());
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());
188 StringExp
*se
= (StringExp
*)e
;
191 { error("string must be chars");
194 Identifier
*id
= Lexer::idPool((char *)se
->string
);
198 Dsymbol
*s
= isDsymbol(o
);
200 e
= new TypeDotIdExp(loc
, t
, id
);
202 e
= new DotIdExp(loc
, e
, id
);
204 { e
= new DsymbolExp(loc
, s
);
205 e
= new DotIdExp(loc
, e
, id
);
208 { error("invalid first argument");
212 if (ident
== Id::hasMember
)
213 { /* Take any errors as meaning it wasn't found
215 unsigned errors
= global
.errors
;
219 if (errors
!= global
.errors
)
220 { if (global
.gag
== 0)
221 global
.errors
= errors
;
227 else if (ident
== Id::getMember
)
232 else if (ident
== Id::getVirtualFunctions
)
234 unsigned errors
= global
.errors
;
237 if (errors
< global
.errors
)
238 error("%s cannot be resolved", ex
->toChars());
240 /* Create tuple of virtual function overloads of e
243 Expressions
*exps
= new Expressions();
246 { VarExp
*ve
= (VarExp
*)e
;
247 f
= ve
->var
->isFuncDeclaration();
249 else if (e
->op
== TOKdotvar
)
250 { DotVarExp
*dve
= (DotVarExp
*)e
;
251 f
= dve
->var
->isFuncDeclaration();
258 overloadApply(f
, fpvirtuals
, &p
);
260 TupleExp
*tup
= new TupleExp(loc
, exps
);
261 return tup
->semantic(sc
);
266 else if (ident
== Id::classInstanceSize
)
270 Object
*o
= (Object
*)args
->data
[0];
271 Dsymbol
*s
= getDsymbol(o
);
272 ClassDeclaration
*cd
;
273 if (!s
|| (cd
= s
->isClassDeclaration()) == NULL
)
275 error("first argument is not a class");
278 return new IntegerExp(loc
, cd
->structsize
, Type::tsize_t
);
280 else if (ident
== Id::allMembers
|| ident
== Id::derivedMembers
)
284 Object
*o
= (Object
*)args
->data
[0];
285 Dsymbol
*s
= getDsymbol(o
);
289 error("argument has no members");
292 if ((sd
= s
->isScopeDsymbol()) == NULL
)
294 error("%s %s has no members", s
->kind(), s
->toChars());
297 Expressions
*exps
= new Expressions
;
299 { size_t dim
= ScopeDsymbol::dim(sd
->members
);
300 for (size_t i
= 0; i
< dim
; i
++)
302 Dsymbol
*sm
= ScopeDsymbol::getNth(sd
->members
, i
);
303 //printf("\t[%i] %s %s\n", i, sm->kind(), sm->toChars());
306 //printf("\t%s\n", sm->ident->toChars());
307 char *str
= sm
->ident
->toChars();
309 /* Skip if already present in exps[]
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)
317 StringExp
*se
= new StringExp(loc
, str
);
323 ClassDeclaration
*cd
= sd
->isClassDeclaration();
324 if (cd
&& cd
->baseClass
&& ident
== Id::allMembers
)
325 sd
= cd
->baseClass
; // do again with base class
329 Expression
*e
= new ArrayLiteralExp(loc
, exps
);
333 else if (ident
== Id::compiles
)
335 /* Determine if all the objects - types, expressions, or symbols -
336 * compile without error
341 for (size_t i
= 0; i
< dim
; i
++)
342 { Object
*o
= (Object
*)args
->data
[i
];
347 unsigned errors
= global
.errors
;
352 { t
->resolve(loc
, sc
, &e
, &t
, &s
);
354 t
->semantic(loc
, sc
);
359 { e
= isExpression(o
);
365 if (errors
!= global
.errors
)
366 { if (global
.gag
== 0)
367 global
.errors
= errors
;
373 else if (ident
== Id::isSame
)
374 { /* Determine if two symbols are the same
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
);
385 printf("o1: %p\n", o1
);
386 printf("o2: %p\n", o2
);
388 { Expression
*ea
= isExpression(o1
);
390 printf("%s\n", ea
->toChars());
391 Type
*ta
= isType(o1
);
393 printf("%s\n", ta
->toChars());
397 printf("%s %s\n", s1
->kind(), s1
->toChars());
400 { Expression
*ea1
= isExpression(o1
);
401 Expression
*ea2
= isExpression(o2
);
402 if (ea1
&& ea2
&& ea1
->equals(ea2
))
418 { error("unrecognized trait %s", ident
->toChars());
425 error("%s is not a type", o
->toChars());
429 error("wrong number of arguments %d", dim
);
434 return new IntegerExp(loc
, 0, Type::tbool
);
437 return new IntegerExp(loc
, 1, Type::tbool
);