Mercurial > projects > ldc
annotate dmd/constfold.c @ 837:331a176c1f4f
Removed error on naked, not fully complete, but I'll be doing more work on it during this Christmas, and some things do work.
Fixed taking delegate of final class method. see mini/delegate3.d.
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Tue, 09 Dec 2008 14:07:30 +0100 |
parents | eee9efe5b51f |
children | b30fe7e1dbb9 |
rev | line source |
---|---|
336 | 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 <assert.h> | |
14 #include <math.h> | |
15 | |
16 #if __DMC__ | |
17 #include <complex.h> | |
18 #endif | |
19 | |
20 #include "mem.h" | |
21 #include "root.h" | |
22 | |
23 #include "mtype.h" | |
24 #include "expression.h" | |
25 #include "aggregate.h" | |
26 #include "declaration.h" | |
27 | |
28 #ifdef IN_GCC | |
29 #include "d-gcc-real.h" | |
30 | |
31 /* %% fix? */ | |
32 extern "C" bool real_isnan (const real_t *); | |
33 #endif | |
34 | |
35 static real_t zero; // work around DMC bug for now | |
36 | |
37 #define LOG 0 | |
38 | |
39 Expression *expType(Type *type, Expression *e) | |
40 { | |
41 if (type != e->type) | |
42 { | |
43 e = e->copy(); | |
44 e->type = type; | |
45 } | |
46 return e; | |
47 } | |
48 | |
49 /* ================================== isConst() ============================== */ | |
50 | |
51 int Expression::isConst() | |
52 { | |
53 //printf("Expression::isConst(): %s\n", toChars()); | |
54 return 0; | |
55 } | |
56 | |
57 int IntegerExp::isConst() | |
58 { | |
59 return 1; | |
60 } | |
61 | |
62 int RealExp::isConst() | |
63 { | |
64 return 1; | |
65 } | |
66 | |
67 int ComplexExp::isConst() | |
68 { | |
69 return 1; | |
70 } | |
71 | |
72 int SymOffExp::isConst() | |
73 { | |
74 return 2; | |
75 } | |
76 | |
77 /* =============================== constFold() ============================== */ | |
78 | |
79 /* The constFold() functions were redundant with the optimize() ones, | |
80 * and so have been folded in with them. | |
81 */ | |
82 | |
83 /* ========================================================================== */ | |
84 | |
85 Expression *Neg(Type *type, Expression *e1) | |
86 { Expression *e; | |
87 Loc loc = e1->loc; | |
88 | |
89 if (e1->type->isreal()) | |
90 { | |
91 e = new RealExp(loc, -e1->toReal(), type); | |
92 } | |
93 else if (e1->type->isimaginary()) | |
94 { | |
95 e = new RealExp(loc, -e1->toImaginary(), type); | |
96 } | |
97 else if (e1->type->iscomplex()) | |
98 { | |
99 e = new ComplexExp(loc, -e1->toComplex(), type); | |
100 } | |
101 else | |
102 e = new IntegerExp(loc, -e1->toInteger(), type); | |
103 return e; | |
104 } | |
105 | |
106 Expression *Com(Type *type, Expression *e1) | |
107 { Expression *e; | |
108 Loc loc = e1->loc; | |
109 | |
110 e = new IntegerExp(loc, ~e1->toInteger(), type); | |
111 return e; | |
112 } | |
113 | |
114 Expression *Not(Type *type, Expression *e1) | |
115 { Expression *e; | |
116 Loc loc = e1->loc; | |
117 | |
118 e = new IntegerExp(loc, e1->isBool(0), type); | |
119 return e; | |
120 } | |
121 | |
122 Expression *Bool(Type *type, Expression *e1) | |
123 { Expression *e; | |
124 Loc loc = e1->loc; | |
125 | |
126 e = new IntegerExp(loc, e1->isBool(1), type); | |
127 return e; | |
128 } | |
129 | |
130 Expression *Add(Type *type, Expression *e1, Expression *e2) | |
131 { Expression *e; | |
132 Loc loc = e1->loc; | |
133 | |
134 #if LOG | |
135 printf("Add(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars()); | |
136 #endif | |
137 if (type->isreal()) | |
138 { | |
139 e = new RealExp(loc, e1->toReal() + e2->toReal(), type); | |
140 } | |
141 else if (type->isimaginary()) | |
142 { | |
143 e = new RealExp(loc, e1->toImaginary() + e2->toImaginary(), type); | |
144 } | |
145 else if (type->iscomplex()) | |
146 { | |
147 // This rigamarole is necessary so that -0.0 doesn't get | |
148 // converted to +0.0 by doing an extraneous add with +0.0 | |
149 complex_t c1; | |
150 real_t r1; | |
151 real_t i1; | |
152 | |
153 complex_t c2; | |
154 real_t r2; | |
155 real_t i2; | |
156 | |
157 complex_t v; | |
158 int x; | |
159 | |
160 if (e1->type->isreal()) | |
161 { r1 = e1->toReal(); | |
162 x = 0; | |
163 } | |
164 else if (e1->type->isimaginary()) | |
165 { i1 = e1->toImaginary(); | |
166 x = 3; | |
167 } | |
168 else | |
169 { c1 = e1->toComplex(); | |
170 x = 6; | |
171 } | |
172 | |
173 if (e2->type->isreal()) | |
174 { r2 = e2->toReal(); | |
175 } | |
176 else if (e2->type->isimaginary()) | |
177 { i2 = e2->toImaginary(); | |
178 x += 1; | |
179 } | |
180 else | |
181 { c2 = e2->toComplex(); | |
182 x += 2; | |
183 } | |
184 | |
185 switch (x) | |
186 { | |
187 #if __DMC__ | |
188 case 0+0: v = (complex_t) (r1 + r2); break; | |
189 case 0+1: v = r1 + i2 * I; break; | |
190 case 0+2: v = r1 + c2; break; | |
191 case 3+0: v = i1 * I + r2; break; | |
192 case 3+1: v = (complex_t) ((i1 + i2) * I); break; | |
193 case 3+2: v = i1 * I + c2; break; | |
194 case 6+0: v = c1 + r2; break; | |
195 case 6+1: v = c1 + i2 * I; break; | |
196 case 6+2: v = c1 + c2; break; | |
197 #else | |
198 case 0+0: v = complex_t(r1 + r2, 0); break; | |
199 case 0+1: v = complex_t(r1, i2); break; | |
200 case 0+2: v = complex_t(r1 + creall(c2), cimagl(c2)); break; | |
201 case 3+0: v = complex_t(r2, i1); break; | |
202 case 3+1: v = complex_t(0, i1 + i2); break; | |
203 case 3+2: v = complex_t(creall(c2), i1 + cimagl(c2)); break; | |
204 case 6+0: v = complex_t(creall(c1) + r2, cimagl(c2)); break; | |
205 case 6+1: v = complex_t(creall(c1), cimagl(c1) + i2); break; | |
206 case 6+2: v = c1 + c2; break; | |
207 #endif | |
208 default: assert(0); | |
209 } | |
210 e = new ComplexExp(loc, v, type); | |
211 } | |
212 else if (e1->op == TOKsymoff) | |
213 { | |
214 SymOffExp *soe = (SymOffExp *)e1; | |
215 e = new SymOffExp(loc, soe->var, soe->offset + e2->toInteger()); | |
216 e->type = type; | |
217 } | |
218 else if (e2->op == TOKsymoff) | |
219 { | |
220 SymOffExp *soe = (SymOffExp *)e2; | |
221 e = new SymOffExp(loc, soe->var, soe->offset + e1->toInteger()); | |
222 e->type = type; | |
223 } | |
224 else | |
225 e = new IntegerExp(loc, e1->toInteger() + e2->toInteger(), type); | |
226 return e; | |
227 } | |
228 | |
229 | |
230 Expression *Min(Type *type, Expression *e1, Expression *e2) | |
231 { Expression *e; | |
232 Loc loc = e1->loc; | |
233 | |
234 if (type->isreal()) | |
235 { | |
236 e = new RealExp(loc, e1->toReal() - e2->toReal(), type); | |
237 } | |
238 else if (type->isimaginary()) | |
239 { | |
240 e = new RealExp(loc, e1->toImaginary() - e2->toImaginary(), type); | |
241 } | |
242 else if (type->iscomplex()) | |
243 { | |
244 // This rigamarole is necessary so that -0.0 doesn't get | |
245 // converted to +0.0 by doing an extraneous add with +0.0 | |
246 complex_t c1; | |
247 real_t r1; | |
248 real_t i1; | |
249 | |
250 complex_t c2; | |
251 real_t r2; | |
252 real_t i2; | |
253 | |
254 complex_t v; | |
255 int x; | |
256 | |
257 if (e1->type->isreal()) | |
258 { r1 = e1->toReal(); | |
259 x = 0; | |
260 } | |
261 else if (e1->type->isimaginary()) | |
262 { i1 = e1->toImaginary(); | |
263 x = 3; | |
264 } | |
265 else | |
266 { c1 = e1->toComplex(); | |
267 x = 6; | |
268 } | |
269 | |
270 if (e2->type->isreal()) | |
271 { r2 = e2->toReal(); | |
272 } | |
273 else if (e2->type->isimaginary()) | |
274 { i2 = e2->toImaginary(); | |
275 x += 1; | |
276 } | |
277 else | |
278 { c2 = e2->toComplex(); | |
279 x += 2; | |
280 } | |
281 | |
282 switch (x) | |
283 { | |
284 #if __DMC__ | |
285 case 0+0: v = (complex_t) (r1 - r2); break; | |
286 case 0+1: v = r1 - i2 * I; break; | |
287 case 0+2: v = r1 - c2; break; | |
288 case 3+0: v = i1 * I - r2; break; | |
289 case 3+1: v = (complex_t) ((i1 - i2) * I); break; | |
290 case 3+2: v = i1 * I - c2; break; | |
291 case 6+0: v = c1 - r2; break; | |
292 case 6+1: v = c1 - i2 * I; break; | |
293 case 6+2: v = c1 - c2; break; | |
294 #else | |
295 case 0+0: v = complex_t(r1 - r2, 0); break; | |
296 case 0+1: v = complex_t(r1, -i2); break; | |
297 case 0+2: v = complex_t(r1 - creall(c2), -cimagl(c2)); break; | |
298 case 3+0: v = complex_t(-r2, i1); break; | |
299 case 3+1: v = complex_t(0, i1 - i2); break; | |
300 case 3+2: v = complex_t(-creall(c2), i1 - cimagl(c2)); break; | |
301 case 6+0: v = complex_t(creall(c1) - r2, cimagl(c1)); break; | |
302 case 6+1: v = complex_t(creall(c1), cimagl(c1) - i2); break; | |
303 case 6+2: v = c1 - c2; break; | |
304 #endif | |
305 default: assert(0); | |
306 } | |
307 e = new ComplexExp(loc, v, type); | |
308 } | |
309 else if (e1->op == TOKsymoff) | |
310 { | |
311 SymOffExp *soe = (SymOffExp *)e1; | |
312 e = new SymOffExp(loc, soe->var, soe->offset - e2->toInteger()); | |
313 e->type = type; | |
314 } | |
315 else | |
316 { | |
317 e = new IntegerExp(loc, e1->toInteger() - e2->toInteger(), type); | |
318 } | |
319 return e; | |
320 } | |
321 | |
322 Expression *Mul(Type *type, Expression *e1, Expression *e2) | |
323 { Expression *e; | |
324 Loc loc = e1->loc; | |
325 | |
326 if (type->isfloating()) | |
327 { complex_t c; | |
328 #ifdef IN_GCC | |
329 real_t r; | |
330 #else | |
331 d_float80 r; | |
332 #endif | |
333 | |
334 if (e1->type->isreal()) | |
335 { | |
336 #if __DMC__ | |
337 c = e1->toReal() * e2->toComplex(); | |
338 #else | |
339 r = e1->toReal(); | |
340 c = e2->toComplex(); | |
341 c = complex_t(r * creall(c), r * cimagl(c)); | |
342 #endif | |
343 } | |
344 else if (e1->type->isimaginary()) | |
345 { | |
346 #if __DMC__ | |
347 c = e1->toImaginary() * I * e2->toComplex(); | |
348 #else | |
349 r = e1->toImaginary(); | |
350 c = e2->toComplex(); | |
351 c = complex_t(-r * cimagl(c), r * creall(c)); | |
352 #endif | |
353 } | |
354 else if (e2->type->isreal()) | |
355 { | |
356 #if __DMC__ | |
357 c = e2->toReal() * e1->toComplex(); | |
358 #else | |
359 r = e2->toReal(); | |
360 c = e1->toComplex(); | |
361 c = complex_t(r * creall(c), r * cimagl(c)); | |
362 #endif | |
363 } | |
364 else if (e2->type->isimaginary()) | |
365 { | |
366 #if __DMC__ | |
367 c = e1->toComplex() * e2->toImaginary() * I; | |
368 #else | |
369 r = e2->toImaginary(); | |
370 c = e1->toComplex(); | |
371 c = complex_t(-r * cimagl(c), r * creall(c)); | |
372 #endif | |
373 } | |
374 else | |
375 c = e1->toComplex() * e2->toComplex(); | |
376 | |
377 if (type->isreal()) | |
378 e = new RealExp(loc, creall(c), type); | |
379 else if (type->isimaginary()) | |
380 e = new RealExp(loc, cimagl(c), type); | |
381 else if (type->iscomplex()) | |
382 e = new ComplexExp(loc, c, type); | |
383 else | |
384 assert(0); | |
385 } | |
386 else | |
387 { | |
388 e = new IntegerExp(loc, e1->toInteger() * e2->toInteger(), type); | |
389 } | |
390 return e; | |
391 } | |
392 | |
393 Expression *Div(Type *type, Expression *e1, Expression *e2) | |
394 { Expression *e; | |
395 Loc loc = e1->loc; | |
396 | |
397 if (type->isfloating()) | |
398 { complex_t c; | |
399 #ifdef IN_GCC | |
400 real_t r; | |
401 #else | |
402 d_float80 r; | |
403 #endif | |
404 | |
405 //e1->type->print(); | |
406 //e2->type->print(); | |
407 if (e2->type->isreal()) | |
408 { | |
409 if (e1->type->isreal()) | |
410 { | |
411 e = new RealExp(loc, e1->toReal() / e2->toReal(), type); | |
412 return e; | |
413 } | |
414 #if __DMC__ | |
415 //r = e2->toReal(); | |
416 //c = e1->toComplex(); | |
417 //printf("(%Lg + %Lgi) / %Lg\n", creall(c), cimagl(c), r); | |
418 | |
419 c = e1->toComplex() / e2->toReal(); | |
420 #else | |
421 r = e2->toReal(); | |
422 c = e1->toComplex(); | |
423 c = complex_t(creall(c) / r, cimagl(c) / r); | |
424 #endif | |
425 } | |
426 else if (e2->type->isimaginary()) | |
427 { | |
428 #if __DMC__ | |
429 //r = e2->toImaginary(); | |
430 //c = e1->toComplex(); | |
431 //printf("(%Lg + %Lgi) / %Lgi\n", creall(c), cimagl(c), r); | |
432 | |
433 c = e1->toComplex() / (e2->toImaginary() * I); | |
434 #else | |
435 r = e2->toImaginary(); | |
436 c = e1->toComplex(); | |
437 c = complex_t(cimagl(c) / r, -creall(c) / r); | |
438 #endif | |
439 } | |
440 else | |
441 { | |
442 c = e1->toComplex() / e2->toComplex(); | |
443 } | |
444 | |
445 if (type->isreal()) | |
446 e = new RealExp(loc, creall(c), type); | |
447 else if (type->isimaginary()) | |
448 e = new RealExp(loc, cimagl(c), type); | |
449 else if (type->iscomplex()) | |
450 e = new ComplexExp(loc, c, type); | |
451 else | |
452 assert(0); | |
453 } | |
454 else | |
455 { sinteger_t n1; | |
456 sinteger_t n2; | |
457 sinteger_t n; | |
458 | |
459 n1 = e1->toInteger(); | |
460 n2 = e2->toInteger(); | |
461 if (n2 == 0) | |
462 { e2->error("divide by 0"); | |
463 e2 = new IntegerExp(0, 1, e2->type); | |
464 n2 = 1; | |
465 } | |
466 if (e1->type->isunsigned() || e2->type->isunsigned()) | |
467 n = ((d_uns64) n1) / ((d_uns64) n2); | |
468 else | |
469 n = n1 / n2; | |
470 e = new IntegerExp(loc, n, type); | |
471 } | |
472 return e; | |
473 } | |
474 | |
475 Expression *Mod(Type *type, Expression *e1, Expression *e2) | |
476 { Expression *e; | |
477 Loc loc = e1->loc; | |
478 | |
479 if (type->isfloating()) | |
480 { | |
481 complex_t c; | |
482 | |
483 if (e2->type->isreal()) | |
484 { real_t r2 = e2->toReal(); | |
485 | |
486 #ifdef __DMC__ | |
487 c = fmodl(e1->toReal(), r2) + fmodl(e1->toImaginary(), r2) * I; | |
488 #elif defined(IN_GCC) | |
489 c = complex_t(e1->toReal() % r2, e1->toImaginary() % r2); | |
735
eee9efe5b51f
Attempt at getting LLVM to provide a proper target data layout. Should assert now if things are borked.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
734
diff
changeset
|
490 #elif (defined(__FreeBSD__) && __FreeBSD_version < 800000) || defined(__arm__) || defined(__thumb__) |
734
6dcab994ddc3
Fold in mandel's patch for ARM from #106
Christian Kamm <kamm incasoftware de>
parents:
717
diff
changeset
|
491 // freebsd is kinda messed up. the STABLE branch doesn't support C99's fmodl !?! |
6dcab994ddc3
Fold in mandel's patch for ARM from #106
Christian Kamm <kamm incasoftware de>
parents:
717
diff
changeset
|
492 // arm also doesn't like fmodl |
6dcab994ddc3
Fold in mandel's patch for ARM from #106
Christian Kamm <kamm incasoftware de>
parents:
717
diff
changeset
|
493 c = complex_t(fmod(e1->toReal(), r2), fmod(e1->toImaginary(), r2)); |
336 | 494 #else |
495 c = complex_t(fmodl(e1->toReal(), r2), fmodl(e1->toImaginary(), r2)); | |
496 #endif | |
497 } | |
498 else if (e2->type->isimaginary()) | |
499 { real_t i2 = e2->toImaginary(); | |
500 | |
501 #ifdef __DMC__ | |
502 c = fmodl(e1->toReal(), i2) + fmodl(e1->toImaginary(), i2) * I; | |
503 #elif defined(IN_GCC) | |
504 c = complex_t(e1->toReal() % i2, e1->toImaginary() % i2); | |
735
eee9efe5b51f
Attempt at getting LLVM to provide a proper target data layout. Should assert now if things are borked.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
734
diff
changeset
|
505 #elif (defined(__FreeBSD__) && __FreeBSD_version < 800000) || defined(__arm__) || defined(__thumb__) |
637
29dc68c949b0
Applied the FreeBSD patch from Ralith, closes ticket #95 , slightly changed but basically the same. Thanx Ralith :)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
506 // freebsd is kinda messed up. the STABLE branch doesn't support C99's fmodl !?! |
734
6dcab994ddc3
Fold in mandel's patch for ARM from #106
Christian Kamm <kamm incasoftware de>
parents:
717
diff
changeset
|
507 // arm also doesn't like fmodl |
6dcab994ddc3
Fold in mandel's patch for ARM from #106
Christian Kamm <kamm incasoftware de>
parents:
717
diff
changeset
|
508 c = complex_t(fmod(e1->toReal(), i2), fmod(e1->toImaginary(), i2)); |
336 | 509 #else |
510 c = complex_t(fmodl(e1->toReal(), i2), fmodl(e1->toImaginary(), i2)); | |
511 #endif | |
512 } | |
513 else | |
514 assert(0); | |
515 | |
516 if (type->isreal()) | |
517 e = new RealExp(loc, creall(c), type); | |
518 else if (type->isimaginary()) | |
519 e = new RealExp(loc, cimagl(c), type); | |
520 else if (type->iscomplex()) | |
521 e = new ComplexExp(loc, c, type); | |
522 else | |
523 assert(0); | |
524 } | |
525 else | |
526 { sinteger_t n1; | |
527 sinteger_t n2; | |
528 sinteger_t n; | |
529 | |
530 n1 = e1->toInteger(); | |
531 n2 = e2->toInteger(); | |
532 if (n2 == 0) | |
533 { e2->error("divide by 0"); | |
534 e2 = new IntegerExp(0, 1, e2->type); | |
535 n2 = 1; | |
536 } | |
537 if (e1->type->isunsigned() || e2->type->isunsigned()) | |
538 n = ((d_uns64) n1) % ((d_uns64) n2); | |
539 else | |
540 n = n1 % n2; | |
541 e = new IntegerExp(loc, n, type); | |
542 } | |
543 return e; | |
544 } | |
545 | |
546 Expression *Shl(Type *type, Expression *e1, Expression *e2) | |
547 { Expression *e; | |
548 Loc loc = e1->loc; | |
549 | |
550 e = new IntegerExp(loc, e1->toInteger() << e2->toInteger(), type); | |
551 return e; | |
552 } | |
553 | |
554 Expression *Shr(Type *type, Expression *e1, Expression *e2) | |
555 { Expression *e; | |
556 Loc loc = e1->loc; | |
557 unsigned count; | |
558 integer_t value; | |
559 | |
560 value = e1->toInteger(); | |
561 count = e2->toInteger(); | |
562 switch (e1->type->toBasetype()->ty) | |
563 { | |
564 case Tint8: | |
565 value = (d_int8)(value) >> count; | |
566 break; | |
567 | |
568 case Tuns8: | |
569 value = (d_uns8)(value) >> count; | |
570 break; | |
571 | |
572 case Tint16: | |
573 value = (d_int16)(value) >> count; | |
574 break; | |
575 | |
576 case Tuns16: | |
577 value = (d_uns16)(value) >> count; | |
578 break; | |
579 | |
580 case Tint32: | |
581 value = (d_int32)(value) >> count; | |
582 break; | |
583 | |
584 case Tuns32: | |
585 value = (d_uns32)(value) >> count; | |
586 break; | |
587 | |
588 case Tint64: | |
589 value = (d_int64)(value) >> count; | |
590 break; | |
591 | |
592 case Tuns64: | |
593 value = (d_uns64)(value) >> count; | |
594 break; | |
595 | |
596 default: | |
597 assert(0); | |
598 } | |
599 e = new IntegerExp(loc, value, type); | |
600 return e; | |
601 } | |
602 | |
603 Expression *Ushr(Type *type, Expression *e1, Expression *e2) | |
604 { Expression *e; | |
605 Loc loc = e1->loc; | |
606 unsigned count; | |
607 integer_t value; | |
608 | |
609 value = e1->toInteger(); | |
610 count = e2->toInteger(); | |
611 switch (e1->type->toBasetype()->ty) | |
612 { | |
613 case Tint8: | |
614 case Tuns8: | |
615 assert(0); // no way to trigger this | |
616 value = (value & 0xFF) >> count; | |
617 break; | |
618 | |
619 case Tint16: | |
620 case Tuns16: | |
621 assert(0); // no way to trigger this | |
622 value = (value & 0xFFFF) >> count; | |
623 break; | |
624 | |
625 case Tint32: | |
626 case Tuns32: | |
627 value = (value & 0xFFFFFFFF) >> count; | |
628 break; | |
629 | |
630 case Tint64: | |
631 case Tuns64: | |
632 value = (d_uns64)(value) >> count; | |
633 break; | |
634 | |
635 default: | |
636 assert(0); | |
637 } | |
638 e = new IntegerExp(loc, value, type); | |
639 return e; | |
640 } | |
641 | |
642 Expression *And(Type *type, Expression *e1, Expression *e2) | |
643 { Expression *e; | |
644 Loc loc = e1->loc; | |
645 | |
646 e = new IntegerExp(loc, e1->toInteger() & e2->toInteger(), type); | |
647 return e; | |
648 } | |
649 | |
650 Expression *Or(Type *type, Expression *e1, Expression *e2) | |
651 { Expression *e; | |
652 Loc loc = e1->loc; | |
653 | |
654 e = new IntegerExp(loc, e1->toInteger() | e2->toInteger(), type); | |
655 return e; | |
656 } | |
657 | |
658 Expression *Xor(Type *type, Expression *e1, Expression *e2) | |
659 { Expression *e; | |
660 Loc loc = e1->loc; | |
661 | |
662 e = new IntegerExp(loc, e1->toInteger() ^ e2->toInteger(), type); | |
663 return e; | |
664 } | |
665 | |
666 /* Also returns EXP_CANT_INTERPRET if cannot be computed. | |
667 */ | |
668 Expression *Equal(enum TOK op, Type *type, Expression *e1, Expression *e2) | |
669 { Expression *e; | |
670 Loc loc = e1->loc; | |
671 int cmp; | |
672 real_t r1; | |
673 real_t r2; | |
674 | |
675 //printf("Equal(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars()); | |
676 | |
677 assert(op == TOKequal || op == TOKnotequal); | |
678 | |
679 if (e1->op == TOKnull) | |
680 { | |
681 if (e2->op == TOKnull) | |
682 cmp = 1; | |
683 else if (e2->op == TOKstring) | |
684 { StringExp *es2 = (StringExp *)e2; | |
685 cmp = (0 == es2->len); | |
686 } | |
687 else if (e2->op == TOKarrayliteral) | |
688 { ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; | |
689 cmp = !es2->elements || (0 == es2->elements->dim); | |
690 } | |
691 else | |
692 return EXP_CANT_INTERPRET; | |
693 } | |
694 else if (e2->op == TOKnull) | |
695 { | |
696 if (e1->op == TOKstring) | |
697 { StringExp *es1 = (StringExp *)e1; | |
698 cmp = (0 == es1->len); | |
699 } | |
700 else if (e1->op == TOKarrayliteral) | |
701 { ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; | |
702 cmp = !es1->elements || (0 == es1->elements->dim); | |
703 } | |
704 else | |
705 return EXP_CANT_INTERPRET; | |
706 } | |
707 else if (e1->op == TOKstring && e2->op == TOKstring) | |
708 { StringExp *es1 = (StringExp *)e1; | |
709 StringExp *es2 = (StringExp *)e2; | |
710 | |
658
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
711 if (es1->sz != es2->sz) |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
712 { |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
713 assert(global.errors); |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
714 return EXP_CANT_INTERPRET; |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
715 } |
336 | 716 if (es1->len == es2->len && |
717 memcmp(es1->string, es2->string, es1->sz * es1->len) == 0) | |
718 cmp = 1; | |
719 else | |
720 cmp = 0; | |
721 } | |
722 else if (e1->op == TOKarrayliteral && e2->op == TOKarrayliteral) | |
723 { ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; | |
724 ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; | |
725 | |
726 if ((!es1->elements || !es1->elements->dim) && | |
727 (!es2->elements || !es2->elements->dim)) | |
728 cmp = 1; // both arrays are empty | |
729 else if (!es1->elements || !es2->elements) | |
730 cmp = 0; | |
731 else if (es1->elements->dim != es2->elements->dim) | |
732 cmp = 0; | |
733 else | |
734 { | |
735 for (size_t i = 0; i < es1->elements->dim; i++) | |
736 { Expression *ee1 = (Expression *)es1->elements->data[i]; | |
737 Expression *ee2 = (Expression *)es2->elements->data[i]; | |
738 | |
739 Expression *v = Equal(TOKequal, Type::tint32, ee1, ee2); | |
740 if (v == EXP_CANT_INTERPRET) | |
741 return EXP_CANT_INTERPRET; | |
742 cmp = v->toInteger(); | |
743 if (cmp == 0) | |
744 break; | |
745 } | |
746 } | |
747 } | |
748 else if (e1->op == TOKarrayliteral && e2->op == TOKstring) | |
749 { // Swap operands and use common code | |
750 Expression *e = e1; | |
751 e1 = e2; | |
752 e2 = e; | |
753 goto Lsa; | |
754 } | |
755 else if (e1->op == TOKstring && e2->op == TOKarrayliteral) | |
756 { | |
757 Lsa: | |
758 StringExp *es1 = (StringExp *)e1; | |
759 ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; | |
760 size_t dim1 = es1->len; | |
761 size_t dim2 = es2->elements ? es2->elements->dim : 0; | |
762 if (dim1 != dim2) | |
763 cmp = 0; | |
764 else | |
765 { | |
766 for (size_t i = 0; i < dim1; i++) | |
767 { | |
768 uinteger_t c = es1->charAt(i); | |
769 Expression *ee2 = (Expression *)es2->elements->data[i]; | |
770 if (ee2->isConst() != 1) | |
771 return EXP_CANT_INTERPRET; | |
772 cmp = (c == ee2->toInteger()); | |
773 if (cmp == 0) | |
774 break; | |
775 } | |
776 } | |
777 } | |
778 else if (e1->op == TOKstructliteral && e2->op == TOKstructliteral) | |
779 { StructLiteralExp *es1 = (StructLiteralExp *)e1; | |
780 StructLiteralExp *es2 = (StructLiteralExp *)e2; | |
781 | |
782 if (es1->sd != es2->sd) | |
783 cmp = 0; | |
784 else if ((!es1->elements || !es1->elements->dim) && | |
785 (!es2->elements || !es2->elements->dim)) | |
786 cmp = 1; // both arrays are empty | |
787 else if (!es1->elements || !es2->elements) | |
788 cmp = 0; | |
789 else if (es1->elements->dim != es2->elements->dim) | |
790 cmp = 0; | |
791 else | |
792 { | |
793 cmp = 1; | |
794 for (size_t i = 0; i < es1->elements->dim; i++) | |
795 { Expression *ee1 = (Expression *)es1->elements->data[i]; | |
796 Expression *ee2 = (Expression *)es2->elements->data[i]; | |
797 | |
798 if (ee1 == ee2) | |
799 continue; | |
800 if (!ee1 || !ee2) | |
801 { cmp = 0; | |
802 break; | |
803 } | |
804 Expression *v = Equal(TOKequal, Type::tint32, ee1, ee2); | |
805 if (v == EXP_CANT_INTERPRET) | |
806 return EXP_CANT_INTERPRET; | |
807 cmp = v->toInteger(); | |
808 if (cmp == 0) | |
809 break; | |
810 } | |
811 } | |
812 } | |
813 #if 0 // Should handle this | |
814 else if (e1->op == TOKarrayliteral && e2->op == TOKstring) | |
815 { | |
816 } | |
817 #endif | |
818 else if (e1->isConst() != 1 || e2->isConst() != 1) | |
819 return EXP_CANT_INTERPRET; | |
820 else if (e1->type->isreal()) | |
821 { | |
822 r1 = e1->toReal(); | |
823 r2 = e2->toReal(); | |
824 goto L1; | |
825 } | |
826 else if (e1->type->isimaginary()) | |
827 { | |
828 r1 = e1->toImaginary(); | |
829 r2 = e2->toImaginary(); | |
830 L1: | |
831 #if __DMC__ | |
832 cmp = (r1 == r2); | |
833 #else | |
834 if (isnan(r1) || isnan(r2)) // if unordered | |
835 { | |
836 cmp = 0; | |
837 } | |
838 else | |
839 { | |
840 cmp = (r1 == r2); | |
841 } | |
842 #endif | |
843 } | |
844 else if (e1->type->iscomplex()) | |
845 { | |
846 cmp = e1->toComplex() == e2->toComplex(); | |
847 } | |
848 else if (e1->type->isintegral()) | |
849 { | |
850 cmp = (e1->toInteger() == e2->toInteger()); | |
851 } | |
852 else | |
853 return EXP_CANT_INTERPRET; | |
854 if (op == TOKnotequal) | |
855 cmp ^= 1; | |
856 e = new IntegerExp(loc, cmp, type); | |
857 return e; | |
858 } | |
859 | |
860 Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2) | |
861 { Expression *e; | |
862 Loc loc = e1->loc; | |
863 int cmp; | |
864 | |
865 if (e1->op == TOKnull && e2->op == TOKnull) | |
866 { | |
867 cmp = 1; | |
868 } | |
869 else if (e1->op == TOKsymoff && e2->op == TOKsymoff) | |
870 { | |
871 SymOffExp *es1 = (SymOffExp *)e1; | |
872 SymOffExp *es2 = (SymOffExp *)e2; | |
873 | |
874 cmp = (es1->var == es2->var && es1->offset == es2->offset); | |
875 } | |
876 else if (e1->isConst() == 1 && e2->isConst() == 1) | |
877 return Equal((op == TOKidentity) ? TOKequal : TOKnotequal, | |
878 type, e1, e2); | |
879 else | |
880 assert(0); | |
881 if (op == TOKnotidentity) | |
882 cmp ^= 1; | |
883 return new IntegerExp(loc, cmp, type); | |
884 } | |
885 | |
886 | |
887 Expression *Cmp(enum TOK op, Type *type, Expression *e1, Expression *e2) | |
888 { Expression *e; | |
889 Loc loc = e1->loc; | |
890 integer_t n; | |
891 real_t r1; | |
892 real_t r2; | |
893 | |
894 if (e1->type->isreal()) | |
895 { | |
896 r1 = e1->toReal(); | |
897 r2 = e2->toReal(); | |
898 goto L1; | |
899 } | |
900 else if (e1->type->isimaginary()) | |
901 { | |
902 r1 = e1->toImaginary(); | |
903 r2 = e2->toImaginary(); | |
904 L1: | |
905 #if __DMC__ | |
906 // DMC is the only compiler I know of that handles NAN arguments | |
907 // correctly in comparisons. | |
908 switch (op) | |
909 { | |
910 case TOKlt: n = r1 < r2; break; | |
911 case TOKle: n = r1 <= r2; break; | |
912 case TOKgt: n = r1 > r2; break; | |
913 case TOKge: n = r1 >= r2; break; | |
914 | |
915 case TOKleg: n = r1 <>= r2; break; | |
916 case TOKlg: n = r1 <> r2; break; | |
917 case TOKunord: n = r1 !<>= r2; break; | |
918 case TOKue: n = r1 !<> r2; break; | |
919 case TOKug: n = r1 !<= r2; break; | |
920 case TOKuge: n = r1 !< r2; break; | |
921 case TOKul: n = r1 !>= r2; break; | |
922 case TOKule: n = r1 !> r2; break; | |
923 | |
924 default: | |
925 assert(0); | |
926 } | |
927 #else | |
928 // Don't rely on compiler, handle NAN arguments separately | |
929 #if IN_GCC | |
930 if (real_isnan(&r1) || real_isnan(&r2)) // if unordered | |
931 #else | |
932 if (isnan(r1) || isnan(r2)) // if unordered | |
933 #endif | |
934 { | |
935 switch (op) | |
936 { | |
937 case TOKlt: n = 0; break; | |
938 case TOKle: n = 0; break; | |
939 case TOKgt: n = 0; break; | |
940 case TOKge: n = 0; break; | |
941 | |
942 case TOKleg: n = 0; break; | |
943 case TOKlg: n = 0; break; | |
944 case TOKunord: n = 1; break; | |
945 case TOKue: n = 1; break; | |
946 case TOKug: n = 1; break; | |
947 case TOKuge: n = 1; break; | |
948 case TOKul: n = 1; break; | |
949 case TOKule: n = 1; break; | |
950 | |
951 default: | |
952 assert(0); | |
953 } | |
954 } | |
955 else | |
956 { | |
957 switch (op) | |
958 { | |
959 case TOKlt: n = r1 < r2; break; | |
960 case TOKle: n = r1 <= r2; break; | |
961 case TOKgt: n = r1 > r2; break; | |
962 case TOKge: n = r1 >= r2; break; | |
963 | |
964 case TOKleg: n = 1; break; | |
965 case TOKlg: n = r1 != r2; break; | |
966 case TOKunord: n = 0; break; | |
967 case TOKue: n = r1 == r2; break; | |
968 case TOKug: n = r1 > r2; break; | |
969 case TOKuge: n = r1 >= r2; break; | |
970 case TOKul: n = r1 < r2; break; | |
971 case TOKule: n = r1 <= r2; break; | |
972 | |
973 default: | |
974 assert(0); | |
975 } | |
976 } | |
977 #endif | |
978 } | |
979 else if (e1->type->iscomplex()) | |
980 { | |
981 assert(0); | |
982 } | |
983 else | |
984 { sinteger_t n1; | |
985 sinteger_t n2; | |
986 | |
987 n1 = e1->toInteger(); | |
988 n2 = e2->toInteger(); | |
989 if (e1->type->isunsigned() || e2->type->isunsigned()) | |
990 { | |
991 switch (op) | |
992 { | |
993 case TOKlt: n = ((d_uns64) n1) < ((d_uns64) n2); break; | |
994 case TOKle: n = ((d_uns64) n1) <= ((d_uns64) n2); break; | |
995 case TOKgt: n = ((d_uns64) n1) > ((d_uns64) n2); break; | |
996 case TOKge: n = ((d_uns64) n1) >= ((d_uns64) n2); break; | |
997 | |
998 case TOKleg: n = 1; break; | |
999 case TOKlg: n = ((d_uns64) n1) != ((d_uns64) n2); break; | |
1000 case TOKunord: n = 0; break; | |
1001 case TOKue: n = ((d_uns64) n1) == ((d_uns64) n2); break; | |
1002 case TOKug: n = ((d_uns64) n1) > ((d_uns64) n2); break; | |
1003 case TOKuge: n = ((d_uns64) n1) >= ((d_uns64) n2); break; | |
1004 case TOKul: n = ((d_uns64) n1) < ((d_uns64) n2); break; | |
1005 case TOKule: n = ((d_uns64) n1) <= ((d_uns64) n2); break; | |
1006 | |
1007 default: | |
1008 assert(0); | |
1009 } | |
1010 } | |
1011 else | |
1012 { | |
1013 switch (op) | |
1014 { | |
1015 case TOKlt: n = n1 < n2; break; | |
1016 case TOKle: n = n1 <= n2; break; | |
1017 case TOKgt: n = n1 > n2; break; | |
1018 case TOKge: n = n1 >= n2; break; | |
1019 | |
1020 case TOKleg: n = 1; break; | |
1021 case TOKlg: n = n1 != n2; break; | |
1022 case TOKunord: n = 0; break; | |
1023 case TOKue: n = n1 == n2; break; | |
1024 case TOKug: n = n1 > n2; break; | |
1025 case TOKuge: n = n1 >= n2; break; | |
1026 case TOKul: n = n1 < n2; break; | |
1027 case TOKule: n = n1 <= n2; break; | |
1028 | |
1029 default: | |
1030 assert(0); | |
1031 } | |
1032 } | |
1033 } | |
1034 e = new IntegerExp(loc, n, type); | |
1035 return e; | |
1036 } | |
1037 | |
1038 /* Also returns EXP_CANT_INTERPRET if cannot be computed. | |
1039 * to: type to cast to | |
1040 * type: type to paint the result | |
1041 */ | |
1042 | |
1043 Expression *Cast(Type *type, Type *to, Expression *e1) | |
1044 { Expression *e = EXP_CANT_INTERPRET; | |
1045 Loc loc = e1->loc; | |
1046 | |
1047 //printf("Cast(type = %s, to = %s, e1 = %s)\n", type->toChars(), to->toChars(), e1->toChars()); | |
1048 //printf("e1->type = %s\n", e1->type->toChars()); | |
1049 if (type->equals(e1->type) && to->equals(type)) | |
1050 return e1; | |
1051 | |
1052 if (e1->isConst() != 1) | |
1053 return EXP_CANT_INTERPRET; | |
1054 | |
1055 Type *tb = to->toBasetype(); | |
1056 if (tb->ty == Tbool) | |
1057 e = new IntegerExp(loc, e1->toInteger() != 0, type); | |
1058 else if (type->isintegral()) | |
1059 { | |
1060 if (e1->type->isfloating()) | |
1061 { integer_t result; | |
1062 real_t r = e1->toReal(); | |
1063 | |
1064 switch (type->toBasetype()->ty) | |
1065 { | |
1066 case Tint8: result = (d_int8)r; break; | |
1067 case Tchar: | |
1068 case Tuns8: result = (d_uns8)r; break; | |
1069 case Tint16: result = (d_int16)r; break; | |
1070 case Twchar: | |
1071 case Tuns16: result = (d_uns16)r; break; | |
1072 case Tint32: result = (d_int32)r; break; | |
1073 case Tdchar: | |
1074 case Tuns32: result = (d_uns32)r; break; | |
1075 case Tint64: result = (d_int64)r; break; | |
1076 case Tuns64: result = (d_uns64)r; break; | |
1077 default: | |
1078 assert(0); | |
1079 } | |
1080 | |
1081 e = new IntegerExp(loc, result, type); | |
1082 } | |
1083 else if (type->isunsigned()) | |
1084 e = new IntegerExp(loc, e1->toUInteger(), type); | |
1085 else | |
1086 e = new IntegerExp(loc, e1->toInteger(), type); | |
1087 } | |
1088 else if (tb->isreal()) | |
1089 { real_t value = e1->toReal(); | |
1090 | |
1091 e = new RealExp(loc, value, type); | |
1092 } | |
1093 else if (tb->isimaginary()) | |
1094 { real_t value = e1->toImaginary(); | |
1095 | |
1096 e = new RealExp(loc, value, type); | |
1097 } | |
1098 else if (tb->iscomplex()) | |
1099 { complex_t value = e1->toComplex(); | |
1100 | |
1101 e = new ComplexExp(loc, value, type); | |
1102 } | |
1103 else if (tb->isscalar()) | |
1104 e = new IntegerExp(loc, e1->toInteger(), type); | |
1105 else if (tb->ty == Tvoid) | |
1106 e = EXP_CANT_INTERPRET; | |
1107 else if (tb->ty == Tstruct && e1->op == TOKint64) | |
1108 { // Struct = 0; | |
1109 StructDeclaration *sd = tb->toDsymbol(NULL)->isStructDeclaration(); | |
1110 assert(sd); | |
1111 Expressions *elements = new Expressions; | |
1112 for (size_t i = 0; i < sd->fields.dim; i++) | |
1113 { Dsymbol *s = (Dsymbol *)sd->fields.data[i]; | |
1114 VarDeclaration *v = s->isVarDeclaration(); | |
1115 assert(v); | |
1116 | |
1117 Expression *exp = new IntegerExp(0); | |
1118 exp = Cast(v->type, v->type, exp); | |
1119 if (exp == EXP_CANT_INTERPRET) | |
1120 return exp; | |
1121 elements->push(exp); | |
1122 } | |
1123 e = new StructLiteralExp(loc, sd, elements); | |
1124 e->type = type; | |
1125 } | |
1126 else | |
1127 { | |
1128 error(loc, "cannot cast %s to %s", e1->type->toChars(), type->toChars()); | |
1129 e = new IntegerExp(loc, 0, type); | |
1130 } | |
1131 return e; | |
1132 } | |
1133 | |
1134 | |
1135 Expression *ArrayLength(Type *type, Expression *e1) | |
1136 { Expression *e; | |
1137 Loc loc = e1->loc; | |
1138 | |
1139 if (e1->op == TOKstring) | |
1140 { StringExp *es1 = (StringExp *)e1; | |
1141 | |
1142 e = new IntegerExp(loc, es1->len, type); | |
1143 } | |
1144 else if (e1->op == TOKarrayliteral) | |
1145 { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; | |
1146 size_t dim; | |
1147 | |
1148 dim = ale->elements ? ale->elements->dim : 0; | |
1149 e = new IntegerExp(loc, dim, type); | |
1150 } | |
1151 else if (e1->op == TOKassocarrayliteral) | |
1152 { AssocArrayLiteralExp *ale = (AssocArrayLiteralExp *)e1; | |
1153 size_t dim = ale->keys->dim; | |
1154 | |
1155 e = new IntegerExp(loc, dim, type); | |
1156 } | |
1157 else | |
1158 e = EXP_CANT_INTERPRET; | |
1159 return e; | |
1160 } | |
1161 | |
1162 /* Also return EXP_CANT_INTERPRET if this fails | |
1163 */ | |
1164 Expression *Index(Type *type, Expression *e1, Expression *e2) | |
1165 { Expression *e = EXP_CANT_INTERPRET; | |
1166 Loc loc = e1->loc; | |
1167 | |
1168 //printf("Index(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars()); | |
1169 assert(e1->type); | |
1170 if (e1->op == TOKstring && e2->op == TOKint64) | |
1171 { StringExp *es1 = (StringExp *)e1; | |
1172 uinteger_t i = e2->toInteger(); | |
1173 | |
1174 if (i >= es1->len) | |
1175 e1->error("string index %llu is out of bounds [0 .. %"PRIuSIZE"]", i, es1->len); | |
1176 else | |
1177 { unsigned value = es1->charAt(i); | |
1178 e = new IntegerExp(loc, value, type); | |
1179 } | |
1180 } | |
1181 else if (e1->type->toBasetype()->ty == Tsarray && e2->op == TOKint64) | |
1182 { TypeSArray *tsa = (TypeSArray *)e1->type->toBasetype(); | |
1183 uinteger_t length = tsa->dim->toInteger(); | |
1184 uinteger_t i = e2->toInteger(); | |
1185 | |
1186 if (i >= length) | |
1187 { | |
1188 e2->error("array index %llu is out of bounds %s[0 .. %llu]", i, e1->toChars(), length); | |
1189 } | |
1190 else if (e1->op == TOKarrayliteral && !e1->checkSideEffect(2)) | |
1191 { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; | |
1192 e = (Expression *)ale->elements->data[i]; | |
1193 e->type = type; | |
1194 } | |
1195 } | |
1196 else if (e1->type->toBasetype()->ty == Tarray && e2->op == TOKint64) | |
1197 { | |
1198 uinteger_t i = e2->toInteger(); | |
1199 | |
1200 if (e1->op == TOKarrayliteral && !e1->checkSideEffect(2)) | |
1201 { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; | |
1202 if (i >= ale->elements->dim) | |
1203 { | |
1204 e2->error("array index %llu is out of bounds %s[0 .. %u]", i, e1->toChars(), ale->elements->dim); | |
1205 } | |
1206 else | |
1207 { e = (Expression *)ale->elements->data[i]; | |
1208 e->type = type; | |
1209 } | |
1210 } | |
1211 } | |
1212 else if (e1->op == TOKassocarrayliteral && !e1->checkSideEffect(2)) | |
1213 { | |
1214 AssocArrayLiteralExp *ae = (AssocArrayLiteralExp *)e1; | |
1215 /* Search the keys backwards, in case there are duplicate keys | |
1216 */ | |
1217 for (size_t i = ae->keys->dim; i;) | |
1218 { | |
1219 i--; | |
1220 Expression *ekey = (Expression *)ae->keys->data[i]; | |
1221 Expression *ex = Equal(TOKequal, Type::tbool, ekey, e2); | |
1222 if (ex == EXP_CANT_INTERPRET) | |
1223 return ex; | |
1224 if (ex->isBool(TRUE)) | |
1225 { e = (Expression *)ae->values->data[i]; | |
1226 e->type = type; | |
1227 break; | |
1228 } | |
1229 } | |
1230 } | |
1231 return e; | |
1232 } | |
1233 | |
1234 /* Also return EXP_CANT_INTERPRET if this fails | |
1235 */ | |
1236 Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr) | |
1237 { Expression *e = EXP_CANT_INTERPRET; | |
1238 Loc loc = e1->loc; | |
1239 | |
1240 #if LOG | |
1241 printf("Slice()\n"); | |
1242 if (lwr) | |
1243 { printf("\te1 = %s\n", e1->toChars()); | |
1244 printf("\tlwr = %s\n", lwr->toChars()); | |
1245 printf("\tupr = %s\n", upr->toChars()); | |
1246 } | |
1247 #endif | |
1248 if (e1->op == TOKstring && lwr->op == TOKint64 && upr->op == TOKint64) | |
1249 { StringExp *es1 = (StringExp *)e1; | |
1250 uinteger_t ilwr = lwr->toInteger(); | |
1251 uinteger_t iupr = upr->toInteger(); | |
1252 | |
1253 if (iupr > es1->len || ilwr > iupr) | |
1254 e1->error("string slice [%llu .. %llu] is out of bounds", ilwr, iupr); | |
1255 else | |
1256 { integer_t value; | |
1257 void *s; | |
1258 size_t len = iupr - ilwr; | |
1259 int sz = es1->sz; | |
1260 StringExp *es; | |
1261 | |
1262 s = mem.malloc((len + 1) * sz); | |
1263 memcpy((unsigned char *)s, (unsigned char *)es1->string + ilwr * sz, len * sz); | |
1264 memset((unsigned char *)s + len * sz, 0, sz); | |
1265 | |
1266 es = new StringExp(loc, s, len, es1->postfix); | |
1267 es->sz = sz; | |
1268 es->committed = 1; | |
1269 es->type = type; | |
1270 e = es; | |
1271 } | |
1272 } | |
1273 else if (e1->op == TOKarrayliteral && | |
1274 lwr->op == TOKint64 && upr->op == TOKint64 && | |
1275 !e1->checkSideEffect(2)) | |
1276 { ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; | |
1277 uinteger_t ilwr = lwr->toInteger(); | |
1278 uinteger_t iupr = upr->toInteger(); | |
1279 | |
1280 if (iupr > es1->elements->dim || ilwr > iupr) | |
1281 e1->error("array slice [%llu .. %llu] is out of bounds", ilwr, iupr); | |
1282 else | |
1283 { | |
1284 Expressions *elements = new Expressions(); | |
1285 elements->setDim(iupr - ilwr); | |
1286 memcpy(elements->data, | |
1287 es1->elements->data + ilwr, | |
1288 (iupr - ilwr) * sizeof(es1->elements->data[0])); | |
1289 e = new ArrayLiteralExp(e1->loc, elements); | |
1290 e->type = type; | |
1291 } | |
1292 } | |
1293 return e; | |
1294 } | |
1295 | |
1296 /* Also return EXP_CANT_INTERPRET if this fails | |
1297 */ | |
1298 Expression *Cat(Type *type, Expression *e1, Expression *e2) | |
1299 { Expression *e = EXP_CANT_INTERPRET; | |
1300 Loc loc = e1->loc; | |
1301 Type *t; | |
717
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1302 Type *t1 = e1->type->toBasetype(); |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1303 Type *t2 = e2->type->toBasetype(); |
336 | 1304 |
1305 //printf("Cat(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars()); | |
1306 | |
1307 if (e1->op == TOKnull && (e2->op == TOKint64 || e2->op == TOKstructliteral)) | |
1308 { e = e2; | |
1309 goto L2; | |
1310 } | |
1311 else if ((e1->op == TOKint64 || e1->op == TOKstructliteral) && e2->op == TOKnull) | |
1312 { e = e1; | |
1313 L2: | |
1314 Type *tn = e->type->toBasetype(); | |
1315 if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar) | |
1316 { | |
1317 // Create a StringExp | |
1318 void *s; | |
1319 StringExp *es; | |
1320 size_t len = 1; | |
1321 int sz = tn->size(); | |
1322 integer_t v = e->toInteger(); | |
1323 | |
1324 s = mem.malloc((len + 1) * sz); | |
1325 memcpy((unsigned char *)s, &v, sz); | |
1326 | |
1327 // Add terminating 0 | |
1328 memset((unsigned char *)s + len * sz, 0, sz); | |
1329 | |
1330 es = new StringExp(loc, s, len); | |
1331 es->sz = sz; | |
1332 es->committed = 1; | |
1333 e = es; | |
1334 } | |
1335 else | |
1336 { // Create an ArrayLiteralExp | |
1337 Expressions *elements = new Expressions(); | |
1338 elements->push(e); | |
1339 e = new ArrayLiteralExp(e->loc, elements); | |
1340 } | |
1341 e->type = type; | |
1342 return e; | |
1343 } | |
1344 else if (e1->op == TOKstring && e2->op == TOKstring) | |
1345 { | |
1346 // Concatenate the strings | |
1347 void *s; | |
1348 StringExp *es1 = (StringExp *)e1; | |
1349 StringExp *es2 = (StringExp *)e2; | |
1350 StringExp *es; | |
1351 Type *t; | |
1352 size_t len = es1->len + es2->len; | |
1353 int sz = es1->sz; | |
1354 | |
658
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
1355 if (sz != es2->sz) |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
1356 { |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
1357 /* Can happen with: |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
1358 * auto s = "foo"d ~ "bar"c; |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
1359 */ |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
1360 assert(global.errors); |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
1361 return e; |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
1362 } |
336 | 1363 s = mem.malloc((len + 1) * sz); |
1364 memcpy(s, es1->string, es1->len * sz); | |
1365 memcpy((unsigned char *)s + es1->len * sz, es2->string, es2->len * sz); | |
1366 | |
1367 // Add terminating 0 | |
1368 memset((unsigned char *)s + len * sz, 0, sz); | |
1369 | |
1370 es = new StringExp(loc, s, len); | |
1371 es->sz = sz; | |
1372 es->committed = es1->committed | es2->committed; | |
1373 if (es1->committed) | |
1374 t = es1->type; | |
1375 else | |
1376 t = es2->type; | |
1377 es->type = type; | |
1378 e = es; | |
1379 } | |
1380 else if (e1->op == TOKstring && e2->op == TOKint64) | |
1381 { | |
1382 // Concatenate the strings | |
1383 void *s; | |
1384 StringExp *es1 = (StringExp *)e1; | |
1385 StringExp *es; | |
1386 Type *t; | |
1387 size_t len = es1->len + 1; | |
1388 int sz = es1->sz; | |
1389 integer_t v = e2->toInteger(); | |
1390 | |
1391 s = mem.malloc((len + 1) * sz); | |
1392 memcpy(s, es1->string, es1->len * sz); | |
1393 memcpy((unsigned char *)s + es1->len * sz, &v, sz); | |
1394 | |
1395 // Add terminating 0 | |
1396 memset((unsigned char *)s + len * sz, 0, sz); | |
1397 | |
1398 es = new StringExp(loc, s, len); | |
1399 es->sz = sz; | |
1400 es->committed = es1->committed; | |
1401 t = es1->type; | |
1402 es->type = type; | |
1403 e = es; | |
1404 } | |
1405 else if (e1->op == TOKint64 && e2->op == TOKstring) | |
1406 { | |
1407 // Concatenate the strings | |
1408 void *s; | |
1409 StringExp *es2 = (StringExp *)e2; | |
1410 StringExp *es; | |
1411 Type *t; | |
1412 size_t len = 1 + es2->len; | |
1413 int sz = es2->sz; | |
1414 integer_t v = e1->toInteger(); | |
1415 | |
1416 s = mem.malloc((len + 1) * sz); | |
1417 memcpy((unsigned char *)s, &v, sz); | |
1418 memcpy((unsigned char *)s + sz, es2->string, es2->len * sz); | |
1419 | |
1420 // Add terminating 0 | |
1421 memset((unsigned char *)s + len * sz, 0, sz); | |
1422 | |
1423 es = new StringExp(loc, s, len); | |
1424 es->sz = sz; | |
1425 es->committed = es2->committed; | |
1426 t = es2->type; | |
1427 es->type = type; | |
1428 e = es; | |
1429 } | |
1430 else if (e1->op == TOKarrayliteral && e2->op == TOKarrayliteral && | |
1431 e1->type->equals(e2->type)) | |
1432 { | |
1433 // Concatenate the arrays | |
1434 ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; | |
1435 ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; | |
1436 | |
1437 es1 = new ArrayLiteralExp(es1->loc, (Expressions *)es1->elements->copy()); | |
1438 es1->elements->insert(es1->elements->dim, es2->elements); | |
1439 e = es1; | |
1440 | |
1441 if (type->toBasetype()->ty == Tsarray) | |
1442 { | |
1443 e->type = new TypeSArray(e1->type->toBasetype()->next, new IntegerExp(0, es1->elements->dim, Type::tindex)); | |
1444 e->type = e->type->semantic(loc, NULL); | |
1445 } | |
1446 else | |
1447 e->type = type; | |
1448 } | |
717
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1449 else if (e1->op == TOKarrayliteral && e2->op == TOKnull && |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1450 t1->nextOf()->equals(t2->nextOf())) |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1451 { |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1452 e = e1; |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1453 goto L3; |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1454 } |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1455 else if (e1->op == TOKnull && e2->op == TOKarrayliteral && |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1456 t1->nextOf()->equals(t2->nextOf())) |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1457 { |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1458 e = e2; |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1459 L3: |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1460 // Concatenate the array with null |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1461 ArrayLiteralExp *es = (ArrayLiteralExp *)e; |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1462 |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1463 es = new ArrayLiteralExp(es->loc, (Expressions *)es->elements->copy()); |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1464 e = es; |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1465 |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1466 if (type->toBasetype()->ty == Tsarray) |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1467 { |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1468 e->type = new TypeSArray(t1->nextOf(), new IntegerExp(loc, es->elements->dim, Type::tindex)); |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1469 e->type = e->type->semantic(loc, NULL); |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1470 } |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1471 else |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1472 e->type = type; |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1473 } |
336 | 1474 else if ((e1->op == TOKarrayliteral || e1->op == TOKnull) && |
1475 e1->type->toBasetype()->nextOf()->equals(e2->type)) | |
1476 { | |
1477 ArrayLiteralExp *es1; | |
1478 if (e1->op == TOKarrayliteral) | |
1479 { es1 = (ArrayLiteralExp *)e1; | |
1480 es1 = new ArrayLiteralExp(es1->loc, (Expressions *)es1->elements->copy()); | |
1481 es1->elements->push(e2); | |
1482 } | |
1483 else | |
1484 { | |
1485 es1 = new ArrayLiteralExp(e1->loc, e2); | |
1486 } | |
1487 e = es1; | |
1488 | |
1489 if (type->toBasetype()->ty == Tsarray) | |
1490 { | |
1491 e->type = new TypeSArray(e2->type, new IntegerExp(0, es1->elements->dim, Type::tindex)); | |
1492 e->type = e->type->semantic(loc, NULL); | |
1493 } | |
1494 else | |
1495 e->type = type; | |
1496 } | |
1497 else if (e2->op == TOKarrayliteral && | |
1498 e2->type->toBasetype()->nextOf()->equals(e1->type)) | |
1499 { | |
1500 ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; | |
1501 | |
1502 es2 = new ArrayLiteralExp(es2->loc, (Expressions *)es2->elements->copy()); | |
1503 es2->elements->shift(e1); | |
1504 e = es2; | |
1505 | |
1506 if (type->toBasetype()->ty == Tsarray) | |
1507 { | |
1508 e->type = new TypeSArray(e1->type, new IntegerExp(0, es2->elements->dim, Type::tindex)); | |
1509 e->type = e->type->semantic(loc, NULL); | |
1510 } | |
1511 else | |
1512 e->type = type; | |
1513 } | |
1514 else if (e1->op == TOKnull && e2->op == TOKstring) | |
1515 { | |
1516 t = e1->type; | |
1517 e = e2; | |
1518 goto L1; | |
1519 } | |
1520 else if (e1->op == TOKstring && e2->op == TOKnull) | |
1521 { e = e1; | |
1522 t = e2->type; | |
1523 L1: | |
1524 Type *tb = t->toBasetype(); | |
1525 if (tb->ty == Tarray && tb->nextOf()->equals(e->type)) | |
1526 { Expressions *expressions = new Expressions(); | |
1527 expressions->push(e); | |
1528 e = new ArrayLiteralExp(loc, expressions); | |
1529 e->type = t; | |
1530 } | |
1531 if (!e->type->equals(type)) | |
1532 { StringExp *se = (StringExp *)e->copy(); | |
1533 e = se->castTo(NULL, type); | |
1534 } | |
1535 } | |
1536 return e; | |
1537 } | |
1538 | |
1539 Expression *Ptr(Type *type, Expression *e1) | |
1540 { | |
1541 //printf("Ptr(e1 = %s)\n", e1->toChars()); | |
1542 if (e1->op == TOKadd) | |
1543 { AddExp *ae = (AddExp *)e1; | |
1544 if (ae->e1->op == TOKaddress && ae->e2->op == TOKint64) | |
1545 { AddrExp *ade = (AddrExp *)ae->e1; | |
1546 if (ade->e1->op == TOKstructliteral) | |
1547 { StructLiteralExp *se = (StructLiteralExp *)ade->e1; | |
1548 unsigned offset = ae->e2->toInteger(); | |
1549 Expression *e = se->getField(type, offset); | |
1550 if (!e) | |
1551 e = EXP_CANT_INTERPRET; | |
1552 return e; | |
1553 } | |
1554 } | |
1555 } | |
1556 return EXP_CANT_INTERPRET; | |
1557 } | |
1558 |