Mercurial > projects > ddmd
annotate dmd/IntegerExp.d @ 192:eb38fdcb3e62 default tip
updated to compile with dmd2.062
author | korDen |
---|---|
date | Sat, 02 Mar 2013 01:25:52 -0800 |
parents | b0d41ff5e0df |
children |
rev | line source |
---|---|
72 | 1 module dmd.IntegerExp; |
2 | |
114 | 3 import dmd.common; |
72 | 4 import dmd.Expression; |
5 import dmd.backend.elem; | |
6 import dmd.TY; | |
7 import dmd.TypeEnum; | |
8 import dmd.TypeTypedef; | |
9 import dmd.Global; | |
10 import dmd.InterState; | |
11 import dmd.MATCH; | |
12 import dmd.Type; | |
13 import dmd.OutBuffer; | |
14 import dmd.Loc; | |
15 import dmd.Scope; | |
16 import dmd.IntRange; | |
17 import dmd.IRState; | |
18 import dmd.HdrGenState; | |
19 import dmd.TOK; | |
20 import dmd.Complex; | |
21 | |
22 import dmd.backend.dt_t; | |
23 import dmd.backend.Util; | |
24 | |
25 import core.stdc.ctype : isprint; | |
73 | 26 import std.stdio; |
72 | 27 |
187
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
178
diff
changeset
|
28 import dmd.DDMDExtensions; |
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
178
diff
changeset
|
29 |
0 | 30 class IntegerExp : Expression |
31 { | |
187
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
178
diff
changeset
|
32 mixin insertMemberExtension!(typeof(this)); |
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
178
diff
changeset
|
33 |
0 | 34 ulong value; |
35 | |
36 this(Loc loc, ulong value, Type type) | |
37 { | |
178 | 38 register(); |
72 | 39 super(loc, TOK.TOKint64, IntegerExp.sizeof); |
40 | |
41 //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type.toChars() : ""); | |
42 if (type && !type.isscalar()) | |
43 { | |
44 //printf("%s, loc = %d\n", toChars(), loc.linnum); | |
45 error("integral constant must be scalar type, not %s", type.toChars()); | |
46 type = Type.terror; | |
47 } | |
48 this.type = type; | |
0 | 49 this.value = value; |
50 } | |
51 | |
52 this(ulong value) | |
72 | 53 { |
178 | 54 register(); |
0 | 55 super(Loc(0), TOK.TOKint64, IntegerExp.sizeof); |
72 | 56 this.type = Type.tint32; |
0 | 57 this.value = value; |
58 } | |
59 | |
72 | 60 override bool equals(Object o) |
0 | 61 { |
72 | 62 IntegerExp ne; |
63 | |
64 if (this == o || | |
65 ((cast(Expression)o).op == TOKint64 && | |
66 ((ne = cast(IntegerExp)o), type.toHeadMutable().equals(ne.type.toHeadMutable())) && | |
67 value == ne.value) | |
68 ) | |
69 return 1; | |
70 | |
0 | 71 return 0; |
72 } | |
73 | |
72 | 74 override Expression semantic(Scope sc) |
0 | 75 { |
72 | 76 if (!type) |
77 { | |
78 // Determine what the type of this number is | |
79 ulong number = value; | |
80 | |
81 if (number & 0x8000000000000000) | |
82 type = Type.tuns64; | |
83 else if (number & 0xFFFFFFFF80000000) | |
84 type = Type.tint64; | |
85 else | |
86 type = Type.tint32; | |
87 } | |
88 else | |
89 { if (!type.deco) | |
90 type = type.semantic(loc, sc); | |
91 } | |
0 | 92 return this; |
93 } | |
94 | |
72 | 95 override Expression interpret(InterState istate) |
0 | 96 { |
72 | 97 version (LOG) { |
98 printf("IntegerExp.interpret() %s\n", toChars()); | |
99 } | |
63 | 100 return this; |
0 | 101 } |
102 | |
72 | 103 override string toChars() |
0 | 104 { |
72 | 105 static if (true) { |
106 return Expression.toChars(); | |
107 } else { | |
108 static char buffer[value.sizeof * 3 + 1]; | |
109 int len = sprintf(buffer.ptr, "%jd", value); | |
110 return buffer[0..len].idup; | |
0 | 111 } |
112 } | |
113 | |
72 | 114 override void dump(int indent) |
0 | 115 { |
116 assert(false); | |
117 } | |
118 | |
72 | 119 override IntRange getIntRange() |
0 | 120 { |
72 | 121 IntRange ir; |
122 ir.imin = value & type.sizemask(); | |
123 ir.imax = ir.imin; | |
53 | 124 return ir; |
0 | 125 } |
126 | |
72 | 127 override ulong toInteger() |
0 | 128 { |
72 | 129 Type t; |
130 | |
131 t = type; | |
132 while (t) | |
133 { | |
134 switch (t.ty) | |
135 { | |
136 case TY.Tbit: | |
137 case TY.Tbool: value = (value != 0); break; | |
138 case TY.Tint8: value = cast(byte) value; break; | |
139 case TY.Tchar: | |
140 case TY.Tuns8: value = cast(ubyte) value; break; | |
141 case TY.Tint16: value = cast(short) value; break; | |
142 case TY.Twchar: | |
143 case TY.Tuns16: value = cast(ushort)value; break; | |
144 case TY.Tint32: value = cast(int) value; break; | |
145 case TY.Tdchar: | |
146 case TY.Tuns32: value = cast(uint) value; break; | |
147 case TY.Tint64: value = cast(long) value; break; | |
148 case TY.Tuns64: value = cast(ulong) value; break; | |
149 case TY.Tpointer: | |
150 if (PTRSIZE == 4) | |
151 value = cast(uint) value; | |
152 else if (PTRSIZE == 8) | |
153 value = cast(ulong) value; | |
154 else | |
155 assert(0); | |
156 break; | |
157 | |
158 case TY.Tenum: | |
159 { | |
160 TypeEnum te = cast(TypeEnum)t; | |
161 t = te.sym.memtype; | |
162 continue; | |
163 } | |
164 | |
165 case TY.Ttypedef: | |
166 { | |
167 TypeTypedef tt = cast(TypeTypedef)t; | |
168 t = tt.sym.basetype; | |
169 continue; | |
170 } | |
171 | |
172 default: | |
173 /* This can happen if errors, such as | |
174 * the type is painted on like in fromConstInitializer(). | |
175 */ | |
176 if (!global.errors) | |
73 | 177 { |
109 | 178 writef("%s %p\n", type.toChars(), type); |
72 | 179 assert(0); |
180 } | |
181 break; | |
73 | 182 |
72 | 183 } |
184 break; | |
185 } | |
0 | 186 return value; |
187 } | |
188 | |
72 | 189 override real toReal() |
0 | 190 { |
72 | 191 Type t; |
192 | |
193 toInteger(); | |
194 t = type.toBasetype(); | |
195 if (t.ty == Tuns64) | |
196 return cast(real)cast(ulong)value; | |
197 else | |
0 | 198 return cast(real)cast(long)value; |
199 } | |
200 | |
72 | 201 override real toImaginary() |
0 | 202 { |
203 assert(false); | |
204 } | |
205 | |
72 | 206 override Complex!(real) toComplex() |
0 | 207 { |
208 assert(false); | |
209 } | |
210 | |
72 | 211 override int isConst() |
0 | 212 { |
213 return 1; | |
214 } | |
215 | |
72 | 216 override bool isBool(bool result) |
0 | 217 { |
135 | 218 int r = toInteger() != 0; |
219 return cast(bool)(result ? r : !r); | |
0 | 220 } |
221 | |
72 | 222 override MATCH implicitConvTo(Type t) |
0 | 223 { |
72 | 224 static if (false) { |
225 printf("IntegerExp.implicitConvTo(this=%s, type=%s, t=%s)\n", | |
226 toChars(), type.toChars(), t.toChars()); | |
227 } | |
228 | |
229 MATCH m = type.implicitConvTo(t); | |
230 if (m >= MATCH.MATCHconst) | |
231 return m; | |
232 | |
233 TY ty = type.toBasetype().ty; | |
234 TY toty = t.toBasetype().ty; | |
235 | |
236 if (m == MATCH.MATCHnomatch && t.ty == TY.Tenum) | |
237 goto Lno; | |
238 | |
239 switch (ty) | |
240 { | |
241 case TY.Tbit: | |
242 case TY.Tbool: | |
243 value &= 1; | |
244 ty = TY.Tint32; | |
245 break; | |
246 | |
247 case TY.Tint8: | |
248 value = cast(byte)value; | |
249 ty = TY.Tint32; | |
250 break; | |
251 | |
252 case TY.Tchar: | |
253 case TY.Tuns8: | |
254 value &= 0xFF; | |
255 ty = TY.Tint32; | |
256 break; | |
257 | |
258 case TY.Tint16: | |
259 value = cast(short)value; | |
260 ty = TY.Tint32; | |
261 break; | |
262 | |
263 case TY.Tuns16: | |
264 case TY.Twchar: | |
265 value &= 0xFFFF; | |
266 ty = TY.Tint32; | |
267 break; | |
268 | |
269 case TY.Tint32: | |
270 value = cast(int)value; | |
271 break; | |
272 | |
273 case TY.Tuns32: | |
274 case TY.Tdchar: | |
275 value &= 0xFFFFFFFF; | |
276 ty = TY.Tuns32; | |
277 break; | |
278 | |
279 default: | |
280 break; | |
281 } | |
282 | |
283 // Only allow conversion if no change in value | |
284 switch (toty) | |
285 { | |
286 case TY.Tbit: | |
287 case TY.Tbool: | |
288 if ((value & 1) != value) | |
289 goto Lno; | |
290 goto Lyes; | |
291 | |
292 case TY.Tint8: | |
293 if (cast(byte)value != value) | |
294 goto Lno; | |
295 goto Lyes; | |
296 | |
297 case TY.Tchar: | |
298 case TY.Tuns8: | |
299 //printf("value = %llu %llu\n", (dinteger_t)(unsigned char)value, value); | |
300 if (cast(ubyte)value != value) | |
301 goto Lno; | |
302 goto Lyes; | |
303 | |
304 case TY.Tint16: | |
305 if (cast(short)value != value) | |
306 goto Lno; | |
307 goto Lyes; | |
308 | |
309 case TY.Tuns16: | |
310 if (cast(ushort)value != value) | |
311 goto Lno; | |
312 goto Lyes; | |
313 | |
314 case TY.Tint32: | |
315 if (ty == TY.Tuns32) { | |
316 ; | |
317 } | |
318 else if (cast(int)value != value) { | |
319 goto Lno; | |
320 } | |
321 goto Lyes; | |
322 | |
323 case TY.Tuns32: | |
324 if (ty == TY.Tint32) { | |
325 } else if (cast(uint)value != value) { | |
326 goto Lno; | |
327 } | |
328 goto Lyes; | |
329 | |
330 case TY.Tdchar: | |
331 if (value > 0x10FFFF) { | |
332 goto Lno; | |
333 } | |
334 goto Lyes; | |
335 | |
336 case TY.Twchar: | |
337 if (cast(ushort)value != value) { | |
338 goto Lno; | |
339 } | |
340 goto Lyes; | |
341 | |
342 case TY.Tfloat32: | |
343 { | |
344 /*volatile*/ float f; /// | |
345 if (type.isunsigned()) { | |
346 f = cast(float)value; | |
347 if (f != value) { | |
348 goto Lno; | |
349 } | |
350 } else { | |
351 f = cast(float)cast(long)value; | |
352 if (f != cast(long)value) { | |
353 goto Lno; | |
354 } | |
355 } | |
356 goto Lyes; | |
357 } | |
358 | |
359 case TY.Tfloat64: | |
360 { | |
361 /*volatile*/ double f; /// | |
362 if (type.isunsigned()) { | |
363 f = cast(double)value; | |
364 if (f != value) | |
365 goto Lno; | |
366 } else { | |
367 f = cast(double)cast(long)value; | |
368 if (f != cast(long)value) | |
369 goto Lno; | |
370 } | |
371 goto Lyes; | |
372 } | |
373 | |
374 case TY.Tfloat80: | |
375 { | |
376 /*volatile*/ real f; /// | |
377 if (type.isunsigned()) { | |
378 f = cast(real)value; | |
379 if (f != value) | |
380 goto Lno; | |
381 } else { | |
382 f = cast(real)cast(long)value; | |
383 if (f != cast(long)value) | |
384 goto Lno; | |
385 } | |
386 goto Lyes; | |
387 } | |
388 | |
389 case TY.Tpointer: | |
390 //printf("type = %s\n", type.toBasetype().toChars()); | |
391 //printf("t = %s\n", t.toBasetype().toChars()); | |
392 if (ty == TY.Tpointer && type.toBasetype().nextOf().ty == t.toBasetype().nextOf().ty) | |
393 { | |
394 /* Allow things like: | |
395 * const char* P = cast(char *)3; | |
396 * char* q = P; | |
397 */ | |
398 goto Lyes; | |
399 } | |
400 break; | |
401 | |
402 default: | |
403 break; /// | |
404 } | |
405 | |
406 return Expression.implicitConvTo(t); | |
407 | |
408 Lyes: | |
409 //printf("MATCHconvert\n"); | |
410 return MATCH.MATCHconvert; | |
411 | |
412 Lno: | |
413 //printf("MATCHnomatch\n"); | |
0 | 414 return MATCH.MATCHnomatch; |
415 } | |
416 | |
72 | 417 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 418 { |
72 | 419 long v = toInteger(); |
420 | |
421 if (type) | |
422 { | |
423 Type t = type; | |
424 | |
425 L1: | |
426 switch (t.ty) | |
427 { | |
428 case TY.Tenum: | |
429 { | |
430 TypeEnum te = cast(TypeEnum)t; | |
431 buf.printf("cast(%s)", te.sym.toChars()); | |
432 t = te.sym.memtype; | |
433 goto L1; | |
434 } | |
435 | |
436 case TY.Ttypedef: | |
437 { | |
438 TypeTypedef tt = cast(TypeTypedef)t; | |
439 buf.printf("cast(%s)", tt.sym.toChars()); | |
440 t = tt.sym.basetype; | |
441 goto L1; | |
442 } | |
443 | |
444 case TY.Twchar: // BUG: need to cast(wchar) | |
445 case TY.Tdchar: // BUG: need to cast(dchar) | |
446 if (cast(ulong)v > 0xFF) | |
447 { | |
448 buf.printf("'\\U%08x'", v); | |
449 break; | |
450 } | |
451 case TY.Tchar: | |
452 if (v == '\'') | |
453 buf.writestring("'\\''"); | |
454 else if (isprint(cast(int)v) && v != '\\') | |
162 | 455 buf.printf("'%s'", cast(char)v); /// ! |
72 | 456 else |
457 buf.printf("'\\x%02x'", cast(int)v); | |
458 break; | |
459 | |
460 case TY.Tint8: | |
461 buf.writestring("cast(byte)"); | |
462 goto L2; | |
463 | |
464 case TY.Tint16: | |
465 buf.writestring("cast(short)"); | |
466 goto L2; | |
467 | |
468 case TY.Tint32: | |
469 L2: | |
470 buf.printf("%d", cast(int)v); | |
471 break; | |
472 | |
473 case TY.Tuns8: | |
474 buf.writestring("cast(ubyte)"); | |
475 goto L3; | |
476 | |
477 case TY.Tuns16: | |
478 buf.writestring("cast(ushort)"); | |
479 goto L3; | |
480 | |
481 case TY.Tuns32: | |
482 L3: | |
483 buf.printf("%du", cast(uint)v); | |
484 break; | |
485 | |
486 case TY.Tint64: | |
487 //buf.printf("%jdL", v); | |
488 buf.printf("%sL", v); | |
489 break; | |
490 | |
491 case TY.Tuns64: | |
492 L4: | |
493 //buf.printf("%juLU", v); | |
494 buf.printf("%sLU", v); | |
495 break; | |
496 | |
497 case TY.Tbit: | |
498 case TY.Tbool: | |
499 buf.writestring(v ? "true" : "false"); | |
500 break; | |
501 | |
502 case TY.Tpointer: | |
503 buf.writestring("cast("); | |
504 buf.writestring(t.toChars()); | |
505 buf.writeByte(')'); | |
506 if (PTRSIZE == 4) | |
507 goto L3; | |
508 else if (PTRSIZE == 8) | |
509 goto L4; | |
510 else | |
511 assert(0); | |
512 | |
513 default: | |
514 /* This can happen if errors, such as | |
515 * the type is painted on like in fromConstInitializer(). | |
516 */ | |
517 if (!global.errors) | |
518 { | |
519 debug { | |
520 writef("%s\n", t.toChars()); | |
521 } | |
522 assert(0); | |
523 } | |
524 break; | |
525 } | |
526 } | |
527 else if (v & 0x8000000000000000L) | |
528 buf.printf("0x%jx", v); | |
529 else | |
0 | 530 buf.printf("%jd", v); |
531 } | |
532 | |
72 | 533 override void toMangleBuffer(OutBuffer buf) |
0 | 534 { |
72 | 535 if (cast(long)value < 0) |
536 buf.printf("N%d", -value); | |
537 else | |
538 buf.printf("%d", value); | |
0 | 539 } |
540 | |
72 | 541 override Expression toLvalue(Scope sc, Expression e) |
0 | 542 { |
72 | 543 if (!e) |
544 e = this; | |
545 else if (!loc.filename) | |
546 loc = e.loc; | |
547 e.error("constant %s is not an lvalue", e.toChars()); | |
0 | 548 return this; |
549 } | |
550 | |
72 | 551 override elem* toElem(IRState* irs) |
0 | 552 { |
72 | 553 elem* e = el_long(type.totym(), value); |
554 el_setLoc(e,loc); | |
0 | 555 return e; |
556 } | |
557 | |
72 | 558 override dt_t** toDt(dt_t** pdt) |
0 | 559 { |
72 | 560 //printf("IntegerExp.toDt() %d\n", op); |
561 uint sz = cast(uint)type.size(); | |
562 if (value == 0) | |
563 pdt = dtnzeros(pdt, sz); | |
564 else | |
565 pdt = dtnbytes(pdt, sz, cast(char*)&value); | |
566 | |
0 | 567 return pdt; |
568 } | |
569 } | |
570 |