comparison dmd/IntegerExp.d @ 0:10317f0c89a5

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