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