Mercurial > projects > ddmd
annotate dmd/IntegerExp.d @ 50:adf6f7f216ea
CondExp.toCBuffer
IsExp.toCBuffer
TemplateValueParameter.toCBuffer
Dsymbol.search
TemplateDeclaration.overloadInsert bug fixed
author | korDen |
---|---|
date | Sat, 21 Aug 2010 10:38:26 +0400 |
parents | ccbc1e0bb3f0 |
children | a8b50ff7f201 |
rev | line source |
---|---|
0 | 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 | |
45 | 52 bool equals(Object o) |
0 | 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: | |
50 | 476 //buf.printf("%juLU", v); |
477 buf.printf("%sLU", v); | |
0 | 478 break; |
479 | |
480 case TY.Tbit: | |
481 case TY.Tbool: | |
482 buf.writestring(v ? "true" : "false"); | |
483 break; | |
484 | |
485 case TY.Tpointer: | |
486 buf.writestring("cast("); | |
487 buf.writestring(t.toChars()); | |
488 buf.writeByte(')'); | |
489 if (PTRSIZE == 4) | |
490 goto L3; | |
491 else if (PTRSIZE == 8) | |
492 goto L4; | |
493 else | |
494 assert(0); | |
495 | |
496 default: | |
497 /* This can happen if errors, such as | |
498 * the type is painted on like in fromConstInitializer(). | |
499 */ | |
500 if (!global.errors) | |
501 { | |
502 debug { | |
503 writef("%s\n", t.toChars()); | |
504 } | |
505 assert(0); | |
506 } | |
507 break; | |
508 } | |
509 } | |
510 else if (v & 0x8000000000000000L) | |
511 buf.printf("0x%jx", v); | |
512 else | |
513 buf.printf("%jd", v); | |
514 } | |
515 | |
516 void toMangleBuffer(OutBuffer buf) | |
517 { | |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
518 if (cast(long)value < 0) |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
519 buf.printf("N%d", -value); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
520 else |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
521 buf.printf("%d", value); |
0 | 522 } |
523 | |
524 Expression toLvalue(Scope sc, Expression e) | |
525 { | |
526 if (!e) | |
527 e = this; | |
528 else if (!loc.filename) | |
529 loc = e.loc; | |
530 e.error("constant %s is not an lvalue", e.toChars()); | |
531 return this; | |
532 } | |
533 | |
534 elem* toElem(IRState* irs) | |
535 { | |
536 elem* e = el_long(type.totym(), value); | |
537 el_setLoc(e,loc); | |
538 return e; | |
539 } | |
540 | |
541 dt_t** toDt(dt_t** pdt) | |
542 { | |
543 //printf("IntegerExp.toDt() %d\n", op); | |
544 uint sz = cast(uint)type.size(); | |
545 if (value == 0) | |
546 pdt = dtnzeros(pdt, sz); | |
547 else | |
548 pdt = dtnbytes(pdt, sz, cast(char*)&value); | |
549 | |
550 return pdt; | |
551 } | |
552 } | |
553 |