Mercurial > projects > ldc
annotate dmd/expression.c @ 468:45a67b6f1310
Removed the 'needsstorage' thing from Dsymbol. Arguments are not always given storage when applicable. This is not longer treat specially
in this regard. Code for accessing nested variables and contexts rewritten. Probably more. Fairly well tested.
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Mon, 04 Aug 2008 02:59:34 +0200 |
parents | 1c65b5477eaa |
children | e19e20103119 |
rev | line source |
---|---|
159 | 1 |
2 // Compiler implementation of the D programming language | |
3 // Copyright (c) 1999-2008 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 <stdlib.h> | |
13 #include <ctype.h> | |
14 #include <assert.h> | |
15 #include <complex> | |
16 #include <math.h> | |
17 | |
18 #if _WIN32 && __DMC__ | |
19 extern "C" char * __cdecl __locale_decpoint; | |
20 #endif | |
21 | |
285
297690b5d4a5
[svn r306] Fixed: it's now possible to compile and link llvmdc with MinGW32 and msys on Win32 :D I tried it myself ;) Building the runtime still needs some work, but it's a step in the right direction.
lindquist
parents:
163
diff
changeset
|
22 #if __MINGW32__ |
297690b5d4a5
[svn r306] Fixed: it's now possible to compile and link llvmdc with MinGW32 and msys on Win32 :D I tried it myself ;) Building the runtime still needs some work, but it's a step in the right direction.
lindquist
parents:
163
diff
changeset
|
23 #ifndef isnan |
297690b5d4a5
[svn r306] Fixed: it's now possible to compile and link llvmdc with MinGW32 and msys on Win32 :D I tried it myself ;) Building the runtime still needs some work, but it's a step in the right direction.
lindquist
parents:
163
diff
changeset
|
24 #define isnan _isnan |
297690b5d4a5
[svn r306] Fixed: it's now possible to compile and link llvmdc with MinGW32 and msys on Win32 :D I tried it myself ;) Building the runtime still needs some work, but it's a step in the right direction.
lindquist
parents:
163
diff
changeset
|
25 #endif |
297690b5d4a5
[svn r306] Fixed: it's now possible to compile and link llvmdc with MinGW32 and msys on Win32 :D I tried it myself ;) Building the runtime still needs some work, but it's a step in the right direction.
lindquist
parents:
163
diff
changeset
|
26 #endif |
297690b5d4a5
[svn r306] Fixed: it's now possible to compile and link llvmdc with MinGW32 and msys on Win32 :D I tried it myself ;) Building the runtime still needs some work, but it's a step in the right direction.
lindquist
parents:
163
diff
changeset
|
27 |
159 | 28 #if IN_GCC |
29 // Issues with using -include total.h (defines integer_t) and then complex.h fails... | |
30 #undef integer_t | |
31 #endif | |
32 | |
33 #ifdef __APPLE__ | |
34 #define integer_t dmd_integer_t | |
35 #endif | |
36 | |
37 #if IN_GCC || IN_LLVM | |
38 #include "mem.h" | |
39 #elif _WIN32 | |
40 #include "..\root\mem.h" | |
41 #elif linux | |
42 #include "../root/mem.h" | |
43 #endif | |
44 | |
45 //#include "port.h" | |
46 #include "mtype.h" | |
47 #include "init.h" | |
48 #include "expression.h" | |
49 #include "template.h" | |
50 #include "utf.h" | |
51 #include "enum.h" | |
52 #include "scope.h" | |
53 #include "statement.h" | |
54 #include "declaration.h" | |
55 #include "aggregate.h" | |
56 #include "import.h" | |
57 #include "id.h" | |
58 #include "dsymbol.h" | |
59 #include "module.h" | |
60 #include "attrib.h" | |
61 #include "hdrgen.h" | |
62 #include "parse.h" | |
63 | |
64 Expression *createTypeInfoArray(Scope *sc, Expression *args[], int dim); | |
65 | |
66 #define LOGSEMANTIC 0 | |
67 | |
68 /********************************** | |
69 * Set operator precedence for each operator. | |
70 */ | |
71 | |
72 // Operator precedence - greater values are higher precedence | |
73 | |
74 enum PREC | |
75 { | |
76 PREC_zero, | |
77 PREC_expr, | |
78 PREC_assign, | |
79 PREC_cond, | |
80 PREC_oror, | |
81 PREC_andand, | |
82 PREC_or, | |
83 PREC_xor, | |
84 PREC_and, | |
85 PREC_equal, | |
86 PREC_rel, | |
87 PREC_shift, | |
88 PREC_add, | |
89 PREC_mul, | |
90 PREC_unary, | |
91 PREC_primary, | |
92 }; | |
93 | |
94 enum PREC precedence[TOKMAX]; | |
95 | |
96 void initPrecedence() | |
97 { | |
98 precedence[TOKdotvar] = PREC_primary; | |
99 precedence[TOKimport] = PREC_primary; | |
100 precedence[TOKidentifier] = PREC_primary; | |
101 precedence[TOKthis] = PREC_primary; | |
102 precedence[TOKsuper] = PREC_primary; | |
103 precedence[TOKint64] = PREC_primary; | |
104 precedence[TOKfloat64] = PREC_primary; | |
105 precedence[TOKnull] = PREC_primary; | |
106 precedence[TOKstring] = PREC_primary; | |
107 precedence[TOKarrayliteral] = PREC_primary; | |
108 precedence[TOKtypedot] = PREC_primary; | |
109 precedence[TOKtypeid] = PREC_primary; | |
110 precedence[TOKis] = PREC_primary; | |
111 precedence[TOKassert] = PREC_primary; | |
112 precedence[TOKfunction] = PREC_primary; | |
113 precedence[TOKvar] = PREC_primary; | |
336 | 114 #if DMDV2 |
115 precedence[TOKdefault] = PREC_primary; | |
116 #endif | |
159 | 117 |
118 // post | |
119 precedence[TOKdotti] = PREC_primary; | |
120 precedence[TOKdot] = PREC_primary; | |
121 // precedence[TOKarrow] = PREC_primary; | |
122 precedence[TOKplusplus] = PREC_primary; | |
123 precedence[TOKminusminus] = PREC_primary; | |
124 precedence[TOKcall] = PREC_primary; | |
125 precedence[TOKslice] = PREC_primary; | |
126 precedence[TOKarray] = PREC_primary; | |
127 | |
128 precedence[TOKaddress] = PREC_unary; | |
129 precedence[TOKstar] = PREC_unary; | |
130 precedence[TOKneg] = PREC_unary; | |
131 precedence[TOKuadd] = PREC_unary; | |
132 precedence[TOKnot] = PREC_unary; | |
133 precedence[TOKtobool] = PREC_add; | |
134 precedence[TOKtilde] = PREC_unary; | |
135 precedence[TOKdelete] = PREC_unary; | |
136 precedence[TOKnew] = PREC_unary; | |
137 precedence[TOKcast] = PREC_unary; | |
138 | |
139 precedence[TOKmul] = PREC_mul; | |
140 precedence[TOKdiv] = PREC_mul; | |
141 precedence[TOKmod] = PREC_mul; | |
142 | |
143 precedence[TOKadd] = PREC_add; | |
144 precedence[TOKmin] = PREC_add; | |
145 precedence[TOKcat] = PREC_add; | |
146 | |
147 precedence[TOKshl] = PREC_shift; | |
148 precedence[TOKshr] = PREC_shift; | |
149 precedence[TOKushr] = PREC_shift; | |
150 | |
151 precedence[TOKlt] = PREC_rel; | |
152 precedence[TOKle] = PREC_rel; | |
153 precedence[TOKgt] = PREC_rel; | |
154 precedence[TOKge] = PREC_rel; | |
155 precedence[TOKunord] = PREC_rel; | |
156 precedence[TOKlg] = PREC_rel; | |
157 precedence[TOKleg] = PREC_rel; | |
158 precedence[TOKule] = PREC_rel; | |
159 precedence[TOKul] = PREC_rel; | |
160 precedence[TOKuge] = PREC_rel; | |
161 precedence[TOKug] = PREC_rel; | |
162 precedence[TOKue] = PREC_rel; | |
163 precedence[TOKin] = PREC_rel; | |
164 | |
165 precedence[TOKequal] = PREC_equal; | |
166 precedence[TOKnotequal] = PREC_equal; | |
167 precedence[TOKidentity] = PREC_equal; | |
168 precedence[TOKnotidentity] = PREC_equal; | |
169 | |
170 precedence[TOKand] = PREC_and; | |
171 | |
172 precedence[TOKxor] = PREC_xor; | |
173 | |
174 precedence[TOKor] = PREC_or; | |
175 | |
176 precedence[TOKandand] = PREC_andand; | |
177 | |
178 precedence[TOKoror] = PREC_oror; | |
179 | |
180 precedence[TOKquestion] = PREC_cond; | |
181 | |
182 precedence[TOKassign] = PREC_assign; | |
183 precedence[TOKconstruct] = PREC_assign; | |
184 precedence[TOKblit] = PREC_assign; | |
185 precedence[TOKaddass] = PREC_assign; | |
186 precedence[TOKminass] = PREC_assign; | |
187 precedence[TOKcatass] = PREC_assign; | |
188 precedence[TOKmulass] = PREC_assign; | |
189 precedence[TOKdivass] = PREC_assign; | |
190 precedence[TOKmodass] = PREC_assign; | |
191 precedence[TOKshlass] = PREC_assign; | |
192 precedence[TOKshrass] = PREC_assign; | |
193 precedence[TOKushrass] = PREC_assign; | |
194 precedence[TOKandass] = PREC_assign; | |
195 precedence[TOKorass] = PREC_assign; | |
196 precedence[TOKxorass] = PREC_assign; | |
197 | |
198 precedence[TOKcomma] = PREC_expr; | |
199 } | |
200 | |
336 | 201 /************************************************************* |
202 * Given var, we need to get the | |
203 * right 'this' pointer if var is in an outer class, but our | |
204 * existing 'this' pointer is in an inner class. | |
205 * Input: | |
206 * e1 existing 'this' | |
207 * ad struct or class we need the correct 'this' for | |
208 * var the specific member of ad we're accessing | |
209 */ | |
210 | |
211 Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad, | |
212 Expression *e1, Declaration *var) | |
213 { | |
214 //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1->toChars(), ad->toChars(), var->toChars()); | |
215 L1: | |
216 Type *t = e1->type->toBasetype(); | |
217 //printf("e1->type = %s, var->type = %s\n", e1->type->toChars(), var->type->toChars()); | |
218 | |
219 /* If e1 is not the 'this' pointer for ad | |
220 */ | |
221 if (ad && | |
222 !(t->ty == Tpointer && t->nextOf()->ty == Tstruct && | |
223 ((TypeStruct *)t->nextOf())->sym == ad) | |
224 && | |
225 !(t->ty == Tstruct && | |
226 ((TypeStruct *)t)->sym == ad) | |
227 ) | |
228 { | |
229 ClassDeclaration *cd = ad->isClassDeclaration(); | |
230 ClassDeclaration *tcd = t->isClassHandle(); | |
231 | |
232 /* e1 is the right this if ad is a base class of e1 | |
233 */ | |
234 if (!cd || !tcd || | |
235 !(tcd == cd || cd->isBaseOf(tcd, NULL)) | |
236 ) | |
237 { | |
238 /* Only classes can be inner classes with an 'outer' | |
239 * member pointing to the enclosing class instance | |
240 */ | |
241 if (tcd && tcd->isNested()) | |
242 { /* e1 is the 'this' pointer for an inner class: tcd. | |
243 * Rewrite it as the 'this' pointer for the outer class. | |
244 */ | |
245 | |
246 e1 = new DotVarExp(loc, e1, tcd->vthis); | |
247 e1->type = tcd->vthis->type; | |
248 // Do not call checkNestedRef() | |
249 //e1 = e1->semantic(sc); | |
250 | |
251 // Skip up over nested functions, and get the enclosing | |
252 // class type. | |
253 int n = 0; | |
254 Dsymbol *s; | |
255 for (s = tcd->toParent(); | |
256 s && s->isFuncDeclaration(); | |
257 s = s->toParent()) | |
258 { FuncDeclaration *f = s->isFuncDeclaration(); | |
259 if (f->vthis) | |
260 { | |
261 //printf("rewriting e1 to %s's this\n", f->toChars()); | |
262 n++; | |
263 e1 = new VarExp(loc, f->vthis); | |
264 } | |
265 } | |
266 if (s && s->isClassDeclaration()) | |
267 { e1->type = s->isClassDeclaration()->type; | |
268 if (n > 1) | |
269 e1 = e1->semantic(sc); | |
270 } | |
271 else | |
272 e1 = e1->semantic(sc); | |
273 goto L1; | |
274 } | |
275 /* Can't find a path from e1 to ad | |
276 */ | |
277 e1->error("this for %s needs to be type %s not type %s", | |
278 var->toChars(), ad->toChars(), t->toChars()); | |
279 } | |
280 } | |
281 return e1; | |
282 } | |
283 | |
159 | 284 /***************************************** |
285 * Determine if 'this' is available. | |
286 * If it is, return the FuncDeclaration that has it. | |
287 */ | |
288 | |
289 FuncDeclaration *hasThis(Scope *sc) | |
290 { FuncDeclaration *fd; | |
291 FuncDeclaration *fdthis; | |
292 | |
293 //printf("hasThis()\n"); | |
294 fdthis = sc->parent->isFuncDeclaration(); | |
295 //printf("fdthis = %p, '%s'\n", fdthis, fdthis ? fdthis->toChars() : ""); | |
296 | |
297 // Go upwards until we find the enclosing member function | |
298 fd = fdthis; | |
299 while (1) | |
300 { | |
301 if (!fd) | |
302 { | |
303 goto Lno; | |
304 } | |
305 if (!fd->isNested()) | |
306 break; | |
307 | |
308 Dsymbol *parent = fd->parent; | |
309 while (parent) | |
310 { | |
311 TemplateInstance *ti = parent->isTemplateInstance(); | |
312 if (ti) | |
313 parent = ti->parent; | |
314 else | |
315 break; | |
316 } | |
317 | |
318 fd = fd->parent->isFuncDeclaration(); | |
319 } | |
320 | |
321 if (!fd->isThis()) | |
322 { //printf("test '%s'\n", fd->toChars()); | |
323 goto Lno; | |
324 } | |
325 | |
326 assert(fd->vthis); | |
327 return fd; | |
328 | |
329 Lno: | |
330 return NULL; // don't have 'this' available | |
331 } | |
332 | |
333 | |
334 /*************************************** | |
335 * Pull out any properties. | |
336 */ | |
337 | |
338 Expression *resolveProperties(Scope *sc, Expression *e) | |
339 { | |
340 //printf("resolveProperties(%s)\n", e->toChars()); | |
341 if (e->type) | |
342 { | |
343 Type *t = e->type->toBasetype(); | |
344 | |
345 if (t->ty == Tfunction) | |
346 { | |
347 e = new CallExp(e->loc, e); | |
348 e = e->semantic(sc); | |
349 } | |
350 | |
351 /* Look for e being a lazy parameter; rewrite as delegate call | |
352 */ | |
353 else if (e->op == TOKvar) | |
354 { VarExp *ve = (VarExp *)e; | |
355 | |
356 if (ve->var->storage_class & STClazy) | |
357 { | |
358 e = new CallExp(e->loc, e); | |
359 e = e->semantic(sc); | |
360 } | |
361 } | |
362 | |
363 else if (e->op == TOKdotexp) | |
364 { | |
365 e->error("expression has no value"); | |
366 } | |
367 } | |
368 return e; | |
369 } | |
370 | |
371 /****************************** | |
372 * Perform semantic() on an array of Expressions. | |
373 */ | |
374 | |
375 void arrayExpressionSemantic(Expressions *exps, Scope *sc) | |
376 { | |
377 if (exps) | |
378 { | |
379 for (size_t i = 0; i < exps->dim; i++) | |
380 { Expression *e = (Expression *)exps->data[i]; | |
381 | |
382 e = e->semantic(sc); | |
383 exps->data[i] = (void *)e; | |
384 } | |
385 } | |
386 } | |
387 | |
388 /**************************************** | |
389 * Expand tuples. | |
390 */ | |
391 | |
392 void expandTuples(Expressions *exps) | |
393 { | |
394 //printf("expandTuples()\n"); | |
395 if (exps) | |
396 { | |
397 for (size_t i = 0; i < exps->dim; i++) | |
398 { Expression *arg = (Expression *)exps->data[i]; | |
399 if (!arg) | |
400 continue; | |
401 | |
402 // Look for tuple with 0 members | |
403 if (arg->op == TOKtype) | |
404 { TypeExp *e = (TypeExp *)arg; | |
405 if (e->type->toBasetype()->ty == Ttuple) | |
406 { TypeTuple *tt = (TypeTuple *)e->type->toBasetype(); | |
407 | |
408 if (!tt->arguments || tt->arguments->dim == 0) | |
409 { | |
410 exps->remove(i); | |
411 if (i == exps->dim) | |
412 return; | |
413 i--; | |
414 continue; | |
415 } | |
416 } | |
417 } | |
418 | |
419 // Inline expand all the tuples | |
420 while (arg->op == TOKtuple) | |
421 { TupleExp *te = (TupleExp *)arg; | |
422 | |
423 exps->remove(i); // remove arg | |
424 exps->insert(i, te->exps); // replace with tuple contents | |
425 if (i == exps->dim) | |
426 return; // empty tuple, no more arguments | |
427 arg = (Expression *)exps->data[i]; | |
428 } | |
429 } | |
430 } | |
431 } | |
432 | |
433 /**************************************** | |
434 * Preprocess arguments to function. | |
435 */ | |
436 | |
437 void preFunctionArguments(Loc loc, Scope *sc, Expressions *exps) | |
438 { | |
439 if (exps) | |
440 { | |
441 expandTuples(exps); | |
442 | |
443 for (size_t i = 0; i < exps->dim; i++) | |
444 { Expression *arg = (Expression *)exps->data[i]; | |
445 | |
446 if (!arg->type) | |
447 { | |
448 #ifdef DEBUG | |
449 if (!global.gag) | |
450 printf("1: \n"); | |
451 #endif | |
452 arg->error("%s is not an expression", arg->toChars()); | |
453 arg = new IntegerExp(arg->loc, 0, Type::tint32); | |
454 } | |
455 | |
456 arg = resolveProperties(sc, arg); | |
457 exps->data[i] = (void *) arg; | |
458 | |
459 //arg->rvalue(); | |
460 #if 0 | |
461 if (arg->type->ty == Tfunction) | |
462 { | |
463 arg = new AddrExp(arg->loc, arg); | |
464 arg = arg->semantic(sc); | |
465 exps->data[i] = (void *) arg; | |
466 } | |
467 #endif | |
468 } | |
469 } | |
470 } | |
471 | |
336 | 472 /********************************************* |
473 * Call copy constructor for struct value argument. | |
474 */ | |
475 #if DMDV2 | |
476 Expression *callCpCtor(Loc loc, Scope *sc, Expression *e) | |
477 { | |
478 Type *tb = e->type->toBasetype(); | |
479 assert(tb->ty == Tstruct); | |
480 StructDeclaration *sd = ((TypeStruct *)tb)->sym; | |
481 if (sd->cpctor) | |
482 { | |
483 /* Create a variable tmp, and replace the argument e with: | |
484 * (tmp = e),tmp | |
485 * and let AssignExp() handle the construction. | |
486 * This is not the most efficent, ideally tmp would be constructed | |
487 * directly onto the stack. | |
488 */ | |
489 Identifier *idtmp = Lexer::uniqueId("__tmp"); | |
490 VarDeclaration *tmp = new VarDeclaration(loc, tb, idtmp, new ExpInitializer(0, e)); | |
491 Expression *ae = new DeclarationExp(loc, tmp); | |
492 e = new CommaExp(loc, ae, new VarExp(loc, tmp)); | |
493 e = e->semantic(sc); | |
494 } | |
495 return e; | |
496 } | |
497 #endif | |
159 | 498 |
499 /**************************************** | |
500 * Now that we know the exact type of the function we're calling, | |
501 * the arguments[] need to be adjusted: | |
502 * 1) implicitly convert argument to the corresponding parameter type | |
503 * 2) add default arguments for any missing arguments | |
504 * 3) do default promotions on arguments corresponding to ... | |
505 * 4) add hidden _arguments[] argument | |
506 */ | |
507 | |
508 void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *arguments) | |
509 { | |
510 unsigned n; | |
511 int done; | |
512 Type *tb; | |
513 | |
514 //printf("functionArguments()\n"); | |
515 assert(arguments); | |
516 size_t nargs = arguments ? arguments->dim : 0; | |
517 size_t nparams = Argument::dim(tf->parameters); | |
518 | |
519 if (nargs > nparams && tf->varargs == 0) | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
520 error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs); |
159 | 521 |
522 n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams) | |
523 | |
524 done = 0; | |
525 for (size_t i = 0; i < n; i++) | |
526 { | |
527 Expression *arg; | |
528 | |
529 if (i < nargs) | |
530 arg = (Expression *)arguments->data[i]; | |
531 else | |
532 arg = NULL; | |
533 | |
534 if (i < nparams) | |
535 { | |
536 Argument *p = Argument::getNth(tf->parameters, i); | |
537 | |
538 if (!arg) | |
539 { | |
540 if (!p->defaultArg) | |
541 { | |
542 if (tf->varargs == 2 && i + 1 == nparams) | |
543 goto L2; | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
544 error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs); |
159 | 545 break; |
546 } | |
336 | 547 arg = p->defaultArg; |
548 #if DMDV2 | |
549 if (arg->op == TOKdefault) | |
550 { DefaultInitExp *de = (DefaultInitExp *)arg; | |
551 arg = de->resolve(loc, sc); | |
552 } | |
553 else | |
554 #endif | |
555 arg = arg->copy(); | |
159 | 556 arguments->push(arg); |
557 nargs++; | |
558 } | |
559 | |
560 if (tf->varargs == 2 && i + 1 == nparams) | |
561 { | |
562 //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars()); | |
563 if (arg->implicitConvTo(p->type)) | |
564 { | |
565 if (nargs != nparams) | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
566 error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs); |
159 | 567 goto L1; |
568 } | |
569 L2: | |
570 Type *tb = p->type->toBasetype(); | |
571 Type *tret = p->isLazyArray(); | |
572 switch (tb->ty) | |
573 { | |
574 case Tsarray: | |
575 case Tarray: | |
576 { // Create a static array variable v of type arg->type | |
577 #ifdef IN_GCC | |
578 /* GCC 4.0 does not like zero length arrays used like | |
579 this; pass a null array value instead. Could also | |
580 just make a one-element array. */ | |
581 if (nargs - i == 0) | |
582 { | |
583 arg = new NullExp(loc); | |
584 break; | |
585 } | |
586 #endif | |
587 static int idn; | |
588 char name[10 + sizeof(idn)*3 + 1]; | |
589 sprintf(name, "__arrayArg%d", ++idn); | |
590 Identifier *id = Lexer::idPool(name); | |
591 Type *t = new TypeSArray(tb->next, new IntegerExp(nargs - i)); | |
592 t = t->semantic(loc, sc); | |
593 VarDeclaration *v = new VarDeclaration(loc, t, id, new VoidInitializer(loc)); | |
594 v->semantic(sc); | |
595 v->parent = sc->parent; | |
596 //sc->insert(v); | |
597 | |
598 Expression *c = new DeclarationExp(0, v); | |
599 c->type = v->type; | |
600 | |
601 for (size_t u = i; u < nargs; u++) | |
602 { Expression *a = (Expression *)arguments->data[u]; | |
603 if (tret && !tb->next->equals(a->type)) | |
604 a = a->toDelegate(sc, tret); | |
605 | |
606 Expression *e = new VarExp(loc, v); | |
607 e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams)); | |
608 e = new AssignExp(loc, e, a); | |
609 if (c) | |
610 c = new CommaExp(loc, c, e); | |
611 else | |
612 c = e; | |
613 } | |
614 arg = new VarExp(loc, v); | |
615 if (c) | |
616 arg = new CommaExp(loc, c, arg); | |
617 break; | |
618 } | |
619 case Tclass: | |
620 { /* Set arg to be: | |
621 * new Tclass(arg0, arg1, ..., argn) | |
622 */ | |
623 Expressions *args = new Expressions(); | |
624 args->setDim(nargs - i); | |
625 for (size_t u = i; u < nargs; u++) | |
626 args->data[u - i] = arguments->data[u]; | |
627 arg = new NewExp(loc, NULL, NULL, p->type, args); | |
628 break; | |
629 } | |
630 default: | |
631 if (!arg) | |
632 { error(loc, "not enough arguments"); | |
633 return; | |
634 } | |
635 break; | |
636 } | |
637 arg = arg->semantic(sc); | |
638 //printf("\targ = '%s'\n", arg->toChars()); | |
639 arguments->setDim(i + 1); | |
640 done = 1; | |
641 } | |
642 | |
643 L1: | |
644 if (!(p->storageClass & STClazy && p->type->ty == Tvoid)) | |
645 arg = arg->implicitCastTo(sc, p->type); | |
646 if (p->storageClass & (STCout | STCref)) | |
647 { | |
648 // BUG: should check that argument to ref is type 'invariant' | |
649 // BUG: assignments to ref should also be type 'invariant' | |
650 arg = arg->modifiableLvalue(sc, arg); | |
651 | |
652 //if (arg->op == TOKslice) | |
653 //arg->error("cannot modify slice %s", arg->toChars()); | |
654 } | |
655 | |
656 // Convert static arrays to pointers | |
657 tb = arg->type->toBasetype(); | |
658 if (tb->ty == Tsarray) | |
659 { | |
660 arg = arg->checkToPointer(); | |
661 } | |
662 | |
663 // Convert lazy argument to a delegate | |
664 if (p->storageClass & STClazy) | |
665 { | |
666 arg = arg->toDelegate(sc, p->type); | |
667 } | |
668 } | |
669 else | |
670 { | |
671 | |
672 // If not D linkage, do promotions | |
673 if (tf->linkage != LINKd) | |
674 { | |
675 // Promote bytes, words, etc., to ints | |
676 arg = arg->integralPromotions(sc); | |
677 | |
678 // Promote floats to doubles | |
679 switch (arg->type->ty) | |
680 { | |
681 case Tfloat32: | |
682 arg = arg->castTo(sc, Type::tfloat64); | |
683 break; | |
684 | |
685 case Timaginary32: | |
686 arg = arg->castTo(sc, Type::timaginary64); | |
687 break; | |
688 } | |
689 } | |
690 | |
691 // Convert static arrays to dynamic arrays | |
692 tb = arg->type->toBasetype(); | |
693 if (tb->ty == Tsarray) | |
694 { TypeSArray *ts = (TypeSArray *)tb; | |
336 | 695 Type *ta = ts->next->arrayOf(); |
159 | 696 if (ts->size(arg->loc) == 0) |
697 { arg = new NullExp(arg->loc); | |
698 arg->type = ta; | |
699 } | |
700 else | |
701 arg = arg->castTo(sc, ta); | |
702 } | |
336 | 703 #if DMDV2 |
704 if (tb->ty == Tstruct) | |
705 { | |
706 arg = callCpCtor(loc, sc, arg); | |
707 } | |
708 | |
709 // Give error for overloaded function addresses | |
710 if (arg->op == TOKsymoff) | |
711 { SymOffExp *se = (SymOffExp *)arg; | |
712 if (se->hasOverloads && !se->var->isFuncDeclaration()->isUnique()) | |
713 arg->error("function %s is overloaded", arg->toChars()); | |
714 } | |
715 #endif | |
159 | 716 arg->rvalue(); |
717 } | |
718 arg = arg->optimize(WANTvalue); | |
719 arguments->data[i] = (void *) arg; | |
720 if (done) | |
721 break; | |
722 } | |
723 | |
724 #if !IN_LLVM | |
725 // If D linkage and variadic, add _arguments[] as first argument | |
726 if (tf->linkage == LINKd && tf->varargs == 1) | |
727 { | |
728 Expression *e; | |
729 | |
730 e = createTypeInfoArray(sc, (Expression **)&arguments->data[nparams], | |
731 arguments->dim - nparams); | |
732 arguments->insert(0, e); | |
733 } | |
734 #endif | |
735 } | |
736 | |
737 /************************************************** | |
738 * Write expression out to buf, but wrap it | |
739 * in ( ) if its precedence is less than pr. | |
740 */ | |
741 | |
742 void expToCBuffer(OutBuffer *buf, HdrGenState *hgs, Expression *e, enum PREC pr) | |
743 { | |
336 | 744 //if (precedence[e->op] == 0) e->dump(0); |
159 | 745 if (precedence[e->op] < pr) |
746 { | |
747 buf->writeByte('('); | |
748 e->toCBuffer(buf, hgs); | |
749 buf->writeByte(')'); | |
750 } | |
751 else | |
752 e->toCBuffer(buf, hgs); | |
753 } | |
754 | |
755 /************************************************** | |
756 * Write out argument list to buf. | |
757 */ | |
758 | |
759 void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs) | |
760 { | |
761 if (arguments) | |
762 { | |
763 for (size_t i = 0; i < arguments->dim; i++) | |
764 { Expression *arg = (Expression *)arguments->data[i]; | |
765 | |
766 if (arg) | |
767 { if (i) | |
768 buf->writeByte(','); | |
769 expToCBuffer(buf, hgs, arg, PREC_assign); | |
770 } | |
771 } | |
772 } | |
773 } | |
774 | |
775 /************************************************** | |
776 * Write out argument types to buf. | |
777 */ | |
778 | |
779 void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs) | |
780 { | |
781 if (arguments) | |
782 { OutBuffer argbuf; | |
783 | |
784 for (size_t i = 0; i < arguments->dim; i++) | |
785 { Expression *arg = (Expression *)arguments->data[i]; | |
786 | |
787 if (i) | |
788 buf->writeByte(','); | |
789 argbuf.reset(); | |
790 arg->type->toCBuffer2(&argbuf, hgs, 0); | |
791 buf->write(&argbuf); | |
792 } | |
793 } | |
794 } | |
795 | |
796 /******************************** Expression **************************/ | |
797 | |
798 Expression::Expression(Loc loc, enum TOK op, int size) | |
799 : loc(loc) | |
800 { | |
801 this->loc = loc; | |
802 this->op = op; | |
803 this->size = size; | |
804 type = NULL; | |
805 } | |
806 | |
807 Expression *Expression::syntaxCopy() | |
808 { | |
809 //printf("Expression::syntaxCopy()\n"); | |
810 //dump(0); | |
811 return copy(); | |
812 } | |
813 | |
814 /********************************* | |
815 * Does *not* do a deep copy. | |
816 */ | |
817 | |
818 Expression *Expression::copy() | |
819 { | |
820 Expression *e; | |
821 if (!size) | |
822 { | |
823 #ifdef DEBUG | |
824 fprintf(stdmsg, "No expression copy for: %s\n", toChars()); | |
825 printf("op = %d\n", op); | |
826 dump(0); | |
827 #endif | |
828 assert(0); | |
829 } | |
830 e = (Expression *)mem.malloc(size); | |
831 return (Expression *)memcpy(e, this, size); | |
832 } | |
833 | |
834 /************************** | |
835 * Semantically analyze Expression. | |
836 * Determine types, fold constants, etc. | |
837 */ | |
838 | |
839 Expression *Expression::semantic(Scope *sc) | |
840 { | |
841 #if LOGSEMANTIC | |
336 | 842 printf("Expression::semantic() %s\n", toChars()); |
159 | 843 #endif |
844 if (type) | |
845 type = type->semantic(loc, sc); | |
846 else | |
847 type = Type::tvoid; | |
848 return this; | |
849 } | |
850 | |
851 void Expression::print() | |
852 { | |
853 fprintf(stdmsg, "%s\n", toChars()); | |
854 fflush(stdmsg); | |
855 } | |
856 | |
857 char *Expression::toChars() | |
858 { OutBuffer *buf; | |
859 HdrGenState hgs; | |
860 | |
861 memset(&hgs, 0, sizeof(hgs)); | |
862 buf = new OutBuffer(); | |
863 toCBuffer(buf, &hgs); | |
864 return buf->toChars(); | |
865 } | |
866 | |
867 void Expression::error(const char *format, ...) | |
868 { | |
869 va_list ap; | |
870 va_start(ap, format); | |
871 ::verror(loc, format, ap); | |
872 va_end( ap ); | |
873 } | |
874 | |
875 void Expression::rvalue() | |
876 { | |
877 if (type && type->toBasetype()->ty == Tvoid) | |
878 { error("expression %s is void and has no value", toChars()); | |
879 #if 0 | |
880 dump(0); | |
881 halt(); | |
882 #endif | |
336 | 883 type = Type::tint32; |
159 | 884 } |
885 } | |
886 | |
887 Expression *Expression::combine(Expression *e1, Expression *e2) | |
888 { | |
889 if (e1) | |
890 { | |
891 if (e2) | |
892 { | |
893 e1 = new CommaExp(e1->loc, e1, e2); | |
894 e1->type = e2->type; | |
895 } | |
896 } | |
897 else | |
898 e1 = e2; | |
899 return e1; | |
900 } | |
901 | |
902 integer_t Expression::toInteger() | |
903 { | |
904 //printf("Expression %s\n", Token::toChars(op)); | |
905 error("Integer constant expression expected instead of %s", toChars()); | |
906 return 0; | |
907 } | |
908 | |
909 uinteger_t Expression::toUInteger() | |
910 { | |
911 //printf("Expression %s\n", Token::toChars(op)); | |
912 return (uinteger_t)toInteger(); | |
913 } | |
914 | |
915 real_t Expression::toReal() | |
916 { | |
917 error("Floating point constant expression expected instead of %s", toChars()); | |
918 return 0; | |
919 } | |
920 | |
921 real_t Expression::toImaginary() | |
922 { | |
923 error("Floating point constant expression expected instead of %s", toChars()); | |
924 return 0; | |
925 } | |
926 | |
927 complex_t Expression::toComplex() | |
928 { | |
929 error("Floating point constant expression expected instead of %s", toChars()); | |
930 #ifdef IN_GCC | |
931 return complex_t(real_t(0)); // %% nicer | |
932 #else | |
933 return 0; | |
934 #endif | |
935 } | |
936 | |
937 void Expression::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
938 { | |
939 buf->writestring(Token::toChars(op)); | |
940 } | |
941 | |
942 void Expression::toMangleBuffer(OutBuffer *buf) | |
943 { | |
944 error("expression %s is not a valid template value argument", toChars()); | |
945 } | |
946 | |
947 /******************************* | |
948 * Give error if we're not an lvalue. | |
949 * If we can, convert expression to be an lvalue. | |
950 */ | |
951 | |
952 Expression *Expression::toLvalue(Scope *sc, Expression *e) | |
953 { | |
954 if (!e) | |
955 e = this; | |
956 else if (!loc.filename) | |
957 loc = e->loc; | |
958 error("%s is not an lvalue", e->toChars()); | |
959 return this; | |
960 } | |
961 | |
962 Expression *Expression::modifiableLvalue(Scope *sc, Expression *e) | |
963 { | |
964 // See if this expression is a modifiable lvalue (i.e. not const) | |
965 return toLvalue(sc, e); | |
966 } | |
967 | |
968 /************************************ | |
969 * Detect cases where pointers to the stack can 'escape' the | |
970 * lifetime of the stack frame. | |
971 */ | |
972 | |
973 void Expression::checkEscape() | |
974 { | |
975 } | |
976 | |
977 void Expression::checkScalar() | |
978 { | |
979 if (!type->isscalar()) | |
980 error("'%s' is not a scalar, it is a %s", toChars(), type->toChars()); | |
981 } | |
982 | |
983 void Expression::checkNoBool() | |
984 { | |
985 if (type->toBasetype()->ty == Tbool) | |
986 error("operation not allowed on bool '%s'", toChars()); | |
987 } | |
988 | |
989 Expression *Expression::checkIntegral() | |
990 { | |
991 if (!type->isintegral()) | |
992 { error("'%s' is not of integral type, it is a %s", toChars(), type->toChars()); | |
993 return new IntegerExp(0); | |
994 } | |
995 return this; | |
996 } | |
997 | |
998 Expression *Expression::checkArithmetic() | |
999 { | |
1000 if (!type->isintegral() && !type->isfloating()) | |
1001 { error("'%s' is not of arithmetic type, it is a %s", toChars(), type->toChars()); | |
1002 return new IntegerExp(0); | |
1003 } | |
1004 return this; | |
1005 } | |
1006 | |
1007 void Expression::checkDeprecated(Scope *sc, Dsymbol *s) | |
1008 { | |
1009 s->checkDeprecated(loc, sc); | |
1010 } | |
1011 | |
1012 /******************************** | |
1013 * Check for expressions that have no use. | |
1014 * Input: | |
1015 * flag 0 not going to use the result, so issue error message if no | |
1016 * side effects | |
1017 * 1 the result of the expression is used, but still check | |
1018 * for useless subexpressions | |
1019 * 2 do not issue error messages, just return !=0 if expression | |
1020 * has side effects | |
1021 */ | |
1022 | |
1023 int Expression::checkSideEffect(int flag) | |
1024 { | |
1025 if (flag == 0) | |
1026 { if (op == TOKimport) | |
1027 { | |
1028 error("%s has no effect", toChars()); | |
1029 } | |
1030 else | |
1031 error("%s has no effect in expression (%s)", | |
1032 Token::toChars(op), toChars()); | |
1033 } | |
1034 return 0; | |
1035 } | |
1036 | |
1037 /***************************** | |
1038 * Check that expression can be tested for true or false. | |
1039 */ | |
1040 | |
1041 Expression *Expression::checkToBoolean() | |
1042 { | |
1043 // Default is 'yes' - do nothing | |
1044 | |
1045 #ifdef DEBUG | |
1046 if (!type) | |
1047 dump(0); | |
1048 #endif | |
1049 | |
1050 if (!type->checkBoolean()) | |
1051 { | |
1052 error("expression %s of type %s does not have a boolean value", toChars(), type->toChars()); | |
1053 } | |
1054 return this; | |
1055 } | |
1056 | |
1057 /**************************** | |
1058 */ | |
1059 | |
1060 Expression *Expression::checkToPointer() | |
1061 { | |
1062 Expression *e; | |
1063 Type *tb; | |
1064 | |
1065 //printf("Expression::checkToPointer()\n"); | |
1066 e = this; | |
1067 | |
1068 // If C static array, convert to pointer | |
1069 tb = type->toBasetype(); | |
1070 if (tb->ty == Tsarray) | |
1071 { TypeSArray *ts = (TypeSArray *)tb; | |
1072 if (ts->size(loc) == 0) | |
1073 e = new NullExp(loc); | |
1074 else | |
1075 e = new AddrExp(loc, this); | |
336 | 1076 e->type = ts->next->pointerTo(); |
159 | 1077 } |
1078 return e; | |
1079 } | |
1080 | |
1081 /****************************** | |
1082 * Take address of expression. | |
1083 */ | |
1084 | |
1085 Expression *Expression::addressOf(Scope *sc) | |
1086 { | |
1087 Expression *e; | |
1088 | |
1089 //printf("Expression::addressOf()\n"); | |
1090 e = toLvalue(sc, NULL); | |
1091 e = new AddrExp(loc, e); | |
1092 e->type = type->pointerTo(); | |
1093 return e; | |
1094 } | |
1095 | |
1096 /****************************** | |
1097 * If this is a reference, dereference it. | |
1098 */ | |
1099 | |
1100 Expression *Expression::deref() | |
1101 { | |
1102 //printf("Expression::deref()\n"); | |
1103 if (type->ty == Treference) | |
1104 { Expression *e; | |
1105 | |
1106 e = new PtrExp(loc, this); | |
336 | 1107 e->type = ((TypeReference *)type)->next; |
159 | 1108 return e; |
1109 } | |
1110 return this; | |
1111 } | |
1112 | |
1113 /******************************** | |
1114 * Does this expression statically evaluate to a boolean TRUE or FALSE? | |
1115 */ | |
1116 | |
1117 int Expression::isBool(int result) | |
1118 { | |
1119 return FALSE; | |
1120 } | |
1121 | |
1122 /******************************** | |
1123 * Does this expression result in either a 1 or a 0? | |
1124 */ | |
1125 | |
1126 int Expression::isBit() | |
1127 { | |
1128 return FALSE; | |
1129 } | |
1130 | |
336 | 1131 /******************************** |
1132 * Can this expression throw an exception? | |
1133 * Valid only after semantic() pass. | |
1134 */ | |
1135 | |
1136 int Expression::canThrow() | |
1137 { | |
1138 return TRUE; | |
1139 } | |
1140 | |
1141 | |
1142 | |
159 | 1143 Expressions *Expression::arraySyntaxCopy(Expressions *exps) |
1144 { Expressions *a = NULL; | |
1145 | |
1146 if (exps) | |
1147 { | |
1148 a = new Expressions(); | |
1149 a->setDim(exps->dim); | |
1150 for (int i = 0; i < a->dim; i++) | |
1151 { Expression *e = (Expression *)exps->data[i]; | |
1152 | |
1153 e = e->syntaxCopy(); | |
1154 a->data[i] = e; | |
1155 } | |
1156 } | |
1157 return a; | |
1158 } | |
1159 | |
1160 /******************************** IntegerExp **************************/ | |
1161 | |
1162 IntegerExp::IntegerExp(Loc loc, integer_t value, Type *type) | |
1163 : Expression(loc, TOKint64, sizeof(IntegerExp)) | |
1164 { | |
1165 //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type->toChars() : ""); | |
1166 if (type && !type->isscalar()) | |
1167 { | |
336 | 1168 //printf("%s, loc = %d\n", toChars(), loc.linnum); |
159 | 1169 error("integral constant must be scalar type, not %s", type->toChars()); |
1170 type = Type::terror; | |
1171 } | |
1172 this->type = type; | |
1173 this->value = value; | |
1174 } | |
1175 | |
1176 IntegerExp::IntegerExp(integer_t value) | |
1177 : Expression(0, TOKint64, sizeof(IntegerExp)) | |
1178 { | |
1179 this->type = Type::tint32; | |
1180 this->value = value; | |
1181 } | |
1182 | |
1183 int IntegerExp::equals(Object *o) | |
1184 { IntegerExp *ne; | |
1185 | |
1186 if (this == o || | |
1187 (((Expression *)o)->op == TOKint64 && | |
1188 ((ne = (IntegerExp *)o), type->equals(ne->type)) && | |
1189 value == ne->value)) | |
1190 return 1; | |
1191 return 0; | |
1192 } | |
1193 | |
1194 char *IntegerExp::toChars() | |
1195 { | |
1196 #if 1 | |
1197 return Expression::toChars(); | |
1198 #else | |
1199 static char buffer[sizeof(value) * 3 + 1]; | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1200 sprintf(buffer, "%lld", value); |
159 | 1201 return buffer; |
1202 #endif | |
1203 } | |
1204 | |
1205 integer_t IntegerExp::toInteger() | |
1206 { Type *t; | |
1207 | |
1208 t = type; | |
1209 while (t) | |
1210 { | |
1211 switch (t->ty) | |
1212 { | |
1213 case Tbit: | |
1214 case Tbool: value = (value != 0); break; | |
1215 case Tint8: value = (d_int8) value; break; | |
1216 case Tchar: | |
1217 case Tuns8: value = (d_uns8) value; break; | |
1218 case Tint16: value = (d_int16) value; break; | |
1219 case Twchar: | |
1220 case Tuns16: value = (d_uns16) value; break; | |
1221 case Tint32: value = (d_int32) value; break; | |
1222 case Tpointer: | |
1223 case Tdchar: | |
1224 case Tuns32: value = (d_uns32) value; break; | |
1225 case Tint64: value = (d_int64) value; break; | |
1226 case Tuns64: value = (d_uns64) value; break; | |
1227 | |
1228 case Tenum: | |
1229 { | |
1230 TypeEnum *te = (TypeEnum *)t; | |
1231 t = te->sym->memtype; | |
1232 continue; | |
1233 } | |
1234 | |
1235 case Ttypedef: | |
1236 { | |
1237 TypeTypedef *tt = (TypeTypedef *)t; | |
1238 t = tt->sym->basetype; | |
1239 continue; | |
1240 } | |
1241 | |
1242 default: | |
336 | 1243 /* This can happen if errors, such as |
1244 * the type is painted on like in fromConstInitializer(). | |
1245 */ | |
1246 if (!global.errors) | |
1247 { type->print(); | |
1248 assert(0); | |
1249 } | |
159 | 1250 break; |
1251 } | |
1252 break; | |
1253 } | |
1254 return value; | |
1255 } | |
1256 | |
1257 real_t IntegerExp::toReal() | |
1258 { | |
1259 Type *t; | |
1260 | |
1261 toInteger(); | |
1262 t = type->toBasetype(); | |
1263 if (t->ty == Tuns64) | |
1264 return (real_t)(d_uns64)value; | |
1265 else | |
1266 return (real_t)(d_int64)value; | |
1267 } | |
1268 | |
1269 real_t IntegerExp::toImaginary() | |
1270 { | |
1271 return (real_t) 0; | |
1272 } | |
1273 | |
1274 complex_t IntegerExp::toComplex() | |
1275 { | |
1276 return toReal(); | |
1277 } | |
1278 | |
1279 int IntegerExp::isBool(int result) | |
1280 { | |
1281 return result ? value != 0 : value == 0; | |
1282 } | |
1283 | |
1284 Expression *IntegerExp::semantic(Scope *sc) | |
1285 { | |
1286 if (!type) | |
1287 { | |
1288 // Determine what the type of this number is | |
1289 integer_t number = value; | |
1290 | |
1291 if (number & 0x8000000000000000LL) | |
1292 type = Type::tuns64; | |
1293 else if (number & 0xFFFFFFFF80000000LL) | |
1294 type = Type::tint64; | |
1295 else | |
1296 type = Type::tint32; | |
1297 } | |
1298 else | |
1299 { type = type->semantic(loc, sc); | |
1300 } | |
1301 return this; | |
1302 } | |
1303 | |
1304 Expression *IntegerExp::toLvalue(Scope *sc, Expression *e) | |
1305 { | |
1306 if (!e) | |
1307 e = this; | |
1308 else if (!loc.filename) | |
1309 loc = e->loc; | |
1310 e->error("constant %s is not an lvalue", e->toChars()); | |
1311 return this; | |
1312 } | |
1313 | |
1314 void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1315 { | |
1316 integer_t v = toInteger(); | |
1317 | |
1318 if (type) | |
1319 { Type *t = type; | |
1320 | |
1321 L1: | |
1322 switch (t->ty) | |
1323 { | |
1324 case Tenum: | |
1325 { TypeEnum *te = (TypeEnum *)t; | |
1326 buf->printf("cast(%s)", te->sym->toChars()); | |
1327 t = te->sym->memtype; | |
1328 goto L1; | |
1329 } | |
1330 | |
1331 case Ttypedef: | |
1332 { TypeTypedef *tt = (TypeTypedef *)t; | |
1333 buf->printf("cast(%s)", tt->sym->toChars()); | |
1334 t = tt->sym->basetype; | |
1335 goto L1; | |
1336 } | |
1337 | |
1338 case Twchar: // BUG: need to cast(wchar) | |
1339 case Tdchar: // BUG: need to cast(dchar) | |
1340 if ((uinteger_t)v > 0xFF) | |
1341 { | |
1342 buf->printf("'\\U%08x'", v); | |
1343 break; | |
1344 } | |
1345 case Tchar: | |
1346 if (v == '\'') | |
1347 buf->writestring("'\\''"); | |
1348 else if (isprint(v) && v != '\\') | |
1349 buf->printf("'%c'", (int)v); | |
1350 else | |
1351 buf->printf("'\\x%02x'", (int)v); | |
1352 break; | |
1353 | |
1354 case Tint8: | |
1355 buf->writestring("cast(byte)"); | |
1356 goto L2; | |
1357 | |
1358 case Tint16: | |
1359 buf->writestring("cast(short)"); | |
1360 goto L2; | |
1361 | |
1362 case Tint32: | |
1363 L2: | |
1364 buf->printf("%d", (int)v); | |
1365 break; | |
1366 | |
1367 case Tuns8: | |
1368 buf->writestring("cast(ubyte)"); | |
1369 goto L3; | |
1370 | |
1371 case Tuns16: | |
1372 buf->writestring("cast(ushort)"); | |
1373 goto L3; | |
1374 | |
1375 case Tuns32: | |
1376 L3: | |
1377 buf->printf("%du", (unsigned)v); | |
1378 break; | |
1379 | |
1380 case Tint64: | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1381 buf->printf("%lldL", v); |
159 | 1382 break; |
1383 | |
1384 case Tuns64: | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1385 buf->printf("%lluLU", v); |
159 | 1386 break; |
1387 | |
1388 case Tbit: | |
1389 case Tbool: | |
1390 buf->writestring((char *)(v ? "true" : "false")); | |
1391 break; | |
1392 | |
1393 case Tpointer: | |
1394 buf->writestring("cast("); | |
1395 buf->writestring(t->toChars()); | |
1396 buf->writeByte(')'); | |
1397 goto L3; | |
1398 | |
1399 default: | |
336 | 1400 /* This can happen if errors, such as |
1401 * the type is painted on like in fromConstInitializer(). | |
1402 */ | |
1403 if (!global.errors) | |
1404 { | |
159 | 1405 #ifdef DEBUG |
336 | 1406 t->print(); |
159 | 1407 #endif |
336 | 1408 assert(0); |
1409 } | |
1410 break; | |
159 | 1411 } |
1412 } | |
1413 else if (v & 0x8000000000000000LL) | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1414 buf->printf("0x%llx", v); |
159 | 1415 else |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1416 buf->printf("%lld", v); |
159 | 1417 } |
1418 | |
1419 void IntegerExp::toMangleBuffer(OutBuffer *buf) | |
1420 { | |
1421 if ((sinteger_t)value < 0) | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1422 buf->printf("N%lld", -value); |
159 | 1423 else |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1424 buf->printf("%lld", value); |
159 | 1425 } |
1426 | |
1427 /******************************** RealExp **************************/ | |
1428 | |
1429 RealExp::RealExp(Loc loc, real_t value, Type *type) | |
1430 : Expression(loc, TOKfloat64, sizeof(RealExp)) | |
1431 { | |
1432 //printf("RealExp::RealExp(%Lg)\n", value); | |
1433 this->value = value; | |
1434 this->type = type; | |
1435 } | |
1436 | |
1437 char *RealExp::toChars() | |
1438 { | |
1439 char buffer[sizeof(value) * 3 + 8 + 1 + 1]; | |
1440 | |
1441 #ifdef IN_GCC | |
1442 value.format(buffer, sizeof(buffer)); | |
1443 if (type->isimaginary()) | |
1444 strcat(buffer, "i"); | |
1445 #else | |
1446 sprintf(buffer, type->isimaginary() ? "%Lgi" : "%Lg", value); | |
1447 #endif | |
1448 assert(strlen(buffer) < sizeof(buffer)); | |
1449 return mem.strdup(buffer); | |
1450 } | |
1451 | |
1452 integer_t RealExp::toInteger() | |
1453 { | |
1454 #ifdef IN_GCC | |
1455 return toReal().toInt(); | |
1456 #else | |
1457 return (sinteger_t) toReal(); | |
1458 #endif | |
1459 } | |
1460 | |
1461 uinteger_t RealExp::toUInteger() | |
1462 { | |
1463 #ifdef IN_GCC | |
1464 return (uinteger_t) toReal().toInt(); | |
1465 #else | |
1466 return (uinteger_t) toReal(); | |
1467 #endif | |
1468 } | |
1469 | |
1470 real_t RealExp::toReal() | |
1471 { | |
1472 return type->isreal() ? value : 0; | |
1473 } | |
1474 | |
1475 real_t RealExp::toImaginary() | |
1476 { | |
1477 return type->isreal() ? 0 : value; | |
1478 } | |
1479 | |
1480 complex_t RealExp::toComplex() | |
1481 { | |
1482 #ifdef __DMC__ | |
1483 return toReal() + toImaginary() * I; | |
1484 #else | |
1485 return complex_t(toReal(), toImaginary()); | |
1486 #endif | |
1487 } | |
1488 | |
1489 /******************************** | |
1490 * Test to see if two reals are the same. | |
1491 * Regard NaN's as equivalent. | |
1492 * Regard +0 and -0 as different. | |
1493 */ | |
1494 | |
1495 int RealEquals(real_t x1, real_t x2) | |
1496 { | |
421
1c65b5477eaa
Fix real comparison for real: allow +0 to be distinguished from -0.
Christian Kamm <kamm incasoftware de>
parents:
420
diff
changeset
|
1497 return // special case nans |
1c65b5477eaa
Fix real comparison for real: allow +0 to be distinguished from -0.
Christian Kamm <kamm incasoftware de>
parents:
420
diff
changeset
|
1498 (isnan(x1) && isnan(x2)) || |
1c65b5477eaa
Fix real comparison for real: allow +0 to be distinguished from -0.
Christian Kamm <kamm incasoftware de>
parents:
420
diff
changeset
|
1499 // and zero, in order to distinguish +0 from -0 |
1c65b5477eaa
Fix real comparison for real: allow +0 to be distinguished from -0.
Christian Kamm <kamm incasoftware de>
parents:
420
diff
changeset
|
1500 (x1 == 0 && x2 == 0 && 1./x1 == 1./x2) || |
1c65b5477eaa
Fix real comparison for real: allow +0 to be distinguished from -0.
Christian Kamm <kamm incasoftware de>
parents:
420
diff
changeset
|
1501 // otherwise just compare |
1c65b5477eaa
Fix real comparison for real: allow +0 to be distinguished from -0.
Christian Kamm <kamm incasoftware de>
parents:
420
diff
changeset
|
1502 (x1 != 0. && x1 == x2); |
159 | 1503 } |
1504 | |
1505 int RealExp::equals(Object *o) | |
1506 { RealExp *ne; | |
1507 | |
1508 if (this == o || | |
1509 (((Expression *)o)->op == TOKfloat64 && | |
1510 ((ne = (RealExp *)o), type->equals(ne->type)) && | |
1511 RealEquals(value, ne->value) | |
1512 ) | |
1513 ) | |
1514 return 1; | |
1515 return 0; | |
1516 } | |
1517 | |
1518 Expression *RealExp::semantic(Scope *sc) | |
1519 { | |
1520 if (!type) | |
1521 type = Type::tfloat64; | |
1522 else | |
1523 type = type->semantic(loc, sc); | |
1524 return this; | |
1525 } | |
1526 | |
1527 int RealExp::isBool(int result) | |
1528 { | |
1529 #ifdef IN_GCC | |
1530 return result ? (! value.isZero()) : (value.isZero()); | |
1531 #else | |
1532 return result ? (value != 0) | |
1533 : (value == 0); | |
1534 #endif | |
1535 } | |
1536 | |
1537 void floatToBuffer(OutBuffer *buf, Type *type, real_t value) | |
1538 { | |
1539 /* In order to get an exact representation, try converting it | |
1540 * to decimal then back again. If it matches, use it. | |
1541 * If it doesn't, fall back to hex, which is | |
1542 * always exact. | |
1543 */ | |
1544 char buffer[25]; | |
1545 sprintf(buffer, "%Lg", value); | |
1546 assert(strlen(buffer) < sizeof(buffer)); | |
1547 #if _WIN32 && __DMC__ | |
1548 char *save = __locale_decpoint; | |
1549 __locale_decpoint = "."; | |
1550 real_t r = strtold(buffer, NULL); | |
1551 __locale_decpoint = save; | |
1552 #else | |
1553 real_t r = strtold(buffer, NULL); | |
1554 #endif | |
1555 if (r == value) // if exact duplication | |
1556 buf->writestring(buffer); | |
1557 else | |
1558 buf->printf("%La", value); // ensure exact duplication | |
1559 | |
1560 if (type) | |
1561 { | |
1562 Type *t = type->toBasetype(); | |
1563 switch (t->ty) | |
1564 { | |
1565 case Tfloat32: | |
1566 case Timaginary32: | |
1567 case Tcomplex32: | |
1568 buf->writeByte('F'); | |
1569 break; | |
1570 | |
1571 case Tfloat80: | |
1572 case Timaginary80: | |
1573 case Tcomplex80: | |
1574 buf->writeByte('L'); | |
1575 break; | |
1576 | |
1577 default: | |
1578 break; | |
1579 } | |
1580 if (t->isimaginary()) | |
1581 buf->writeByte('i'); | |
1582 } | |
1583 } | |
1584 | |
1585 void RealExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1586 { | |
1587 floatToBuffer(buf, type, value); | |
1588 } | |
1589 | |
1590 void realToMangleBuffer(OutBuffer *buf, real_t value) | |
1591 { | |
1592 /* Rely on %A to get portable mangling. | |
1593 * Must munge result to get only identifier characters. | |
1594 * | |
1595 * Possible values from %A => mangled result | |
1596 * NAN => NAN | |
1597 * -INF => NINF | |
1598 * INF => INF | |
1599 * -0X1.1BC18BA997B95P+79 => N11BC18BA997B95P79 | |
1600 * 0X1.9P+2 => 19P2 | |
1601 */ | |
1602 | |
1603 if (isnan(value)) | |
1604 buf->writestring("NAN"); // no -NAN bugs | |
1605 else | |
1606 { | |
1607 char buffer[32]; | |
1608 int n = sprintf(buffer, "%LA", value); | |
1609 assert(n > 0 && n < sizeof(buffer)); | |
1610 for (int i = 0; i < n; i++) | |
1611 { char c = buffer[i]; | |
1612 | |
1613 switch (c) | |
1614 { | |
1615 case '-': | |
1616 buf->writeByte('N'); | |
1617 break; | |
1618 | |
1619 case '+': | |
1620 case 'X': | |
1621 case '.': | |
1622 break; | |
1623 | |
1624 case '0': | |
1625 if (i < 2) | |
1626 break; // skip leading 0X | |
1627 default: | |
1628 buf->writeByte(c); | |
1629 break; | |
1630 } | |
1631 } | |
1632 } | |
1633 } | |
1634 | |
1635 void RealExp::toMangleBuffer(OutBuffer *buf) | |
1636 { | |
1637 buf->writeByte('e'); | |
1638 realToMangleBuffer(buf, value); | |
1639 } | |
1640 | |
1641 | |
1642 /******************************** ComplexExp **************************/ | |
1643 | |
1644 ComplexExp::ComplexExp(Loc loc, complex_t value, Type *type) | |
1645 : Expression(loc, TOKcomplex80, sizeof(ComplexExp)) | |
1646 { | |
1647 this->value = value; | |
1648 this->type = type; | |
1649 //printf("ComplexExp::ComplexExp(%s)\n", toChars()); | |
1650 } | |
1651 | |
1652 char *ComplexExp::toChars() | |
1653 { | |
1654 char buffer[sizeof(value) * 3 + 8 + 1]; | |
1655 | |
1656 #ifdef IN_GCC | |
1657 char buf1[sizeof(value) * 3 + 8 + 1]; | |
1658 char buf2[sizeof(value) * 3 + 8 + 1]; | |
1659 creall(value).format(buf1, sizeof(buf1)); | |
1660 cimagl(value).format(buf2, sizeof(buf2)); | |
1661 sprintf(buffer, "(%s+%si)", buf1, buf2); | |
1662 #else | |
1663 sprintf(buffer, "(%Lg+%Lgi)", creall(value), cimagl(value)); | |
1664 assert(strlen(buffer) < sizeof(buffer)); | |
1665 #endif | |
1666 return mem.strdup(buffer); | |
1667 } | |
1668 | |
1669 integer_t ComplexExp::toInteger() | |
1670 { | |
1671 #ifdef IN_GCC | |
1672 return (sinteger_t) toReal().toInt(); | |
1673 #else | |
1674 return (sinteger_t) toReal(); | |
1675 #endif | |
1676 } | |
1677 | |
1678 uinteger_t ComplexExp::toUInteger() | |
1679 { | |
1680 #ifdef IN_GCC | |
1681 return (uinteger_t) toReal().toInt(); | |
1682 #else | |
1683 return (uinteger_t) toReal(); | |
1684 #endif | |
1685 } | |
1686 | |
1687 real_t ComplexExp::toReal() | |
1688 { | |
1689 return creall(value); | |
1690 } | |
1691 | |
1692 real_t ComplexExp::toImaginary() | |
1693 { | |
1694 return cimagl(value); | |
1695 } | |
1696 | |
1697 complex_t ComplexExp::toComplex() | |
1698 { | |
1699 return value; | |
1700 } | |
1701 | |
1702 int ComplexExp::equals(Object *o) | |
1703 { ComplexExp *ne; | |
1704 | |
1705 if (this == o || | |
1706 (((Expression *)o)->op == TOKcomplex80 && | |
1707 ((ne = (ComplexExp *)o), type->equals(ne->type)) && | |
1708 RealEquals(creall(value), creall(ne->value)) && | |
1709 RealEquals(cimagl(value), cimagl(ne->value)) | |
1710 ) | |
1711 ) | |
1712 return 1; | |
1713 return 0; | |
1714 } | |
1715 | |
1716 Expression *ComplexExp::semantic(Scope *sc) | |
1717 { | |
1718 if (!type) | |
1719 type = Type::tcomplex80; | |
1720 else | |
1721 type = type->semantic(loc, sc); | |
1722 return this; | |
1723 } | |
1724 | |
1725 int ComplexExp::isBool(int result) | |
1726 { | |
1727 if (result) | |
1728 return (bool)(value); | |
1729 else | |
1730 return !value; | |
1731 } | |
1732 | |
1733 void ComplexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1734 { | |
1735 /* Print as: | |
1736 * (re+imi) | |
1737 */ | |
1738 #ifdef IN_GCC | |
1739 char buf1[sizeof(value) * 3 + 8 + 1]; | |
1740 char buf2[sizeof(value) * 3 + 8 + 1]; | |
1741 creall(value).format(buf1, sizeof(buf1)); | |
1742 cimagl(value).format(buf2, sizeof(buf2)); | |
1743 buf->printf("(%s+%si)", buf1, buf2); | |
1744 #else | |
1745 buf->writeByte('('); | |
1746 floatToBuffer(buf, type, creall(value)); | |
1747 buf->writeByte('+'); | |
1748 floatToBuffer(buf, type, cimagl(value)); | |
1749 buf->writestring("i)"); | |
1750 #endif | |
1751 } | |
1752 | |
1753 void ComplexExp::toMangleBuffer(OutBuffer *buf) | |
1754 { | |
1755 buf->writeByte('c'); | |
1756 real_t r = toReal(); | |
1757 realToMangleBuffer(buf, r); | |
1758 buf->writeByte('c'); // separate the two | |
1759 r = toImaginary(); | |
1760 realToMangleBuffer(buf, r); | |
1761 } | |
1762 | |
1763 /******************************** IdentifierExp **************************/ | |
1764 | |
1765 IdentifierExp::IdentifierExp(Loc loc, Identifier *ident) | |
1766 : Expression(loc, TOKidentifier, sizeof(IdentifierExp)) | |
1767 { | |
1768 this->ident = ident; | |
1769 } | |
1770 | |
1771 Expression *IdentifierExp::semantic(Scope *sc) | |
1772 { | |
1773 Dsymbol *s; | |
1774 Dsymbol *scopesym; | |
1775 | |
1776 #if LOGSEMANTIC | |
1777 printf("IdentifierExp::semantic('%s')\n", ident->toChars()); | |
1778 #endif | |
1779 s = sc->search(loc, ident, &scopesym); | |
1780 if (s) | |
1781 { Expression *e; | |
1782 WithScopeSymbol *withsym; | |
1783 | |
1784 // See if it was a with class | |
1785 withsym = scopesym->isWithScopeSymbol(); | |
1786 if (withsym) | |
1787 { | |
1788 s = s->toAlias(); | |
1789 | |
1790 // Same as wthis.ident | |
1791 if (s->needThis() || s->isTemplateDeclaration()) | |
1792 { | |
1793 e = new VarExp(loc, withsym->withstate->wthis); | |
1794 e = new DotIdExp(loc, e, ident); | |
1795 } | |
1796 else | |
1797 { Type *t = withsym->withstate->wthis->type; | |
1798 if (t->ty == Tpointer) | |
1799 t = t->next; | |
1800 e = new TypeDotIdExp(loc, t, ident); | |
1801 } | |
1802 } | |
1803 else | |
1804 { | |
1805 if (!s->parent && scopesym->isArrayScopeSymbol()) | |
1806 { // Kludge to run semantic() here because | |
1807 // ArrayScopeSymbol::search() doesn't have access to sc. | |
1808 s->semantic(sc); | |
1809 } | |
1810 // Look to see if f is really a function template | |
1811 FuncDeclaration *f = s->isFuncDeclaration(); | |
1812 if (f && f->parent) | |
1813 { TemplateInstance *ti = f->parent->isTemplateInstance(); | |
1814 | |
1815 if (ti && | |
1816 !ti->isTemplateMixin() && | |
1817 (ti->name == f->ident || | |
1818 ti->toAlias()->ident == f->ident) | |
1819 && | |
1820 ti->tempdecl && ti->tempdecl->onemember) | |
1821 { | |
1822 TemplateDeclaration *tempdecl = ti->tempdecl; | |
1823 if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's | |
1824 tempdecl = tempdecl->overroot; // then get the start | |
1825 e = new TemplateExp(loc, tempdecl); | |
1826 e = e->semantic(sc); | |
1827 return e; | |
1828 } | |
1829 } | |
1830 e = new DsymbolExp(loc, s); | |
1831 } | |
1832 return e->semantic(sc); | |
1833 } | |
1834 error("undefined identifier %s", ident->toChars()); | |
1835 type = Type::terror; | |
1836 return this; | |
1837 } | |
1838 | |
1839 char *IdentifierExp::toChars() | |
1840 { | |
1841 return ident->toChars(); | |
1842 } | |
1843 | |
1844 void IdentifierExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1845 { | |
1846 if (hgs->hdrgen) | |
1847 buf->writestring(ident->toHChars2()); | |
1848 else | |
1849 buf->writestring(ident->toChars()); | |
1850 } | |
1851 | |
1852 Expression *IdentifierExp::toLvalue(Scope *sc, Expression *e) | |
1853 { | |
1854 #if 0 | |
1855 tym = tybasic(e1->ET->Tty); | |
1856 if (!(tyscalar(tym) || | |
1857 tym == TYstruct || | |
1858 tym == TYarray && e->Eoper == TOKaddr)) | |
1859 synerr(EM_lvalue); // lvalue expected | |
1860 #endif | |
1861 return this; | |
1862 } | |
1863 | |
1864 /******************************** DollarExp **************************/ | |
1865 | |
1866 DollarExp::DollarExp(Loc loc) | |
1867 : IdentifierExp(loc, Id::dollar) | |
1868 { | |
1869 } | |
1870 | |
1871 /******************************** DsymbolExp **************************/ | |
1872 | |
1873 DsymbolExp::DsymbolExp(Loc loc, Dsymbol *s) | |
1874 : Expression(loc, TOKdsymbol, sizeof(DsymbolExp)) | |
1875 { | |
1876 this->s = s; | |
1877 } | |
1878 | |
1879 Expression *DsymbolExp::semantic(Scope *sc) | |
1880 { | |
1881 #if LOGSEMANTIC | |
1882 printf("DsymbolExp::semantic('%s')\n", s->toChars()); | |
1883 #endif | |
1884 | |
1885 Lagain: | |
1886 EnumMember *em; | |
1887 Expression *e; | |
1888 VarDeclaration *v; | |
1889 FuncDeclaration *f; | |
1890 FuncLiteralDeclaration *fld; | |
1891 Declaration *d; | |
1892 ClassDeclaration *cd; | |
1893 ClassDeclaration *thiscd = NULL; | |
1894 Import *imp; | |
1895 Package *pkg; | |
1896 Type *t; | |
1897 | |
1898 //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars()); | |
1899 //printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind()); | |
1900 if (type) | |
1901 return this; | |
1902 if (!s->isFuncDeclaration()) // functions are checked after overloading | |
1903 checkDeprecated(sc, s); | |
1904 s = s->toAlias(); | |
1905 //printf("s = '%s', s->kind = '%s', s->needThis() = %p\n", s->toChars(), s->kind(), s->needThis()); | |
1906 if (!s->isFuncDeclaration()) | |
1907 checkDeprecated(sc, s); | |
1908 | |
1909 if (sc->func) | |
1910 thiscd = sc->func->parent->isClassDeclaration(); | |
1911 | |
1912 // BUG: This should happen after overload resolution for functions, not before | |
1913 if (s->needThis()) | |
1914 { | |
1915 if (hasThis(sc) /*&& !s->isFuncDeclaration()*/) | |
1916 { | |
1917 // Supply an implicit 'this', as in | |
1918 // this.ident | |
1919 | |
1920 DotVarExp *de; | |
1921 | |
1922 de = new DotVarExp(loc, new ThisExp(loc), s->isDeclaration()); | |
1923 return de->semantic(sc); | |
1924 } | |
1925 } | |
1926 | |
1927 em = s->isEnumMember(); | |
1928 if (em) | |
1929 { | |
1930 e = em->value->copy(); | |
1931 e = e->semantic(sc); | |
1932 return e; | |
1933 } | |
1934 v = s->isVarDeclaration(); | |
1935 if (v) | |
1936 { | |
1937 //printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars()); | |
1938 if (!type) | |
1939 { type = v->type; | |
1940 if (!v->type) | |
1941 { error("forward reference of %s", v->toChars()); | |
1942 type = Type::terror; | |
1943 } | |
1944 } | |
1945 if (v->isConst() && type->toBasetype()->ty != Tsarray) | |
1946 { | |
1947 if (v->init) | |
1948 { | |
1949 if (v->inuse) | |
1950 { | |
1951 error("circular reference to '%s'", v->toChars()); | |
1952 type = Type::tint32; | |
1953 return this; | |
1954 } | |
1955 ExpInitializer *ei = v->init->isExpInitializer(); | |
1956 if (ei) | |
1957 { | |
1958 e = ei->exp->copy(); // make copy so we can change loc | |
1959 if (e->op == TOKstring || !e->type) | |
1960 e = e->semantic(sc); | |
1961 e = e->implicitCastTo(sc, type); | |
1962 e->loc = loc; | |
1963 return e; | |
1964 } | |
1965 } | |
1966 else | |
1967 { | |
1968 e = type->defaultInit(); | |
1969 e->loc = loc; | |
1970 return e; | |
1971 } | |
1972 } | |
1973 e = new VarExp(loc, v); | |
1974 e->type = type; | |
1975 e = e->semantic(sc); | |
1976 return e->deref(); | |
1977 } | |
1978 fld = s->isFuncLiteralDeclaration(); | |
1979 if (fld) | |
1980 { //printf("'%s' is a function literal\n", fld->toChars()); | |
1981 e = new FuncExp(loc, fld); | |
1982 return e->semantic(sc); | |
1983 } | |
1984 f = s->isFuncDeclaration(); | |
1985 if (f) | |
1986 { //printf("'%s' is a function\n", f->toChars()); | |
1987 return new VarExp(loc, f); | |
1988 } | |
1989 cd = s->isClassDeclaration(); | |
1990 if (cd && thiscd && cd->isBaseOf(thiscd, NULL) && sc->func->needThis()) | |
1991 { | |
1992 // We need to add an implicit 'this' if cd is this class or a base class. | |
1993 DotTypeExp *dte; | |
1994 | |
1995 dte = new DotTypeExp(loc, new ThisExp(loc), s); | |
1996 return dte->semantic(sc); | |
1997 } | |
1998 imp = s->isImport(); | |
1999 if (imp) | |
2000 { | |
2001 ScopeExp *ie; | |
2002 | |
2003 ie = new ScopeExp(loc, imp->pkg); | |
2004 return ie->semantic(sc); | |
2005 } | |
2006 pkg = s->isPackage(); | |
2007 if (pkg) | |
2008 { | |
2009 ScopeExp *ie; | |
2010 | |
2011 ie = new ScopeExp(loc, pkg); | |
2012 return ie->semantic(sc); | |
2013 } | |
2014 Module *mod = s->isModule(); | |
2015 if (mod) | |
2016 { | |
2017 ScopeExp *ie; | |
2018 | |
2019 ie = new ScopeExp(loc, mod); | |
2020 return ie->semantic(sc); | |
2021 } | |
2022 | |
2023 t = s->getType(); | |
2024 if (t) | |
2025 { | |
2026 return new TypeExp(loc, t); | |
2027 } | |
2028 | |
2029 TupleDeclaration *tup = s->isTupleDeclaration(); | |
2030 if (tup) | |
2031 { | |
2032 e = new TupleExp(loc, tup); | |
2033 e = e->semantic(sc); | |
2034 return e; | |
2035 } | |
2036 | |
2037 TemplateInstance *ti = s->isTemplateInstance(); | |
2038 if (ti && !global.errors) | |
2039 { if (!ti->semanticdone) | |
2040 ti->semantic(sc); | |
2041 s = ti->inst->toAlias(); | |
2042 if (!s->isTemplateInstance()) | |
2043 goto Lagain; | |
2044 e = new ScopeExp(loc, ti); | |
2045 e = e->semantic(sc); | |
2046 return e; | |
2047 } | |
2048 | |
2049 TemplateDeclaration *td = s->isTemplateDeclaration(); | |
2050 if (td) | |
2051 { | |
2052 e = new TemplateExp(loc, td); | |
2053 e = e->semantic(sc); | |
2054 return e; | |
2055 } | |
2056 | |
2057 Lerr: | |
2058 error("%s '%s' is not a variable", s->kind(), s->toChars()); | |
2059 type = Type::terror; | |
2060 return this; | |
2061 } | |
2062 | |
2063 char *DsymbolExp::toChars() | |
2064 { | |
2065 return s->toChars(); | |
2066 } | |
2067 | |
2068 void DsymbolExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2069 { | |
2070 buf->writestring(s->toChars()); | |
2071 } | |
2072 | |
2073 Expression *DsymbolExp::toLvalue(Scope *sc, Expression *e) | |
2074 { | |
2075 #if 0 | |
2076 tym = tybasic(e1->ET->Tty); | |
2077 if (!(tyscalar(tym) || | |
2078 tym == TYstruct || | |
2079 tym == TYarray && e->Eoper == TOKaddr)) | |
2080 synerr(EM_lvalue); // lvalue expected | |
2081 #endif | |
2082 return this; | |
2083 } | |
2084 | |
2085 /******************************** ThisExp **************************/ | |
2086 | |
2087 ThisExp::ThisExp(Loc loc) | |
2088 : Expression(loc, TOKthis, sizeof(ThisExp)) | |
2089 { | |
2090 var = NULL; | |
2091 } | |
2092 | |
2093 Expression *ThisExp::semantic(Scope *sc) | |
2094 { FuncDeclaration *fd; | |
2095 FuncDeclaration *fdthis; | |
2096 int nested = 0; | |
2097 | |
2098 #if LOGSEMANTIC | |
2099 printf("ThisExp::semantic()\n"); | |
2100 #endif | |
2101 if (type) | |
2102 { //assert(global.errors || var); | |
2103 return this; | |
2104 } | |
2105 | |
2106 /* Special case for typeof(this) and typeof(super) since both | |
2107 * should work even if they are not inside a non-static member function | |
2108 */ | |
2109 if (sc->intypeof) | |
2110 { | |
2111 // Find enclosing struct or class | |
2112 for (Dsymbol *s = sc->parent; 1; s = s->parent) | |
2113 { | |
2114 ClassDeclaration *cd; | |
2115 StructDeclaration *sd; | |
2116 | |
2117 if (!s) | |
2118 { | |
2119 error("%s is not in a struct or class scope", toChars()); | |
2120 goto Lerr; | |
2121 } | |
2122 cd = s->isClassDeclaration(); | |
2123 if (cd) | |
2124 { | |
2125 type = cd->type; | |
2126 return this; | |
2127 } | |
2128 sd = s->isStructDeclaration(); | |
2129 if (sd) | |
2130 { | |
2131 type = sd->type->pointerTo(); | |
2132 return this; | |
2133 } | |
2134 } | |
2135 } | |
2136 | |
2137 fdthis = sc->parent->isFuncDeclaration(); | |
2138 fd = hasThis(sc); // fd is the uplevel function with the 'this' variable | |
2139 if (!fd) | |
2140 goto Lerr; | |
2141 | |
2142 assert(fd->vthis); | |
2143 var = fd->vthis; | |
2144 assert(var->parent); | |
2145 type = var->type; | |
2146 var->isVarDeclaration()->checkNestedReference(sc, loc); | |
2147 #if 0 | |
2148 if (fd != fdthis) // if nested | |
2149 { | |
2150 fdthis->getLevel(loc, fd); | |
2151 fd->vthis->nestedref = 1; | |
2152 fd->nestedFrameRef = 1; | |
2153 } | |
2154 #endif | |
336 | 2155 if (!sc->intypeof) |
2156 sc->callSuper |= CSXthis; | |
159 | 2157 return this; |
2158 | |
2159 Lerr: | |
2160 error("'this' is only allowed in non-static member functions, not %s", sc->parent->toChars()); | |
2161 type = Type::tint32; | |
2162 return this; | |
2163 } | |
2164 | |
2165 int ThisExp::isBool(int result) | |
2166 { | |
2167 return result ? TRUE : FALSE; | |
2168 } | |
2169 | |
2170 void ThisExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2171 { | |
2172 buf->writestring("this"); | |
2173 } | |
2174 | |
2175 Expression *ThisExp::toLvalue(Scope *sc, Expression *e) | |
2176 { | |
2177 return this; | |
2178 } | |
2179 | |
2180 /******************************** SuperExp **************************/ | |
2181 | |
2182 SuperExp::SuperExp(Loc loc) | |
2183 : ThisExp(loc) | |
2184 { | |
2185 op = TOKsuper; | |
2186 } | |
2187 | |
2188 Expression *SuperExp::semantic(Scope *sc) | |
2189 { FuncDeclaration *fd; | |
2190 FuncDeclaration *fdthis; | |
2191 ClassDeclaration *cd; | |
2192 Dsymbol *s; | |
2193 | |
2194 #if LOGSEMANTIC | |
2195 printf("SuperExp::semantic('%s')\n", toChars()); | |
2196 #endif | |
2197 if (type) | |
2198 return this; | |
2199 | |
2200 /* Special case for typeof(this) and typeof(super) since both | |
2201 * should work even if they are not inside a non-static member function | |
2202 */ | |
2203 if (sc->intypeof) | |
2204 { | |
2205 // Find enclosing class | |
2206 for (Dsymbol *s = sc->parent; 1; s = s->parent) | |
2207 { | |
2208 ClassDeclaration *cd; | |
2209 | |
2210 if (!s) | |
2211 { | |
2212 error("%s is not in a class scope", toChars()); | |
2213 goto Lerr; | |
2214 } | |
2215 cd = s->isClassDeclaration(); | |
2216 if (cd) | |
2217 { | |
2218 cd = cd->baseClass; | |
2219 if (!cd) | |
2220 { error("class %s has no 'super'", s->toChars()); | |
2221 goto Lerr; | |
2222 } | |
2223 type = cd->type; | |
2224 return this; | |
2225 } | |
2226 } | |
2227 } | |
2228 | |
2229 fdthis = sc->parent->isFuncDeclaration(); | |
2230 fd = hasThis(sc); | |
2231 if (!fd) | |
2232 goto Lerr; | |
2233 assert(fd->vthis); | |
2234 var = fd->vthis; | |
2235 assert(var->parent); | |
2236 | |
2237 s = fd->toParent(); | |
2238 while (s && s->isTemplateInstance()) | |
2239 s = s->toParent(); | |
2240 assert(s); | |
2241 cd = s->isClassDeclaration(); | |
2242 //printf("parent is %s %s\n", fd->toParent()->kind(), fd->toParent()->toChars()); | |
2243 if (!cd) | |
2244 goto Lerr; | |
2245 if (!cd->baseClass) | |
2246 { | |
2247 error("no base class for %s", cd->toChars()); | |
2248 type = fd->vthis->type; | |
2249 } | |
2250 else | |
2251 { | |
2252 type = cd->baseClass->type; | |
2253 } | |
2254 | |
2255 var->isVarDeclaration()->checkNestedReference(sc, loc); | |
2256 #if 0 | |
2257 if (fd != fdthis) | |
2258 { | |
2259 fdthis->getLevel(loc, fd); | |
2260 fd->vthis->nestedref = 1; | |
2261 fd->nestedFrameRef = 1; | |
2262 } | |
2263 #endif | |
2264 | |
336 | 2265 if (!sc->intypeof) |
2266 sc->callSuper |= CSXsuper; | |
159 | 2267 return this; |
2268 | |
2269 | |
2270 Lerr: | |
2271 error("'super' is only allowed in non-static class member functions"); | |
2272 type = Type::tint32; | |
2273 return this; | |
2274 } | |
2275 | |
2276 void SuperExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2277 { | |
2278 buf->writestring("super"); | |
2279 } | |
2280 | |
2281 | |
2282 /******************************** NullExp **************************/ | |
2283 | |
2284 NullExp::NullExp(Loc loc) | |
2285 : Expression(loc, TOKnull, sizeof(NullExp)) | |
2286 { | |
2287 committed = 0; | |
2288 } | |
2289 | |
2290 Expression *NullExp::semantic(Scope *sc) | |
2291 { | |
2292 #if LOGSEMANTIC | |
2293 printf("NullExp::semantic('%s')\n", toChars()); | |
2294 #endif | |
2295 // NULL is the same as (void *)0 | |
2296 if (!type) | |
2297 type = Type::tvoid->pointerTo(); | |
2298 return this; | |
2299 } | |
2300 | |
2301 int NullExp::isBool(int result) | |
2302 { | |
2303 return result ? FALSE : TRUE; | |
2304 } | |
2305 | |
2306 void NullExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2307 { | |
2308 buf->writestring("null"); | |
2309 } | |
2310 | |
2311 void NullExp::toMangleBuffer(OutBuffer *buf) | |
2312 { | |
2313 buf->writeByte('n'); | |
2314 } | |
2315 | |
2316 /******************************** StringExp **************************/ | |
2317 | |
2318 StringExp::StringExp(Loc loc, char *string) | |
2319 : Expression(loc, TOKstring, sizeof(StringExp)) | |
2320 { | |
2321 this->string = string; | |
2322 this->len = strlen(string); | |
2323 this->sz = 1; | |
2324 this->committed = 0; | |
2325 this->postfix = 0; | |
2326 } | |
2327 | |
2328 StringExp::StringExp(Loc loc, void *string, size_t len) | |
2329 : Expression(loc, TOKstring, sizeof(StringExp)) | |
2330 { | |
2331 this->string = string; | |
2332 this->len = len; | |
2333 this->sz = 1; | |
2334 this->committed = 0; | |
2335 this->postfix = 0; | |
2336 } | |
2337 | |
2338 StringExp::StringExp(Loc loc, void *string, size_t len, unsigned char postfix) | |
2339 : Expression(loc, TOKstring, sizeof(StringExp)) | |
2340 { | |
2341 this->string = string; | |
2342 this->len = len; | |
2343 this->sz = 1; | |
2344 this->committed = 0; | |
2345 this->postfix = postfix; | |
2346 } | |
2347 | |
2348 #if 0 | |
2349 Expression *StringExp::syntaxCopy() | |
2350 { | |
2351 printf("StringExp::syntaxCopy() %s\n", toChars()); | |
2352 return copy(); | |
2353 } | |
2354 #endif | |
2355 | |
2356 int StringExp::equals(Object *o) | |
2357 { | |
2358 //printf("StringExp::equals('%s')\n", o->toChars()); | |
2359 if (o && o->dyncast() == DYNCAST_EXPRESSION) | |
2360 { Expression *e = (Expression *)o; | |
2361 | |
2362 if (e->op == TOKstring) | |
2363 { | |
2364 return compare(o) == 0; | |
2365 } | |
2366 } | |
2367 return FALSE; | |
2368 } | |
2369 | |
2370 char *StringExp::toChars() | |
2371 { | |
2372 OutBuffer buf; | |
2373 HdrGenState hgs; | |
2374 char *p; | |
2375 | |
2376 memset(&hgs, 0, sizeof(hgs)); | |
2377 toCBuffer(&buf, &hgs); | |
2378 buf.writeByte(0); | |
2379 p = (char *)buf.data; | |
2380 buf.data = NULL; | |
2381 return p; | |
2382 } | |
2383 | |
2384 Expression *StringExp::semantic(Scope *sc) | |
2385 { | |
2386 #if LOGSEMANTIC | |
2387 printf("StringExp::semantic() %s\n", toChars()); | |
2388 #endif | |
2389 if (!type) | |
2390 { OutBuffer buffer; | |
2391 size_t newlen = 0; | |
2392 char *p; | |
2393 size_t u; | |
2394 unsigned c; | |
2395 | |
2396 switch (postfix) | |
2397 { | |
2398 case 'd': | |
2399 for (u = 0; u < len;) | |
2400 { | |
2401 p = utf_decodeChar((unsigned char *)string, len, &u, &c); | |
2402 if (p) | |
2403 { error("%s", p); | |
2404 break; | |
2405 } | |
2406 else | |
2407 { buffer.write4(c); | |
2408 newlen++; | |
2409 } | |
2410 } | |
2411 buffer.write4(0); | |
2412 string = buffer.extractData(); | |
2413 len = newlen; | |
2414 sz = 4; | |
2415 type = new TypeSArray(Type::tdchar, new IntegerExp(loc, len, Type::tindex)); | |
2416 committed = 1; | |
2417 break; | |
2418 | |
2419 case 'w': | |
2420 for (u = 0; u < len;) | |
2421 { | |
2422 p = utf_decodeChar((unsigned char *)string, len, &u, &c); | |
2423 if (p) | |
2424 { error("%s", p); | |
2425 break; | |
2426 } | |
2427 else | |
2428 { buffer.writeUTF16(c); | |
2429 newlen++; | |
2430 if (c >= 0x10000) | |
2431 newlen++; | |
2432 } | |
2433 } | |
2434 buffer.writeUTF16(0); | |
2435 string = buffer.extractData(); | |
2436 len = newlen; | |
2437 sz = 2; | |
2438 type = new TypeSArray(Type::twchar, new IntegerExp(loc, len, Type::tindex)); | |
2439 committed = 1; | |
2440 break; | |
2441 | |
2442 case 'c': | |
2443 committed = 1; | |
2444 default: | |
2445 type = new TypeSArray(Type::tchar, new IntegerExp(loc, len, Type::tindex)); | |
2446 break; | |
2447 } | |
2448 type = type->semantic(loc, sc); | |
2449 } | |
2450 return this; | |
2451 } | |
2452 | |
2453 /**************************************** | |
2454 * Convert string to char[]. | |
2455 */ | |
2456 | |
2457 StringExp *StringExp::toUTF8(Scope *sc) | |
2458 { | |
2459 if (sz != 1) | |
2460 { // Convert to UTF-8 string | |
2461 committed = 0; | |
2462 Expression *e = castTo(sc, Type::tchar->arrayOf()); | |
2463 e = e->optimize(WANTvalue); | |
2464 assert(e->op == TOKstring); | |
2465 StringExp *se = (StringExp *)e; | |
2466 assert(se->sz == 1); | |
2467 return se; | |
2468 } | |
2469 return this; | |
2470 } | |
2471 | |
2472 int StringExp::compare(Object *obj) | |
2473 { | |
2474 // Used to sort case statement expressions so we can do an efficient lookup | |
2475 StringExp *se2 = (StringExp *)(obj); | |
2476 | |
2477 // This is a kludge so isExpression() in template.c will return 5 | |
2478 // for StringExp's. | |
2479 if (!se2) | |
2480 return 5; | |
2481 | |
2482 assert(se2->op == TOKstring); | |
2483 | |
2484 int len1 = len; | |
2485 int len2 = se2->len; | |
2486 | |
2487 if (len1 == len2) | |
2488 { | |
2489 switch (sz) | |
2490 { | |
2491 case 1: | |
2492 return strcmp((char *)string, (char *)se2->string); | |
2493 | |
2494 case 2: | |
2495 { unsigned u; | |
2496 d_wchar *s1 = (d_wchar *)string; | |
2497 d_wchar *s2 = (d_wchar *)se2->string; | |
2498 | |
2499 for (u = 0; u < len; u++) | |
2500 { | |
2501 if (s1[u] != s2[u]) | |
2502 return s1[u] - s2[u]; | |
2503 } | |
2504 } | |
2505 | |
2506 case 4: | |
2507 { unsigned u; | |
2508 d_dchar *s1 = (d_dchar *)string; | |
2509 d_dchar *s2 = (d_dchar *)se2->string; | |
2510 | |
2511 for (u = 0; u < len; u++) | |
2512 { | |
2513 if (s1[u] != s2[u]) | |
2514 return s1[u] - s2[u]; | |
2515 } | |
2516 } | |
2517 break; | |
2518 | |
2519 default: | |
2520 assert(0); | |
2521 } | |
2522 } | |
2523 return len1 - len2; | |
2524 } | |
2525 | |
2526 int StringExp::isBool(int result) | |
2527 { | |
2528 return result ? TRUE : FALSE; | |
2529 } | |
2530 | |
2531 unsigned StringExp::charAt(size_t i) | |
2532 { unsigned value; | |
2533 | |
2534 switch (sz) | |
2535 { | |
2536 case 1: | |
2537 value = ((unsigned char *)string)[i]; | |
2538 break; | |
2539 | |
2540 case 2: | |
2541 value = ((unsigned short *)string)[i]; | |
2542 break; | |
2543 | |
2544 case 4: | |
2545 value = ((unsigned int *)string)[i]; | |
2546 break; | |
2547 | |
2548 default: | |
2549 assert(0); | |
2550 break; | |
2551 } | |
2552 return value; | |
2553 } | |
2554 | |
2555 void StringExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2556 { | |
2557 buf->writeByte('"'); | |
2558 for (size_t i = 0; i < len; i++) | |
2559 { unsigned c = charAt(i); | |
2560 | |
2561 switch (c) | |
2562 { | |
2563 case '"': | |
2564 case '\\': | |
2565 if (!hgs->console) | |
2566 buf->writeByte('\\'); | |
2567 default: | |
2568 if (c <= 0xFF) | |
2569 { if (c <= 0x7F && (isprint(c) || hgs->console)) | |
2570 buf->writeByte(c); | |
2571 else | |
2572 buf->printf("\\x%02x", c); | |
2573 } | |
2574 else if (c <= 0xFFFF) | |
2575 buf->printf("\\x%02x\\x%02x", c & 0xFF, c >> 8); | |
2576 else | |
2577 buf->printf("\\x%02x\\x%02x\\x%02x\\x%02x", | |
2578 c & 0xFF, (c >> 8) & 0xFF, (c >> 16) & 0xFF, c >> 24); | |
2579 break; | |
2580 } | |
2581 } | |
2582 buf->writeByte('"'); | |
2583 if (postfix) | |
2584 buf->writeByte(postfix); | |
2585 } | |
2586 | |
2587 void StringExp::toMangleBuffer(OutBuffer *buf) | |
2588 { char m; | |
2589 OutBuffer tmp; | |
2590 char *p; | |
2591 unsigned c; | |
2592 size_t u; | |
2593 unsigned char *q; | |
2594 unsigned qlen; | |
2595 | |
2596 /* Write string in UTF-8 format | |
2597 */ | |
2598 switch (sz) | |
2599 { case 1: | |
2600 m = 'a'; | |
2601 q = (unsigned char *)string; | |
2602 qlen = len; | |
2603 break; | |
2604 case 2: | |
2605 m = 'w'; | |
2606 for (u = 0; u < len; ) | |
2607 { | |
2608 p = utf_decodeWchar((unsigned short *)string, len, &u, &c); | |
2609 if (p) | |
2610 error("%s", p); | |
2611 else | |
2612 tmp.writeUTF8(c); | |
2613 } | |
2614 q = tmp.data; | |
2615 qlen = tmp.offset; | |
2616 break; | |
2617 case 4: | |
2618 m = 'd'; | |
2619 for (u = 0; u < len; u++) | |
2620 { | |
2621 c = ((unsigned *)string)[u]; | |
2622 if (!utf_isValidDchar(c)) | |
2623 error("invalid UCS-32 char \\U%08x", c); | |
2624 else | |
2625 tmp.writeUTF8(c); | |
2626 } | |
2627 q = tmp.data; | |
2628 qlen = tmp.offset; | |
2629 break; | |
2630 default: | |
2631 assert(0); | |
2632 } | |
2633 buf->writeByte(m); | |
2634 buf->printf("%d_", qlen); | |
2635 for (size_t i = 0; i < qlen; i++) | |
2636 buf->printf("%02x", q[i]); | |
2637 } | |
2638 | |
2639 /************************ ArrayLiteralExp ************************************/ | |
2640 | |
2641 // [ e1, e2, e3, ... ] | |
2642 | |
2643 ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expressions *elements) | |
2644 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp)) | |
2645 { | |
2646 this->elements = elements; | |
2647 } | |
2648 | |
2649 ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expression *e) | |
2650 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp)) | |
2651 { | |
2652 elements = new Expressions; | |
2653 elements->push(e); | |
2654 } | |
2655 | |
2656 Expression *ArrayLiteralExp::syntaxCopy() | |
2657 { | |
2658 return new ArrayLiteralExp(loc, arraySyntaxCopy(elements)); | |
2659 } | |
2660 | |
2661 Expression *ArrayLiteralExp::semantic(Scope *sc) | |
2662 { Expression *e; | |
2663 Type *t0 = NULL; | |
2664 | |
2665 #if LOGSEMANTIC | |
2666 printf("ArrayLiteralExp::semantic('%s')\n", toChars()); | |
2667 #endif | |
2668 if (type) | |
2669 return this; | |
2670 | |
2671 // Run semantic() on each element | |
2672 for (int i = 0; i < elements->dim; i++) | |
2673 { e = (Expression *)elements->data[i]; | |
2674 e = e->semantic(sc); | |
2675 elements->data[i] = (void *)e; | |
2676 } | |
2677 expandTuples(elements); | |
2678 for (int i = 0; i < elements->dim; i++) | |
2679 { e = (Expression *)elements->data[i]; | |
2680 | |
2681 if (!e->type) | |
2682 error("%s has no value", e->toChars()); | |
2683 e = resolveProperties(sc, e); | |
2684 | |
2685 unsigned char committed = 1; | |
2686 if (e->op == TOKstring) | |
2687 committed = ((StringExp *)e)->committed; | |
2688 | |
2689 if (!t0) | |
2690 { t0 = e->type; | |
2691 // Convert any static arrays to dynamic arrays | |
2692 if (t0->ty == Tsarray) | |
2693 { | |
2694 t0 = t0->next->arrayOf(); | |
2695 e = e->implicitCastTo(sc, t0); | |
2696 } | |
2697 } | |
2698 else | |
2699 e = e->implicitCastTo(sc, t0); | |
2700 if (!committed && e->op == TOKstring) | |
2701 { StringExp *se = (StringExp *)e; | |
2702 se->committed = 0; | |
2703 } | |
2704 elements->data[i] = (void *)e; | |
2705 } | |
2706 | |
2707 if (!t0) | |
2708 t0 = Type::tvoid; | |
2709 type = new TypeSArray(t0, new IntegerExp(elements->dim)); | |
2710 type = type->semantic(loc, sc); | |
2711 return this; | |
2712 } | |
2713 | |
2714 int ArrayLiteralExp::checkSideEffect(int flag) | |
2715 { int f = 0; | |
2716 | |
2717 for (size_t i = 0; i < elements->dim; i++) | |
2718 { Expression *e = (Expression *)elements->data[i]; | |
2719 | |
2720 f |= e->checkSideEffect(2); | |
2721 } | |
2722 if (flag == 0 && f == 0) | |
2723 Expression::checkSideEffect(0); | |
2724 return f; | |
2725 } | |
2726 | |
2727 int ArrayLiteralExp::isBool(int result) | |
2728 { | |
2729 size_t dim = elements ? elements->dim : 0; | |
2730 return result ? (dim != 0) : (dim == 0); | |
2731 } | |
2732 | |
2733 void ArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2734 { | |
2735 buf->writeByte('['); | |
2736 argsToCBuffer(buf, elements, hgs); | |
2737 buf->writeByte(']'); | |
2738 } | |
2739 | |
2740 void ArrayLiteralExp::toMangleBuffer(OutBuffer *buf) | |
2741 { | |
2742 size_t dim = elements ? elements->dim : 0; | |
2743 buf->printf("A%u", dim); | |
2744 for (size_t i = 0; i < dim; i++) | |
2745 { Expression *e = (Expression *)elements->data[i]; | |
2746 e->toMangleBuffer(buf); | |
2747 } | |
2748 } | |
2749 | |
2750 /************************ AssocArrayLiteralExp ************************************/ | |
2751 | |
2752 // [ key0 : value0, key1 : value1, ... ] | |
2753 | |
2754 AssocArrayLiteralExp::AssocArrayLiteralExp(Loc loc, | |
2755 Expressions *keys, Expressions *values) | |
2756 : Expression(loc, TOKassocarrayliteral, sizeof(AssocArrayLiteralExp)) | |
2757 { | |
2758 assert(keys->dim == values->dim); | |
2759 this->keys = keys; | |
2760 this->values = values; | |
2761 } | |
2762 | |
2763 Expression *AssocArrayLiteralExp::syntaxCopy() | |
2764 { | |
2765 return new AssocArrayLiteralExp(loc, | |
2766 arraySyntaxCopy(keys), arraySyntaxCopy(values)); | |
2767 } | |
2768 | |
2769 Expression *AssocArrayLiteralExp::semantic(Scope *sc) | |
2770 { Expression *e; | |
2771 Type *tkey = NULL; | |
2772 Type *tvalue = NULL; | |
2773 | |
2774 #if LOGSEMANTIC | |
2775 printf("AssocArrayLiteralExp::semantic('%s')\n", toChars()); | |
2776 #endif | |
2777 | |
2778 // Run semantic() on each element | |
2779 for (size_t i = 0; i < keys->dim; i++) | |
2780 { Expression *key = (Expression *)keys->data[i]; | |
2781 Expression *value = (Expression *)values->data[i]; | |
2782 | |
2783 key = key->semantic(sc); | |
2784 value = value->semantic(sc); | |
2785 | |
2786 keys->data[i] = (void *)key; | |
2787 values->data[i] = (void *)value; | |
2788 } | |
2789 expandTuples(keys); | |
2790 expandTuples(values); | |
2791 if (keys->dim != values->dim) | |
2792 { | |
2793 error("number of keys is %u, must match number of values %u", keys->dim, values->dim); | |
2794 keys->setDim(0); | |
2795 values->setDim(0); | |
2796 } | |
2797 for (size_t i = 0; i < keys->dim; i++) | |
2798 { Expression *key = (Expression *)keys->data[i]; | |
2799 Expression *value = (Expression *)values->data[i]; | |
2800 | |
2801 if (!key->type) | |
2802 error("%s has no value", key->toChars()); | |
2803 if (!value->type) | |
2804 error("%s has no value", value->toChars()); | |
2805 key = resolveProperties(sc, key); | |
2806 value = resolveProperties(sc, value); | |
2807 | |
2808 if (!tkey) | |
2809 tkey = key->type; | |
2810 else | |
2811 key = key->implicitCastTo(sc, tkey); | |
2812 keys->data[i] = (void *)key; | |
2813 | |
2814 if (!tvalue) | |
2815 tvalue = value->type; | |
2816 else | |
2817 value = value->implicitCastTo(sc, tvalue); | |
2818 values->data[i] = (void *)value; | |
2819 } | |
2820 | |
2821 if (!tkey) | |
2822 tkey = Type::tvoid; | |
2823 if (!tvalue) | |
2824 tvalue = Type::tvoid; | |
2825 type = new TypeAArray(tvalue, tkey); | |
2826 type = type->semantic(loc, sc); | |
2827 return this; | |
2828 } | |
2829 | |
2830 int AssocArrayLiteralExp::checkSideEffect(int flag) | |
2831 { int f = 0; | |
2832 | |
2833 for (size_t i = 0; i < keys->dim; i++) | |
2834 { Expression *key = (Expression *)keys->data[i]; | |
2835 Expression *value = (Expression *)values->data[i]; | |
2836 | |
2837 f |= key->checkSideEffect(2); | |
2838 f |= value->checkSideEffect(2); | |
2839 } | |
2840 if (flag == 0 && f == 0) | |
2841 Expression::checkSideEffect(0); | |
2842 return f; | |
2843 } | |
2844 | |
2845 int AssocArrayLiteralExp::isBool(int result) | |
2846 { | |
2847 size_t dim = keys->dim; | |
2848 return result ? (dim != 0) : (dim == 0); | |
2849 } | |
2850 | |
2851 void AssocArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2852 { | |
2853 buf->writeByte('['); | |
2854 for (size_t i = 0; i < keys->dim; i++) | |
2855 { Expression *key = (Expression *)keys->data[i]; | |
2856 Expression *value = (Expression *)values->data[i]; | |
2857 | |
2858 if (i) | |
2859 buf->writeByte(','); | |
2860 expToCBuffer(buf, hgs, key, PREC_assign); | |
2861 buf->writeByte(':'); | |
2862 expToCBuffer(buf, hgs, value, PREC_assign); | |
2863 } | |
2864 buf->writeByte(']'); | |
2865 } | |
2866 | |
2867 void AssocArrayLiteralExp::toMangleBuffer(OutBuffer *buf) | |
2868 { | |
2869 size_t dim = keys->dim; | |
2870 buf->printf("A%u", dim); | |
2871 for (size_t i = 0; i < dim; i++) | |
2872 { Expression *key = (Expression *)keys->data[i]; | |
2873 Expression *value = (Expression *)values->data[i]; | |
2874 | |
2875 key->toMangleBuffer(buf); | |
2876 value->toMangleBuffer(buf); | |
2877 } | |
2878 } | |
2879 | |
2880 /************************ StructLiteralExp ************************************/ | |
2881 | |
2882 // sd( e1, e2, e3, ... ) | |
2883 | |
2884 StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements) | |
2885 : Expression(loc, TOKstructliteral, sizeof(StructLiteralExp)) | |
2886 { | |
2887 this->sd = sd; | |
2888 this->elements = elements; | |
2889 this->sym = NULL; | |
2890 this->soffset = 0; | |
2891 this->fillHoles = 1; | |
2892 } | |
2893 | |
2894 Expression *StructLiteralExp::syntaxCopy() | |
2895 { | |
2896 return new StructLiteralExp(loc, sd, arraySyntaxCopy(elements)); | |
2897 } | |
2898 | |
2899 Expression *StructLiteralExp::semantic(Scope *sc) | |
2900 { Expression *e; | |
2901 | |
2902 #if LOGSEMANTIC | |
2903 printf("StructLiteralExp::semantic('%s')\n", toChars()); | |
2904 #endif | |
2905 | |
2906 // Run semantic() on each element | |
2907 for (size_t i = 0; i < elements->dim; i++) | |
2908 { e = (Expression *)elements->data[i]; | |
2909 if (!e) | |
2910 continue; | |
2911 e = e->semantic(sc); | |
2912 elements->data[i] = (void *)e; | |
2913 } | |
2914 expandTuples(elements); | |
2915 size_t offset = 0; | |
2916 for (size_t i = 0; i < elements->dim; i++) | |
2917 { e = (Expression *)elements->data[i]; | |
2918 if (!e) | |
2919 continue; | |
2920 | |
2921 if (!e->type) | |
2922 error("%s has no value", e->toChars()); | |
2923 e = resolveProperties(sc, e); | |
2924 if (i >= sd->fields.dim) | |
2925 { error("more initializers than fields of %s", sd->toChars()); | |
2926 break; | |
2927 } | |
2928 Dsymbol *s = (Dsymbol *)sd->fields.data[i]; | |
2929 VarDeclaration *v = s->isVarDeclaration(); | |
2930 assert(v); | |
2931 if (v->offset < offset) | |
2932 error("overlapping initialization for %s", v->toChars()); | |
2933 offset = v->offset + v->type->size(); | |
2934 | |
2935 Type *telem = v->type; | |
2936 while (!e->implicitConvTo(telem) && telem->toBasetype()->ty == Tsarray) | |
2937 { /* Static array initialization, as in: | |
2938 * T[3][5] = e; | |
2939 */ | |
2940 telem = telem->toBasetype()->nextOf(); | |
2941 } | |
2942 | |
2943 e = e->implicitCastTo(sc, telem); | |
2944 | |
2945 elements->data[i] = (void *)e; | |
2946 } | |
2947 | |
2948 /* Fill out remainder of elements[] with default initializers for fields[] | |
2949 */ | |
2950 for (size_t i = elements->dim; i < sd->fields.dim; i++) | |
2951 { Dsymbol *s = (Dsymbol *)sd->fields.data[i]; | |
2952 VarDeclaration *v = s->isVarDeclaration(); | |
2953 assert(v); | |
2954 | |
2955 if (v->offset < offset) | |
2956 { e = NULL; | |
2957 sd->hasUnions = 1; | |
2958 } | |
2959 else | |
2960 { | |
2961 if (v->init) | |
2962 { e = v->init->toExpression(); | |
2963 if (!e) | |
2964 error("cannot make expression out of initializer for %s", v->toChars()); | |
2965 } | |
2966 else | |
2967 { e = v->type->defaultInit(); | |
2968 e->loc = loc; | |
2969 } | |
2970 offset = v->offset + v->type->size(); | |
2971 } | |
2972 elements->push(e); | |
2973 } | |
2974 | |
2975 type = sd->type; | |
2976 return this; | |
2977 } | |
2978 | |
2979 /************************************** | |
2980 * Gets expression at offset of type. | |
2981 * Returns NULL if not found. | |
2982 */ | |
2983 | |
2984 Expression *StructLiteralExp::getField(Type *type, unsigned offset) | |
2985 { Expression *e = NULL; | |
2986 int i = getFieldIndex(type, offset); | |
2987 | |
2988 if (i != -1) | |
2989 { e = (Expression *)elements->data[i]; | |
2990 if (e) | |
2991 { | |
2992 e = e->copy(); | |
2993 e->type = type; | |
2994 } | |
2995 } | |
2996 return e; | |
2997 } | |
2998 | |
2999 /************************************ | |
3000 * Get index of field. | |
3001 * Returns -1 if not found. | |
3002 */ | |
3003 | |
3004 int StructLiteralExp::getFieldIndex(Type *type, unsigned offset) | |
3005 { | |
3006 /* Find which field offset is by looking at the field offsets | |
3007 */ | |
3008 for (size_t i = 0; i < sd->fields.dim; i++) | |
3009 { | |
3010 Dsymbol *s = (Dsymbol *)sd->fields.data[i]; | |
3011 VarDeclaration *v = s->isVarDeclaration(); | |
3012 assert(v); | |
3013 | |
3014 if (offset == v->offset && | |
3015 type->size() == v->type->size()) | |
3016 { Expression *e = (Expression *)elements->data[i]; | |
3017 if (e) | |
3018 { | |
3019 return i; | |
3020 } | |
3021 break; | |
3022 } | |
3023 } | |
3024 return -1; | |
3025 } | |
3026 | |
3027 | |
3028 Expression *StructLiteralExp::toLvalue(Scope *sc, Expression *e) | |
3029 { | |
3030 return this; | |
3031 } | |
3032 | |
3033 | |
3034 int StructLiteralExp::checkSideEffect(int flag) | |
3035 { int f = 0; | |
3036 | |
3037 for (size_t i = 0; i < elements->dim; i++) | |
3038 { Expression *e = (Expression *)elements->data[i]; | |
3039 if (!e) | |
3040 continue; | |
3041 | |
3042 f |= e->checkSideEffect(2); | |
3043 } | |
3044 if (flag == 0 && f == 0) | |
3045 Expression::checkSideEffect(0); | |
3046 return f; | |
3047 } | |
3048 | |
3049 void StructLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3050 { | |
3051 buf->writestring(sd->toChars()); | |
3052 buf->writeByte('('); | |
3053 argsToCBuffer(buf, elements, hgs); | |
3054 buf->writeByte(')'); | |
3055 } | |
3056 | |
3057 void StructLiteralExp::toMangleBuffer(OutBuffer *buf) | |
3058 { | |
3059 size_t dim = elements ? elements->dim : 0; | |
3060 buf->printf("S%u", dim); | |
3061 for (size_t i = 0; i < dim; i++) | |
3062 { Expression *e = (Expression *)elements->data[i]; | |
3063 if (e) | |
3064 e->toMangleBuffer(buf); | |
3065 else | |
3066 buf->writeByte('v'); // 'v' for void | |
3067 } | |
3068 } | |
3069 | |
3070 /************************ TypeDotIdExp ************************************/ | |
3071 | |
3072 /* Things like: | |
3073 * int.size | |
3074 * foo.size | |
3075 * (foo).size | |
3076 * cast(foo).size | |
3077 */ | |
3078 | |
3079 TypeDotIdExp::TypeDotIdExp(Loc loc, Type *type, Identifier *ident) | |
3080 : Expression(loc, TOKtypedot, sizeof(TypeDotIdExp)) | |
3081 { | |
3082 this->type = type; | |
3083 this->ident = ident; | |
3084 } | |
3085 | |
3086 Expression *TypeDotIdExp::syntaxCopy() | |
3087 { | |
3088 TypeDotIdExp *te = new TypeDotIdExp(loc, type->syntaxCopy(), ident); | |
3089 return te; | |
3090 } | |
3091 | |
3092 Expression *TypeDotIdExp::semantic(Scope *sc) | |
3093 { Expression *e; | |
3094 | |
3095 #if LOGSEMANTIC | |
3096 printf("TypeDotIdExp::semantic()\n"); | |
3097 #endif | |
3098 e = new DotIdExp(loc, new TypeExp(loc, type), ident); | |
3099 e = e->semantic(sc); | |
3100 return e; | |
3101 } | |
3102 | |
3103 void TypeDotIdExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3104 { | |
3105 buf->writeByte('('); | |
3106 type->toCBuffer(buf, NULL, hgs); | |
3107 buf->writeByte(')'); | |
3108 buf->writeByte('.'); | |
3109 buf->writestring(ident->toChars()); | |
3110 } | |
3111 | |
3112 /************************************************************/ | |
3113 | |
3114 // Mainly just a placeholder | |
3115 | |
3116 TypeExp::TypeExp(Loc loc, Type *type) | |
3117 : Expression(loc, TOKtype, sizeof(TypeExp)) | |
3118 { | |
3119 //printf("TypeExp::TypeExp(%s)\n", type->toChars()); | |
3120 this->type = type; | |
3121 } | |
3122 | |
3123 Expression *TypeExp::semantic(Scope *sc) | |
3124 { | |
3125 //printf("TypeExp::semantic(%s)\n", type->toChars()); | |
3126 type = type->semantic(loc, sc); | |
3127 return this; | |
3128 } | |
3129 | |
3130 void TypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3131 { | |
3132 type->toCBuffer(buf, NULL, hgs); | |
3133 } | |
3134 | |
3135 /************************************************************/ | |
3136 | |
3137 // Mainly just a placeholder | |
3138 | |
3139 ScopeExp::ScopeExp(Loc loc, ScopeDsymbol *pkg) | |
3140 : Expression(loc, TOKimport, sizeof(ScopeExp)) | |
3141 { | |
3142 //printf("ScopeExp::ScopeExp(pkg = '%s')\n", pkg->toChars()); | |
3143 //static int count; if (++count == 38) *(char*)0=0; | |
3144 this->sds = pkg; | |
3145 } | |
3146 | |
3147 Expression *ScopeExp::syntaxCopy() | |
3148 { | |
3149 ScopeExp *se = new ScopeExp(loc, (ScopeDsymbol *)sds->syntaxCopy(NULL)); | |
3150 return se; | |
3151 } | |
3152 | |
3153 Expression *ScopeExp::semantic(Scope *sc) | |
3154 { | |
3155 TemplateInstance *ti; | |
3156 ScopeDsymbol *sds2; | |
3157 | |
3158 #if LOGSEMANTIC | |
3159 printf("+ScopeExp::semantic('%s')\n", toChars()); | |
3160 #endif | |
3161 Lagain: | |
3162 ti = sds->isTemplateInstance(); | |
3163 if (ti && !global.errors) | |
3164 { Dsymbol *s; | |
3165 if (!ti->semanticdone) | |
3166 ti->semantic(sc); | |
3167 s = ti->inst->toAlias(); | |
3168 sds2 = s->isScopeDsymbol(); | |
3169 if (!sds2) | |
3170 { Expression *e; | |
3171 | |
3172 //printf("s = %s, '%s'\n", s->kind(), s->toChars()); | |
3173 if (ti->withsym) | |
3174 { | |
3175 // Same as wthis.s | |
3176 e = new VarExp(loc, ti->withsym->withstate->wthis); | |
3177 e = new DotVarExp(loc, e, s->isDeclaration()); | |
3178 } | |
3179 else | |
3180 e = new DsymbolExp(loc, s); | |
3181 e = e->semantic(sc); | |
3182 //printf("-1ScopeExp::semantic()\n"); | |
3183 return e; | |
3184 } | |
3185 if (sds2 != sds) | |
3186 { | |
3187 sds = sds2; | |
3188 goto Lagain; | |
3189 } | |
3190 //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars()); | |
3191 } | |
3192 else | |
3193 { | |
3194 //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars()); | |
3195 //printf("\tparent = '%s'\n", sds->parent->toChars()); | |
3196 sds->semantic(sc); | |
3197 } | |
3198 type = Type::tvoid; | |
3199 //printf("-2ScopeExp::semantic() %s\n", toChars()); | |
3200 return this; | |
3201 } | |
3202 | |
3203 void ScopeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3204 { | |
3205 if (sds->isTemplateInstance()) | |
3206 { | |
3207 sds->toCBuffer(buf, hgs); | |
3208 } | |
3209 else | |
3210 { | |
3211 buf->writestring(sds->kind()); | |
3212 buf->writestring(" "); | |
3213 buf->writestring(sds->toChars()); | |
3214 } | |
3215 } | |
3216 | |
3217 /********************** TemplateExp **************************************/ | |
3218 | |
3219 // Mainly just a placeholder | |
3220 | |
3221 TemplateExp::TemplateExp(Loc loc, TemplateDeclaration *td) | |
3222 : Expression(loc, TOKtemplate, sizeof(TemplateExp)) | |
3223 { | |
3224 //printf("TemplateExp(): %s\n", td->toChars()); | |
3225 this->td = td; | |
3226 } | |
3227 | |
3228 void TemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3229 { | |
3230 buf->writestring(td->toChars()); | |
3231 } | |
3232 | |
3233 void TemplateExp::rvalue() | |
3234 { | |
3235 error("template %s has no value", toChars()); | |
3236 } | |
3237 | |
3238 /********************** NewExp **************************************/ | |
3239 | |
3240 NewExp::NewExp(Loc loc, Expression *thisexp, Expressions *newargs, | |
3241 Type *newtype, Expressions *arguments) | |
3242 : Expression(loc, TOKnew, sizeof(NewExp)) | |
3243 { | |
3244 this->thisexp = thisexp; | |
3245 this->newargs = newargs; | |
3246 this->newtype = newtype; | |
3247 this->arguments = arguments; | |
3248 member = NULL; | |
3249 allocator = NULL; | |
3250 onstack = 0; | |
3251 } | |
3252 | |
3253 Expression *NewExp::syntaxCopy() | |
3254 { | |
3255 return new NewExp(loc, | |
3256 thisexp ? thisexp->syntaxCopy() : NULL, | |
3257 arraySyntaxCopy(newargs), | |
3258 newtype->syntaxCopy(), arraySyntaxCopy(arguments)); | |
3259 } | |
3260 | |
3261 | |
3262 Expression *NewExp::semantic(Scope *sc) | |
3263 { int i; | |
3264 Type *tb; | |
3265 ClassDeclaration *cdthis = NULL; | |
3266 | |
3267 #if LOGSEMANTIC | |
3268 printf("NewExp::semantic() %s\n", toChars()); | |
3269 if (thisexp) | |
3270 printf("\tthisexp = %s\n", thisexp->toChars()); | |
3271 printf("\tnewtype: %s\n", newtype->toChars()); | |
3272 #endif | |
3273 if (type) // if semantic() already run | |
3274 return this; | |
3275 | |
3276 Lagain: | |
3277 if (thisexp) | |
3278 { thisexp = thisexp->semantic(sc); | |
3279 cdthis = thisexp->type->isClassHandle(); | |
3280 if (cdthis) | |
3281 { | |
3282 sc = sc->push(cdthis); | |
3283 type = newtype->semantic(loc, sc); | |
3284 sc = sc->pop(); | |
3285 } | |
3286 else | |
3287 { | |
3288 error("'this' for nested class must be a class type, not %s", thisexp->type->toChars()); | |
3289 type = newtype->semantic(loc, sc); | |
3290 } | |
3291 } | |
3292 else | |
3293 type = newtype->semantic(loc, sc); | |
3294 newtype = type; // in case type gets cast to something else | |
3295 tb = type->toBasetype(); | |
3296 //printf("tb: %s, deco = %s\n", tb->toChars(), tb->deco); | |
3297 | |
3298 arrayExpressionSemantic(newargs, sc); | |
3299 preFunctionArguments(loc, sc, newargs); | |
3300 arrayExpressionSemantic(arguments, sc); | |
3301 preFunctionArguments(loc, sc, arguments); | |
3302 | |
3303 if (thisexp && tb->ty != Tclass) | |
3304 error("e.new is only for allocating nested classes, not %s", tb->toChars()); | |
3305 | |
3306 if (tb->ty == Tclass) | |
3307 { TypeFunction *tf; | |
3308 | |
3309 TypeClass *tc = (TypeClass *)(tb); | |
3310 ClassDeclaration *cd = tc->sym->isClassDeclaration(); | |
3311 if (cd->isInterfaceDeclaration()) | |
3312 error("cannot create instance of interface %s", cd->toChars()); | |
3313 else if (cd->isAbstract()) | |
3314 { error("cannot create instance of abstract class %s", cd->toChars()); | |
3315 for (int i = 0; i < cd->vtbl.dim; i++) | |
3316 { FuncDeclaration *fd = ((Dsymbol *)cd->vtbl.data[i])->isFuncDeclaration(); | |
3317 if (fd && fd->isAbstract()) | |
3318 error("function %s is abstract", fd->toChars()); | |
3319 } | |
3320 } | |
3321 checkDeprecated(sc, cd); | |
3322 if (cd->isNested()) | |
3323 { /* We need a 'this' pointer for the nested class. | |
3324 * Ensure we have the right one. | |
3325 */ | |
3326 Dsymbol *s = cd->toParent2(); | |
3327 ClassDeclaration *cdn = s->isClassDeclaration(); | |
3328 | |
3329 //printf("isNested, cdn = %s\n", cdn ? cdn->toChars() : "null"); | |
3330 if (cdn) | |
3331 { | |
3332 if (!cdthis) | |
3333 { | |
3334 // Supply an implicit 'this' and try again | |
3335 thisexp = new ThisExp(loc); | |
3336 for (Dsymbol *sp = sc->parent; 1; sp = sp->parent) | |
3337 { if (!sp) | |
3338 { | |
3339 error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars()); | |
3340 break; | |
3341 } | |
3342 ClassDeclaration *cdp = sp->isClassDeclaration(); | |
3343 if (!cdp) | |
3344 continue; | |
3345 if (cdp == cdn || cdn->isBaseOf(cdp, NULL)) | |
3346 break; | |
3347 // Add a '.outer' and try again | |
3348 thisexp = new DotIdExp(loc, thisexp, Id::outer); | |
3349 } | |
3350 if (!global.errors) | |
3351 goto Lagain; | |
3352 } | |
3353 if (cdthis) | |
3354 { | |
3355 //printf("cdthis = %s\n", cdthis->toChars()); | |
3356 if (cdthis != cdn && !cdn->isBaseOf(cdthis, NULL)) | |
3357 error("'this' for nested class must be of type %s, not %s", cdn->toChars(), thisexp->type->toChars()); | |
3358 } | |
3359 #if 0 | |
3360 else | |
3361 { | |
3362 for (Dsymbol *sf = sc->func; 1; sf= sf->toParent2()->isFuncDeclaration()) | |
3363 { | |
3364 if (!sf) | |
3365 { | |
3366 error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars()); | |
3367 break; | |
3368 } | |
3369 printf("sf = %s\n", sf->toChars()); | |
3370 AggregateDeclaration *ad = sf->isThis(); | |
3371 if (ad && (ad == cdn || cdn->isBaseOf(ad->isClassDeclaration(), NULL))) | |
3372 break; | |
3373 } | |
3374 } | |
3375 #endif | |
3376 } | |
3377 else if (thisexp) | |
3378 error("e.new is only for allocating nested classes"); | |
3379 } | |
3380 else if (thisexp) | |
3381 error("e.new is only for allocating nested classes"); | |
3382 | |
3383 FuncDeclaration *f = cd->ctor; | |
3384 if (f) | |
3385 { | |
3386 assert(f); | |
3387 f = f->overloadResolve(loc, arguments); | |
3388 checkDeprecated(sc, f); | |
3389 member = f->isCtorDeclaration(); | |
3390 assert(member); | |
3391 | |
3392 cd->accessCheck(loc, sc, member); | |
3393 | |
3394 tf = (TypeFunction *)f->type; | |
3395 type = tf->next; | |
3396 | |
3397 if (!arguments) | |
3398 arguments = new Expressions(); | |
3399 functionArguments(loc, sc, tf, arguments); | |
3400 } | |
3401 else | |
3402 { | |
3403 if (arguments && arguments->dim) | |
3404 error("no constructor for %s", cd->toChars()); | |
3405 } | |
3406 | |
3407 if (cd->aggNew) | |
3408 { Expression *e; | |
3409 | |
3410 f = cd->aggNew; | |
3411 | |
3412 // Prepend the uint size argument to newargs[] | |
3413 e = new IntegerExp(loc, cd->size(loc), Type::tuns32); | |
3414 if (!newargs) | |
3415 newargs = new Expressions(); | |
3416 newargs->shift(e); | |
3417 | |
3418 f = f->overloadResolve(loc, newargs); | |
3419 allocator = f->isNewDeclaration(); | |
3420 assert(allocator); | |
3421 | |
3422 tf = (TypeFunction *)f->type; | |
3423 functionArguments(loc, sc, tf, newargs); | |
3424 } | |
3425 else | |
3426 { | |
3427 if (newargs && newargs->dim) | |
3428 error("no allocator for %s", cd->toChars()); | |
3429 } | |
3430 | |
3431 } | |
3432 else if (tb->ty == Tstruct) | |
3433 { | |
3434 TypeStruct *ts = (TypeStruct *)tb; | |
3435 StructDeclaration *sd = ts->sym; | |
3436 FuncDeclaration *f = sd->aggNew; | |
3437 TypeFunction *tf; | |
3438 | |
3439 if (arguments && arguments->dim) | |
3440 error("no constructor for %s", type->toChars()); | |
3441 | |
3442 if (f) | |
3443 { | |
3444 Expression *e; | |
3445 | |
3446 // Prepend the uint size argument to newargs[] | |
3447 e = new IntegerExp(loc, sd->size(loc), Type::tuns32); | |
3448 if (!newargs) | |
3449 newargs = new Expressions(); | |
3450 newargs->shift(e); | |
3451 | |
3452 f = f->overloadResolve(loc, newargs); | |
3453 allocator = f->isNewDeclaration(); | |
3454 assert(allocator); | |
3455 | |
3456 tf = (TypeFunction *)f->type; | |
3457 functionArguments(loc, sc, tf, newargs); | |
3458 | |
3459 e = new VarExp(loc, f); | |
3460 e = new CallExp(loc, e, newargs); | |
3461 e = e->semantic(sc); | |
3462 e->type = type->pointerTo(); | |
3463 return e; | |
3464 } | |
3465 | |
3466 type = type->pointerTo(); | |
3467 } | |
3468 else if (tb->ty == Tarray && (arguments && arguments->dim)) | |
3469 { | |
3470 for (size_t i = 0; i < arguments->dim; i++) | |
3471 { | |
3472 if (tb->ty != Tarray) | |
3473 { error("too many arguments for array"); | |
3474 arguments->dim = i; | |
3475 break; | |
3476 } | |
3477 | |
3478 Expression *arg = (Expression *)arguments->data[i]; | |
3479 arg = resolveProperties(sc, arg); | |
3480 arg = arg->implicitCastTo(sc, Type::tsize_t); | |
3481 if (arg->op == TOKint64 && (long long)arg->toInteger() < 0) | |
3482 error("negative array index %s", arg->toChars()); | |
3483 arguments->data[i] = (void *) arg; | |
3484 tb = tb->next->toBasetype(); | |
3485 } | |
3486 } | |
3487 else if (tb->isscalar()) | |
3488 { | |
3489 if (arguments && arguments->dim) | |
3490 error("no constructor for %s", type->toChars()); | |
3491 | |
3492 type = type->pointerTo(); | |
3493 } | |
3494 else | |
3495 { | |
3496 error("new can only create structs, dynamic arrays or class objects, not %s's", type->toChars()); | |
3497 type = type->pointerTo(); | |
3498 } | |
3499 | |
3500 //printf("NewExp: '%s'\n", toChars()); | |
3501 //printf("NewExp:type '%s'\n", type->toChars()); | |
3502 | |
3503 return this; | |
3504 } | |
3505 | |
3506 int NewExp::checkSideEffect(int flag) | |
3507 { | |
3508 return 1; | |
3509 } | |
3510 | |
3511 void NewExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3512 { int i; | |
3513 | |
3514 if (thisexp) | |
3515 { expToCBuffer(buf, hgs, thisexp, PREC_primary); | |
3516 buf->writeByte('.'); | |
3517 } | |
3518 buf->writestring("new "); | |
3519 if (newargs && newargs->dim) | |
3520 { | |
3521 buf->writeByte('('); | |
3522 argsToCBuffer(buf, newargs, hgs); | |
3523 buf->writeByte(')'); | |
3524 } | |
3525 newtype->toCBuffer(buf, NULL, hgs); | |
3526 if (arguments && arguments->dim) | |
3527 { | |
3528 buf->writeByte('('); | |
3529 argsToCBuffer(buf, arguments, hgs); | |
3530 buf->writeByte(')'); | |
3531 } | |
3532 } | |
3533 | |
3534 /********************** NewAnonClassExp **************************************/ | |
3535 | |
3536 NewAnonClassExp::NewAnonClassExp(Loc loc, Expression *thisexp, | |
3537 Expressions *newargs, ClassDeclaration *cd, Expressions *arguments) | |
3538 : Expression(loc, TOKnewanonclass, sizeof(NewAnonClassExp)) | |
3539 { | |
3540 this->thisexp = thisexp; | |
3541 this->newargs = newargs; | |
3542 this->cd = cd; | |
3543 this->arguments = arguments; | |
3544 } | |
3545 | |
3546 Expression *NewAnonClassExp::syntaxCopy() | |
3547 { | |
3548 return new NewAnonClassExp(loc, | |
3549 thisexp ? thisexp->syntaxCopy() : NULL, | |
3550 arraySyntaxCopy(newargs), | |
3551 (ClassDeclaration *)cd->syntaxCopy(NULL), | |
3552 arraySyntaxCopy(arguments)); | |
3553 } | |
3554 | |
3555 | |
3556 Expression *NewAnonClassExp::semantic(Scope *sc) | |
3557 { | |
3558 #if LOGSEMANTIC | |
3559 printf("NewAnonClassExp::semantic() %s\n", toChars()); | |
336 | 3560 //printf("thisexp = %p\n", thisexp); |
159 | 3561 //printf("type: %s\n", type->toChars()); |
3562 #endif | |
3563 | |
3564 Expression *d = new DeclarationExp(loc, cd); | |
3565 d = d->semantic(sc); | |
3566 | |
3567 Expression *n = new NewExp(loc, thisexp, newargs, cd->type, arguments); | |
3568 | |
3569 Expression *c = new CommaExp(loc, d, n); | |
3570 return c->semantic(sc); | |
3571 } | |
3572 | |
3573 int NewAnonClassExp::checkSideEffect(int flag) | |
3574 { | |
3575 return 1; | |
3576 } | |
3577 | |
3578 void NewAnonClassExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3579 { int i; | |
3580 | |
3581 if (thisexp) | |
3582 { expToCBuffer(buf, hgs, thisexp, PREC_primary); | |
3583 buf->writeByte('.'); | |
3584 } | |
3585 buf->writestring("new"); | |
3586 if (newargs && newargs->dim) | |
3587 { | |
3588 buf->writeByte('('); | |
3589 argsToCBuffer(buf, newargs, hgs); | |
3590 buf->writeByte(')'); | |
3591 } | |
3592 buf->writestring(" class "); | |
3593 if (arguments && arguments->dim) | |
3594 { | |
3595 buf->writeByte('('); | |
3596 argsToCBuffer(buf, arguments, hgs); | |
3597 buf->writeByte(')'); | |
3598 } | |
3599 //buf->writestring(" { }"); | |
3600 if (cd) | |
3601 { | |
3602 cd->toCBuffer(buf, hgs); | |
3603 } | |
3604 } | |
3605 | |
3606 /********************** SymOffExp **************************************/ | |
3607 | |
3608 SymOffExp::SymOffExp(Loc loc, Declaration *var, unsigned offset) | |
3609 : Expression(loc, TOKsymoff, sizeof(SymOffExp)) | |
3610 { | |
3611 assert(var); | |
3612 this->var = var; | |
3613 this->offset = offset; | |
3614 VarDeclaration *v = var->isVarDeclaration(); | |
3615 if (v && v->needThis()) | |
3616 error("need 'this' for address of %s", v->toChars()); | |
3617 } | |
3618 | |
3619 Expression *SymOffExp::semantic(Scope *sc) | |
3620 { | |
3621 #if LOGSEMANTIC | |
3622 printf("SymOffExp::semantic('%s')\n", toChars()); | |
3623 #endif | |
3624 //var->semantic(sc); | |
3625 if (!type) | |
3626 type = var->type->pointerTo(); | |
3627 VarDeclaration *v = var->isVarDeclaration(); | |
3628 if (v) | |
3629 { | |
3630 v->checkNestedReference(sc, loc); | |
3631 } | |
3632 return this; | |
3633 } | |
3634 | |
3635 int SymOffExp::isBool(int result) | |
3636 { | |
3637 return result ? TRUE : FALSE; | |
3638 } | |
3639 | |
3640 void SymOffExp::checkEscape() | |
3641 { | |
3642 VarDeclaration *v = var->isVarDeclaration(); | |
3643 if (v) | |
3644 { | |
3645 if (!v->isDataseg()) | |
3646 error("escaping reference to local variable %s", v->toChars()); | |
3647 } | |
3648 } | |
3649 | |
3650 void SymOffExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3651 { | |
3652 if (offset) | |
3653 buf->printf("(& %s+%u)", var->toChars(), offset); | |
3654 else | |
3655 buf->printf("& %s", var->toChars()); | |
3656 } | |
3657 | |
3658 /******************************** VarExp **************************/ | |
3659 | |
3660 VarExp::VarExp(Loc loc, Declaration *var) | |
3661 : Expression(loc, TOKvar, sizeof(VarExp)) | |
3662 { | |
3663 //printf("VarExp(this = %p, '%s')\n", this, var->toChars()); | |
3664 this->var = var; | |
3665 this->type = var->type; | |
3666 } | |
3667 | |
3668 int VarExp::equals(Object *o) | |
3669 { VarExp *ne; | |
3670 | |
3671 if (this == o || | |
3672 (((Expression *)o)->op == TOKvar && | |
3673 ((ne = (VarExp *)o), type->equals(ne->type)) && | |
3674 var == ne->var)) | |
3675 return 1; | |
3676 return 0; | |
3677 } | |
3678 | |
3679 Expression *VarExp::semantic(Scope *sc) | |
3680 { FuncLiteralDeclaration *fd; | |
3681 | |
3682 #if LOGSEMANTIC | |
3683 printf("VarExp::semantic(%s)\n", toChars()); | |
3684 #endif | |
3685 if (!type) | |
3686 { type = var->type; | |
3687 #if 0 | |
3688 if (var->storage_class & STClazy) | |
3689 { | |
3690 TypeFunction *tf = new TypeFunction(NULL, type, 0, LINKd); | |
3691 type = new TypeDelegate(tf); | |
3692 type = type->semantic(loc, sc); | |
3693 } | |
3694 #endif | |
3695 } | |
3696 | |
163
a8cd9bc1021a
[svn r179] lots and lots of fixes, much more of tango now compiles/works.
lindquist
parents:
159
diff
changeset
|
3697 // LLVMDC: Fixes bug 1161, http://d.puremagic.com/issues/show_bug.cgi?id=1161 |
a8cd9bc1021a
[svn r179] lots and lots of fixes, much more of tango now compiles/works.
lindquist
parents:
159
diff
changeset
|
3698 // check access to VarDeclaration |
a8cd9bc1021a
[svn r179] lots and lots of fixes, much more of tango now compiles/works.
lindquist
parents:
159
diff
changeset
|
3699 accessCheck(loc, sc, NULL, var); |
a8cd9bc1021a
[svn r179] lots and lots of fixes, much more of tango now compiles/works.
lindquist
parents:
159
diff
changeset
|
3700 |
159 | 3701 VarDeclaration *v = var->isVarDeclaration(); |
3702 if (v) | |
3703 { | |
3704 if (v->isConst() && type->toBasetype()->ty != Tsarray && v->init) | |
3705 { | |
3706 ExpInitializer *ei = v->init->isExpInitializer(); | |
3707 if (ei) | |
3708 { | |
3709 //ei->exp->implicitCastTo(sc, type)->print(); | |
3710 return ei->exp->implicitCastTo(sc, type); | |
3711 } | |
3712 } | |
3713 v->checkNestedReference(sc, loc); | |
3714 } | |
3715 #if 0 | |
3716 else if ((fd = var->isFuncLiteralDeclaration()) != NULL) | |
3717 { Expression *e; | |
3718 e = new FuncExp(loc, fd); | |
3719 e->type = type; | |
3720 return e; | |
3721 } | |
3722 #endif | |
3723 return this; | |
3724 } | |
3725 | |
3726 char *VarExp::toChars() | |
3727 { | |
3728 return var->toChars(); | |
3729 } | |
3730 | |
3731 void VarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3732 { | |
3733 buf->writestring(var->toChars()); | |
3734 } | |
3735 | |
3736 void VarExp::checkEscape() | |
3737 { | |
3738 VarDeclaration *v = var->isVarDeclaration(); | |
3739 if (v) | |
3740 { Type *tb = v->type->toBasetype(); | |
3741 // if reference type | |
3742 if (tb->ty == Tarray || tb->ty == Tsarray || tb->ty == Tclass) | |
3743 { | |
3744 if ((v->isAuto() || v->isScope()) && !v->noauto) | |
3745 error("escaping reference to auto local %s", v->toChars()); | |
3746 else if (v->storage_class & STCvariadic) | |
3747 error("escaping reference to variadic parameter %s", v->toChars()); | |
3748 } | |
3749 } | |
3750 } | |
3751 | |
3752 Expression *VarExp::toLvalue(Scope *sc, Expression *e) | |
3753 { | |
3754 #if 0 | |
3755 tym = tybasic(e1->ET->Tty); | |
3756 if (!(tyscalar(tym) || | |
3757 tym == TYstruct || | |
3758 tym == TYarray && e->Eoper == TOKaddr)) | |
3759 synerr(EM_lvalue); // lvalue expected | |
3760 #endif | |
3761 if (var->storage_class & STClazy) | |
3762 error("lazy variables cannot be lvalues"); | |
3763 return this; | |
3764 } | |
3765 | |
3766 Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e) | |
3767 { | |
3768 //printf("VarExp::modifiableLvalue('%s')\n", var->toChars()); | |
3769 if (sc->incontract && var->isParameter()) | |
3770 error("cannot modify parameter '%s' in contract", var->toChars()); | |
3771 | |
3772 if (type && type->toBasetype()->ty == Tsarray) | |
3773 error("cannot change reference to static array '%s'", var->toChars()); | |
3774 | |
3775 VarDeclaration *v = var->isVarDeclaration(); | |
3776 if (v && v->canassign == 0 && | |
3777 (var->isConst() || (global.params.Dversion > 1 && var->isFinal()))) | |
3778 error("cannot modify final variable '%s'", var->toChars()); | |
3779 | |
3780 if (var->isCtorinit()) | |
3781 { // It's only modifiable if inside the right constructor | |
3782 Dsymbol *s = sc->func; | |
3783 while (1) | |
3784 { | |
3785 FuncDeclaration *fd = NULL; | |
3786 if (s) | |
3787 fd = s->isFuncDeclaration(); | |
3788 if (fd && | |
3789 ((fd->isCtorDeclaration() && var->storage_class & STCfield) || | |
3790 (fd->isStaticCtorDeclaration() && !(var->storage_class & STCfield))) && | |
3791 fd->toParent() == var->toParent() | |
3792 ) | |
3793 { | |
3794 VarDeclaration *v = var->isVarDeclaration(); | |
3795 assert(v); | |
3796 v->ctorinit = 1; | |
3797 //printf("setting ctorinit\n"); | |
3798 } | |
3799 else | |
3800 { | |
3801 if (s) | |
3802 { s = s->toParent2(); | |
3803 continue; | |
3804 } | |
3805 else | |
3806 { | |
3807 const char *p = var->isStatic() ? "static " : ""; | |
3808 error("can only initialize %sconst %s inside %sconstructor", | |
3809 p, var->toChars(), p); | |
3810 } | |
3811 } | |
3812 break; | |
3813 } | |
3814 } | |
3815 | |
3816 // See if this expression is a modifiable lvalue (i.e. not const) | |
3817 return toLvalue(sc, e); | |
3818 } | |
3819 | |
3820 | |
3821 /******************************** TupleExp **************************/ | |
3822 | |
3823 TupleExp::TupleExp(Loc loc, Expressions *exps) | |
3824 : Expression(loc, TOKtuple, sizeof(TupleExp)) | |
3825 { | |
3826 //printf("TupleExp(this = %p)\n", this); | |
3827 this->exps = exps; | |
3828 this->type = NULL; | |
3829 } | |
3830 | |
3831 | |
3832 TupleExp::TupleExp(Loc loc, TupleDeclaration *tup) | |
3833 : Expression(loc, TOKtuple, sizeof(TupleExp)) | |
3834 { | |
3835 exps = new Expressions(); | |
3836 type = NULL; | |
3837 | |
3838 exps->reserve(tup->objects->dim); | |
3839 for (size_t i = 0; i < tup->objects->dim; i++) | |
3840 { Object *o = (Object *)tup->objects->data[i]; | |
3841 if (o->dyncast() == DYNCAST_EXPRESSION) | |
3842 { | |
3843 Expression *e = (Expression *)o; | |
3844 e = e->syntaxCopy(); | |
3845 exps->push(e); | |
3846 } | |
3847 else if (o->dyncast() == DYNCAST_DSYMBOL) | |
3848 { | |
3849 Dsymbol *s = (Dsymbol *)o; | |
3850 Expression *e = new DsymbolExp(loc, s); | |
3851 exps->push(e); | |
3852 } | |
3853 else if (o->dyncast() == DYNCAST_TYPE) | |
3854 { | |
3855 Type *t = (Type *)o; | |
3856 Expression *e = new TypeExp(loc, t); | |
3857 exps->push(e); | |
3858 } | |
3859 else | |
3860 { | |
3861 error("%s is not an expression", o->toChars()); | |
3862 } | |
3863 } | |
3864 } | |
3865 | |
3866 int TupleExp::equals(Object *o) | |
3867 { TupleExp *ne; | |
3868 | |
3869 if (this == o) | |
3870 return 1; | |
3871 if (((Expression *)o)->op == TOKtuple) | |
3872 { | |
3873 TupleExp *te = (TupleExp *)o; | |
3874 if (exps->dim != te->exps->dim) | |
3875 return 0; | |
3876 for (size_t i = 0; i < exps->dim; i++) | |
3877 { Expression *e1 = (Expression *)exps->data[i]; | |
3878 Expression *e2 = (Expression *)te->exps->data[i]; | |
3879 | |
3880 if (!e1->equals(e2)) | |
3881 return 0; | |
3882 } | |
3883 return 1; | |
3884 } | |
3885 return 0; | |
3886 } | |
3887 | |
3888 Expression *TupleExp::syntaxCopy() | |
3889 { | |
3890 return new TupleExp(loc, arraySyntaxCopy(exps)); | |
3891 } | |
3892 | |
3893 Expression *TupleExp::semantic(Scope *sc) | |
3894 { | |
3895 #if LOGSEMANTIC | |
3896 printf("+TupleExp::semantic(%s)\n", toChars()); | |
3897 #endif | |
3898 if (type) | |
3899 return this; | |
3900 | |
3901 // Run semantic() on each argument | |
3902 for (size_t i = 0; i < exps->dim; i++) | |
3903 { Expression *e = (Expression *)exps->data[i]; | |
3904 | |
3905 e = e->semantic(sc); | |
3906 if (!e->type) | |
3907 { error("%s has no value", e->toChars()); | |
3908 e->type = Type::terror; | |
3909 } | |
3910 exps->data[i] = (void *)e; | |
3911 } | |
3912 | |
3913 expandTuples(exps); | |
3914 if (0 && exps->dim == 1) | |
3915 { | |
3916 return (Expression *)exps->data[0]; | |
3917 } | |
3918 type = new TypeTuple(exps); | |
3919 //printf("-TupleExp::semantic(%s)\n", toChars()); | |
3920 return this; | |
3921 } | |
3922 | |
3923 void TupleExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3924 { | |
3925 buf->writestring("tuple("); | |
3926 argsToCBuffer(buf, exps, hgs); | |
3927 buf->writeByte(')'); | |
3928 } | |
3929 | |
3930 int TupleExp::checkSideEffect(int flag) | |
3931 { int f = 0; | |
3932 | |
3933 for (int i = 0; i < exps->dim; i++) | |
3934 { Expression *e = (Expression *)exps->data[i]; | |
3935 | |
3936 f |= e->checkSideEffect(2); | |
3937 } | |
3938 if (flag == 0 && f == 0) | |
3939 Expression::checkSideEffect(0); | |
3940 return f; | |
3941 } | |
3942 | |
3943 void TupleExp::checkEscape() | |
3944 { | |
3945 for (size_t i = 0; i < exps->dim; i++) | |
3946 { Expression *e = (Expression *)exps->data[i]; | |
3947 e->checkEscape(); | |
3948 } | |
3949 } | |
3950 | |
3951 /******************************** FuncExp *********************************/ | |
3952 | |
3953 FuncExp::FuncExp(Loc loc, FuncLiteralDeclaration *fd) | |
3954 : Expression(loc, TOKfunction, sizeof(FuncExp)) | |
3955 { | |
3956 this->fd = fd; | |
3957 } | |
3958 | |
3959 Expression *FuncExp::syntaxCopy() | |
3960 { | |
3961 return new FuncExp(loc, (FuncLiteralDeclaration *)fd->syntaxCopy(NULL)); | |
3962 } | |
3963 | |
3964 Expression *FuncExp::semantic(Scope *sc) | |
3965 { | |
3966 #if LOGSEMANTIC | |
3967 printf("FuncExp::semantic(%s)\n", toChars()); | |
3968 #endif | |
3969 if (!type) | |
3970 { | |
3971 fd->semantic(sc); | |
3972 fd->parent = sc->parent; | |
3973 if (global.errors) | |
3974 { | |
3975 if (!fd->type->next) | |
3976 fd->type->next = Type::terror; | |
3977 } | |
3978 else | |
3979 { | |
3980 fd->semantic2(sc); | |
3981 if (!global.errors) | |
3982 { | |
3983 fd->semantic3(sc); | |
3984 | |
3985 if (!global.errors && global.params.useInline) | |
3986 fd->inlineScan(); | |
3987 } | |
3988 } | |
3989 | |
3990 // Type is a "delegate to" or "pointer to" the function literal | |
3991 if (fd->isNested()) | |
3992 { | |
3993 type = new TypeDelegate(fd->type); | |
3994 type = type->semantic(loc, sc); | |
3995 } | |
3996 else | |
3997 { | |
3998 type = fd->type->pointerTo(); | |
3999 } | |
4000 } | |
4001 return this; | |
4002 } | |
4003 | |
4004 char *FuncExp::toChars() | |
4005 { | |
4006 return fd->toChars(); | |
4007 } | |
4008 | |
4009 void FuncExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4010 { | |
4011 buf->writestring(fd->toChars()); | |
4012 } | |
4013 | |
4014 | |
4015 /******************************** DeclarationExp **************************/ | |
4016 | |
4017 DeclarationExp::DeclarationExp(Loc loc, Dsymbol *declaration) | |
4018 : Expression(loc, TOKdeclaration, sizeof(DeclarationExp)) | |
4019 { | |
4020 this->declaration = declaration; | |
4021 } | |
4022 | |
4023 Expression *DeclarationExp::syntaxCopy() | |
4024 { | |
4025 return new DeclarationExp(loc, declaration->syntaxCopy(NULL)); | |
4026 } | |
4027 | |
4028 Expression *DeclarationExp::semantic(Scope *sc) | |
4029 { | |
4030 if (type) | |
4031 return this; | |
4032 | |
4033 #if LOGSEMANTIC | |
4034 printf("DeclarationExp::semantic() %s\n", toChars()); | |
4035 #endif | |
4036 | |
4037 /* This is here to support extern(linkage) declaration, | |
4038 * where the extern(linkage) winds up being an AttribDeclaration | |
4039 * wrapper. | |
4040 */ | |
4041 Dsymbol *s = declaration; | |
4042 | |
4043 AttribDeclaration *ad = declaration->isAttribDeclaration(); | |
4044 if (ad) | |
4045 { | |
4046 if (ad->decl && ad->decl->dim == 1) | |
4047 s = (Dsymbol *)ad->decl->data[0]; | |
4048 } | |
4049 | |
4050 if (s->isVarDeclaration()) | |
4051 { // Do semantic() on initializer first, so: | |
4052 // int a = a; | |
4053 // will be illegal. | |
4054 declaration->semantic(sc); | |
4055 s->parent = sc->parent; | |
4056 } | |
4057 | |
4058 //printf("inserting '%s' %p into sc = %p\n", s->toChars(), s, sc); | |
4059 // Insert into both local scope and function scope. | |
4060 // Must be unique in both. | |
4061 if (s->ident) | |
4062 { | |
4063 if (!sc->insert(s)) | |
4064 error("declaration %s is already defined", s->toPrettyChars()); | |
4065 else if (sc->func) | |
4066 { VarDeclaration *v = s->isVarDeclaration(); | |
4067 if ((s->isFuncDeclaration() /*|| v && v->storage_class & STCstatic*/) && | |
4068 !sc->func->localsymtab->insert(s)) | |
4069 error("declaration %s is already defined in another scope in %s", s->toPrettyChars(), sc->func->toChars()); | |
4070 else if (!global.params.useDeprecated) | |
4071 { // Disallow shadowing | |
4072 | |
4073 for (Scope *scx = sc->enclosing; scx && scx->func == sc->func; scx = scx->enclosing) | |
4074 { Dsymbol *s2; | |
4075 | |
4076 if (scx->scopesym && scx->scopesym->symtab && | |
4077 (s2 = scx->scopesym->symtab->lookup(s->ident)) != NULL && | |
4078 s != s2) | |
4079 { | |
4080 error("shadowing declaration %s is deprecated", s->toPrettyChars()); | |
4081 } | |
4082 } | |
4083 } | |
4084 } | |
4085 } | |
4086 if (!s->isVarDeclaration()) | |
4087 { | |
4088 declaration->semantic(sc); | |
4089 s->parent = sc->parent; | |
4090 } | |
4091 if (!global.errors) | |
4092 { | |
4093 declaration->semantic2(sc); | |
4094 if (!global.errors) | |
4095 { | |
4096 declaration->semantic3(sc); | |
4097 | |
4098 if (!global.errors && global.params.useInline) | |
4099 declaration->inlineScan(); | |
4100 } | |
4101 } | |
4102 | |
4103 type = Type::tvoid; | |
4104 return this; | |
4105 } | |
4106 | |
4107 int DeclarationExp::checkSideEffect(int flag) | |
4108 { | |
4109 return 1; | |
4110 } | |
4111 | |
4112 void DeclarationExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4113 { | |
4114 declaration->toCBuffer(buf, hgs); | |
4115 } | |
4116 | |
4117 | |
4118 /************************ TypeidExp ************************************/ | |
4119 | |
4120 /* | |
4121 * typeid(int) | |
4122 */ | |
4123 | |
4124 TypeidExp::TypeidExp(Loc loc, Type *typeidType) | |
4125 : Expression(loc, TOKtypeid, sizeof(TypeidExp)) | |
4126 { | |
4127 this->typeidType = typeidType; | |
4128 } | |
4129 | |
4130 | |
4131 Expression *TypeidExp::syntaxCopy() | |
4132 { | |
4133 return new TypeidExp(loc, typeidType->syntaxCopy()); | |
4134 } | |
4135 | |
4136 | |
4137 Expression *TypeidExp::semantic(Scope *sc) | |
4138 { Expression *e; | |
4139 | |
4140 #if LOGSEMANTIC | |
4141 printf("TypeidExp::semantic()\n"); | |
4142 #endif | |
4143 typeidType = typeidType->semantic(loc, sc); | |
4144 e = typeidType->getTypeInfo(sc); | |
336 | 4145 if (e->loc.linnum == 0) |
4146 e->loc = loc; // so there's at least some line number info | |
159 | 4147 return e; |
4148 } | |
4149 | |
4150 void TypeidExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4151 { | |
4152 buf->writestring("typeid("); | |
4153 typeidType->toCBuffer(buf, NULL, hgs); | |
4154 buf->writeByte(')'); | |
4155 } | |
4156 | |
4157 /************************************************************/ | |
4158 | |
4159 HaltExp::HaltExp(Loc loc) | |
4160 : Expression(loc, TOKhalt, sizeof(HaltExp)) | |
4161 { | |
4162 } | |
4163 | |
4164 Expression *HaltExp::semantic(Scope *sc) | |
4165 { | |
4166 #if LOGSEMANTIC | |
4167 printf("HaltExp::semantic()\n"); | |
4168 #endif | |
4169 type = Type::tvoid; | |
4170 return this; | |
4171 } | |
4172 | |
4173 int HaltExp::checkSideEffect(int flag) | |
4174 { | |
4175 return 1; | |
4176 } | |
4177 | |
4178 void HaltExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4179 { | |
4180 buf->writestring("halt"); | |
4181 } | |
4182 | |
4183 /************************************************************/ | |
4184 | |
4185 IsExp::IsExp(Loc loc, Type *targ, Identifier *id, enum TOK tok, | |
4186 Type *tspec, enum TOK tok2) | |
4187 : Expression(loc, TOKis, sizeof(IsExp)) | |
4188 { | |
4189 this->targ = targ; | |
4190 this->id = id; | |
4191 this->tok = tok; | |
4192 this->tspec = tspec; | |
4193 this->tok2 = tok2; | |
4194 } | |
4195 | |
4196 Expression *IsExp::syntaxCopy() | |
4197 { | |
4198 return new IsExp(loc, | |
4199 targ->syntaxCopy(), | |
4200 id, | |
4201 tok, | |
4202 tspec ? tspec->syntaxCopy() : NULL, | |
4203 tok2); | |
4204 } | |
4205 | |
4206 Expression *IsExp::semantic(Scope *sc) | |
4207 { Type *tded; | |
4208 | |
4209 //printf("IsExp::semantic()\n"); | |
4210 if (id && !(sc->flags & SCOPEstaticif)) | |
4211 error("can only declare type aliases within static if conditionals"); | |
4212 | |
4213 unsigned errors_save = global.errors; | |
4214 global.errors = 0; | |
4215 global.gag++; // suppress printing of error messages | |
4216 targ = targ->semantic(loc, sc); | |
4217 global.gag--; | |
4218 unsigned gerrors = global.errors; | |
4219 global.errors = errors_save; | |
4220 | |
4221 if (gerrors) // if any errors happened | |
4222 { // then condition is false | |
4223 goto Lno; | |
4224 } | |
4225 else if (tok2 != TOKreserved) | |
4226 { | |
4227 switch (tok2) | |
4228 { | |
4229 case TOKtypedef: | |
4230 if (targ->ty != Ttypedef) | |
4231 goto Lno; | |
4232 tded = ((TypeTypedef *)targ)->sym->basetype; | |
4233 break; | |
4234 | |
4235 case TOKstruct: | |
4236 if (targ->ty != Tstruct) | |
4237 goto Lno; | |
4238 if (((TypeStruct *)targ)->sym->isUnionDeclaration()) | |
4239 goto Lno; | |
4240 tded = targ; | |
4241 break; | |
4242 | |
4243 case TOKunion: | |
4244 if (targ->ty != Tstruct) | |
4245 goto Lno; | |
4246 if (!((TypeStruct *)targ)->sym->isUnionDeclaration()) | |
4247 goto Lno; | |
4248 tded = targ; | |
4249 break; | |
4250 | |
4251 case TOKclass: | |
4252 if (targ->ty != Tclass) | |
4253 goto Lno; | |
4254 if (((TypeClass *)targ)->sym->isInterfaceDeclaration()) | |
4255 goto Lno; | |
4256 tded = targ; | |
4257 break; | |
4258 | |
4259 case TOKinterface: | |
4260 if (targ->ty != Tclass) | |
4261 goto Lno; | |
4262 if (!((TypeClass *)targ)->sym->isInterfaceDeclaration()) | |
4263 goto Lno; | |
4264 tded = targ; | |
4265 break; | |
4266 | |
4267 case TOKsuper: | |
4268 // If class or interface, get the base class and interfaces | |
4269 if (targ->ty != Tclass) | |
4270 goto Lno; | |
4271 else | |
4272 { ClassDeclaration *cd = ((TypeClass *)targ)->sym; | |
4273 Arguments *args = new Arguments; | |
4274 args->reserve(cd->baseclasses.dim); | |
4275 for (size_t i = 0; i < cd->baseclasses.dim; i++) | |
4276 { BaseClass *b = (BaseClass *)cd->baseclasses.data[i]; | |
4277 args->push(new Argument(STCin, b->type, NULL, NULL)); | |
4278 } | |
4279 tded = new TypeTuple(args); | |
4280 } | |
4281 break; | |
4282 | |
4283 case TOKenum: | |
4284 if (targ->ty != Tenum) | |
4285 goto Lno; | |
4286 tded = ((TypeEnum *)targ)->sym->memtype; | |
4287 break; | |
4288 | |
4289 case TOKdelegate: | |
4290 if (targ->ty != Tdelegate) | |
4291 goto Lno; | |
4292 tded = targ->next; // the underlying function type | |
4293 break; | |
4294 | |
4295 case TOKfunction: | |
4296 { if (targ->ty != Tfunction) | |
4297 goto Lno; | |
4298 tded = targ; | |
4299 | |
4300 /* Generate tuple from function parameter types. | |
4301 */ | |
4302 assert(tded->ty == Tfunction); | |
4303 Arguments *params = ((TypeFunction *)tded)->parameters; | |
4304 size_t dim = Argument::dim(params); | |
4305 Arguments *args = new Arguments; | |
4306 args->reserve(dim); | |
4307 for (size_t i = 0; i < dim; i++) | |
4308 { Argument *arg = Argument::getNth(params, i); | |
4309 assert(arg && arg->type); | |
4310 args->push(new Argument(arg->storageClass, arg->type, NULL, NULL)); | |
4311 } | |
4312 tded = new TypeTuple(args); | |
4313 break; | |
4314 } | |
4315 case TOKreturn: | |
4316 /* Get the 'return type' for the function, | |
4317 * delegate, or pointer to function. | |
4318 */ | |
4319 if (targ->ty == Tfunction) | |
4320 tded = targ->next; | |
4321 else if (targ->ty == Tdelegate) | |
4322 tded = targ->next->next; | |
4323 else if (targ->ty == Tpointer && targ->next->ty == Tfunction) | |
4324 tded = targ->next->next; | |
4325 else | |
4326 goto Lno; | |
4327 break; | |
4328 | |
4329 default: | |
4330 assert(0); | |
4331 } | |
4332 goto Lyes; | |
4333 } | |
4334 else if (id && tspec) | |
4335 { | |
4336 /* Evaluate to TRUE if targ matches tspec. | |
4337 * If TRUE, declare id as an alias for the specialized type. | |
4338 */ | |
4339 | |
4340 MATCH m; | |
4341 TemplateTypeParameter tp(loc, id, NULL, NULL); | |
4342 | |
4343 TemplateParameters parameters; | |
4344 parameters.setDim(1); | |
4345 parameters.data[0] = (void *)&tp; | |
4346 | |
4347 Objects dedtypes; | |
4348 dedtypes.setDim(1); | |
4349 dedtypes.data[0] = NULL; | |
4350 | |
4351 m = targ->deduceType(NULL, tspec, ¶meters, &dedtypes); | |
4352 if (m == MATCHnomatch || | |
4353 (m != MATCHexact && tok == TOKequal)) | |
4354 goto Lno; | |
4355 else | |
4356 { | |
4357 assert(dedtypes.dim == 1); | |
4358 tded = (Type *)dedtypes.data[0]; | |
4359 if (!tded) | |
4360 tded = targ; | |
4361 goto Lyes; | |
4362 } | |
4363 } | |
4364 else if (id) | |
4365 { | |
4366 /* Declare id as an alias for type targ. Evaluate to TRUE | |
4367 */ | |
4368 tded = targ; | |
4369 goto Lyes; | |
4370 } | |
4371 else if (tspec) | |
4372 { | |
4373 /* Evaluate to TRUE if targ matches tspec | |
4374 */ | |
4375 tspec = tspec->semantic(loc, sc); | |
4376 //printf("targ = %s\n", targ->toChars()); | |
4377 //printf("tspec = %s\n", tspec->toChars()); | |
4378 if (tok == TOKcolon) | |
4379 { if (targ->implicitConvTo(tspec)) | |
4380 goto Lyes; | |
4381 else | |
4382 goto Lno; | |
4383 } | |
4384 else /* == */ | |
4385 { if (targ->equals(tspec)) | |
4386 goto Lyes; | |
4387 else | |
4388 goto Lno; | |
4389 } | |
4390 } | |
4391 | |
4392 Lyes: | |
4393 if (id) | |
4394 { | |
4395 Dsymbol *s = new AliasDeclaration(loc, id, tded); | |
4396 s->semantic(sc); | |
4397 sc->insert(s); | |
4398 if (sc->sd) | |
4399 s->addMember(sc, sc->sd, 1); | |
4400 } | |
4401 return new IntegerExp(1); | |
4402 | |
4403 Lno: | |
4404 return new IntegerExp(0); | |
4405 } | |
4406 | |
4407 void IsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4408 { | |
4409 buf->writestring("is("); | |
4410 targ->toCBuffer(buf, id, hgs); | |
4411 if (tok2 != TOKreserved) | |
4412 { | |
4413 buf->printf(" %s %s", Token::toChars(tok), Token::toChars(tok2)); | |
4414 } | |
4415 else if (tspec) | |
4416 { | |
4417 if (tok == TOKcolon) | |
4418 buf->writestring(" : "); | |
4419 else | |
4420 buf->writestring(" == "); | |
4421 tspec->toCBuffer(buf, NULL, hgs); | |
4422 } | |
336 | 4423 #if DMDV2 |
159 | 4424 if (parameters) |
4425 { // First parameter is already output, so start with second | |
4426 for (int i = 1; i < parameters->dim; i++) | |
4427 { | |
4428 buf->writeByte(','); | |
4429 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | |
4430 tp->toCBuffer(buf, hgs); | |
4431 } | |
4432 } | |
4433 #endif | |
4434 buf->writeByte(')'); | |
4435 } | |
4436 | |
4437 | |
4438 /************************************************************/ | |
4439 | |
4440 UnaExp::UnaExp(Loc loc, enum TOK op, int size, Expression *e1) | |
4441 : Expression(loc, op, size) | |
4442 { | |
4443 this->e1 = e1; | |
4444 } | |
4445 | |
4446 Expression *UnaExp::syntaxCopy() | |
4447 { UnaExp *e; | |
4448 | |
4449 e = (UnaExp *)copy(); | |
4450 e->type = NULL; | |
4451 e->e1 = e->e1->syntaxCopy(); | |
4452 return e; | |
4453 } | |
4454 | |
4455 Expression *UnaExp::semantic(Scope *sc) | |
4456 { | |
4457 #if LOGSEMANTIC | |
4458 printf("UnaExp::semantic('%s')\n", toChars()); | |
4459 #endif | |
4460 e1 = e1->semantic(sc); | |
4461 // if (!e1->type) | |
4462 // error("%s has no value", e1->toChars()); | |
4463 return this; | |
4464 } | |
4465 | |
4466 void UnaExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4467 { | |
4468 buf->writestring(Token::toChars(op)); | |
4469 expToCBuffer(buf, hgs, e1, precedence[op]); | |
4470 } | |
4471 | |
4472 /************************************************************/ | |
4473 | |
4474 BinExp::BinExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2) | |
4475 : Expression(loc, op, size) | |
4476 { | |
4477 this->e1 = e1; | |
4478 this->e2 = e2; | |
4479 } | |
4480 | |
4481 Expression *BinExp::syntaxCopy() | |
4482 { BinExp *e; | |
4483 | |
4484 e = (BinExp *)copy(); | |
4485 e->type = NULL; | |
4486 e->e1 = e->e1->syntaxCopy(); | |
4487 e->e2 = e->e2->syntaxCopy(); | |
4488 return e; | |
4489 } | |
4490 | |
4491 Expression *BinExp::semantic(Scope *sc) | |
4492 { | |
4493 #if LOGSEMANTIC | |
4494 printf("BinExp::semantic('%s')\n", toChars()); | |
4495 #endif | |
4496 e1 = e1->semantic(sc); | |
4497 if (!e1->type) | |
4498 { | |
4499 error("%s has no value", e1->toChars()); | |
4500 e1->type = Type::terror; | |
4501 } | |
4502 e2 = e2->semantic(sc); | |
4503 if (!e2->type) | |
4504 { | |
4505 error("%s has no value", e2->toChars()); | |
4506 e2->type = Type::terror; | |
4507 } | |
4508 assert(e1->type); | |
4509 return this; | |
4510 } | |
4511 | |
4512 Expression *BinExp::semanticp(Scope *sc) | |
4513 { | |
4514 BinExp::semantic(sc); | |
4515 e1 = resolveProperties(sc, e1); | |
4516 e2 = resolveProperties(sc, e2); | |
4517 return this; | |
4518 } | |
4519 | |
4520 /*************************** | |
4521 * Common semantic routine for some xxxAssignExp's. | |
4522 */ | |
4523 | |
4524 Expression *BinExp::commonSemanticAssign(Scope *sc) | |
4525 { Expression *e; | |
4526 | |
4527 if (!type) | |
4528 { | |
4529 BinExp::semantic(sc); | |
4530 e2 = resolveProperties(sc, e2); | |
4531 | |
4532 e = op_overload(sc); | |
4533 if (e) | |
4534 return e; | |
4535 | |
4536 e1 = e1->modifiableLvalue(sc, e1); | |
4537 e1->checkScalar(); | |
4538 type = e1->type; | |
4539 if (type->toBasetype()->ty == Tbool) | |
4540 { | |
4541 error("operator not allowed on bool expression %s", toChars()); | |
4542 } | |
4543 typeCombine(sc); | |
4544 e1->checkArithmetic(); | |
4545 e2->checkArithmetic(); | |
4546 | |
4547 if (op == TOKmodass && e2->type->iscomplex()) | |
4548 { error("cannot perform modulo complex arithmetic"); | |
4549 return new IntegerExp(0); | |
4550 } | |
4551 } | |
4552 return this; | |
4553 } | |
4554 | |
4555 Expression *BinExp::commonSemanticAssignIntegral(Scope *sc) | |
4556 { Expression *e; | |
4557 | |
4558 if (!type) | |
4559 { | |
4560 BinExp::semantic(sc); | |
4561 e2 = resolveProperties(sc, e2); | |
4562 | |
4563 e = op_overload(sc); | |
4564 if (e) | |
4565 return e; | |
4566 | |
4567 e1 = e1->modifiableLvalue(sc, e1); | |
4568 e1->checkScalar(); | |
4569 type = e1->type; | |
4570 if (type->toBasetype()->ty == Tbool) | |
4571 { | |
4572 e2 = e2->implicitCastTo(sc, type); | |
4573 } | |
4574 | |
4575 typeCombine(sc); | |
4576 e1->checkIntegral(); | |
4577 e2->checkIntegral(); | |
4578 } | |
4579 return this; | |
4580 } | |
4581 | |
4582 int BinExp::checkSideEffect(int flag) | |
4583 { | |
4584 if (op == TOKplusplus || | |
4585 op == TOKminusminus || | |
4586 op == TOKassign || | |
4587 op == TOKconstruct || | |
4588 op == TOKblit || | |
4589 op == TOKaddass || | |
4590 op == TOKminass || | |
4591 op == TOKcatass || | |
4592 op == TOKmulass || | |
4593 op == TOKdivass || | |
4594 op == TOKmodass || | |
4595 op == TOKshlass || | |
4596 op == TOKshrass || | |
4597 op == TOKushrass || | |
4598 op == TOKandass || | |
4599 op == TOKorass || | |
4600 op == TOKxorass || | |
4601 op == TOKin || | |
4602 op == TOKremove) | |
4603 return 1; | |
4604 return Expression::checkSideEffect(flag); | |
4605 } | |
4606 | |
4607 void BinExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4608 { | |
4609 expToCBuffer(buf, hgs, e1, precedence[op]); | |
4610 buf->writeByte(' '); | |
4611 buf->writestring(Token::toChars(op)); | |
4612 buf->writeByte(' '); | |
4613 expToCBuffer(buf, hgs, e2, (enum PREC)(precedence[op] + 1)); | |
4614 } | |
4615 | |
4616 int BinExp::isunsigned() | |
4617 { | |
4618 return e1->type->isunsigned() || e2->type->isunsigned(); | |
4619 } | |
4620 | |
4621 void BinExp::incompatibleTypes() | |
4622 { | |
4623 error("incompatible types for ((%s) %s (%s)): '%s' and '%s'", | |
4624 e1->toChars(), Token::toChars(op), e2->toChars(), | |
4625 e1->type->toChars(), e2->type->toChars()); | |
4626 } | |
4627 | |
4628 /************************************************************/ | |
4629 | |
4630 CompileExp::CompileExp(Loc loc, Expression *e) | |
4631 : UnaExp(loc, TOKmixin, sizeof(CompileExp), e) | |
4632 { | |
4633 } | |
4634 | |
4635 Expression *CompileExp::semantic(Scope *sc) | |
4636 { | |
4637 #if LOGSEMANTIC | |
4638 printf("CompileExp::semantic('%s')\n", toChars()); | |
4639 #endif | |
4640 UnaExp::semantic(sc); | |
4641 e1 = resolveProperties(sc, e1); | |
4642 e1 = e1->optimize(WANTvalue | WANTinterpret); | |
4643 if (e1->op != TOKstring) | |
4644 { error("argument to mixin must be a string, not (%s)", e1->toChars()); | |
4645 type = Type::terror; | |
4646 return this; | |
4647 } | |
4648 StringExp *se = (StringExp *)e1; | |
4649 se = se->toUTF8(sc); | |
4650 Parser p(sc->module, (unsigned char *)se->string, se->len, 0); | |
4651 p.loc = loc; | |
4652 p.nextToken(); | |
4653 Expression *e = p.parseExpression(); | |
4654 if (p.token.value != TOKeof) | |
4655 error("incomplete mixin expression (%s)", se->toChars()); | |
4656 return e->semantic(sc); | |
4657 } | |
4658 | |
4659 void CompileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4660 { | |
4661 buf->writestring("mixin("); | |
4662 expToCBuffer(buf, hgs, e1, PREC_assign); | |
4663 buf->writeByte(')'); | |
4664 } | |
4665 | |
4666 /************************************************************/ | |
4667 | |
4668 FileExp::FileExp(Loc loc, Expression *e) | |
4669 : UnaExp(loc, TOKmixin, sizeof(FileExp), e) | |
4670 { | |
4671 } | |
4672 | |
4673 Expression *FileExp::semantic(Scope *sc) | |
4674 { char *name; | |
4675 StringExp *se; | |
4676 | |
4677 #if LOGSEMANTIC | |
4678 printf("FileExp::semantic('%s')\n", toChars()); | |
4679 #endif | |
4680 UnaExp::semantic(sc); | |
4681 e1 = resolveProperties(sc, e1); | |
4682 e1 = e1->optimize(WANTvalue); | |
4683 if (e1->op != TOKstring) | |
4684 { error("file name argument must be a string, not (%s)", e1->toChars()); | |
4685 goto Lerror; | |
4686 } | |
4687 se = (StringExp *)e1; | |
4688 se = se->toUTF8(sc); | |
4689 name = (char *)se->string; | |
4690 | |
4691 if (!global.params.fileImppath) | |
4692 { error("need -Jpath switch to import text file %s", name); | |
4693 goto Lerror; | |
4694 } | |
4695 | |
4696 if (name != FileName::name(name)) | |
4697 { error("use -Jpath switch to provide path for filename %s", name); | |
4698 goto Lerror; | |
4699 } | |
4700 | |
4701 name = FileName::searchPath(global.filePath, name, 0); | |
4702 if (!name) | |
4703 { error("file %s cannot be found, check -Jpath", se->toChars()); | |
4704 goto Lerror; | |
4705 } | |
4706 | |
4707 if (global.params.verbose) | |
4708 printf("file %s\t(%s)\n", se->string, name); | |
4709 | |
4710 { File f(name); | |
4711 if (f.read()) | |
4712 { error("cannot read file %s", f.toChars()); | |
4713 goto Lerror; | |
4714 } | |
4715 else | |
4716 { | |
4717 f.ref = 1; | |
4718 se = new StringExp(loc, f.buffer, f.len); | |
4719 } | |
4720 } | |
4721 Lret: | |
4722 return se->semantic(sc); | |
4723 | |
4724 Lerror: | |
4725 se = new StringExp(loc, ""); | |
4726 goto Lret; | |
4727 } | |
4728 | |
4729 void FileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4730 { | |
4731 buf->writestring("import("); | |
4732 expToCBuffer(buf, hgs, e1, PREC_assign); | |
4733 buf->writeByte(')'); | |
4734 } | |
4735 | |
4736 /************************************************************/ | |
4737 | |
4738 AssertExp::AssertExp(Loc loc, Expression *e, Expression *msg) | |
4739 : UnaExp(loc, TOKassert, sizeof(AssertExp), e) | |
4740 { | |
4741 this->msg = msg; | |
4742 } | |
4743 | |
4744 Expression *AssertExp::syntaxCopy() | |
4745 { | |
4746 AssertExp *ae = new AssertExp(loc, e1->syntaxCopy(), | |
4747 msg ? msg->syntaxCopy() : NULL); | |
4748 return ae; | |
4749 } | |
4750 | |
4751 Expression *AssertExp::semantic(Scope *sc) | |
4752 { | |
4753 #if LOGSEMANTIC | |
4754 printf("AssertExp::semantic('%s')\n", toChars()); | |
4755 #endif | |
4756 UnaExp::semantic(sc); | |
4757 e1 = resolveProperties(sc, e1); | |
4758 // BUG: see if we can do compile time elimination of the Assert | |
4759 e1 = e1->optimize(WANTvalue); | |
4760 e1 = e1->checkToBoolean(); | |
4761 if (msg) | |
4762 { | |
4763 msg = msg->semantic(sc); | |
4764 msg = resolveProperties(sc, msg); | |
4765 msg = msg->implicitCastTo(sc, Type::tchar->arrayOf()); | |
4766 msg = msg->optimize(WANTvalue); | |
4767 } | |
4768 if (e1->isBool(FALSE)) | |
4769 { | |
4770 FuncDeclaration *fd = sc->parent->isFuncDeclaration(); | |
4771 fd->hasReturnExp |= 4; | |
4772 | |
4773 if (!global.params.useAssert) | |
4774 { Expression *e = new HaltExp(loc); | |
4775 e = e->semantic(sc); | |
4776 return e; | |
4777 } | |
4778 } | |
4779 type = Type::tvoid; | |
4780 return this; | |
4781 } | |
4782 | |
4783 int AssertExp::checkSideEffect(int flag) | |
4784 { | |
4785 return 1; | |
4786 } | |
4787 | |
4788 void AssertExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4789 { | |
4790 buf->writestring("assert("); | |
4791 expToCBuffer(buf, hgs, e1, PREC_assign); | |
4792 if (msg) | |
4793 { | |
4794 buf->writeByte(','); | |
4795 expToCBuffer(buf, hgs, msg, PREC_assign); | |
4796 } | |
4797 buf->writeByte(')'); | |
4798 } | |
4799 | |
4800 /************************************************************/ | |
4801 | |
4802 DotIdExp::DotIdExp(Loc loc, Expression *e, Identifier *ident) | |
4803 : UnaExp(loc, TOKdot, sizeof(DotIdExp), e) | |
4804 { | |
4805 this->ident = ident; | |
4806 } | |
4807 | |
4808 Expression *DotIdExp::semantic(Scope *sc) | |
4809 { Expression *e; | |
4810 Expression *eleft; | |
4811 Expression *eright; | |
4812 | |
4813 #if LOGSEMANTIC | |
4814 printf("DotIdExp::semantic(this = %p, '%s')\n", this, toChars()); | |
4815 //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op)); | |
4816 #endif | |
4817 | |
4818 //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; } | |
4819 | |
4820 #if 0 | |
4821 /* Don't do semantic analysis if we'll be converting | |
4822 * it to a string. | |
4823 */ | |
4824 if (ident == Id::stringof) | |
4825 { char *s = e1->toChars(); | |
4826 e = new StringExp(loc, s, strlen(s), 'c'); | |
4827 e = e->semantic(sc); | |
4828 return e; | |
4829 } | |
4830 #endif | |
4831 | |
4832 /* Special case: rewrite this.id and super.id | |
4833 * to be classtype.id and baseclasstype.id | |
4834 * if we have no this pointer. | |
4835 */ | |
4836 if ((e1->op == TOKthis || e1->op == TOKsuper) && !hasThis(sc)) | |
4837 { ClassDeclaration *cd; | |
4838 StructDeclaration *sd; | |
4839 AggregateDeclaration *ad; | |
4840 | |
4841 ad = sc->getStructClassScope(); | |
4842 if (ad) | |
4843 { | |
4844 cd = ad->isClassDeclaration(); | |
4845 if (cd) | |
4846 { | |
4847 if (e1->op == TOKthis) | |
4848 { | |
4849 e = new TypeDotIdExp(loc, cd->type, ident); | |
4850 return e->semantic(sc); | |
4851 } | |
4852 else if (cd->baseClass && e1->op == TOKsuper) | |
4853 { | |
4854 e = new TypeDotIdExp(loc, cd->baseClass->type, ident); | |
4855 return e->semantic(sc); | |
4856 } | |
4857 } | |
4858 else | |
4859 { | |
4860 sd = ad->isStructDeclaration(); | |
4861 if (sd) | |
4862 { | |
4863 if (e1->op == TOKthis) | |
4864 { | |
4865 e = new TypeDotIdExp(loc, sd->type, ident); | |
4866 return e->semantic(sc); | |
4867 } | |
4868 } | |
4869 } | |
4870 } | |
4871 } | |
4872 | |
4873 UnaExp::semantic(sc); | |
4874 | |
4875 if (e1->op == TOKdotexp) | |
4876 { | |
4877 DotExp *de = (DotExp *)e1; | |
4878 eleft = de->e1; | |
4879 eright = de->e2; | |
4880 } | |
4881 else | |
4882 { | |
4883 e1 = resolveProperties(sc, e1); | |
4884 eleft = NULL; | |
4885 eright = e1; | |
4886 } | |
4887 | |
4888 if (e1->op == TOKtuple && ident == Id::length) | |
4889 { | |
4890 TupleExp *te = (TupleExp *)e1; | |
4891 e = new IntegerExp(loc, te->exps->dim, Type::tsize_t); | |
4892 return e; | |
4893 } | |
4894 | |
4895 if (eright->op == TOKimport) // also used for template alias's | |
4896 { | |
4897 Dsymbol *s; | |
4898 ScopeExp *ie = (ScopeExp *)eright; | |
4899 | |
4900 s = ie->sds->search(loc, ident, 0); | |
4901 if (s) | |
4902 { | |
4903 s = s->toAlias(); | |
4904 checkDeprecated(sc, s); | |
4905 | |
4906 EnumMember *em = s->isEnumMember(); | |
4907 if (em) | |
4908 { | |
4909 e = em->value; | |
4910 e = e->semantic(sc); | |
4911 return e; | |
4912 } | |
4913 | |
4914 VarDeclaration *v = s->isVarDeclaration(); | |
4915 if (v) | |
4916 { | |
4917 //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars()); | |
4918 if (v->inuse) | |
4919 { | |
4920 error("circular reference to '%s'", v->toChars()); | |
4921 type = Type::tint32; | |
4922 return this; | |
4923 } | |
4924 type = v->type; | |
4925 if (v->isConst()) | |
4926 { | |
4927 if (v->init) | |
4928 { | |
4929 ExpInitializer *ei = v->init->isExpInitializer(); | |
4930 if (ei) | |
4931 { | |
4932 //printf("\tei: %p (%s)\n", ei->exp, ei->exp->toChars()); | |
4933 //ei->exp = ei->exp->semantic(sc); | |
4934 if (ei->exp->type == type) | |
4935 { | |
4936 e = ei->exp->copy(); // make copy so we can change loc | |
4937 e->loc = loc; | |
4938 return e; | |
4939 } | |
4940 } | |
4941 } | |
4942 else if (type->isscalar()) | |
4943 { | |
4944 e = type->defaultInit(); | |
4945 e->loc = loc; | |
4946 return e; | |
4947 } | |
4948 } | |
4949 if (v->needThis()) | |
4950 { | |
4951 if (!eleft) | |
4952 eleft = new ThisExp(loc); | |
4953 e = new DotVarExp(loc, eleft, v); | |
4954 e = e->semantic(sc); | |
4955 } | |
4956 else | |
4957 { | |
4958 e = new VarExp(loc, v); | |
4959 if (eleft) | |
4960 { e = new CommaExp(loc, eleft, e); | |
4961 e->type = v->type; | |
4962 } | |
4963 } | |
4964 return e->deref(); | |
4965 } | |
4966 | |
4967 FuncDeclaration *f = s->isFuncDeclaration(); | |
4968 if (f) | |
4969 { | |
4970 //printf("it's a function\n"); | |
4971 if (f->needThis()) | |
4972 { | |
4973 if (!eleft) | |
4974 eleft = new ThisExp(loc); | |
4975 e = new DotVarExp(loc, eleft, f); | |
4976 e = e->semantic(sc); | |
4977 } | |
4978 else | |
4979 { | |
4980 e = new VarExp(loc, f); | |
4981 if (eleft) | |
4982 { e = new CommaExp(loc, eleft, e); | |
4983 e->type = f->type; | |
4984 } | |
4985 } | |
4986 return e; | |
4987 } | |
4988 | |
4989 Type *t = s->getType(); | |
4990 if (t) | |
4991 { | |
4992 return new TypeExp(loc, t); | |
4993 } | |
4994 | |
336 | 4995 TupleDeclaration *tup = s->isTupleDeclaration(); |
4996 if (tup) | |
4997 { | |
4998 if (eleft) | |
4999 error("cannot have e.tuple"); | |
5000 e = new TupleExp(loc, tup); | |
5001 e = e->semantic(sc); | |
5002 return e; | |
5003 } | |
5004 | |
159 | 5005 ScopeDsymbol *sds = s->isScopeDsymbol(); |
5006 if (sds) | |
5007 { | |
5008 //printf("it's a ScopeDsymbol\n"); | |
5009 e = new ScopeExp(loc, sds); | |
5010 e = e->semantic(sc); | |
5011 if (eleft) | |
5012 e = new DotExp(loc, eleft, e); | |
5013 return e; | |
5014 } | |
5015 | |
5016 Import *imp = s->isImport(); | |
5017 if (imp) | |
5018 { | |
5019 ScopeExp *ie; | |
5020 | |
5021 ie = new ScopeExp(loc, imp->pkg); | |
5022 return ie->semantic(sc); | |
5023 } | |
5024 | |
5025 // BUG: handle other cases like in IdentifierExp::semantic() | |
5026 #ifdef DEBUG | |
5027 printf("s = '%s', kind = '%s'\n", s->toChars(), s->kind()); | |
5028 #endif | |
5029 assert(0); | |
5030 } | |
5031 else if (ident == Id::stringof) | |
5032 { char *s = ie->toChars(); | |
5033 e = new StringExp(loc, s, strlen(s), 'c'); | |
5034 e = e->semantic(sc); | |
5035 return e; | |
5036 } | |
5037 error("undefined identifier %s", toChars()); | |
5038 type = Type::tvoid; | |
5039 return this; | |
5040 } | |
5041 else if (e1->type->ty == Tpointer && | |
5042 ident != Id::init && ident != Id::__sizeof && | |
5043 ident != Id::alignof && ident != Id::offsetof && | |
5044 ident != Id::mangleof && ident != Id::stringof) | |
5045 { | |
5046 e = new PtrExp(loc, e1); | |
5047 e->type = e1->type->next; | |
5048 return e->type->dotExp(sc, e, ident); | |
5049 } | |
5050 else | |
5051 { | |
5052 e = e1->type->dotExp(sc, e1, ident); | |
5053 e = e->semantic(sc); | |
5054 return e; | |
5055 } | |
5056 } | |
5057 | |
5058 void DotIdExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5059 { | |
5060 //printf("DotIdExp::toCBuffer()\n"); | |
5061 expToCBuffer(buf, hgs, e1, PREC_primary); | |
5062 buf->writeByte('.'); | |
5063 buf->writestring(ident->toChars()); | |
5064 } | |
5065 | |
5066 /********************** DotTemplateExp ***********************************/ | |
5067 | |
5068 // Mainly just a placeholder | |
5069 | |
5070 DotTemplateExp::DotTemplateExp(Loc loc, Expression *e, TemplateDeclaration *td) | |
5071 : UnaExp(loc, TOKdottd, sizeof(DotTemplateExp), e) | |
5072 | |
5073 { | |
5074 this->td = td; | |
5075 } | |
5076 | |
5077 void DotTemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5078 { | |
5079 expToCBuffer(buf, hgs, e1, PREC_primary); | |
5080 buf->writeByte('.'); | |
5081 buf->writestring(td->toChars()); | |
5082 } | |
5083 | |
5084 | |
5085 /************************************************************/ | |
5086 | |
5087 DotVarExp::DotVarExp(Loc loc, Expression *e, Declaration *v) | |
5088 : UnaExp(loc, TOKdotvar, sizeof(DotVarExp), e) | |
5089 { | |
5090 //printf("DotVarExp()\n"); | |
5091 this->var = v; | |
5092 } | |
5093 | |
5094 Expression *DotVarExp::semantic(Scope *sc) | |
5095 { | |
5096 #if LOGSEMANTIC | |
5097 printf("DotVarExp::semantic('%s')\n", toChars()); | |
5098 #endif | |
5099 if (!type) | |
5100 { | |
5101 var = var->toAlias()->isDeclaration(); | |
5102 | |
5103 TupleDeclaration *tup = var->isTupleDeclaration(); | |
5104 if (tup) | |
5105 { /* Replace: | |
5106 * e1.tuple(a, b, c) | |
5107 * with: | |
5108 * tuple(e1.a, e1.b, e1.c) | |
5109 */ | |
5110 Expressions *exps = new Expressions; | |
5111 | |
5112 exps->reserve(tup->objects->dim); | |
5113 for (size_t i = 0; i < tup->objects->dim; i++) | |
5114 { Object *o = (Object *)tup->objects->data[i]; | |
5115 if (o->dyncast() != DYNCAST_EXPRESSION) | |
5116 { | |
5117 error("%s is not an expression", o->toChars()); | |
5118 } | |
5119 else | |
5120 { | |
5121 Expression *e = (Expression *)o; | |
5122 if (e->op != TOKdsymbol) | |
5123 error("%s is not a member", e->toChars()); | |
5124 else | |
5125 { DsymbolExp *ve = (DsymbolExp *)e; | |
5126 | |
5127 e = new DotVarExp(loc, e1, ve->s->isDeclaration()); | |
5128 exps->push(e); | |
5129 } | |
5130 } | |
5131 } | |
5132 Expression *e = new TupleExp(loc, exps); | |
5133 e = e->semantic(sc); | |
5134 return e; | |
5135 } | |
5136 | |
5137 e1 = e1->semantic(sc); | |
5138 type = var->type; | |
5139 if (!type && global.errors) | |
5140 { // var is goofed up, just return 0 | |
5141 return new IntegerExp(0); | |
5142 } | |
5143 assert(type); | |
5144 | |
5145 if (!var->isFuncDeclaration()) // for functions, do checks after overload resolution | |
5146 { | |
5147 AggregateDeclaration *ad = var->toParent()->isAggregateDeclaration(); | |
336 | 5148 e1 = getRightThis(loc, sc, ad, e1, var); |
5149 if (!sc->noaccesscheck) | |
5150 accessCheck(loc, sc, e1, var); | |
5151 | |
5152 VarDeclaration *v = var->isVarDeclaration(); | |
5153 if (v && v->isConst()) | |
5154 { ExpInitializer *ei = v->getExpInitializer(); | |
5155 if (ei) | |
5156 { Expression *e = ei->exp->copy(); | |
5157 e = e->semantic(sc); | |
5158 return e; | |
159 | 5159 } |
5160 } | |
5161 } | |
5162 } | |
5163 //printf("-DotVarExp::semantic('%s')\n", toChars()); | |
5164 return this; | |
5165 } | |
5166 | |
5167 Expression *DotVarExp::toLvalue(Scope *sc, Expression *e) | |
5168 { | |
5169 //printf("DotVarExp::toLvalue(%s)\n", toChars()); | |
5170 return this; | |
5171 } | |
5172 | |
5173 Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e) | |
5174 { | |
5175 //printf("DotVarExp::modifiableLvalue(%s)\n", toChars()); | |
5176 | |
5177 if (var->isCtorinit()) | |
5178 { // It's only modifiable if inside the right constructor | |
5179 Dsymbol *s = sc->func; | |
5180 while (1) | |
5181 { | |
5182 FuncDeclaration *fd = NULL; | |
5183 if (s) | |
5184 fd = s->isFuncDeclaration(); | |
5185 if (fd && | |
5186 ((fd->isCtorDeclaration() && var->storage_class & STCfield) || | |
5187 (fd->isStaticCtorDeclaration() && !(var->storage_class & STCfield))) && | |
5188 fd->toParent() == var->toParent() && | |
5189 e1->op == TOKthis | |
5190 ) | |
5191 { | |
5192 VarDeclaration *v = var->isVarDeclaration(); | |
5193 assert(v); | |
5194 v->ctorinit = 1; | |
5195 //printf("setting ctorinit\n"); | |
5196 } | |
5197 else | |
5198 { | |
5199 if (s) | |
5200 { s = s->toParent2(); | |
5201 continue; | |
5202 } | |
5203 else | |
5204 { | |
5205 const char *p = var->isStatic() ? "static " : ""; | |
5206 error("can only initialize %sconst member %s inside %sconstructor", | |
5207 p, var->toChars(), p); | |
5208 } | |
5209 } | |
5210 break; | |
5211 } | |
5212 } | |
5213 return this; | |
5214 } | |
5215 | |
5216 void DotVarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5217 { | |
5218 expToCBuffer(buf, hgs, e1, PREC_primary); | |
5219 buf->writeByte('.'); | |
5220 buf->writestring(var->toChars()); | |
5221 } | |
5222 | |
5223 /************************************************************/ | |
5224 | |
5225 /* Things like: | |
5226 * foo.bar!(args) | |
5227 */ | |
5228 | |
5229 DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc, Expression *e, TemplateInstance *ti) | |
5230 : UnaExp(loc, TOKdotti, sizeof(DotTemplateInstanceExp), e) | |
5231 { | |
5232 //printf("DotTemplateInstanceExp()\n"); | |
5233 this->ti = ti; | |
5234 } | |
5235 | |
5236 Expression *DotTemplateInstanceExp::syntaxCopy() | |
5237 { | |
5238 DotTemplateInstanceExp *de = new DotTemplateInstanceExp(loc, | |
5239 e1->syntaxCopy(), | |
5240 (TemplateInstance *)ti->syntaxCopy(NULL)); | |
5241 return de; | |
5242 } | |
5243 | |
5244 Expression *DotTemplateInstanceExp::semantic(Scope *sc) | |
5245 { Dsymbol *s; | |
5246 Dsymbol *s2; | |
5247 TemplateDeclaration *td; | |
5248 Expression *e; | |
5249 Identifier *id; | |
5250 Type *t1; | |
5251 Expression *eleft = NULL; | |
5252 Expression *eright; | |
5253 | |
5254 #if LOGSEMANTIC | |
5255 printf("DotTemplateInstanceExp::semantic('%s')\n", toChars()); | |
5256 #endif | |
5257 //e1->print(); | |
5258 //print(); | |
5259 e1 = e1->semantic(sc); | |
5260 t1 = e1->type; | |
5261 if (t1) | |
5262 t1 = t1->toBasetype(); | |
5263 //t1->print(); | |
5264 if (e1->op == TOKdotexp) | |
5265 { DotExp *de = (DotExp *)e1; | |
5266 eleft = de->e1; | |
5267 eright = de->e2; | |
5268 } | |
5269 else | |
5270 { eleft = NULL; | |
5271 eright = e1; | |
5272 } | |
5273 if (eright->op == TOKimport) | |
5274 { | |
5275 s = ((ScopeExp *)eright)->sds; | |
5276 } | |
5277 else if (e1->op == TOKtype) | |
5278 { | |
5279 s = t1->isClassHandle(); | |
5280 if (!s) | |
5281 { if (t1->ty == Tstruct) | |
5282 s = ((TypeStruct *)t1)->sym; | |
5283 else | |
5284 goto L1; | |
5285 } | |
5286 } | |
5287 else if (t1 && (t1->ty == Tstruct || t1->ty == Tclass)) | |
5288 { | |
5289 s = t1->toDsymbol(sc); | |
5290 eleft = e1; | |
5291 } | |
5292 else if (t1 && t1->ty == Tpointer) | |
5293 { | |
5294 t1 = t1->next->toBasetype(); | |
5295 if (t1->ty != Tstruct) | |
5296 goto L1; | |
5297 s = t1->toDsymbol(sc); | |
5298 eleft = e1; | |
5299 } | |
5300 else | |
5301 { | |
5302 L1: | |
5303 error("template %s is not a member of %s", ti->toChars(), e1->toChars()); | |
5304 goto Lerr; | |
5305 } | |
5306 | |
5307 assert(s); | |
5308 id = ti->name; | |
5309 s2 = s->search(loc, id, 0); | |
5310 if (!s2) | |
5311 { error("template identifier %s is not a member of %s %s", id->toChars(), s->kind(), s->ident->toChars()); | |
5312 goto Lerr; | |
5313 } | |
5314 s = s2; | |
5315 s->semantic(sc); | |
5316 s = s->toAlias(); | |
5317 td = s->isTemplateDeclaration(); | |
5318 if (!td) | |
5319 { | |
5320 error("%s is not a template", id->toChars()); | |
5321 goto Lerr; | |
5322 } | |
5323 if (global.errors) | |
5324 goto Lerr; | |
5325 | |
5326 ti->tempdecl = td; | |
5327 | |
5328 if (eleft) | |
5329 { Declaration *v; | |
5330 | |
5331 ti->semantic(sc); | |
5332 s = ti->inst->toAlias(); | |
5333 v = s->isDeclaration(); | |
5334 if (v) | |
5335 { e = new DotVarExp(loc, eleft, v); | |
5336 e = e->semantic(sc); | |
5337 return e; | |
5338 } | |
5339 } | |
5340 | |
5341 e = new ScopeExp(loc, ti); | |
5342 if (eleft) | |
5343 { | |
5344 e = new DotExp(loc, eleft, e); | |
5345 } | |
5346 e = e->semantic(sc); | |
5347 return e; | |
5348 | |
5349 Lerr: | |
336 | 5350 return new IntegerExp(loc, 0, Type::tint32); |
159 | 5351 } |
5352 | |
5353 void DotTemplateInstanceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5354 { | |
5355 expToCBuffer(buf, hgs, e1, PREC_primary); | |
5356 buf->writeByte('.'); | |
5357 ti->toCBuffer(buf, hgs); | |
5358 } | |
5359 | |
5360 /************************************************************/ | |
5361 | |
5362 DelegateExp::DelegateExp(Loc loc, Expression *e, FuncDeclaration *f) | |
5363 : UnaExp(loc, TOKdelegate, sizeof(DelegateExp), e) | |
5364 { | |
5365 this->func = f; | |
5366 } | |
5367 | |
5368 Expression *DelegateExp::semantic(Scope *sc) | |
5369 { | |
5370 #if LOGSEMANTIC | |
5371 printf("DelegateExp::semantic('%s')\n", toChars()); | |
5372 #endif | |
5373 if (!type) | |
5374 { | |
5375 e1 = e1->semantic(sc); | |
5376 type = new TypeDelegate(func->type); | |
5377 type = type->semantic(loc, sc); | |
5378 AggregateDeclaration *ad = func->toParent()->isAggregateDeclaration(); | |
336 | 5379 if (func->needThis()) |
5380 e1 = getRightThis(loc, sc, ad, e1, func); | |
159 | 5381 } |
5382 return this; | |
5383 } | |
5384 | |
5385 void DelegateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5386 { | |
5387 buf->writeByte('&'); | |
5388 if (!func->isNested()) | |
5389 { | |
5390 expToCBuffer(buf, hgs, e1, PREC_primary); | |
5391 buf->writeByte('.'); | |
5392 } | |
5393 buf->writestring(func->toChars()); | |
5394 } | |
5395 | |
5396 /************************************************************/ | |
5397 | |
5398 DotTypeExp::DotTypeExp(Loc loc, Expression *e, Dsymbol *s) | |
5399 : UnaExp(loc, TOKdottype, sizeof(DotTypeExp), e) | |
5400 { | |
5401 this->sym = s; | |
5402 this->type = s->getType(); | |
5403 } | |
5404 | |
5405 Expression *DotTypeExp::semantic(Scope *sc) | |
5406 { | |
5407 #if LOGSEMANTIC | |
5408 printf("DotTypeExp::semantic('%s')\n", toChars()); | |
5409 #endif | |
5410 UnaExp::semantic(sc); | |
5411 return this; | |
5412 } | |
5413 | |
5414 void DotTypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5415 { | |
5416 expToCBuffer(buf, hgs, e1, PREC_primary); | |
5417 buf->writeByte('.'); | |
5418 buf->writestring(sym->toChars()); | |
5419 } | |
5420 | |
5421 /************************************************************/ | |
5422 | |
5423 CallExp::CallExp(Loc loc, Expression *e, Expressions *exps) | |
5424 : UnaExp(loc, TOKcall, sizeof(CallExp), e) | |
5425 { | |
5426 this->arguments = exps; | |
5427 } | |
5428 | |
5429 CallExp::CallExp(Loc loc, Expression *e) | |
5430 : UnaExp(loc, TOKcall, sizeof(CallExp), e) | |
5431 { | |
5432 this->arguments = NULL; | |
5433 } | |
5434 | |
5435 CallExp::CallExp(Loc loc, Expression *e, Expression *earg1) | |
5436 : UnaExp(loc, TOKcall, sizeof(CallExp), e) | |
5437 { | |
5438 Expressions *arguments = new Expressions(); | |
5439 arguments->setDim(1); | |
5440 arguments->data[0] = (void *)earg1; | |
5441 | |
5442 this->arguments = arguments; | |
5443 } | |
5444 | |
5445 CallExp::CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2) | |
5446 : UnaExp(loc, TOKcall, sizeof(CallExp), e) | |
5447 { | |
5448 Expressions *arguments = new Expressions(); | |
5449 arguments->setDim(2); | |
5450 arguments->data[0] = (void *)earg1; | |
5451 arguments->data[1] = (void *)earg2; | |
5452 | |
5453 this->arguments = arguments; | |
5454 } | |
5455 | |
5456 Expression *CallExp::syntaxCopy() | |
5457 { | |
5458 return new CallExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments)); | |
5459 } | |
5460 | |
5461 | |
5462 Expression *CallExp::semantic(Scope *sc) | |
5463 { | |
5464 TypeFunction *tf; | |
5465 FuncDeclaration *f; | |
5466 int i; | |
5467 Type *t1; | |
5468 int istemp; | |
5469 | |
5470 #if LOGSEMANTIC | |
5471 printf("CallExp::semantic() %s\n", toChars()); | |
5472 #endif | |
5473 if (type) | |
5474 return this; // semantic() already run | |
5475 #if 0 | |
5476 if (arguments && arguments->dim) | |
5477 { | |
5478 Expression *earg = (Expression *)arguments->data[0]; | |
5479 earg->print(); | |
5480 if (earg->type) earg->type->print(); | |
5481 } | |
5482 #endif | |
5483 | |
5484 if (e1->op == TOKdelegate) | |
5485 { DelegateExp *de = (DelegateExp *)e1; | |
5486 | |
5487 e1 = new DotVarExp(de->loc, de->e1, de->func); | |
5488 return semantic(sc); | |
5489 } | |
5490 | |
5491 /* Transform: | |
5492 * array.id(args) into id(array,args) | |
5493 * aa.remove(arg) into delete aa[arg] | |
5494 */ | |
5495 if (e1->op == TOKdot) | |
5496 { | |
5497 // BUG: we should handle array.a.b.c.e(args) too | |
5498 | |
5499 DotIdExp *dotid = (DotIdExp *)(e1); | |
5500 dotid->e1 = dotid->e1->semantic(sc); | |
5501 assert(dotid->e1); | |
5502 if (dotid->e1->type) | |
5503 { | |
5504 TY e1ty = dotid->e1->type->toBasetype()->ty; | |
5505 if (e1ty == Taarray && dotid->ident == Id::remove) | |
5506 { | |
5507 if (!arguments || arguments->dim != 1) | |
5508 { error("expected key as argument to aa.remove()"); | |
5509 goto Lagain; | |
5510 } | |
5511 Expression *key = (Expression *)arguments->data[0]; | |
5512 key = key->semantic(sc); | |
5513 key = resolveProperties(sc, key); | |
5514 key->rvalue(); | |
5515 | |
5516 TypeAArray *taa = (TypeAArray *)dotid->e1->type->toBasetype(); | |
5517 key = key->implicitCastTo(sc, taa->index); | |
5518 key = key->implicitCastTo(sc, taa->key); | |
5519 | |
5520 return new RemoveExp(loc, dotid->e1, key); | |
5521 } | |
5522 else if (e1ty == Tarray || e1ty == Tsarray || e1ty == Taarray) | |
5523 { | |
5524 if (!arguments) | |
5525 arguments = new Expressions(); | |
5526 arguments->shift(dotid->e1); | |
5527 e1 = new IdentifierExp(dotid->loc, dotid->ident); | |
5528 } | |
5529 } | |
5530 } | |
5531 | |
5532 istemp = 0; | |
5533 Lagain: | |
5534 f = NULL; | |
5535 if (e1->op == TOKthis || e1->op == TOKsuper) | |
5536 { | |
5537 // semantic() run later for these | |
5538 } | |
5539 else | |
5540 { | |
5541 UnaExp::semantic(sc); | |
5542 | |
5543 /* Look for e1 being a lazy parameter | |
5544 */ | |
5545 if (e1->op == TOKvar) | |
5546 { VarExp *ve = (VarExp *)e1; | |
5547 | |
5548 if (ve->var->storage_class & STClazy) | |
5549 { | |
5550 TypeFunction *tf = new TypeFunction(NULL, ve->var->type, 0, LINKd); | |
5551 TypeDelegate *t = new TypeDelegate(tf); | |
5552 ve->type = t->semantic(loc, sc); | |
5553 } | |
5554 } | |
5555 | |
5556 if (e1->op == TOKimport) | |
5557 { // Perhaps this should be moved to ScopeExp::semantic() | |
5558 ScopeExp *se = (ScopeExp *)e1; | |
5559 e1 = new DsymbolExp(loc, se->sds); | |
5560 e1 = e1->semantic(sc); | |
5561 } | |
5562 #if 1 // patch for #540 by Oskar Linde | |
5563 else if (e1->op == TOKdotexp) | |
5564 { | |
5565 DotExp *de = (DotExp *) e1; | |
5566 | |
5567 if (de->e2->op == TOKimport) | |
5568 { // This should *really* be moved to ScopeExp::semantic() | |
5569 ScopeExp *se = (ScopeExp *)de->e2; | |
5570 de->e2 = new DsymbolExp(loc, se->sds); | |
5571 de->e2 = de->e2->semantic(sc); | |
5572 } | |
5573 | |
5574 if (de->e2->op == TOKtemplate) | |
5575 { TemplateExp *te = (TemplateExp *) de->e2; | |
5576 e1 = new DotTemplateExp(loc,de->e1,te->td); | |
5577 } | |
5578 } | |
5579 #endif | |
5580 } | |
5581 | |
5582 if (e1->op == TOKcomma) | |
5583 { | |
5584 CommaExp *ce = (CommaExp *)e1; | |
5585 | |
5586 e1 = ce->e2; | |
5587 e1->type = ce->type; | |
5588 ce->e2 = this; | |
5589 ce->type = NULL; | |
5590 return ce->semantic(sc); | |
5591 } | |
5592 | |
5593 t1 = NULL; | |
5594 if (e1->type) | |
5595 t1 = e1->type->toBasetype(); | |
5596 | |
5597 // Check for call operator overload | |
5598 if (t1) | |
5599 { AggregateDeclaration *ad; | |
5600 | |
5601 if (t1->ty == Tstruct) | |
5602 { | |
5603 ad = ((TypeStruct *)t1)->sym; | |
5604 if (search_function(ad, Id::call)) | |
5605 goto L1; // overload of opCall, therefore it's a call | |
5606 | |
5607 if (e1->op != TOKtype) | |
5608 error("%s %s does not overload ()", ad->kind(), ad->toChars()); | |
5609 /* It's a struct literal | |
5610 */ | |
5611 Expression *e = new StructLiteralExp(loc, (StructDeclaration *)ad, arguments); | |
5612 e = e->semantic(sc); | |
5613 e->type = e1->type; // in case e1->type was a typedef | |
5614 return e; | |
5615 } | |
5616 else if (t1->ty == Tclass) | |
5617 { | |
5618 ad = ((TypeClass *)t1)->sym; | |
5619 goto L1; | |
5620 L1: | |
5621 // Rewrite as e1.call(arguments) | |
5622 Expression *e = new DotIdExp(loc, e1, Id::call); | |
5623 e = new CallExp(loc, e, arguments); | |
5624 e = e->semantic(sc); | |
5625 return e; | |
5626 } | |
5627 } | |
5628 | |
5629 arrayExpressionSemantic(arguments, sc); | |
5630 preFunctionArguments(loc, sc, arguments); | |
5631 | |
5632 if (e1->op == TOKdotvar && t1->ty == Tfunction || | |
5633 e1->op == TOKdottd) | |
5634 { | |
5635 DotVarExp *dve; | |
5636 DotTemplateExp *dte; | |
5637 AggregateDeclaration *ad; | |
5638 UnaExp *ue = (UnaExp *)(e1); | |
336 | 5639 |
159 | 5640 if (e1->op == TOKdotvar) |
5641 { // Do overload resolution | |
5642 dve = (DotVarExp *)(e1); | |
5643 | |
5644 f = dve->var->isFuncDeclaration(); | |
5645 assert(f); | |
5646 f = f->overloadResolve(loc, arguments); | |
5647 | |
5648 ad = f->toParent()->isAggregateDeclaration(); | |
5649 } | |
5650 else | |
5651 { dte = (DotTemplateExp *)(e1); | |
5652 TemplateDeclaration *td = dte->td; | |
5653 assert(td); | |
5654 if (!arguments) | |
5655 // Should fix deduceFunctionTemplate() so it works on NULL argument | |
5656 arguments = new Expressions(); | |
5657 f = td->deduceFunctionTemplate(sc, loc, NULL, arguments); | |
5658 if (!f) | |
5659 { type = Type::terror; | |
5660 return this; | |
5661 } | |
5662 ad = td->toParent()->isAggregateDeclaration(); | |
5663 } | |
336 | 5664 if (f->needThis()) |
5665 { | |
5666 ue->e1 = getRightThis(loc, sc, ad, ue->e1, f); | |
5667 } | |
5668 | |
5669 /* Cannot call public functions from inside invariant | |
5670 * (because then the invariant would have infinite recursion) | |
159 | 5671 */ |
336 | 5672 if (sc->func && sc->func->isInvariantDeclaration() && |
5673 ue->e1->op == TOKthis && | |
5674 f->addPostInvariant() | |
159 | 5675 ) |
5676 { | |
336 | 5677 error("cannot call public/export function %s from invariant", f->toChars()); |
159 | 5678 } |
5679 | |
5680 checkDeprecated(sc, f); | |
5681 accessCheck(loc, sc, ue->e1, f); | |
5682 if (!f->needThis()) | |
5683 { | |
5684 VarExp *ve = new VarExp(loc, f); | |
5685 e1 = new CommaExp(loc, ue->e1, ve); | |
5686 e1->type = f->type; | |
5687 } | |
5688 else | |
5689 { | |
5690 if (e1->op == TOKdotvar) | |
5691 dve->var = f; | |
5692 else | |
5693 e1 = new DotVarExp(loc, dte->e1, f); | |
5694 e1->type = f->type; | |
5695 | |
5696 // See if we need to adjust the 'this' pointer | |
5697 AggregateDeclaration *ad = f->isThis(); | |
5698 ClassDeclaration *cd = ue->e1->type->isClassHandle(); | |
5699 if (ad && cd && ad->isClassDeclaration() && ad != cd && | |
5700 ue->e1->op != TOKsuper) | |
5701 { | |
5702 ue->e1 = ue->e1->castTo(sc, ad->type); //new CastExp(loc, ue->e1, ad->type); | |
5703 ue->e1 = ue->e1->semantic(sc); | |
5704 } | |
5705 } | |
5706 t1 = e1->type; | |
5707 } | |
5708 else if (e1->op == TOKsuper) | |
5709 { | |
5710 // Base class constructor call | |
5711 ClassDeclaration *cd = NULL; | |
5712 | |
5713 if (sc->func) | |
5714 cd = sc->func->toParent()->isClassDeclaration(); | |
5715 if (!cd || !cd->baseClass || !sc->func->isCtorDeclaration()) | |
5716 { | |
5717 error("super class constructor call must be in a constructor"); | |
5718 type = Type::terror; | |
5719 return this; | |
5720 } | |
5721 else | |
5722 { | |
5723 f = cd->baseClass->ctor; | |
5724 if (!f) | |
5725 { error("no super class constructor for %s", cd->baseClass->toChars()); | |
5726 type = Type::terror; | |
5727 return this; | |
5728 } | |
5729 else | |
5730 { | |
336 | 5731 if (!sc->intypeof) |
5732 { | |
159 | 5733 #if 0 |
336 | 5734 if (sc->callSuper & (CSXthis | CSXsuper)) |
5735 error("reference to this before super()"); | |
159 | 5736 #endif |
336 | 5737 if (sc->noctor || sc->callSuper & CSXlabel) |
5738 error("constructor calls not allowed in loops or after labels"); | |
5739 if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor)) | |
5740 error("multiple constructor calls"); | |
5741 sc->callSuper |= CSXany_ctor | CSXsuper_ctor; | |
5742 } | |
159 | 5743 |
5744 f = f->overloadResolve(loc, arguments); | |
5745 checkDeprecated(sc, f); | |
5746 e1 = new DotVarExp(e1->loc, e1, f); | |
5747 e1 = e1->semantic(sc); | |
5748 t1 = e1->type; | |
5749 } | |
5750 } | |
5751 } | |
5752 else if (e1->op == TOKthis) | |
5753 { | |
5754 // same class constructor call | |
5755 ClassDeclaration *cd = NULL; | |
5756 | |
5757 if (sc->func) | |
5758 cd = sc->func->toParent()->isClassDeclaration(); | |
5759 if (!cd || !sc->func->isCtorDeclaration()) | |
5760 { | |
5761 error("class constructor call must be in a constructor"); | |
5762 type = Type::terror; | |
5763 return this; | |
5764 } | |
5765 else | |
5766 { | |
336 | 5767 if (!sc->intypeof) |
5768 { | |
159 | 5769 #if 0 |
336 | 5770 if (sc->callSuper & (CSXthis | CSXsuper)) |
5771 error("reference to this before super()"); | |
159 | 5772 #endif |
336 | 5773 if (sc->noctor || sc->callSuper & CSXlabel) |
5774 error("constructor calls not allowed in loops or after labels"); | |
5775 if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor)) | |
5776 error("multiple constructor calls"); | |
5777 sc->callSuper |= CSXany_ctor | CSXthis_ctor; | |
5778 } | |
159 | 5779 |
5780 f = cd->ctor; | |
5781 f = f->overloadResolve(loc, arguments); | |
5782 checkDeprecated(sc, f); | |
5783 e1 = new DotVarExp(e1->loc, e1, f); | |
5784 e1 = e1->semantic(sc); | |
5785 t1 = e1->type; | |
5786 | |
5787 // BUG: this should really be done by checking the static | |
5788 // call graph | |
5789 if (f == sc->func) | |
5790 error("cyclic constructor call"); | |
5791 } | |
5792 } | |
5793 else if (!t1) | |
5794 { | |
5795 error("function expected before (), not '%s'", e1->toChars()); | |
5796 type = Type::terror; | |
5797 return this; | |
5798 } | |
5799 else if (t1->ty != Tfunction) | |
5800 { | |
5801 if (t1->ty == Tdelegate) | |
5802 { | |
5803 assert(t1->next->ty == Tfunction); | |
5804 tf = (TypeFunction *)(t1->next); | |
5805 goto Lcheckargs; | |
5806 } | |
5807 else if (t1->ty == Tpointer && t1->next->ty == Tfunction) | |
5808 { Expression *e; | |
5809 | |
5810 e = new PtrExp(loc, e1); | |
5811 t1 = t1->next; | |
5812 e->type = t1; | |
5813 e1 = e; | |
5814 } | |
5815 else if (e1->op == TOKtemplate) | |
5816 { | |
5817 TemplateExp *te = (TemplateExp *)e1; | |
5818 f = te->td->deduceFunctionTemplate(sc, loc, NULL, arguments); | |
5819 if (!f) | |
5820 { type = Type::terror; | |
5821 return this; | |
5822 } | |
5823 if (f->needThis() && hasThis(sc)) | |
5824 { | |
5825 // Supply an implicit 'this', as in | |
5826 // this.ident | |
5827 | |
5828 e1 = new DotTemplateExp(loc, (new ThisExp(loc))->semantic(sc), te->td); | |
5829 goto Lagain; | |
5830 } | |
5831 | |
5832 e1 = new VarExp(loc, f); | |
5833 goto Lagain; | |
5834 } | |
5835 else | |
5836 { error("function expected before (), not %s of type %s", e1->toChars(), e1->type->toChars()); | |
5837 type = Type::terror; | |
5838 return this; | |
5839 } | |
5840 } | |
5841 else if (e1->op == TOKvar) | |
5842 { | |
5843 // Do overload resolution | |
5844 VarExp *ve = (VarExp *)e1; | |
5845 | |
5846 f = ve->var->isFuncDeclaration(); | |
5847 assert(f); | |
5848 | |
5849 // Look to see if f is really a function template | |
5850 if (0 && !istemp && f->parent) | |
5851 { TemplateInstance *ti = f->parent->isTemplateInstance(); | |
5852 | |
5853 if (ti && | |
5854 (ti->name == f->ident || | |
5855 ti->toAlias()->ident == f->ident) | |
5856 && | |
5857 ti->tempdecl) | |
5858 { | |
5859 /* This is so that one can refer to the enclosing | |
5860 * template, even if it has the same name as a member | |
5861 * of the template, if it has a !(arguments) | |
5862 */ | |
5863 TemplateDeclaration *tempdecl = ti->tempdecl; | |
5864 if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's | |
5865 tempdecl = tempdecl->overroot; // then get the start | |
5866 e1 = new TemplateExp(loc, tempdecl); | |
5867 istemp = 1; | |
5868 goto Lagain; | |
5869 } | |
5870 } | |
5871 | |
5872 f = f->overloadResolve(loc, arguments); | |
5873 checkDeprecated(sc, f); | |
5874 | |
5875 if (f->needThis() && hasThis(sc)) | |
5876 { | |
5877 // Supply an implicit 'this', as in | |
5878 // this.ident | |
5879 | |
5880 e1 = new DotVarExp(loc, new ThisExp(loc), f); | |
5881 goto Lagain; | |
5882 } | |
5883 | |
5884 accessCheck(loc, sc, NULL, f); | |
5885 | |
5886 ve->var = f; | |
5887 ve->type = f->type; | |
5888 t1 = f->type; | |
5889 } | |
5890 assert(t1->ty == Tfunction); | |
5891 tf = (TypeFunction *)(t1); | |
5892 | |
5893 Lcheckargs: | |
5894 assert(tf->ty == Tfunction); | |
5895 type = tf->next; | |
5896 | |
5897 if (!arguments) | |
5898 arguments = new Expressions(); | |
5899 functionArguments(loc, sc, tf, arguments); | |
5900 | |
5901 assert(type); | |
5902 | |
5903 if (f && f->tintro) | |
5904 { | |
5905 Type *t = type; | |
5906 int offset = 0; | |
5907 | |
5908 if (f->tintro->next->isBaseOf(t, &offset) && offset) | |
5909 { | |
5910 type = f->tintro->next; | |
5911 return castTo(sc, t); | |
5912 } | |
5913 } | |
5914 | |
5915 return this; | |
5916 } | |
5917 | |
5918 int CallExp::checkSideEffect(int flag) | |
5919 { | |
5920 return 1; | |
5921 } | |
5922 | |
5923 Expression *CallExp::toLvalue(Scope *sc, Expression *e) | |
5924 { | |
5925 if (type->toBasetype()->ty == Tstruct) | |
5926 return this; | |
5927 else | |
5928 return Expression::toLvalue(sc, e); | |
5929 } | |
5930 | |
5931 void CallExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5932 { int i; | |
5933 | |
5934 expToCBuffer(buf, hgs, e1, precedence[op]); | |
5935 buf->writeByte('('); | |
5936 argsToCBuffer(buf, arguments, hgs); | |
5937 buf->writeByte(')'); | |
5938 } | |
5939 | |
5940 | |
5941 /************************************************************/ | |
5942 | |
5943 AddrExp::AddrExp(Loc loc, Expression *e) | |
5944 : UnaExp(loc, TOKaddress, sizeof(AddrExp), e) | |
5945 { | |
5946 } | |
5947 | |
5948 Expression *AddrExp::semantic(Scope *sc) | |
5949 { | |
5950 #if LOGSEMANTIC | |
5951 printf("AddrExp::semantic('%s')\n", toChars()); | |
5952 #endif | |
5953 if (!type) | |
5954 { | |
5955 UnaExp::semantic(sc); | |
5956 e1 = e1->toLvalue(sc, NULL); | |
5957 if (!e1->type) | |
5958 { | |
5959 error("cannot take address of %s", e1->toChars()); | |
5960 type = Type::tint32; | |
5961 return this; | |
5962 } | |
5963 type = e1->type->pointerTo(); | |
5964 | |
5965 // See if this should really be a delegate | |
5966 if (e1->op == TOKdotvar) | |
5967 { | |
5968 DotVarExp *dve = (DotVarExp *)e1; | |
5969 FuncDeclaration *f = dve->var->isFuncDeclaration(); | |
5970 | |
5971 if (f) | |
5972 { Expression *e; | |
5973 | |
5974 e = new DelegateExp(loc, dve->e1, f); | |
5975 e = e->semantic(sc); | |
5976 return e; | |
5977 } | |
5978 } | |
5979 else if (e1->op == TOKvar) | |
5980 { | |
5981 VarExp *dve = (VarExp *)e1; | |
5982 FuncDeclaration *f = dve->var->isFuncDeclaration(); | |
5983 VarDeclaration *v = dve->var->isVarDeclaration(); | |
5984 | |
5985 if (f && f->isNested()) | |
5986 { Expression *e; | |
5987 | |
5988 e = new DelegateExp(loc, e1, f); | |
5989 e = e->semantic(sc); | |
5990 return e; | |
5991 } | |
5992 } | |
5993 else if (e1->op == TOKarray) | |
5994 { | |
5995 if (e1->type->toBasetype()->ty == Tbit) | |
5996 error("cannot take address of bit in array"); | |
5997 } | |
5998 return optimize(WANTvalue); | |
5999 } | |
6000 return this; | |
6001 } | |
6002 | |
6003 /************************************************************/ | |
6004 | |
6005 PtrExp::PtrExp(Loc loc, Expression *e) | |
6006 : UnaExp(loc, TOKstar, sizeof(PtrExp), e) | |
6007 { | |
6008 if (e->type) | |
6009 type = e->type->next; | |
6010 } | |
6011 | |
6012 PtrExp::PtrExp(Loc loc, Expression *e, Type *t) | |
6013 : UnaExp(loc, TOKstar, sizeof(PtrExp), e) | |
6014 { | |
6015 type = t; | |
6016 } | |
6017 | |
6018 Expression *PtrExp::semantic(Scope *sc) | |
6019 { Type *tb; | |
6020 | |
6021 #if LOGSEMANTIC | |
6022 printf("PtrExp::semantic('%s')\n", toChars()); | |
6023 #endif | |
6024 UnaExp::semantic(sc); | |
6025 e1 = resolveProperties(sc, e1); | |
6026 if (type) | |
6027 return this; | |
6028 if (!e1->type) | |
6029 printf("PtrExp::semantic('%s')\n", toChars()); | |
6030 tb = e1->type->toBasetype(); | |
6031 switch (tb->ty) | |
6032 { | |
6033 case Tpointer: | |
6034 type = tb->next; | |
6035 if (type->isbit()) | |
6036 { Expression *e; | |
6037 | |
6038 // Rewrite *p as p[0] | |
6039 e = new IndexExp(loc, e1, new IntegerExp(0)); | |
6040 return e->semantic(sc); | |
6041 } | |
6042 break; | |
6043 | |
6044 case Tsarray: | |
6045 case Tarray: | |
6046 type = tb->next; | |
6047 e1 = e1->castTo(sc, type->pointerTo()); | |
6048 break; | |
6049 | |
6050 default: | |
6051 error("can only * a pointer, not a '%s'", e1->type->toChars()); | |
6052 type = Type::tint32; | |
6053 break; | |
6054 } | |
6055 rvalue(); | |
6056 return this; | |
6057 } | |
6058 | |
6059 Expression *PtrExp::toLvalue(Scope *sc, Expression *e) | |
6060 { | |
6061 #if 0 | |
6062 tym = tybasic(e1->ET->Tty); | |
6063 if (!(tyscalar(tym) || | |
6064 tym == TYstruct || | |
6065 tym == TYarray && e->Eoper == TOKaddr)) | |
6066 synerr(EM_lvalue); // lvalue expected | |
6067 #endif | |
6068 return this; | |
6069 } | |
6070 | |
6071 void PtrExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
6072 { | |
6073 buf->writeByte('*'); | |
6074 expToCBuffer(buf, hgs, e1, precedence[op]); | |
6075 } | |
6076 | |
6077 /************************************************************/ | |
6078 | |
6079 NegExp::NegExp(Loc loc, Expression *e) | |
6080 : UnaExp(loc, TOKneg, sizeof(NegExp), e) | |
6081 { | |
6082 } | |
6083 | |
6084 Expression *NegExp::semantic(Scope *sc) | |
6085 { Expression *e; | |
6086 | |
6087 #if LOGSEMANTIC | |
6088 printf("NegExp::semantic('%s')\n", toChars()); | |
6089 #endif | |
6090 if (!type) | |
6091 { | |
6092 UnaExp::semantic(sc); | |
6093 e1 = resolveProperties(sc, e1); | |
6094 e = op_overload(sc); | |
6095 if (e) | |
6096 return e; | |
6097 | |
6098 e1->checkNoBool(); | |
6099 e1->checkArithmetic(); | |
6100 type = e1->type; | |
6101 } | |
6102 return this; | |
6103 } | |
6104 | |
6105 /************************************************************/ | |
6106 | |
6107 UAddExp::UAddExp(Loc loc, Expression *e) | |
6108 : UnaExp(loc, TOKuadd, sizeof(UAddExp), e) | |
6109 { | |
6110 } | |
6111 | |
6112 Expression *UAddExp::semantic(Scope *sc) | |
6113 { Expression *e; | |
6114 | |
6115 #if LOGSEMANTIC | |
6116 printf("UAddExp::semantic('%s')\n", toChars()); | |
6117 #endif | |
6118 assert(!type); | |
6119 UnaExp::semantic(sc); | |
6120 e1 = resolveProperties(sc, e1); | |
6121 e = op_overload(sc); | |
6122 if (e) | |
6123 return e; | |
6124 e1->checkNoBool(); | |
6125 e1->checkArithmetic(); | |
6126 return e1; | |
6127 } | |
6128 | |
6129 /************************************************************/ | |
6130 | |
6131 ComExp::ComExp(Loc loc, Expression *e) | |
6132 : UnaExp(loc, TOKtilde, sizeof(ComExp), e) | |
6133 { | |
6134 } | |
6135 | |
6136 Expression *ComExp::semantic(Scope *sc) | |
6137 { Expression *e; | |
6138 | |
6139 if (!type) | |
6140 { | |
6141 UnaExp::semantic(sc); | |
6142 e1 = resolveProperties(sc, e1); | |
6143 e = op_overload(sc); | |
6144 if (e) | |
6145 return e; | |
6146 | |
6147 e1->checkNoBool(); | |
6148 e1 = e1->checkIntegral(); | |
6149 type = e1->type; | |
6150 } | |
6151 return this; | |
6152 } | |
6153 | |
6154 /************************************************************/ | |
6155 | |
6156 NotExp::NotExp(Loc loc, Expression *e) | |
6157 : UnaExp(loc, TOKnot, sizeof(NotExp), e) | |
6158 { | |
6159 } | |
6160 | |
6161 Expression *NotExp::semantic(Scope *sc) | |
6162 { | |
6163 UnaExp::semantic(sc); | |
6164 e1 = resolveProperties(sc, e1); | |
6165 e1 = e1->checkToBoolean(); | |
6166 type = Type::tboolean; | |
6167 return this; | |
6168 } | |
6169 | |
6170 int NotExp::isBit() | |
6171 { | |
6172 return TRUE; | |
6173 } | |
6174 | |
6175 | |
6176 | |
6177 /************************************************************/ | |
6178 | |
6179 BoolExp::BoolExp(Loc loc, Expression *e, Type *t) | |
6180 : UnaExp(loc, TOKtobool, sizeof(BoolExp), e) | |
6181 { | |
6182 type = t; | |
6183 } | |
6184 | |
6185 Expression *BoolExp::semantic(Scope *sc) | |
6186 { | |
6187 UnaExp::semantic(sc); | |
6188 e1 = resolveProperties(sc, e1); | |
6189 e1 = e1->checkToBoolean(); | |
6190 type = Type::tboolean; | |
6191 return this; | |
6192 } | |
6193 | |
6194 int BoolExp::isBit() | |
6195 { | |
6196 return TRUE; | |
6197 } | |
6198 | |
6199 /************************************************************/ | |
6200 | |
6201 DeleteExp::DeleteExp(Loc loc, Expression *e) | |
6202 : UnaExp(loc, TOKdelete, sizeof(DeleteExp), e) | |
6203 { | |
6204 } | |
6205 | |
6206 Expression *DeleteExp::semantic(Scope *sc) | |
6207 { | |
6208 Type *tb; | |
6209 | |
6210 UnaExp::semantic(sc); | |
6211 e1 = resolveProperties(sc, e1); | |
6212 e1 = e1->toLvalue(sc, NULL); | |
6213 type = Type::tvoid; | |
6214 | |
6215 tb = e1->type->toBasetype(); | |
6216 switch (tb->ty) | |
6217 { case Tclass: | |
6218 { TypeClass *tc = (TypeClass *)tb; | |
6219 ClassDeclaration *cd = tc->sym; | |
6220 | |
6221 if (cd->isCOMinterface()) | |
6222 { /* Because COM classes are deleted by IUnknown.Release() | |
6223 */ | |
6224 error("cannot delete instance of COM interface %s", cd->toChars()); | |
6225 } | |
6226 break; | |
6227 } | |
6228 case Tpointer: | |
6229 tb = tb->next->toBasetype(); | |
6230 if (tb->ty == Tstruct) | |
6231 { | |
6232 TypeStruct *ts = (TypeStruct *)tb; | |
6233 StructDeclaration *sd = ts->sym; | |
6234 FuncDeclaration *f = sd->aggDelete; | |
6235 | |
6236 if (f) | |
6237 { | |
6238 Type *tpv = Type::tvoid->pointerTo(); | |
6239 | |
6240 Expression *e = e1->castTo(sc, tpv); | |
6241 Expression *ec = new VarExp(loc, f); | |
6242 e = new CallExp(loc, ec, e); | |
6243 return e->semantic(sc); | |
6244 } | |
6245 } | |
6246 break; | |
6247 | |
6248 case Tarray: | |
6249 break; | |
6250 | |
6251 default: | |
6252 if (e1->op == TOKindex) | |
6253 { | |
6254 IndexExp *ae = (IndexExp *)(e1); | |
6255 Type *tb1 = ae->e1->type->toBasetype(); | |
6256 if (tb1->ty == Taarray) | |
6257 break; | |
6258 } | |
6259 error("cannot delete type %s", e1->type->toChars()); | |
6260 break; | |
6261 } | |
6262 | |
6263 if (e1->op == TOKindex) | |
6264 { | |
6265 IndexExp *ae = (IndexExp *)(e1); | |
6266 Type *tb1 = ae->e1->type->toBasetype(); | |
6267 if (tb1->ty == Taarray) | |
6268 { if (!global.params.useDeprecated) | |
6269 error("delete aa[key] deprecated, use aa.remove(key)"); | |
6270 } | |
6271 } | |
6272 | |
6273 return this; | |
6274 } | |
6275 | |
6276 int DeleteExp::checkSideEffect(int flag) | |
6277 { | |
6278 return 1; | |
6279 } | |
6280 | |
6281 Expression *DeleteExp::checkToBoolean() | |
6282 { | |
6283 error("delete does not give a boolean result"); | |
6284 return this; | |
6285 } | |
6286 | |
6287 void DeleteExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
6288 { | |
6289 buf->writestring("delete "); | |
6290 expToCBuffer(buf, hgs, e1, precedence[op]); | |
6291 } | |
6292 | |
6293 /************************************************************/ | |
6294 | |
6295 CastExp::CastExp(Loc loc, Expression *e, Type *t) | |
6296 : UnaExp(loc, TOKcast, sizeof(CastExp), e) | |
6297 { | |
6298 to = t; | |
6299 } | |
6300 | |
6301 Expression *CastExp::syntaxCopy() | |
6302 { | |
6303 return new CastExp(loc, e1->syntaxCopy(), to->syntaxCopy()); | |
6304 } | |
6305 | |
6306 | |
6307 Expression *CastExp::semantic(Scope *sc) | |
6308 { Expression *e; | |
6309 BinExp *b; | |
6310 UnaExp *u; | |
6311 | |
6312 #if LOGSEMANTIC | |
6313 printf("CastExp::semantic('%s')\n", toChars()); | |
6314 #endif | |
6315 | |
6316 //static int x; assert(++x < 10); | |
6317 | |
6318 if (type) | |
6319 return this; | |
6320 UnaExp::semantic(sc); | |
6321 if (e1->type) // if not a tuple | |
6322 { | |
6323 e1 = resolveProperties(sc, e1); | |
6324 to = to->semantic(loc, sc); | |
6325 | |
6326 e = op_overload(sc); | |
6327 if (e) | |
6328 { | |
6329 return e->implicitCastTo(sc, to); | |
6330 } | |
6331 | |
6332 Type *tob = to->toBasetype(); | |
6333 if (tob->ty == Tstruct && | |
6334 !tob->equals(e1->type->toBasetype()) && | |
6335 ((TypeStruct *)to)->sym->search(0, Id::call, 0) | |
6336 ) | |
6337 { | |
6338 /* Look to replace: | |
6339 * cast(S)t | |
6340 * with: | |
6341 * S(t) | |
6342 */ | |
6343 | |
6344 // Rewrite as to.call(e1) | |
6345 e = new TypeExp(loc, to); | |
6346 e = new DotIdExp(loc, e, Id::call); | |
6347 e = new CallExp(loc, e, e1); | |
6348 e = e->semantic(sc); | |
6349 return e; | |
6350 } | |
6351 } | |
6352 e = e1->castTo(sc, to); | |
6353 return e; | |
6354 } | |
6355 | |
6356 int CastExp::checkSideEffect(int flag) | |
6357 { | |
6358 /* if not: | |
6359 * cast(void) | |
6360 * cast(classtype)func() | |
6361 */ | |
6362 if (!to->equals(Type::tvoid) && | |
6363 !(to->ty == Tclass && e1->op == TOKcall && e1->type->ty == Tclass)) | |
6364 return Expression::checkSideEffect(flag); | |
6365 return 1; | |
6366 } | |
6367 | |
6368 void CastExp::checkEscape() | |
6369 { Type *tb = type->toBasetype(); | |
6370 if (tb->ty == Tarray && e1->op == TOKvar && | |
6371 e1->type->toBasetype()->ty == Tsarray) | |
6372 { VarExp *ve = (VarExp *)e1; | |
6373 VarDeclaration *v = ve->var->isVarDeclaration(); | |
6374 if (v) | |
6375 { | |
6376 if (!v->isDataseg() && !v->isParameter()) | |
6377 error("escaping reference to local %s", v->toChars()); | |
6378 } | |
6379 } | |
6380 } | |
6381 | |
6382 void CastExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
6383 { | |
6384 buf->writestring("cast("); | |
6385 to->toCBuffer(buf, NULL, hgs); | |
6386 buf->writeByte(')'); | |
6387 expToCBuffer(buf, hgs, e1, precedence[op]); | |
6388 } | |
6389 | |
6390 | |
6391 /************************************************************/ | |
6392 | |
6393 SliceExp::SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr) | |
6394 : UnaExp(loc, TOKslice, sizeof(SliceExp), e1) | |
6395 { | |
6396 this->upr = upr; | |
6397 this->lwr = lwr; | |
6398 lengthVar = NULL; | |
6399 } | |
6400 | |
6401 Expression *SliceExp::syntaxCopy() | |
6402 { | |
6403 Expression *lwr = NULL; | |
6404 if (this->lwr) | |
6405 lwr = this->lwr->syntaxCopy(); | |
6406 | |
6407 Expression *upr = NULL; | |
6408 if (this->upr) | |
6409 upr = this->upr->syntaxCopy(); | |
6410 | |
6411 return new SliceExp(loc, e1->syntaxCopy(), lwr, upr); | |
6412 } | |
6413 | |
6414 Expression *SliceExp::semantic(Scope *sc) | |
6415 { Expression *e; | |
6416 AggregateDeclaration *ad; | |
6417 //FuncDeclaration *fd; | |
6418 ScopeDsymbol *sym; | |
6419 | |
6420 #if LOGSEMANTIC | |
6421 printf("SliceExp::semantic('%s')\n", toChars()); | |
6422 #endif | |
6423 if (type) | |
6424 return this; | |
6425 | |
6426 UnaExp::semantic(sc); | |
6427 e1 = resolveProperties(sc, e1); | |
6428 | |
6429 e = this; | |
6430 | |
6431 Type *t = e1->type->toBasetype(); | |
6432 if (t->ty == Tpointer) | |
6433 { | |
6434 if (!lwr || !upr) | |
6435 error("need upper and lower bound to slice pointer"); | |
6436 } | |
6437 else if (t->ty == Tarray) | |
6438 { | |
6439 } | |
6440 else if (t->ty == Tsarray) | |
6441 { | |
6442 } | |
6443 else if (t->ty == Tclass) | |
6444 { | |
6445 ad = ((TypeClass *)t)->sym; | |
6446 goto L1; | |
6447 } | |
6448 else if (t->ty == Tstruct) | |
6449 { | |
6450 ad = ((TypeStruct *)t)->sym; | |
6451 | |
6452 L1: | |
6453 if (search_function(ad, Id::slice)) | |
6454 { | |
6455 // Rewrite as e1.slice(lwr, upr) | |
6456 e = new DotIdExp(loc, e1, Id::slice); | |
6457 | |
6458 if (lwr) | |
6459 { | |
6460 assert(upr); | |
6461 e = new CallExp(loc, e, lwr, upr); | |
6462 } | |
6463 else | |
6464 { assert(!upr); | |
6465 e = new CallExp(loc, e); | |
6466 } | |
6467 e = e->semantic(sc); | |
6468 return e; | |
6469 } | |
6470 goto Lerror; | |
6471 } | |
6472 else if (t->ty == Ttuple) | |
6473 { | |
6474 if (!lwr && !upr) | |
6475 return e1; | |
6476 if (!lwr || !upr) | |
6477 { error("need upper and lower bound to slice tuple"); | |
6478 goto Lerror; | |
6479 } | |
6480 } | |
6481 else | |
6482 goto Lerror; | |
6483 | |
6484 if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple) | |
6485 { | |
6486 sym = new ArrayScopeSymbol(this); | |
6487 sym->loc = loc; | |
6488 sym->parent = sc->scopesym; | |
6489 sc = sc->push(sym); | |
6490 } | |
6491 | |
6492 if (lwr) | |
6493 { lwr = lwr->semantic(sc); | |
6494 lwr = resolveProperties(sc, lwr); | |
6495 lwr = lwr->implicitCastTo(sc, Type::tsize_t); | |
6496 } | |
6497 if (upr) | |
6498 { upr = upr->semantic(sc); | |
6499 upr = resolveProperties(sc, upr); | |
6500 upr = upr->implicitCastTo(sc, Type::tsize_t); | |
6501 } | |
6502 | |
6503 if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple) | |
6504 sc->pop(); | |
6505 | |
6506 if (t->ty == Ttuple) | |
6507 { | |
6508 lwr = lwr->optimize(WANTvalue); | |
6509 upr = upr->optimize(WANTvalue); | |
6510 uinteger_t i1 = lwr->toUInteger(); | |
6511 uinteger_t i2 = upr->toUInteger(); | |
6512 | |
6513 size_t length; | |
6514 TupleExp *te; | |
6515 TypeTuple *tup; | |
6516 | |
6517 if (e1->op == TOKtuple) // slicing an expression tuple | |
6518 { te = (TupleExp *)e1; | |
6519 length = te->exps->dim; | |
6520 } | |
6521 else if (e1->op == TOKtype) // slicing a type tuple | |
6522 { tup = (TypeTuple *)t; | |
6523 length = Argument::dim(tup->arguments); | |
6524 } | |
6525 else | |
6526 assert(0); | |
6527 | |
6528 if (i1 <= i2 && i2 <= length) | |
6529 { size_t j1 = (size_t) i1; | |
6530 size_t j2 = (size_t) i2; | |
6531 | |
6532 if (e1->op == TOKtuple) | |
6533 { Expressions *exps = new Expressions; | |
6534 exps->setDim(j2 - j1); | |
6535 for (size_t i = 0; i < j2 - j1; i++) | |
6536 { Expression *e = (Expression *)te->exps->data[j1 + i]; | |
6537 exps->data[i] = (void *)e; | |
6538 } | |
6539 e = new TupleExp(loc, exps); | |
6540 } | |
6541 else | |
6542 { Arguments *args = new Arguments; | |
6543 args->reserve(j2 - j1); | |
6544 for (size_t i = j1; i < j2; i++) | |
6545 { Argument *arg = Argument::getNth(tup->arguments, i); | |
6546 args->push(arg); | |
6547 } | |
6548 e = new TypeExp(e1->loc, new TypeTuple(args)); | |
6549 } | |
6550 e = e->semantic(sc); | |
6551 } | |
6552 else | |
6553 { | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
6554 error("string slice [%llu .. %llu] is out of bounds", i1, i2); |
159 | 6555 e = e1; |
6556 } | |
6557 return e; | |
6558 } | |
6559 | |
6560 type = t->next->arrayOf(); | |
6561 return e; | |
6562 | |
6563 Lerror: | |
6564 char *s; | |
6565 if (t->ty == Tvoid) | |
6566 s = e1->toChars(); | |
6567 else | |
6568 s = t->toChars(); | |
6569 error("%s cannot be sliced with []", s); | |
6570 type = Type::terror; | |
6571 return e; | |
6572 } | |
6573 | |
6574 void SliceExp::checkEscape() | |
6575 { | |
6576 e1->checkEscape(); | |
6577 } | |
6578 | |
6579 Expression *SliceExp::toLvalue(Scope *sc, Expression *e) | |
6580 { | |
6581 return this; | |
6582 } | |
6583 | |
6584 Expression *SliceExp::modifiableLvalue(Scope *sc, Expression *e) | |
6585 { | |
6586 error("slice expression %s is not a modifiable lvalue", toChars()); | |
6587 return this; | |
6588 } | |
6589 | |
6590 void SliceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
6591 { | |
6592 expToCBuffer(buf, hgs, e1, precedence[op]); | |
6593 buf->writeByte('['); | |
6594 if (upr || lwr) | |
6595 { | |
6596 if (lwr) | |
6597 expToCBuffer(buf, hgs, lwr, PREC_assign); | |
6598 else | |
6599 buf->writeByte('0'); | |
6600 buf->writestring(".."); | |
6601 if (upr) | |
6602 expToCBuffer(buf, hgs, upr, PREC_assign); | |
6603 else | |
6604 buf->writestring("length"); // BUG: should be array.length | |
6605 } | |
6606 buf->writeByte(']'); | |
6607 } | |
6608 | |
6609 /********************** ArrayLength **************************************/ | |
6610 | |
6611 ArrayLengthExp::ArrayLengthExp(Loc loc, Expression *e1) | |
6612 : UnaExp(loc, TOKarraylength, sizeof(ArrayLengthExp), e1) | |
6613 { | |
6614 } | |
6615 | |
6616 Expression *ArrayLengthExp::semantic(Scope *sc) | |
6617 { Expression *e; | |
6618 | |
6619 #if LOGSEMANTIC | |
6620 printf("ArrayLengthExp::semantic('%s')\n", toChars()); | |
6621 #endif | |
6622 if (!type) | |
6623 { | |
6624 UnaExp::semantic(sc); | |
6625 e1 = resolveProperties(sc, e1); | |
6626 | |
6627 type = Type::tsize_t; | |
6628 } | |
6629 return this; | |
6630 } | |
6631 | |
6632 void ArrayLengthExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
6633 { | |
6634 expToCBuffer(buf, hgs, e1, PREC_primary); | |
6635 buf->writestring(".length"); | |
6636 } | |
6637 | |
6638 /*********************** ArrayExp *************************************/ | |
6639 | |
6640 // e1 [ i1, i2, i3, ... ] | |
6641 | |
6642 ArrayExp::ArrayExp(Loc loc, Expression *e1, Expressions *args) | |
6643 : UnaExp(loc, TOKarray, sizeof(ArrayExp), e1) | |
6644 { | |
6645 arguments = args; | |
6646 } | |
6647 | |
6648 Expression *ArrayExp::syntaxCopy() | |
6649 { | |
6650 return new ArrayExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments)); | |
6651 } | |
6652 | |
6653 Expression *ArrayExp::semantic(Scope *sc) | |
6654 { Expression *e; | |
6655 Type *t1; | |
6656 | |
6657 #if LOGSEMANTIC | |
6658 printf("ArrayExp::semantic('%s')\n", toChars()); | |
6659 #endif | |
6660 UnaExp::semantic(sc); | |
6661 e1 = resolveProperties(sc, e1); | |
6662 | |
6663 t1 = e1->type->toBasetype(); | |
6664 if (t1->ty != Tclass && t1->ty != Tstruct) | |
6665 { // Convert to IndexExp | |
6666 if (arguments->dim != 1) | |
6667 error("only one index allowed to index %s", t1->toChars()); | |
6668 e = new IndexExp(loc, e1, (Expression *)arguments->data[0]); | |
6669 return e->semantic(sc); | |
6670 } | |
6671 | |
6672 // Run semantic() on each argument | |
6673 for (size_t i = 0; i < arguments->dim; i++) | |
6674 { e = (Expression *)arguments->data[i]; | |
6675 | |
6676 e = e->semantic(sc); | |
6677 if (!e->type) | |
6678 error("%s has no value", e->toChars()); | |
6679 arguments->data[i] = (void *)e; | |
6680 } | |
6681 | |
6682 expandTuples(arguments); | |
6683 assert(arguments && arguments->dim); | |
6684 | |
6685 e = op_overload(sc); | |
6686 if (!e) | |
6687 { error("no [] operator overload for type %s", e1->type->toChars()); | |
6688 e = e1; | |
6689 } | |
6690 return e; | |
6691 } | |
6692 | |
6693 | |
6694 Expression *ArrayExp::toLvalue(Scope *sc, Expression *e) | |
6695 { | |
6696 if (type && type->toBasetype()->ty == Tvoid) | |
6697 error("voids have no value"); | |
6698 return this; | |
6699 } | |
6700 | |
6701 | |
6702 void ArrayExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
6703 { int i; | |
6704 | |
6705 expToCBuffer(buf, hgs, e1, PREC_primary); | |
6706 buf->writeByte('['); | |
6707 argsToCBuffer(buf, arguments, hgs); | |
6708 buf->writeByte(']'); | |
6709 } | |
6710 | |
6711 /************************* DotExp ***********************************/ | |
6712 | |
6713 DotExp::DotExp(Loc loc, Expression *e1, Expression *e2) | |
6714 : BinExp(loc, TOKdotexp, sizeof(DotExp), e1, e2) | |
6715 { | |
6716 } | |
6717 | |
6718 Expression *DotExp::semantic(Scope *sc) | |
6719 { | |
6720 #if LOGSEMANTIC | |
6721 printf("DotExp::semantic('%s')\n", toChars()); | |
6722 if (type) printf("\ttype = %s\n", type->toChars()); | |
6723 #endif | |
6724 e1 = e1->semantic(sc); | |
6725 e2 = e2->semantic(sc); | |
6726 if (e2->op == TOKimport) | |
6727 { | |
6728 ScopeExp *se = (ScopeExp *)e2; | |
6729 TemplateDeclaration *td = se->sds->isTemplateDeclaration(); | |
6730 if (td) | |
6731 { Expression *e = new DotTemplateExp(loc, e1, td); | |
6732 e = e->semantic(sc); | |
6733 return e; | |
6734 } | |
6735 } | |
6736 if (!type) | |
6737 type = e2->type; | |
6738 return this; | |
6739 } | |
6740 | |
6741 | |
6742 /************************* CommaExp ***********************************/ | |
6743 | |
6744 CommaExp::CommaExp(Loc loc, Expression *e1, Expression *e2) | |
6745 : BinExp(loc, TOKcomma, sizeof(CommaExp), e1, e2) | |
6746 { | |
6747 } | |
6748 | |
6749 Expression *CommaExp::semantic(Scope *sc) | |
6750 { | |
6751 if (!type) | |
6752 { BinExp::semanticp(sc); | |
6753 type = e2->type; | |
6754 } | |
6755 return this; | |
6756 } | |
6757 | |
6758 void CommaExp::checkEscape() | |
6759 { | |
6760 e2->checkEscape(); | |
6761 } | |
6762 | |
6763 Expression *CommaExp::toLvalue(Scope *sc, Expression *e) | |
6764 { | |
6765 e2 = e2->toLvalue(sc, NULL); | |
6766 return this; | |
6767 } | |
6768 | |
6769 Expression *CommaExp::modifiableLvalue(Scope *sc, Expression *e) | |
6770 { | |
6771 e2 = e2->modifiableLvalue(sc, e); | |
6772 return this; | |
6773 } | |
6774 | |
6775 int CommaExp::isBool(int result) | |
6776 { | |
6777 return e2->isBool(result); | |
6778 } | |
6779 | |
6780 int CommaExp::checkSideEffect(int flag) | |
6781 { | |
6782 if (flag == 2) | |
6783 return e1->checkSideEffect(2) || e2->checkSideEffect(2); | |
6784 else | |
6785 { | |
6786 // Don't check e1 until we cast(void) the a,b code generation | |
6787 return e2->checkSideEffect(flag); | |
6788 } | |
6789 } | |
6790 | |
6791 /************************** IndexExp **********************************/ | |
6792 | |
6793 // e1 [ e2 ] | |
6794 | |
6795 IndexExp::IndexExp(Loc loc, Expression *e1, Expression *e2) | |
6796 : BinExp(loc, TOKindex, sizeof(IndexExp), e1, e2) | |
6797 { | |
6798 //printf("IndexExp::IndexExp('%s')\n", toChars()); | |
6799 lengthVar = NULL; | |
6800 modifiable = 0; // assume it is an rvalue | |
6801 } | |
6802 | |
6803 Expression *IndexExp::semantic(Scope *sc) | |
6804 { Expression *e; | |
6805 BinExp *b; | |
6806 UnaExp *u; | |
6807 Type *t1; | |
6808 ScopeDsymbol *sym; | |
6809 | |
6810 #if LOGSEMANTIC | |
6811 printf("IndexExp::semantic('%s')\n", toChars()); | |
6812 #endif | |
6813 if (type) | |
6814 return this; | |
6815 if (!e1->type) | |
6816 e1 = e1->semantic(sc); | |
6817 assert(e1->type); // semantic() should already be run on it | |
6818 e = this; | |
6819 | |
6820 // Note that unlike C we do not implement the int[ptr] | |
6821 | |
6822 t1 = e1->type->toBasetype(); | |
6823 | |
6824 if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple) | |
6825 { // Create scope for 'length' variable | |
6826 sym = new ArrayScopeSymbol(this); | |
6827 sym->loc = loc; | |
6828 sym->parent = sc->scopesym; | |
6829 sc = sc->push(sym); | |
6830 } | |
6831 | |
6832 e2 = e2->semantic(sc); | |
6833 if (!e2->type) | |
6834 { | |
6835 error("%s has no value", e2->toChars()); | |
6836 e2->type = Type::terror; | |
6837 } | |
6838 e2 = resolveProperties(sc, e2); | |
6839 | |
6840 if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple) | |
6841 sc = sc->pop(); | |
6842 | |
6843 switch (t1->ty) | |
6844 { | |
6845 case Tpointer: | |
6846 case Tarray: | |
6847 e2 = e2->implicitCastTo(sc, Type::tsize_t); | |
6848 e->type = t1->next; | |
6849 break; | |
6850 | |
6851 case Tsarray: | |
6852 { | |
6853 e2 = e2->implicitCastTo(sc, Type::tsize_t); | |
6854 | |
6855 TypeSArray *tsa = (TypeSArray *)t1; | |
6856 | |
6857 #if 0 // Don't do now, because it might be short-circuit evaluated | |
6858 // Do compile time array bounds checking if possible | |
6859 e2 = e2->optimize(WANTvalue); | |
6860 if (e2->op == TOKint64) | |
6861 { | |
6862 integer_t index = e2->toInteger(); | |
6863 integer_t length = tsa->dim->toInteger(); | |
6864 if (index < 0 || index >= length) | |
6865 error("array index [%lld] is outside array bounds [0 .. %lld]", | |
6866 index, length); | |
6867 } | |
6868 #endif | |
6869 e->type = t1->next; | |
6870 break; | |
6871 } | |
6872 | |
6873 case Taarray: | |
6874 { TypeAArray *taa = (TypeAArray *)t1; | |
6875 | |
6876 e2 = e2->implicitCastTo(sc, taa->index); // type checking | |
6877 e2 = e2->implicitCastTo(sc, taa->key); // actual argument type | |
6878 type = taa->next; | |
6879 break; | |
6880 } | |
6881 | |
6882 case Ttuple: | |
6883 { | |
6884 e2 = e2->implicitCastTo(sc, Type::tsize_t); | |
6885 e2 = e2->optimize(WANTvalue); | |
6886 uinteger_t index = e2->toUInteger(); | |
6887 size_t length; | |
6888 TupleExp *te; | |
6889 TypeTuple *tup; | |
6890 | |
6891 if (e1->op == TOKtuple) | |
6892 { te = (TupleExp *)e1; | |
6893 length = te->exps->dim; | |
6894 } | |
6895 else if (e1->op == TOKtype) | |
6896 { | |
6897 tup = (TypeTuple *)t1; | |
6898 length = Argument::dim(tup->arguments); | |
6899 } | |
6900 else | |
6901 assert(0); | |
6902 | |
6903 if (index < length) | |
6904 { | |
6905 | |
6906 if (e1->op == TOKtuple) | |
6907 e = (Expression *)te->exps->data[(size_t)index]; | |
6908 else | |
6909 e = new TypeExp(e1->loc, Argument::getNth(tup->arguments, (size_t)index)->type); | |
6910 } | |
6911 else | |
6912 { | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
6913 error("array index [%llu] is outside array bounds [0 .. %"PRIuSIZE"]", |
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
6914 index, length); |
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
6915 e = e1; |
159 | 6916 } |
6917 break; | |
6918 } | |
6919 | |
6920 default: | |
6921 error("%s must be an array or pointer type, not %s", | |
6922 e1->toChars(), e1->type->toChars()); | |
6923 type = Type::tint32; | |
6924 break; | |
6925 } | |
6926 return e; | |
6927 } | |
6928 | |
6929 Expression *IndexExp::toLvalue(Scope *sc, Expression *e) | |
6930 { | |
6931 // if (type && type->toBasetype()->ty == Tvoid) | |
6932 // error("voids have no value"); | |
6933 return this; | |
6934 } | |
6935 | |
6936 Expression *IndexExp::modifiableLvalue(Scope *sc, Expression *e) | |
6937 { | |
6938 //printf("IndexExp::modifiableLvalue(%s)\n", toChars()); | |
6939 modifiable = 1; | |
6940 if (e1->op == TOKstring) | |
6941 error("string literals are immutable"); | |
6942 if (e1->type->toBasetype()->ty == Taarray) | |
6943 e1 = e1->modifiableLvalue(sc, e1); | |
6944 return toLvalue(sc, e); | |
6945 } | |
6946 | |
6947 void IndexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
6948 { | |
6949 expToCBuffer(buf, hgs, e1, PREC_primary); | |
6950 buf->writeByte('['); | |
6951 expToCBuffer(buf, hgs, e2, PREC_assign); | |
6952 buf->writeByte(']'); | |
6953 } | |
6954 | |
6955 | |
6956 /************************* PostExp ***********************************/ | |
6957 | |
6958 PostExp::PostExp(enum TOK op, Loc loc, Expression *e) | |
6959 : BinExp(loc, op, sizeof(PostExp), e, | |
6960 new IntegerExp(loc, 1, Type::tint32)) | |
6961 { | |
6962 } | |
6963 | |
6964 Expression *PostExp::semantic(Scope *sc) | |
6965 { Expression *e = this; | |
6966 | |
6967 if (!type) | |
6968 { | |
6969 BinExp::semantic(sc); | |
6970 e2 = resolveProperties(sc, e2); | |
6971 | |
6972 e = op_overload(sc); | |
6973 if (e) | |
6974 return e; | |
6975 | |
6976 e = this; | |
6977 e1 = e1->modifiableLvalue(sc, e1); | |
6978 e1->checkScalar(); | |
6979 e1->checkNoBool(); | |
6980 if (e1->type->ty == Tpointer) | |
6981 e = scaleFactor(sc); | |
6982 else | |
6983 e2 = e2->castTo(sc, e1->type); | |
6984 e->type = e1->type; | |
6985 } | |
6986 return e; | |
6987 } | |
6988 | |
6989 void PostExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
6990 { | |
6991 expToCBuffer(buf, hgs, e1, precedence[op]); | |
6992 buf->writestring((op == TOKplusplus) ? (char *)"++" : (char *)"--"); | |
6993 } | |
6994 | |
6995 /************************************************************/ | |
6996 | |
6997 /* Can be TOKconstruct too */ | |
6998 | |
6999 AssignExp::AssignExp(Loc loc, Expression *e1, Expression *e2) | |
7000 : BinExp(loc, TOKassign, sizeof(AssignExp), e1, e2) | |
7001 { | |
7002 ismemset = 0; | |
7003 } | |
7004 | |
7005 Expression *AssignExp::semantic(Scope *sc) | |
7006 { Type *t1; | |
7007 Expression *e1old = e1; | |
7008 | |
7009 #if LOGSEMANTIC | |
7010 printf("AssignExp::semantic('%s')\n", toChars()); | |
7011 #endif | |
7012 //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op)); | |
7013 | |
7014 /* Look for operator overloading of a[i]=value. | |
7015 * Do it before semantic() otherwise the a[i] will have been | |
7016 * converted to a.opIndex() already. | |
7017 */ | |
7018 if (e1->op == TOKarray) | |
7019 { Type *t1; | |
7020 ArrayExp *ae = (ArrayExp *)e1; | |
7021 AggregateDeclaration *ad; | |
7022 Identifier *id = Id::index; | |
7023 | |
7024 ae->e1 = ae->e1->semantic(sc); | |
7025 t1 = ae->e1->type->toBasetype(); | |
7026 if (t1->ty == Tstruct) | |
7027 { | |
7028 ad = ((TypeStruct *)t1)->sym; | |
7029 goto L1; | |
7030 } | |
7031 else if (t1->ty == Tclass) | |
7032 { | |
7033 ad = ((TypeClass *)t1)->sym; | |
7034 L1: | |
7035 // Rewrite (a[i] = value) to (a.opIndexAssign(value, i)) | |
7036 if (search_function(ad, Id::indexass)) | |
7037 { Expression *e = new DotIdExp(loc, ae->e1, Id::indexass); | |
7038 Expressions *a = (Expressions *)ae->arguments->copy(); | |
7039 | |
7040 a->insert(0, e2); | |
7041 e = new CallExp(loc, e, a); | |
7042 e = e->semantic(sc); | |
7043 return e; | |
7044 } | |
7045 else | |
7046 { | |
7047 // Rewrite (a[i] = value) to (a.opIndex(i, value)) | |
7048 if (search_function(ad, id)) | |
7049 { Expression *e = new DotIdExp(loc, ae->e1, id); | |
7050 | |
7051 if (1 || !global.params.useDeprecated) | |
7052 error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)"); | |
7053 | |
7054 e = new CallExp(loc, e, (Expression *)ae->arguments->data[0], e2); | |
7055 e = e->semantic(sc); | |
7056 return e; | |
7057 } | |
7058 } | |
7059 } | |
7060 } | |
7061 /* Look for operator overloading of a[i..j]=value. | |
7062 * Do it before semantic() otherwise the a[i..j] will have been | |
7063 * converted to a.opSlice() already. | |
7064 */ | |
7065 if (e1->op == TOKslice) | |
7066 { Type *t1; | |
7067 SliceExp *ae = (SliceExp *)e1; | |
7068 AggregateDeclaration *ad; | |
7069 Identifier *id = Id::index; | |
7070 | |
7071 ae->e1 = ae->e1->semantic(sc); | |
7072 ae->e1 = resolveProperties(sc, ae->e1); | |
7073 t1 = ae->e1->type->toBasetype(); | |
7074 if (t1->ty == Tstruct) | |
7075 { | |
7076 ad = ((TypeStruct *)t1)->sym; | |
7077 goto L2; | |
7078 } | |
7079 else if (t1->ty == Tclass) | |
7080 { | |
7081 ad = ((TypeClass *)t1)->sym; | |
7082 L2: | |
7083 // Rewrite (a[i..j] = value) to (a.opIndexAssign(value, i, j)) | |
7084 if (search_function(ad, Id::sliceass)) | |
7085 { Expression *e = new DotIdExp(loc, ae->e1, Id::sliceass); | |
7086 Expressions *a = new Expressions(); | |
7087 | |
7088 a->push(e2); | |
7089 if (ae->lwr) | |
7090 { a->push(ae->lwr); | |
7091 assert(ae->upr); | |
7092 a->push(ae->upr); | |
7093 } | |
7094 else | |
7095 assert(!ae->upr); | |
7096 e = new CallExp(loc, e, a); | |
7097 e = e->semantic(sc); | |
7098 return e; | |
7099 } | |
7100 } | |
7101 } | |
7102 | |
7103 BinExp::semantic(sc); | |
7104 e2 = resolveProperties(sc, e2); | |
7105 assert(e1->type); | |
7106 | |
7107 /* Rewrite tuple assignment as a tuple of assignments. | |
7108 */ | |
7109 if (e1->op == TOKtuple && e2->op == TOKtuple) | |
7110 { TupleExp *tup1 = (TupleExp *)e1; | |
7111 TupleExp *tup2 = (TupleExp *)e2; | |
7112 size_t dim = tup1->exps->dim; | |
7113 if (dim != tup2->exps->dim) | |
7114 { | |
7115 error("mismatched tuple lengths, %d and %d", (int)dim, (int)tup2->exps->dim); | |
7116 } | |
7117 else | |
7118 { Expressions *exps = new Expressions; | |
7119 exps->setDim(dim); | |
7120 | |
7121 for (int i = 0; i < dim; i++) | |
7122 { Expression *ex1 = (Expression *)tup1->exps->data[i]; | |
7123 Expression *ex2 = (Expression *)tup2->exps->data[i]; | |
7124 exps->data[i] = (void *) new AssignExp(loc, ex1, ex2); | |
7125 } | |
7126 Expression *e = new TupleExp(loc, exps); | |
7127 e = e->semantic(sc); | |
7128 return e; | |
7129 } | |
7130 } | |
7131 | |
7132 t1 = e1->type->toBasetype(); | |
7133 | |
7134 if (t1->ty == Tfunction) | |
7135 { // Rewrite f=value to f(value) | |
7136 Expression *e; | |
7137 | |
7138 e = new CallExp(loc, e1, e2); | |
7139 e = e->semantic(sc); | |
7140 return e; | |
7141 } | |
7142 | |
7143 /* If it is an assignment from a 'foreign' type, | |
7144 * check for operator overloading. | |
7145 */ | |
7146 if (t1->ty == Tclass || t1->ty == Tstruct) | |
7147 { | |
7148 if (!e2->type->implicitConvTo(e1->type)) | |
7149 { | |
7150 Expression *e = op_overload(sc); | |
7151 if (e) | |
7152 return e; | |
7153 } | |
7154 } | |
7155 | |
7156 e2->rvalue(); | |
7157 | |
7158 if (e1->op == TOKarraylength) | |
7159 { | |
7160 // e1 is not an lvalue, but we let code generator handle it | |
7161 ArrayLengthExp *ale = (ArrayLengthExp *)e1; | |
7162 | |
7163 ale->e1 = ale->e1->modifiableLvalue(sc, e1); | |
7164 } | |
7165 else if (e1->op == TOKslice) | |
7166 ; | |
7167 else | |
7168 { // Try to do a decent error message with the expression | |
7169 // before it got constant folded | |
7170 e1 = e1->modifiableLvalue(sc, e1old); | |
7171 } | |
7172 | |
7173 if (e1->op == TOKslice && | |
7174 t1->nextOf() && | |
7175 e2->implicitConvTo(t1->nextOf()) | |
7176 // !(t1->nextOf()->equals(e2->type->nextOf())) | |
7177 ) | |
7178 { // memset | |
7179 ismemset = 1; // make it easy for back end to tell what this is | |
7180 e2 = e2->implicitCastTo(sc, t1->next); | |
7181 } | |
7182 else if (t1->ty == Tsarray) | |
7183 { | |
7184 error("cannot assign to static array %s", e1->toChars()); | |
7185 } | |
7186 else | |
7187 { | |
7188 e2 = e2->implicitCastTo(sc, e1->type); | |
7189 } | |
7190 type = e1->type; | |
7191 assert(type); | |
7192 return this; | |
7193 } | |
7194 | |
7195 Expression *AssignExp::checkToBoolean() | |
7196 { | |
7197 // Things like: | |
7198 // if (a = b) ... | |
7199 // are usually mistakes. | |
7200 | |
7201 error("'=' does not give a boolean result"); | |
7202 return this; | |
7203 } | |
7204 | |
7205 /************************************************************/ | |
7206 | |
7207 AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7208 : BinExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2) | |
7209 { | |
7210 } | |
7211 | |
7212 Expression *AddAssignExp::semantic(Scope *sc) | |
7213 { Expression *e; | |
7214 | |
7215 if (type) | |
7216 return this; | |
7217 | |
7218 BinExp::semantic(sc); | |
7219 e2 = resolveProperties(sc, e2); | |
7220 | |
7221 e = op_overload(sc); | |
7222 if (e) | |
7223 return e; | |
7224 | |
7225 e1 = e1->modifiableLvalue(sc, e1); | |
7226 | |
7227 Type *tb1 = e1->type->toBasetype(); | |
7228 Type *tb2 = e2->type->toBasetype(); | |
7229 | |
7230 if ((tb1->ty == Tarray || tb1->ty == Tsarray) && | |
7231 (tb2->ty == Tarray || tb2->ty == Tsarray) && | |
7232 tb1->next->equals(tb2->next) | |
7233 ) | |
7234 { | |
7235 type = e1->type; | |
7236 e = this; | |
7237 } | |
7238 else | |
7239 { | |
7240 e1->checkScalar(); | |
7241 e1->checkNoBool(); | |
7242 if (tb1->ty == Tpointer && tb2->isintegral()) | |
7243 e = scaleFactor(sc); | |
7244 else if (tb1->ty == Tbit || tb1->ty == Tbool) | |
7245 { | |
7246 #if 0 | |
7247 // Need to rethink this | |
7248 if (e1->op != TOKvar) | |
7249 { // Rewrite e1+=e2 to (v=&e1),*v=*v+e2 | |
7250 VarDeclaration *v; | |
7251 Expression *ea; | |
7252 Expression *ex; | |
7253 | |
7254 char name[6+6+1]; | |
7255 Identifier *id; | |
7256 static int idn; | |
7257 sprintf(name, "__name%d", ++idn); | |
7258 id = Lexer::idPool(name); | |
7259 | |
7260 v = new VarDeclaration(loc, tb1->pointerTo(), id, NULL); | |
7261 v->semantic(sc); | |
7262 if (!sc->insert(v)) | |
7263 assert(0); | |
7264 v->parent = sc->func; | |
7265 | |
7266 ea = new AddrExp(loc, e1); | |
7267 ea = new AssignExp(loc, new VarExp(loc, v), ea); | |
7268 | |
7269 ex = new VarExp(loc, v); | |
7270 ex = new PtrExp(loc, ex); | |
7271 e = new AddExp(loc, ex, e2); | |
7272 e = new CastExp(loc, e, e1->type); | |
7273 e = new AssignExp(loc, ex->syntaxCopy(), e); | |
7274 | |
7275 e = new CommaExp(loc, ea, e); | |
7276 } | |
7277 else | |
7278 #endif | |
7279 { // Rewrite e1+=e2 to e1=e1+e2 | |
7280 // BUG: doesn't account for side effects in e1 | |
7281 // BUG: other assignment operators for bits aren't handled at all | |
7282 e = new AddExp(loc, e1, e2); | |
7283 e = new CastExp(loc, e, e1->type); | |
7284 e = new AssignExp(loc, e1->syntaxCopy(), e); | |
7285 } | |
7286 e = e->semantic(sc); | |
7287 } | |
7288 else | |
7289 { | |
7290 type = e1->type; | |
7291 typeCombine(sc); | |
7292 e1->checkArithmetic(); | |
7293 e2->checkArithmetic(); | |
7294 if (type->isreal() || type->isimaginary()) | |
7295 { | |
7296 assert(global.errors || e2->type->isfloating()); | |
7297 e2 = e2->castTo(sc, e1->type); | |
7298 } | |
7299 e = this; | |
7300 } | |
7301 } | |
7302 return e; | |
7303 } | |
7304 | |
7305 /************************************************************/ | |
7306 | |
7307 MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7308 : BinExp(loc, TOKminass, sizeof(MinAssignExp), e1, e2) | |
7309 { | |
7310 } | |
7311 | |
7312 Expression *MinAssignExp::semantic(Scope *sc) | |
7313 { Expression *e; | |
7314 | |
7315 if (type) | |
7316 return this; | |
7317 | |
7318 BinExp::semantic(sc); | |
7319 e2 = resolveProperties(sc, e2); | |
7320 | |
7321 e = op_overload(sc); | |
7322 if (e) | |
7323 return e; | |
7324 | |
7325 e1 = e1->modifiableLvalue(sc, e1); | |
7326 e1->checkScalar(); | |
7327 e1->checkNoBool(); | |
7328 if (e1->type->ty == Tpointer && e2->type->isintegral()) | |
7329 e = scaleFactor(sc); | |
7330 else | |
7331 { | |
7332 e1 = e1->checkArithmetic(); | |
7333 e2 = e2->checkArithmetic(); | |
7334 type = e1->type; | |
7335 typeCombine(sc); | |
7336 if (type->isreal() || type->isimaginary()) | |
7337 { | |
7338 assert(e2->type->isfloating()); | |
7339 e2 = e2->castTo(sc, e1->type); | |
7340 } | |
7341 e = this; | |
7342 } | |
7343 return e; | |
7344 } | |
7345 | |
7346 /************************************************************/ | |
7347 | |
7348 CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7349 : BinExp(loc, TOKcatass, sizeof(CatAssignExp), e1, e2) | |
7350 { | |
7351 } | |
7352 | |
7353 Expression *CatAssignExp::semantic(Scope *sc) | |
7354 { Expression *e; | |
7355 | |
7356 BinExp::semantic(sc); | |
7357 e2 = resolveProperties(sc, e2); | |
7358 | |
7359 e = op_overload(sc); | |
7360 if (e) | |
7361 return e; | |
7362 | |
7363 if (e1->op == TOKslice) | |
7364 { SliceExp *se = (SliceExp *)e1; | |
7365 | |
7366 if (se->e1->type->toBasetype()->ty == Tsarray) | |
7367 error("cannot append to static array %s", se->e1->type->toChars()); | |
7368 } | |
7369 | |
7370 e1 = e1->modifiableLvalue(sc, e1); | |
7371 | |
7372 Type *tb1 = e1->type->toBasetype(); | |
7373 Type *tb2 = e2->type->toBasetype(); | |
7374 | |
7375 e2->rvalue(); | |
7376 | |
7377 if ((tb1->ty == Tarray) && | |
7378 (tb2->ty == Tarray || tb2->ty == Tsarray) && | |
7379 e2->implicitConvTo(e1->type) | |
7380 //e1->type->next->equals(e2->type->next) | |
7381 ) | |
7382 { // Append array | |
7383 e2 = e2->castTo(sc, e1->type); | |
7384 type = e1->type; | |
7385 e = this; | |
7386 } | |
7387 else if ((tb1->ty == Tarray) && | |
7388 e2->implicitConvTo(tb1->next) | |
7389 ) | |
7390 { // Append element | |
7391 e2 = e2->castTo(sc, tb1->next); | |
7392 type = e1->type; | |
7393 e = this; | |
7394 } | |
7395 else | |
7396 { | |
7397 error("cannot append type %s to type %s", tb2->toChars(), tb1->toChars()); | |
7398 type = Type::tint32; | |
7399 e = this; | |
7400 } | |
7401 return e; | |
7402 } | |
7403 | |
7404 /************************************************************/ | |
7405 | |
7406 MulAssignExp::MulAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7407 : BinExp(loc, TOKmulass, sizeof(MulAssignExp), e1, e2) | |
7408 { | |
7409 } | |
7410 | |
7411 Expression *MulAssignExp::semantic(Scope *sc) | |
7412 { Expression *e; | |
7413 | |
7414 BinExp::semantic(sc); | |
7415 e2 = resolveProperties(sc, e2); | |
7416 | |
7417 e = op_overload(sc); | |
7418 if (e) | |
7419 return e; | |
7420 | |
7421 e1 = e1->modifiableLvalue(sc, e1); | |
7422 e1->checkScalar(); | |
7423 e1->checkNoBool(); | |
7424 type = e1->type; | |
7425 typeCombine(sc); | |
7426 e1->checkArithmetic(); | |
7427 e2->checkArithmetic(); | |
7428 if (e2->type->isfloating()) | |
7429 { Type *t1; | |
7430 Type *t2; | |
7431 | |
7432 t1 = e1->type; | |
7433 t2 = e2->type; | |
7434 if (t1->isreal()) | |
7435 { | |
7436 if (t2->isimaginary() || t2->iscomplex()) | |
7437 { | |
7438 e2 = e2->castTo(sc, t1); | |
7439 } | |
7440 } | |
7441 else if (t1->isimaginary()) | |
7442 { | |
7443 if (t2->isimaginary() || t2->iscomplex()) | |
7444 { | |
7445 switch (t1->ty) | |
7446 { | |
7447 case Timaginary32: t2 = Type::tfloat32; break; | |
7448 case Timaginary64: t2 = Type::tfloat64; break; | |
7449 case Timaginary80: t2 = Type::tfloat80; break; | |
7450 default: | |
7451 assert(0); | |
7452 } | |
7453 e2 = e2->castTo(sc, t2); | |
7454 } | |
7455 } | |
7456 } | |
7457 return this; | |
7458 } | |
7459 | |
7460 /************************************************************/ | |
7461 | |
7462 DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7463 : BinExp(loc, TOKdivass, sizeof(DivAssignExp), e1, e2) | |
7464 { | |
7465 } | |
7466 | |
7467 Expression *DivAssignExp::semantic(Scope *sc) | |
7468 { Expression *e; | |
7469 | |
7470 BinExp::semantic(sc); | |
7471 e2 = resolveProperties(sc, e2); | |
7472 | |
7473 e = op_overload(sc); | |
7474 if (e) | |
7475 return e; | |
7476 | |
7477 e1 = e1->modifiableLvalue(sc, e1); | |
7478 e1->checkScalar(); | |
7479 e1->checkNoBool(); | |
7480 type = e1->type; | |
7481 typeCombine(sc); | |
7482 e1->checkArithmetic(); | |
7483 e2->checkArithmetic(); | |
7484 if (e2->type->isimaginary()) | |
7485 { Type *t1; | |
7486 Type *t2; | |
7487 | |
7488 t1 = e1->type; | |
7489 if (t1->isreal()) | |
7490 { // x/iv = i(-x/v) | |
7491 // Therefore, the result is 0 | |
7492 e2 = new CommaExp(loc, e2, new RealExp(loc, 0, t1)); | |
7493 e2->type = t1; | |
7494 e = new AssignExp(loc, e1, e2); | |
7495 e->type = t1; | |
7496 return e; | |
7497 } | |
7498 else if (t1->isimaginary()) | |
7499 { Expression *e; | |
7500 | |
7501 switch (t1->ty) | |
7502 { | |
7503 case Timaginary32: t2 = Type::tfloat32; break; | |
7504 case Timaginary64: t2 = Type::tfloat64; break; | |
7505 case Timaginary80: t2 = Type::tfloat80; break; | |
7506 default: | |
7507 assert(0); | |
7508 } | |
7509 e2 = e2->castTo(sc, t2); | |
7510 e = new AssignExp(loc, e1, e2); | |
7511 e->type = t1; | |
7512 return e; | |
7513 } | |
7514 } | |
7515 return this; | |
7516 } | |
7517 | |
7518 /************************************************************/ | |
7519 | |
7520 ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7521 : BinExp(loc, TOKmodass, sizeof(ModAssignExp), e1, e2) | |
7522 { | |
7523 } | |
7524 | |
7525 Expression *ModAssignExp::semantic(Scope *sc) | |
7526 { | |
7527 return commonSemanticAssign(sc); | |
7528 } | |
7529 | |
7530 /************************************************************/ | |
7531 | |
7532 ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7533 : BinExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2) | |
7534 { | |
7535 } | |
7536 | |
7537 Expression *ShlAssignExp::semantic(Scope *sc) | |
7538 { Expression *e; | |
7539 | |
7540 //printf("ShlAssignExp::semantic()\n"); | |
7541 BinExp::semantic(sc); | |
7542 e2 = resolveProperties(sc, e2); | |
7543 | |
7544 e = op_overload(sc); | |
7545 if (e) | |
7546 return e; | |
7547 | |
7548 e1 = e1->modifiableLvalue(sc, e1); | |
7549 e1->checkScalar(); | |
7550 e1->checkNoBool(); | |
7551 type = e1->type; | |
7552 typeCombine(sc); | |
7553 e1->checkIntegral(); | |
7554 e2 = e2->checkIntegral(); | |
7555 //e2 = e2->castTo(sc, Type::tshiftcnt); | |
7556 e2 = e2->castTo(sc, e1->type); // LLVMDC | |
7557 return this; | |
7558 } | |
7559 | |
7560 /************************************************************/ | |
7561 | |
7562 ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7563 : BinExp(loc, TOKshrass, sizeof(ShrAssignExp), e1, e2) | |
7564 { | |
7565 } | |
7566 | |
7567 Expression *ShrAssignExp::semantic(Scope *sc) | |
7568 { Expression *e; | |
7569 | |
7570 BinExp::semantic(sc); | |
7571 e2 = resolveProperties(sc, e2); | |
7572 | |
7573 e = op_overload(sc); | |
7574 if (e) | |
7575 return e; | |
7576 | |
7577 e1 = e1->modifiableLvalue(sc, e1); | |
7578 e1->checkScalar(); | |
7579 e1->checkNoBool(); | |
7580 type = e1->type; | |
7581 typeCombine(sc); | |
7582 e1->checkIntegral(); | |
7583 e2 = e2->checkIntegral(); | |
7584 //e2 = e2->castTo(sc, Type::tshiftcnt); | |
7585 e2 = e2->castTo(sc, e1->type); // LLVMDC | |
7586 return this; | |
7587 } | |
7588 | |
7589 /************************************************************/ | |
7590 | |
7591 UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7592 : BinExp(loc, TOKushrass, sizeof(UshrAssignExp), e1, e2) | |
7593 { | |
7594 } | |
7595 | |
7596 Expression *UshrAssignExp::semantic(Scope *sc) | |
7597 { Expression *e; | |
7598 | |
7599 BinExp::semantic(sc); | |
7600 e2 = resolveProperties(sc, e2); | |
7601 | |
7602 e = op_overload(sc); | |
7603 if (e) | |
7604 return e; | |
7605 | |
7606 e1 = e1->modifiableLvalue(sc, e1); | |
7607 e1->checkScalar(); | |
7608 e1->checkNoBool(); | |
7609 type = e1->type; | |
7610 typeCombine(sc); | |
7611 e1->checkIntegral(); | |
7612 e2 = e2->checkIntegral(); | |
7613 //e2 = e2->castTo(sc, Type::tshiftcnt); | |
7614 e2 = e2->castTo(sc, e1->type); // LLVMDC | |
7615 return this; | |
7616 } | |
7617 | |
7618 /************************************************************/ | |
7619 | |
7620 AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7621 : BinExp(loc, TOKandass, sizeof(AndAssignExp), e1, e2) | |
7622 { | |
7623 } | |
7624 | |
7625 Expression *AndAssignExp::semantic(Scope *sc) | |
7626 { | |
7627 return commonSemanticAssignIntegral(sc); | |
7628 } | |
7629 | |
7630 /************************************************************/ | |
7631 | |
7632 OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7633 : BinExp(loc, TOKorass, sizeof(OrAssignExp), e1, e2) | |
7634 { | |
7635 } | |
7636 | |
7637 Expression *OrAssignExp::semantic(Scope *sc) | |
7638 { | |
7639 return commonSemanticAssignIntegral(sc); | |
7640 } | |
7641 | |
7642 /************************************************************/ | |
7643 | |
7644 XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7645 : BinExp(loc, TOKxorass, sizeof(XorAssignExp), e1, e2) | |
7646 { | |
7647 } | |
7648 | |
7649 Expression *XorAssignExp::semantic(Scope *sc) | |
7650 { | |
7651 return commonSemanticAssignIntegral(sc); | |
7652 } | |
7653 | |
7654 /************************* AddExp *****************************/ | |
7655 | |
7656 AddExp::AddExp(Loc loc, Expression *e1, Expression *e2) | |
7657 : BinExp(loc, TOKadd, sizeof(AddExp), e1, e2) | |
7658 { | |
7659 llvmFieldIndex = false; | |
7660 } | |
7661 | |
7662 Expression *AddExp::semantic(Scope *sc) | |
7663 { Expression *e; | |
7664 | |
7665 #if LOGSEMANTIC | |
7666 printf("AddExp::semantic('%s')\n", toChars()); | |
7667 #endif | |
7668 if (!type) | |
7669 { | |
7670 BinExp::semanticp(sc); | |
7671 | |
7672 e = op_overload(sc); | |
7673 if (e) | |
7674 return e; | |
7675 | |
7676 Type *tb1 = e1->type->toBasetype(); | |
7677 Type *tb2 = e2->type->toBasetype(); | |
7678 | |
7679 if ((tb1->ty == Tarray || tb1->ty == Tsarray) && | |
7680 (tb2->ty == Tarray || tb2->ty == Tsarray) && | |
7681 tb1->next->equals(tb2->next) | |
7682 ) | |
7683 { | |
7684 type = e1->type; | |
7685 e = this; | |
7686 } | |
7687 else if (tb1->ty == Tpointer && e2->type->isintegral() || | |
7688 tb2->ty == Tpointer && e1->type->isintegral()) | |
7689 e = scaleFactor(sc); | |
7690 else if (tb1->ty == Tpointer && tb2->ty == Tpointer) | |
7691 { | |
7692 incompatibleTypes(); | |
7693 type = e1->type; | |
7694 e = this; | |
7695 } | |
7696 else | |
7697 { | |
7698 typeCombine(sc); | |
7699 if ((e1->type->isreal() && e2->type->isimaginary()) || | |
7700 (e1->type->isimaginary() && e2->type->isreal())) | |
7701 { | |
7702 switch (type->toBasetype()->ty) | |
7703 { | |
7704 case Tfloat32: | |
7705 case Timaginary32: | |
7706 type = Type::tcomplex32; | |
7707 break; | |
7708 | |
7709 case Tfloat64: | |
7710 case Timaginary64: | |
7711 type = Type::tcomplex64; | |
7712 break; | |
7713 | |
7714 case Tfloat80: | |
7715 case Timaginary80: | |
7716 type = Type::tcomplex80; | |
7717 break; | |
7718 | |
7719 default: | |
7720 assert(0); | |
7721 } | |
7722 } | |
7723 e = this; | |
7724 } | |
7725 return e; | |
7726 } | |
7727 return this; | |
7728 } | |
7729 | |
7730 /************************************************************/ | |
7731 | |
7732 MinExp::MinExp(Loc loc, Expression *e1, Expression *e2) | |
7733 : BinExp(loc, TOKmin, sizeof(MinExp), e1, e2) | |
7734 { | |
7735 } | |
7736 | |
7737 Expression *MinExp::semantic(Scope *sc) | |
7738 { Expression *e; | |
7739 Type *t1; | |
7740 Type *t2; | |
7741 | |
7742 #if LOGSEMANTIC | |
7743 printf("MinExp::semantic('%s')\n", toChars()); | |
7744 #endif | |
7745 if (type) | |
7746 return this; | |
7747 | |
7748 BinExp::semanticp(sc); | |
7749 | |
7750 e = op_overload(sc); | |
7751 if (e) | |
7752 return e; | |
7753 | |
7754 e = this; | |
7755 t1 = e1->type->toBasetype(); | |
7756 t2 = e2->type->toBasetype(); | |
7757 if (t1->ty == Tpointer) | |
7758 { | |
7759 if (t2->ty == Tpointer) | |
7760 { // Need to divide the result by the stride | |
7761 // Replace (ptr - ptr) with (ptr - ptr) / stride | |
7762 d_int64 stride; | |
7763 Expression *e; | |
7764 | |
7765 typeCombine(sc); // make sure pointer types are compatible | |
7766 type = Type::tptrdiff_t; | |
7767 stride = t2->next->size(); | |
328
7086a84ab3d6
[svn r349] Fixed problems with static arrays of void as well as a static arrays with zero length.
lindquist
parents:
305
diff
changeset
|
7768 if (!stride) |
7086a84ab3d6
[svn r349] Fixed problems with static arrays of void as well as a static arrays with zero length.
lindquist
parents:
305
diff
changeset
|
7769 return new IntegerExp(0, 0, Type::tptrdiff_t); |
159 | 7770 e = new DivExp(loc, this, new IntegerExp(0, stride, Type::tptrdiff_t)); |
7771 e->type = Type::tptrdiff_t; | |
7772 return e; | |
7773 } | |
7774 else if (t2->isintegral()) | |
7775 e = scaleFactor(sc); | |
7776 else | |
7777 { error("incompatible types for -"); | |
7778 return new IntegerExp(0); | |
7779 } | |
7780 } | |
7781 else if (t2->ty == Tpointer) | |
7782 { | |
7783 type = e2->type; | |
7784 error("can't subtract pointer from %s", e1->type->toChars()); | |
7785 return new IntegerExp(0); | |
7786 } | |
7787 else | |
7788 { | |
7789 typeCombine(sc); | |
7790 t1 = e1->type->toBasetype(); | |
7791 t2 = e2->type->toBasetype(); | |
7792 if ((t1->isreal() && t2->isimaginary()) || | |
7793 (t1->isimaginary() && t2->isreal())) | |
7794 { | |
7795 switch (type->ty) | |
7796 { | |
7797 case Tfloat32: | |
7798 case Timaginary32: | |
7799 type = Type::tcomplex32; | |
7800 break; | |
7801 | |
7802 case Tfloat64: | |
7803 case Timaginary64: | |
7804 type = Type::tcomplex64; | |
7805 break; | |
7806 | |
7807 case Tfloat80: | |
7808 case Timaginary80: | |
7809 type = Type::tcomplex80; | |
7810 break; | |
7811 | |
7812 default: | |
7813 assert(0); | |
7814 } | |
7815 } | |
7816 } | |
7817 return e; | |
7818 } | |
7819 | |
7820 /************************* CatExp *****************************/ | |
7821 | |
7822 CatExp::CatExp(Loc loc, Expression *e1, Expression *e2) | |
7823 : BinExp(loc, TOKcat, sizeof(CatExp), e1, e2) | |
7824 { | |
7825 } | |
7826 | |
7827 Expression *CatExp::semantic(Scope *sc) | |
7828 { Expression *e; | |
7829 | |
7830 //printf("CatExp::semantic() %s\n", toChars()); | |
7831 if (!type) | |
7832 { | |
7833 BinExp::semanticp(sc); | |
7834 e = op_overload(sc); | |
7835 if (e) | |
7836 return e; | |
7837 | |
7838 Type *tb1 = e1->type->toBasetype(); | |
7839 Type *tb2 = e2->type->toBasetype(); | |
7840 | |
7841 | |
7842 /* BUG: Should handle things like: | |
7843 * char c; | |
7844 * c ~ ' ' | |
7845 * ' ' ~ c; | |
7846 */ | |
7847 | |
7848 #if 0 | |
7849 e1->type->print(); | |
7850 e2->type->print(); | |
7851 #endif | |
7852 if ((tb1->ty == Tsarray || tb1->ty == Tarray) && | |
7853 e2->type->equals(tb1->next)) | |
7854 { | |
7855 type = tb1->next->arrayOf(); | |
7856 if (tb2->ty == Tarray) | |
7857 { // Make e2 into [e2] | |
7858 e2 = new ArrayLiteralExp(e2->loc, e2); | |
7859 e2->type = type; | |
7860 } | |
7861 return this; | |
7862 } | |
7863 else if ((tb2->ty == Tsarray || tb2->ty == Tarray) && | |
7864 e1->type->equals(tb2->next)) | |
7865 { | |
7866 type = tb2->next->arrayOf(); | |
7867 if (tb1->ty == Tarray) | |
7868 { // Make e1 into [e1] | |
7869 e1 = new ArrayLiteralExp(e1->loc, e1); | |
7870 e1->type = type; | |
7871 } | |
7872 return this; | |
7873 } | |
7874 | |
7875 typeCombine(sc); | |
7876 | |
7877 if (type->toBasetype()->ty == Tsarray) | |
7878 type = type->toBasetype()->next->arrayOf(); | |
7879 #if 0 | |
7880 e1->type->print(); | |
7881 e2->type->print(); | |
7882 type->print(); | |
7883 print(); | |
7884 #endif | |
7885 if (e1->op == TOKstring && e2->op == TOKstring) | |
7886 e = optimize(WANTvalue); | |
7887 else if (e1->type->equals(e2->type) && | |
7888 (e1->type->toBasetype()->ty == Tarray || | |
7889 e1->type->toBasetype()->ty == Tsarray)) | |
7890 { | |
7891 e = this; | |
7892 } | |
7893 else | |
7894 { | |
7895 error("Can only concatenate arrays, not (%s ~ %s)", | |
7896 e1->type->toChars(), e2->type->toChars()); | |
7897 type = Type::tint32; | |
7898 e = this; | |
7899 } | |
7900 e->type = e->type->semantic(loc, sc); | |
7901 return e; | |
7902 } | |
7903 return this; | |
7904 } | |
7905 | |
7906 /************************************************************/ | |
7907 | |
7908 MulExp::MulExp(Loc loc, Expression *e1, Expression *e2) | |
7909 : BinExp(loc, TOKmul, sizeof(MulExp), e1, e2) | |
7910 { | |
7911 } | |
7912 | |
7913 Expression *MulExp::semantic(Scope *sc) | |
7914 { Expression *e; | |
7915 | |
7916 #if 0 | |
7917 printf("MulExp::semantic() %s\n", toChars()); | |
7918 #endif | |
7919 if (type) | |
7920 { | |
7921 return this; | |
7922 } | |
7923 | |
7924 BinExp::semanticp(sc); | |
7925 e = op_overload(sc); | |
7926 if (e) | |
7927 return e; | |
7928 | |
7929 typeCombine(sc); | |
7930 e1->checkArithmetic(); | |
7931 e2->checkArithmetic(); | |
7932 if (type->isfloating()) | |
7933 { Type *t1 = e1->type; | |
7934 Type *t2 = e2->type; | |
7935 | |
7936 if (t1->isreal()) | |
7937 { | |
7938 type = t2; | |
7939 } | |
7940 else if (t2->isreal()) | |
7941 { | |
7942 type = t1; | |
7943 } | |
7944 else if (t1->isimaginary()) | |
7945 { | |
7946 if (t2->isimaginary()) | |
7947 { Expression *e; | |
7948 | |
7949 switch (t1->ty) | |
7950 { | |
7951 case Timaginary32: type = Type::tfloat32; break; | |
7952 case Timaginary64: type = Type::tfloat64; break; | |
7953 case Timaginary80: type = Type::tfloat80; break; | |
7954 default: assert(0); | |
7955 } | |
7956 | |
7957 // iy * iv = -yv | |
7958 e1->type = type; | |
7959 e2->type = type; | |
7960 e = new NegExp(loc, this); | |
7961 e = e->semantic(sc); | |
7962 return e; | |
7963 } | |
7964 else | |
7965 type = t2; // t2 is complex | |
7966 } | |
7967 else if (t2->isimaginary()) | |
7968 { | |
7969 type = t1; // t1 is complex | |
7970 } | |
7971 } | |
7972 return this; | |
7973 } | |
7974 | |
7975 /************************************************************/ | |
7976 | |
7977 DivExp::DivExp(Loc loc, Expression *e1, Expression *e2) | |
7978 : BinExp(loc, TOKdiv, sizeof(DivExp), e1, e2) | |
7979 { | |
7980 } | |
7981 | |
7982 Expression *DivExp::semantic(Scope *sc) | |
7983 { Expression *e; | |
7984 | |
7985 if (type) | |
7986 return this; | |
7987 | |
7988 BinExp::semanticp(sc); | |
7989 e = op_overload(sc); | |
7990 if (e) | |
7991 return e; | |
7992 | |
7993 typeCombine(sc); | |
7994 e1->checkArithmetic(); | |
7995 e2->checkArithmetic(); | |
7996 if (type->isfloating()) | |
7997 { Type *t1 = e1->type; | |
7998 Type *t2 = e2->type; | |
7999 | |
8000 if (t1->isreal()) | |
8001 { | |
8002 type = t2; | |
8003 if (t2->isimaginary()) | |
8004 { Expression *e; | |
8005 | |
8006 // x/iv = i(-x/v) | |
8007 e2->type = t1; | |
8008 e = new NegExp(loc, this); | |
8009 e = e->semantic(sc); | |
8010 return e; | |
8011 } | |
8012 } | |
8013 else if (t2->isreal()) | |
8014 { | |
8015 type = t1; | |
8016 } | |
8017 else if (t1->isimaginary()) | |
8018 { | |
8019 if (t2->isimaginary()) | |
8020 { | |
8021 switch (t1->ty) | |
8022 { | |
8023 case Timaginary32: type = Type::tfloat32; break; | |
8024 case Timaginary64: type = Type::tfloat64; break; | |
8025 case Timaginary80: type = Type::tfloat80; break; | |
8026 default: assert(0); | |
8027 } | |
8028 } | |
8029 else | |
8030 type = t2; // t2 is complex | |
8031 } | |
8032 else if (t2->isimaginary()) | |
8033 { | |
8034 type = t1; // t1 is complex | |
8035 } | |
8036 } | |
8037 return this; | |
8038 } | |
8039 | |
8040 /************************************************************/ | |
8041 | |
8042 ModExp::ModExp(Loc loc, Expression *e1, Expression *e2) | |
8043 : BinExp(loc, TOKmod, sizeof(ModExp), e1, e2) | |
8044 { | |
8045 } | |
8046 | |
8047 Expression *ModExp::semantic(Scope *sc) | |
8048 { Expression *e; | |
8049 | |
8050 if (type) | |
8051 return this; | |
8052 | |
8053 BinExp::semanticp(sc); | |
8054 e = op_overload(sc); | |
8055 if (e) | |
8056 return e; | |
8057 | |
8058 typeCombine(sc); | |
8059 e1->checkArithmetic(); | |
8060 e2->checkArithmetic(); | |
8061 if (type->isfloating()) | |
8062 { type = e1->type; | |
8063 if (e2->type->iscomplex()) | |
8064 { error("cannot perform modulo complex arithmetic"); | |
8065 return new IntegerExp(0); | |
8066 } | |
8067 } | |
8068 return this; | |
8069 } | |
8070 | |
8071 /************************************************************/ | |
8072 | |
8073 ShlExp::ShlExp(Loc loc, Expression *e1, Expression *e2) | |
8074 : BinExp(loc, TOKshl, sizeof(ShlExp), e1, e2) | |
8075 { | |
8076 } | |
8077 | |
8078 Expression *ShlExp::semantic(Scope *sc) | |
8079 { Expression *e; | |
8080 | |
8081 //printf("ShlExp::semantic(), type = %p\n", type); | |
8082 if (!type) | |
8083 { BinExp::semanticp(sc); | |
8084 e = op_overload(sc); | |
8085 if (e) | |
8086 return e; | |
8087 e1 = e1->checkIntegral(); | |
8088 e2 = e2->checkIntegral(); | |
8089 e1 = e1->integralPromotions(sc); | |
8090 //e2 = e2->castTo(sc, Type::tshiftcnt); | |
8091 e2 = e2->castTo(sc, e1->type); // LLVMDC | |
8092 type = e1->type; | |
8093 } | |
8094 return this; | |
8095 } | |
8096 | |
8097 /************************************************************/ | |
8098 | |
8099 ShrExp::ShrExp(Loc loc, Expression *e1, Expression *e2) | |
8100 : BinExp(loc, TOKshr, sizeof(ShrExp), e1, e2) | |
8101 { | |
8102 } | |
8103 | |
8104 Expression *ShrExp::semantic(Scope *sc) | |
8105 { Expression *e; | |
8106 | |
8107 if (!type) | |
8108 { BinExp::semanticp(sc); | |
8109 e = op_overload(sc); | |
8110 if (e) | |
8111 return e; | |
8112 e1 = e1->checkIntegral(); | |
8113 e2 = e2->checkIntegral(); | |
8114 e1 = e1->integralPromotions(sc); | |
8115 //e2 = e2->castTo(sc, Type::tshiftcnt); | |
8116 e2 = e2->castTo(sc, e1->type); // LLVMDC | |
8117 type = e1->type; | |
8118 } | |
8119 return this; | |
8120 } | |
8121 | |
8122 /************************************************************/ | |
8123 | |
8124 UshrExp::UshrExp(Loc loc, Expression *e1, Expression *e2) | |
8125 : BinExp(loc, TOKushr, sizeof(UshrExp), e1, e2) | |
8126 { | |
8127 } | |
8128 | |
8129 Expression *UshrExp::semantic(Scope *sc) | |
8130 { Expression *e; | |
8131 | |
8132 if (!type) | |
8133 { BinExp::semanticp(sc); | |
8134 e = op_overload(sc); | |
8135 if (e) | |
8136 return e; | |
8137 e1 = e1->checkIntegral(); | |
8138 e2 = e2->checkIntegral(); | |
8139 e1 = e1->integralPromotions(sc); | |
8140 //e2 = e2->castTo(sc, Type::tshiftcnt); | |
8141 e2 = e2->castTo(sc, e1->type); // LLVMDC | |
8142 type = e1->type; | |
8143 } | |
8144 return this; | |
8145 } | |
8146 | |
8147 /************************************************************/ | |
8148 | |
8149 AndExp::AndExp(Loc loc, Expression *e1, Expression *e2) | |
8150 : BinExp(loc, TOKand, sizeof(AndExp), e1, e2) | |
8151 { | |
8152 } | |
8153 | |
8154 Expression *AndExp::semantic(Scope *sc) | |
8155 { Expression *e; | |
8156 | |
8157 if (!type) | |
8158 { BinExp::semanticp(sc); | |
8159 e = op_overload(sc); | |
8160 if (e) | |
8161 return e; | |
8162 if (e1->type->toBasetype()->ty == Tbool && | |
8163 e2->type->toBasetype()->ty == Tbool) | |
8164 { | |
8165 type = e1->type; | |
8166 e = this; | |
8167 } | |
8168 else | |
8169 { | |
8170 typeCombine(sc); | |
8171 e1->checkIntegral(); | |
8172 e2->checkIntegral(); | |
8173 } | |
8174 } | |
8175 return this; | |
8176 } | |
8177 | |
8178 /************************************************************/ | |
8179 | |
8180 OrExp::OrExp(Loc loc, Expression *e1, Expression *e2) | |
8181 : BinExp(loc, TOKor, sizeof(OrExp), e1, e2) | |
8182 { | |
8183 } | |
8184 | |
8185 Expression *OrExp::semantic(Scope *sc) | |
8186 { Expression *e; | |
8187 | |
8188 if (!type) | |
8189 { BinExp::semanticp(sc); | |
8190 e = op_overload(sc); | |
8191 if (e) | |
8192 return e; | |
8193 if (e1->type->toBasetype()->ty == Tbool && | |
8194 e2->type->toBasetype()->ty == Tbool) | |
8195 { | |
8196 type = e1->type; | |
8197 e = this; | |
8198 } | |
8199 else | |
8200 { | |
8201 typeCombine(sc); | |
8202 e1->checkIntegral(); | |
8203 e2->checkIntegral(); | |
8204 } | |
8205 } | |
8206 return this; | |
8207 } | |
8208 | |
8209 /************************************************************/ | |
8210 | |
8211 XorExp::XorExp(Loc loc, Expression *e1, Expression *e2) | |
8212 : BinExp(loc, TOKxor, sizeof(XorExp), e1, e2) | |
8213 { | |
8214 } | |
8215 | |
8216 Expression *XorExp::semantic(Scope *sc) | |
8217 { Expression *e; | |
8218 | |
8219 if (!type) | |
8220 { BinExp::semanticp(sc); | |
8221 e = op_overload(sc); | |
8222 if (e) | |
8223 return e; | |
8224 if (e1->type->toBasetype()->ty == Tbool && | |
8225 e2->type->toBasetype()->ty == Tbool) | |
8226 { | |
8227 type = e1->type; | |
8228 e = this; | |
8229 } | |
8230 else | |
8231 { | |
8232 typeCombine(sc); | |
8233 e1->checkIntegral(); | |
8234 e2->checkIntegral(); | |
8235 } | |
8236 } | |
8237 return this; | |
8238 } | |
8239 | |
8240 | |
8241 /************************************************************/ | |
8242 | |
8243 OrOrExp::OrOrExp(Loc loc, Expression *e1, Expression *e2) | |
8244 : BinExp(loc, TOKoror, sizeof(OrOrExp), e1, e2) | |
8245 { | |
8246 } | |
8247 | |
8248 Expression *OrOrExp::semantic(Scope *sc) | |
8249 { | |
8250 unsigned cs1; | |
8251 | |
8252 // same as for AndAnd | |
8253 e1 = e1->semantic(sc); | |
8254 e1 = resolveProperties(sc, e1); | |
8255 e1 = e1->checkToPointer(); | |
8256 e1 = e1->checkToBoolean(); | |
8257 cs1 = sc->callSuper; | |
8258 | |
8259 if (sc->flags & SCOPEstaticif) | |
8260 { | |
8261 /* If in static if, don't evaluate e2 if we don't have to. | |
8262 */ | |
8263 e1 = e1->optimize(WANTflags); | |
8264 if (e1->isBool(TRUE)) | |
8265 { | |
8266 return new IntegerExp(loc, 1, Type::tboolean); | |
8267 } | |
8268 } | |
8269 | |
8270 e2 = e2->semantic(sc); | |
8271 sc->mergeCallSuper(loc, cs1); | |
8272 e2 = resolveProperties(sc, e2); | |
8273 e2 = e2->checkToPointer(); | |
8274 | |
8275 type = Type::tboolean; | |
8276 if (e1->type->ty == Tvoid) | |
8277 type = Type::tvoid; | |
8278 if (e2->op == TOKtype || e2->op == TOKimport) | |
8279 error("%s is not an expression", e2->toChars()); | |
8280 return this; | |
8281 } | |
8282 | |
8283 Expression *OrOrExp::checkToBoolean() | |
8284 { | |
8285 e2 = e2->checkToBoolean(); | |
8286 return this; | |
8287 } | |
8288 | |
8289 int OrOrExp::isBit() | |
8290 { | |
8291 return TRUE; | |
8292 } | |
8293 | |
8294 int OrOrExp::checkSideEffect(int flag) | |
8295 { | |
8296 if (flag == 2) | |
8297 { | |
8298 return e1->checkSideEffect(2) || e2->checkSideEffect(2); | |
8299 } | |
8300 else | |
8301 { e1->checkSideEffect(1); | |
8302 return e2->checkSideEffect(flag); | |
8303 } | |
8304 } | |
8305 | |
8306 /************************************************************/ | |
8307 | |
8308 AndAndExp::AndAndExp(Loc loc, Expression *e1, Expression *e2) | |
8309 : BinExp(loc, TOKandand, sizeof(AndAndExp), e1, e2) | |
8310 { | |
8311 } | |
8312 | |
8313 Expression *AndAndExp::semantic(Scope *sc) | |
8314 { | |
8315 unsigned cs1; | |
8316 | |
8317 // same as for OrOr | |
8318 e1 = e1->semantic(sc); | |
8319 e1 = resolveProperties(sc, e1); | |
8320 e1 = e1->checkToPointer(); | |
8321 e1 = e1->checkToBoolean(); | |
8322 cs1 = sc->callSuper; | |
8323 | |
8324 if (sc->flags & SCOPEstaticif) | |
8325 { | |
8326 /* If in static if, don't evaluate e2 if we don't have to. | |
8327 */ | |
8328 e1 = e1->optimize(WANTflags); | |
8329 if (e1->isBool(FALSE)) | |
8330 { | |
8331 return new IntegerExp(loc, 0, Type::tboolean); | |
8332 } | |
8333 } | |
8334 | |
8335 e2 = e2->semantic(sc); | |
8336 sc->mergeCallSuper(loc, cs1); | |
8337 e2 = resolveProperties(sc, e2); | |
8338 e2 = e2->checkToPointer(); | |
8339 | |
8340 type = Type::tboolean; | |
8341 if (e1->type->ty == Tvoid) | |
8342 type = Type::tvoid; | |
8343 if (e2->op == TOKtype || e2->op == TOKimport) | |
8344 error("%s is not an expression", e2->toChars()); | |
8345 return this; | |
8346 } | |
8347 | |
8348 Expression *AndAndExp::checkToBoolean() | |
8349 { | |
8350 e2 = e2->checkToBoolean(); | |
8351 return this; | |
8352 } | |
8353 | |
8354 int AndAndExp::isBit() | |
8355 { | |
8356 return TRUE; | |
8357 } | |
8358 | |
8359 int AndAndExp::checkSideEffect(int flag) | |
8360 { | |
8361 if (flag == 2) | |
8362 { | |
8363 return e1->checkSideEffect(2) || e2->checkSideEffect(2); | |
8364 } | |
8365 else | |
8366 { | |
8367 e1->checkSideEffect(1); | |
8368 return e2->checkSideEffect(flag); | |
8369 } | |
8370 } | |
8371 | |
8372 /************************************************************/ | |
8373 | |
8374 InExp::InExp(Loc loc, Expression *e1, Expression *e2) | |
8375 : BinExp(loc, TOKin, sizeof(InExp), e1, e2) | |
8376 { | |
8377 } | |
8378 | |
8379 Expression *InExp::semantic(Scope *sc) | |
8380 { Expression *e; | |
8381 | |
8382 if (type) | |
8383 return this; | |
8384 | |
8385 BinExp::semanticp(sc); | |
8386 e = op_overload(sc); | |
8387 if (e) | |
8388 return e; | |
8389 | |
8390 //type = Type::tboolean; | |
8391 Type *t2b = e2->type->toBasetype(); | |
8392 if (t2b->ty != Taarray) | |
8393 { | |
8394 error("rvalue of in expression must be an associative array, not %s", e2->type->toChars()); | |
8395 type = Type::terror; | |
8396 } | |
8397 else | |
8398 { | |
8399 TypeAArray *ta = (TypeAArray *)t2b; | |
8400 | |
8401 // Convert key to type of key | |
8402 e1 = e1->implicitCastTo(sc, ta->index); | |
8403 | |
8404 // Return type is pointer to value | |
8405 type = ta->next->pointerTo(); | |
8406 } | |
8407 return this; | |
8408 } | |
8409 | |
8410 int InExp::isBit() | |
8411 { | |
8412 return FALSE; | |
8413 } | |
8414 | |
8415 | |
8416 /************************************************************/ | |
8417 | |
8418 /* This deletes the key e1 from the associative array e2 | |
8419 */ | |
8420 | |
8421 RemoveExp::RemoveExp(Loc loc, Expression *e1, Expression *e2) | |
8422 : BinExp(loc, TOKremove, sizeof(RemoveExp), e1, e2) | |
8423 { | |
8424 type = Type::tvoid; | |
8425 } | |
8426 | |
8427 /************************************************************/ | |
8428 | |
8429 CmpExp::CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2) | |
8430 : BinExp(loc, op, sizeof(CmpExp), e1, e2) | |
8431 { | |
8432 } | |
8433 | |
8434 Expression *CmpExp::semantic(Scope *sc) | |
8435 { Expression *e; | |
8436 Type *t1; | |
8437 Type *t2; | |
8438 | |
8439 #if LOGSEMANTIC | |
8440 printf("CmpExp::semantic('%s')\n", toChars()); | |
8441 #endif | |
8442 if (type) | |
8443 return this; | |
8444 | |
8445 BinExp::semanticp(sc); | |
8446 | |
8447 if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull || | |
8448 e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull) | |
8449 { | |
8450 error("do not use null when comparing class types"); | |
8451 } | |
8452 | |
8453 e = op_overload(sc); | |
8454 if (e) | |
8455 { | |
8456 e = new CmpExp(op, loc, e, new IntegerExp(loc, 0, Type::tint32)); | |
8457 e = e->semantic(sc); | |
8458 return e; | |
8459 } | |
8460 | |
8461 typeCombine(sc); | |
8462 type = Type::tboolean; | |
8463 | |
8464 // Special handling for array comparisons | |
8465 t1 = e1->type->toBasetype(); | |
8466 t2 = e2->type->toBasetype(); | |
8467 if ((t1->ty == Tarray || t1->ty == Tsarray) && | |
8468 (t2->ty == Tarray || t2->ty == Tsarray)) | |
8469 { | |
8470 if (!t1->next->equals(t2->next)) | |
8471 error("array comparison type mismatch, %s vs %s", t1->next->toChars(), t2->next->toChars()); | |
8472 e = this; | |
8473 } | |
8474 else if (t1->ty == Tstruct || t2->ty == Tstruct || | |
8475 (t1->ty == Tclass && t2->ty == Tclass)) | |
8476 { | |
8477 if (t2->ty == Tstruct) | |
8478 error("need member function opCmp() for %s %s to compare", t2->toDsymbol(sc)->kind(), t2->toChars()); | |
8479 else | |
8480 error("need member function opCmp() for %s %s to compare", t1->toDsymbol(sc)->kind(), t1->toChars()); | |
8481 e = this; | |
8482 } | |
8483 #if 1 | |
8484 else if (t1->iscomplex() || t2->iscomplex()) | |
8485 { | |
8486 error("compare not defined for complex operands"); | |
8487 e = new IntegerExp(0); | |
8488 } | |
8489 #endif | |
8490 else | |
8491 e = this; | |
8492 return e; | |
8493 } | |
8494 | |
8495 int CmpExp::isBit() | |
8496 { | |
8497 return TRUE; | |
8498 } | |
8499 | |
8500 | |
8501 /************************************************************/ | |
8502 | |
8503 EqualExp::EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2) | |
8504 : BinExp(loc, op, sizeof(EqualExp), e1, e2) | |
8505 { | |
8506 assert(op == TOKequal || op == TOKnotequal); | |
8507 } | |
8508 | |
8509 Expression *EqualExp::semantic(Scope *sc) | |
8510 { Expression *e; | |
8511 Type *t1; | |
8512 Type *t2; | |
8513 | |
8514 //printf("EqualExp::semantic('%s')\n", toChars()); | |
8515 if (type) | |
8516 return this; | |
8517 | |
8518 BinExp::semanticp(sc); | |
8519 | |
8520 /* Before checking for operator overloading, check to see if we're | |
8521 * comparing the addresses of two statics. If so, we can just see | |
8522 * if they are the same symbol. | |
8523 */ | |
8524 if (e1->op == TOKaddress && e2->op == TOKaddress) | |
8525 { AddrExp *ae1 = (AddrExp *)e1; | |
8526 AddrExp *ae2 = (AddrExp *)e2; | |
8527 | |
8528 if (ae1->e1->op == TOKvar && ae2->e1->op == TOKvar) | |
8529 { VarExp *ve1 = (VarExp *)ae1->e1; | |
8530 VarExp *ve2 = (VarExp *)ae2->e1; | |
8531 | |
8532 if (ve1->var == ve2->var /*|| ve1->var->toSymbol() == ve2->var->toSymbol()*/) | |
8533 { | |
8534 // They are the same, result is 'true' for ==, 'false' for != | |
8535 e = new IntegerExp(loc, (op == TOKequal), Type::tboolean); | |
8536 return e; | |
8537 } | |
8538 } | |
8539 } | |
8540 | |
8541 if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull || | |
8542 e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull) | |
8543 { | |
8544 error("use '%s' instead of '%s' when comparing with null", | |
8545 Token::toChars(op == TOKequal ? TOKidentity : TOKnotidentity), | |
8546 Token::toChars(op)); | |
8547 } | |
8548 | |
8549 //if (e2->op != TOKnull) | |
8550 { | |
8551 e = op_overload(sc); | |
8552 if (e) | |
8553 { | |
8554 if (op == TOKnotequal) | |
8555 { | |
8556 e = new NotExp(e->loc, e); | |
8557 e = e->semantic(sc); | |
8558 } | |
8559 return e; | |
8560 } | |
8561 } | |
8562 | |
8563 e = typeCombine(sc); | |
8564 type = Type::tboolean; | |
8565 | |
8566 // Special handling for array comparisons | |
8567 t1 = e1->type->toBasetype(); | |
8568 t2 = e2->type->toBasetype(); | |
8569 if ((t1->ty == Tarray || t1->ty == Tsarray) && | |
8570 (t2->ty == Tarray || t2->ty == Tsarray)) | |
8571 { | |
8572 if (!t1->next->equals(t2->next)) | |
8573 error("array comparison type mismatch, %s vs %s", t1->next->toChars(), t2->next->toChars()); | |
8574 } | |
8575 else | |
8576 { | |
8577 if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating()) | |
8578 { | |
8579 // Cast both to complex | |
8580 e1 = e1->castTo(sc, Type::tcomplex80); | |
8581 e2 = e2->castTo(sc, Type::tcomplex80); | |
8582 } | |
8583 } | |
8584 return e; | |
8585 } | |
8586 | |
8587 int EqualExp::isBit() | |
8588 { | |
8589 return TRUE; | |
8590 } | |
8591 | |
8592 | |
8593 | |
8594 /************************************************************/ | |
8595 | |
8596 IdentityExp::IdentityExp(enum TOK op, Loc loc, Expression *e1, Expression *e2) | |
8597 : BinExp(loc, op, sizeof(IdentityExp), e1, e2) | |
8598 { | |
8599 } | |
8600 | |
8601 Expression *IdentityExp::semantic(Scope *sc) | |
8602 { | |
8603 if (type) | |
8604 return this; | |
8605 | |
8606 BinExp::semanticp(sc); | |
8607 type = Type::tboolean; | |
8608 typeCombine(sc); | |
8609 if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating()) | |
8610 { | |
8611 // Cast both to complex | |
8612 e1 = e1->castTo(sc, Type::tcomplex80); | |
8613 e2 = e2->castTo(sc, Type::tcomplex80); | |
8614 } | |
8615 return this; | |
8616 } | |
8617 | |
8618 int IdentityExp::isBit() | |
8619 { | |
8620 return TRUE; | |
8621 } | |
8622 | |
8623 | |
8624 /****************************************************************/ | |
8625 | |
8626 CondExp::CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2) | |
8627 : BinExp(loc, TOKquestion, sizeof(CondExp), e1, e2) | |
8628 { | |
8629 this->econd = econd; | |
8630 } | |
8631 | |
8632 Expression *CondExp::syntaxCopy() | |
8633 { | |
8634 return new CondExp(loc, econd->syntaxCopy(), e1->syntaxCopy(), e2->syntaxCopy()); | |
8635 } | |
8636 | |
8637 | |
8638 Expression *CondExp::semantic(Scope *sc) | |
8639 { Type *t1; | |
8640 Type *t2; | |
8641 unsigned cs0; | |
8642 unsigned cs1; | |
8643 | |
8644 #if LOGSEMANTIC | |
8645 printf("CondExp::semantic('%s')\n", toChars()); | |
8646 #endif | |
8647 if (type) | |
8648 return this; | |
8649 | |
8650 econd = econd->semantic(sc); | |
8651 econd = resolveProperties(sc, econd); | |
8652 econd = econd->checkToPointer(); | |
8653 econd = econd->checkToBoolean(); | |
8654 | |
8655 #if 0 /* this cannot work right because the types of e1 and e2 | |
8656 * both contribute to the type of the result. | |
8657 */ | |
8658 if (sc->flags & SCOPEstaticif) | |
8659 { | |
8660 /* If in static if, don't evaluate what we don't have to. | |
8661 */ | |
8662 econd = econd->optimize(WANTflags); | |
8663 if (econd->isBool(TRUE)) | |
8664 { | |
8665 e1 = e1->semantic(sc); | |
8666 e1 = resolveProperties(sc, e1); | |
8667 return e1; | |
8668 } | |
8669 else if (econd->isBool(FALSE)) | |
8670 { | |
8671 e2 = e2->semantic(sc); | |
8672 e2 = resolveProperties(sc, e2); | |
8673 return e2; | |
8674 } | |
8675 } | |
8676 #endif | |
8677 | |
8678 | |
8679 cs0 = sc->callSuper; | |
8680 e1 = e1->semantic(sc); | |
8681 e1 = resolveProperties(sc, e1); | |
8682 cs1 = sc->callSuper; | |
8683 sc->callSuper = cs0; | |
8684 e2 = e2->semantic(sc); | |
8685 e2 = resolveProperties(sc, e2); | |
8686 sc->mergeCallSuper(loc, cs1); | |
8687 | |
8688 | |
8689 // If either operand is void, the result is void | |
8690 t1 = e1->type; | |
8691 t2 = e2->type; | |
8692 if (t1->ty == Tvoid || t2->ty == Tvoid) | |
8693 type = Type::tvoid; | |
8694 else if (t1 == t2) | |
8695 type = t1; | |
8696 else | |
8697 { | |
8698 typeCombine(sc); | |
8699 switch (e1->type->toBasetype()->ty) | |
8700 { | |
8701 case Tcomplex32: | |
8702 case Tcomplex64: | |
8703 case Tcomplex80: | |
8704 e2 = e2->castTo(sc, e1->type); | |
8705 break; | |
8706 } | |
8707 switch (e2->type->toBasetype()->ty) | |
8708 { | |
8709 case Tcomplex32: | |
8710 case Tcomplex64: | |
8711 case Tcomplex80: | |
8712 e1 = e1->castTo(sc, e2->type); | |
8713 break; | |
8714 } | |
8715 } | |
8716 return this; | |
8717 } | |
8718 | |
8719 Expression *CondExp::toLvalue(Scope *sc, Expression *ex) | |
8720 { | |
8721 PtrExp *e; | |
8722 | |
8723 // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2) | |
8724 e = new PtrExp(loc, this, type); | |
8725 | |
8726 e1 = e1->addressOf(sc); | |
8727 //e1 = e1->toLvalue(sc, NULL); | |
8728 | |
8729 e2 = e2->addressOf(sc); | |
8730 //e2 = e2->toLvalue(sc, NULL); | |
8731 | |
8732 typeCombine(sc); | |
8733 | |
8734 type = e2->type; | |
8735 return e; | |
8736 } | |
8737 | |
8738 Expression *CondExp::modifiableLvalue(Scope *sc, Expression *e) | |
8739 { | |
8740 error("conditional expression %s is not a modifiable lvalue", toChars()); | |
8741 return this; | |
8742 } | |
8743 | |
8744 void CondExp::checkEscape() | |
8745 { | |
8746 e1->checkEscape(); | |
8747 e2->checkEscape(); | |
8748 } | |
8749 | |
8750 | |
8751 Expression *CondExp::checkToBoolean() | |
8752 { | |
8753 e1 = e1->checkToBoolean(); | |
8754 e2 = e2->checkToBoolean(); | |
8755 return this; | |
8756 } | |
8757 | |
8758 int CondExp::checkSideEffect(int flag) | |
8759 { | |
8760 if (flag == 2) | |
8761 { | |
8762 return econd->checkSideEffect(2) || | |
8763 e1->checkSideEffect(2) || | |
8764 e2->checkSideEffect(2); | |
8765 } | |
8766 else | |
8767 { | |
8768 econd->checkSideEffect(1); | |
8769 e1->checkSideEffect(flag); | |
8770 return e2->checkSideEffect(flag); | |
8771 } | |
8772 } | |
8773 | |
8774 void CondExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
8775 { | |
8776 expToCBuffer(buf, hgs, econd, PREC_oror); | |
8777 buf->writestring(" ? "); | |
8778 expToCBuffer(buf, hgs, e1, PREC_expr); | |
8779 buf->writestring(" : "); | |
8780 expToCBuffer(buf, hgs, e2, PREC_cond); | |
8781 } | |
8782 | |
8783 |