Mercurial > projects > ddmd
comparison dmd/Expression.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | 7427ded8caf7 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:10317f0c89a5 |
---|---|
1 module dmd.Expression; | |
2 | |
3 import dmd.Loc; | |
4 import dmd.TOK; | |
5 import dmd.Type; | |
6 import dmd.WANT; | |
7 import dmd.Scope; | |
8 import dmd.ArrayTypes; | |
9 import dmd.OutBuffer; | |
10 import dmd.HdrGenState; | |
11 import dmd.MATCH; | |
12 import dmd.IntRange; | |
13 import dmd.Dsymbol; | |
14 import dmd.FuncDeclaration; | |
15 import dmd.InterState; | |
16 import dmd.InlineCostState; | |
17 import dmd.InlineDoState; | |
18 import dmd.InlineScanState; | |
19 import dmd.Identifier; | |
20 import dmd.IRState; | |
21 import dmd.DotIdExp; | |
22 import dmd.TypeExp; | |
23 import dmd.DYNCAST; | |
24 import dmd.TY; | |
25 import dmd.CallExp; | |
26 import dmd.VarExp; | |
27 import dmd.STC; | |
28 import dmd.TemplateInstance; | |
29 import dmd.CommaExp; | |
30 import dmd.NullExp; | |
31 import dmd.AddrExp; | |
32 import dmd.ErrorExp; | |
33 import dmd.TypeStruct; | |
34 import dmd.CastExp; | |
35 import dmd.Global; | |
36 import dmd.Token; | |
37 import dmd.TypeClass; | |
38 import dmd.PtrExp; | |
39 import dmd.TypeSArray; | |
40 import dmd.TypeReference; | |
41 import dmd.Util; | |
42 import dmd.Complex; | |
43 | |
44 import dmd.backend.elem; | |
45 import dmd.backend.dt_t; | |
46 | |
47 import std.stdio : writef; | |
48 import core.stdc.stdlib : malloc; | |
49 | |
50 import std.conv; | |
51 | |
52 /* Things like: | |
53 * int.size | |
54 * foo.size | |
55 * (foo).size | |
56 * cast(foo).size | |
57 */ | |
58 | |
59 Expression typeDotIdExp(Loc loc, Type type, Identifier ident) | |
60 { | |
61 return new DotIdExp(loc, new TypeExp(loc, type), ident); | |
62 } | |
63 | |
64 /***************************************** | |
65 * Determine if 'this' is available. | |
66 * If it is, return the FuncDeclaration that has it. | |
67 */ | |
68 | |
69 FuncDeclaration hasThis(Scope sc) | |
70 { | |
71 FuncDeclaration fd; | |
72 FuncDeclaration fdthis; | |
73 | |
74 //printf("hasThis()\n"); | |
75 fdthis = sc.parent.isFuncDeclaration(); | |
76 //printf("fdthis = %p, '%s'\n", fdthis, fdthis ? fdthis.toChars() : ""); | |
77 | |
78 // Go upwards until we find the enclosing member function | |
79 fd = fdthis; | |
80 while (1) | |
81 { | |
82 if (!fd) | |
83 { | |
84 goto Lno; | |
85 } | |
86 if (!fd.isNested()) | |
87 break; | |
88 | |
89 Dsymbol parent = fd.parent; | |
90 while (parent) | |
91 { | |
92 TemplateInstance ti = parent.isTemplateInstance(); | |
93 if (ti) | |
94 parent = ti.parent; | |
95 else | |
96 break; | |
97 } | |
98 | |
99 fd = fd.parent.isFuncDeclaration(); | |
100 } | |
101 | |
102 if (!fd.isThis()) | |
103 { | |
104 //printf("test '%s'\n", fd.toChars()); | |
105 goto Lno; | |
106 } | |
107 | |
108 assert(fd.vthis); | |
109 return fd; | |
110 | |
111 Lno: | |
112 return null; // don't have 'this' available | |
113 } | |
114 | |
115 /*************************************** | |
116 * Pull out any properties. | |
117 */ | |
118 | |
119 Expression resolveProperties(Scope sc, Expression e) | |
120 { | |
121 //printf("resolveProperties(%s)\n", e.toChars()); | |
122 if (e.type) | |
123 { | |
124 Type t = e.type.toBasetype(); | |
125 | |
126 if (t.ty == TY.Tfunction || e.op == TOK.TOKoverloadset) | |
127 { | |
128 e = new CallExp(e.loc, e); | |
129 e = e.semantic(sc); | |
130 } | |
131 | |
132 /* Look for e being a lazy parameter; rewrite as delegate call | |
133 */ | |
134 else if (e.op == TOK.TOKvar) | |
135 { VarExp ve = cast(VarExp)e; | |
136 | |
137 if (ve.var.storage_class & STC.STClazy) | |
138 { | |
139 e = new CallExp(e.loc, e); | |
140 e = e.semantic(sc); | |
141 } | |
142 } | |
143 | |
144 else if (e.op == TOK.TOKdotexp) | |
145 { | |
146 e.error("expression has no value"); | |
147 } | |
148 } | |
149 else if (e.op == TOK.TOKdottd) | |
150 { | |
151 e = new CallExp(e.loc, e); | |
152 e = e.semantic(sc); | |
153 } | |
154 | |
155 return e; | |
156 } | |
157 | |
158 class Expression | |
159 { | |
160 Loc loc; // file location | |
161 TOK op; // handy to minimize use of dynamic_cast | |
162 Type type; // !=null means that semantic() has been run | |
163 int size; // # of bytes in Expression so we can copy() it | |
164 | |
165 this(Loc loc, TOK op, int size) | |
166 { | |
167 this.loc = loc; | |
168 //writef("Expression.Expression(op = %d %s) this = %p\n", op, to!(string)(op), this); | |
169 this.op = op; | |
170 this.size = size; | |
171 type = null; | |
172 } | |
173 | |
174 int equals(Object o) | |
175 { | |
176 return this is o; | |
177 } | |
178 | |
179 /********************************* | |
180 * Does *not* do a deep copy. | |
181 */ | |
182 Expression copy() /// bad bad bad | |
183 { | |
184 Expression e; | |
185 if (!size) | |
186 { | |
187 debug { | |
188 writef("No expression copy for: %s\n", toChars()); | |
189 writef("op = %d\n", op); | |
190 dump(0); | |
191 } | |
192 assert(0); | |
193 } | |
194 auto size = this.classinfo.init.length; | |
195 auto ptr = malloc(size); | |
196 memcpy(ptr, cast(void*)this, size); | |
197 | |
198 return cast(Expression)ptr; | |
199 } | |
200 | |
201 Expression syntaxCopy() | |
202 { | |
203 //printf("Expression::syntaxCopy()\n"); | |
204 //dump(0); | |
205 return copy(); | |
206 } | |
207 | |
208 Expression semantic(Scope sc) | |
209 { | |
210 version (LOGSEMANTIC) { | |
211 printf("Expression.semantic() %s\n", toChars()); | |
212 } | |
213 if (type) | |
214 type = type.semantic(loc, sc); | |
215 else | |
216 type = Type.tvoid; | |
217 return this; | |
218 } | |
219 | |
220 Expression trySemantic(Scope sc) | |
221 { | |
222 uint errors = global.errors; | |
223 global.gag++; | |
224 Expression e = semantic(sc); | |
225 global.gag--; | |
226 if (errors != global.errors) | |
227 { | |
228 global.errors = errors; | |
229 e = null; | |
230 } | |
231 return e; | |
232 } | |
233 | |
234 DYNCAST dyncast() { return DYNCAST.DYNCAST_EXPRESSION; } // kludge for template.isExpression() | |
235 | |
236 void print() | |
237 { | |
238 assert(false); | |
239 } | |
240 | |
241 string toChars() | |
242 { | |
243 scope OutBuffer buf = new OutBuffer(); | |
244 HdrGenState hgs; | |
245 | |
246 toCBuffer(buf, &hgs); | |
247 return buf.toChars(); | |
248 } | |
249 | |
250 void dump(int indent) | |
251 { | |
252 assert(false); | |
253 } | |
254 | |
255 void error(T...)(string format, T t) | |
256 { | |
257 .error(loc, format, t); | |
258 } | |
259 | |
260 void warning(T...)(string formar, T t) | |
261 { | |
262 .warning(loc, format, t); | |
263 } | |
264 | |
265 void rvalue() | |
266 { | |
267 if (type && type.toBasetype().ty == TY.Tvoid) | |
268 { | |
269 error("expression %s is void and has no value", toChars()); | |
270 static if (false) { | |
271 dump(0); | |
272 halt(); | |
273 } | |
274 type = Type.terror; | |
275 } | |
276 } | |
277 | |
278 static Expression combine(Expression e1, Expression e2) | |
279 { | |
280 if (e1) | |
281 { | |
282 if (e2) | |
283 { | |
284 e1 = new CommaExp(e1.loc, e1, e2); | |
285 e1.type = e2.type; | |
286 } | |
287 } | |
288 else | |
289 { | |
290 e1 = e2; | |
291 } | |
292 | |
293 return e1; | |
294 } | |
295 | |
296 static Expressions arraySyntaxCopy(Expressions exps) | |
297 { | |
298 Expressions a = null; | |
299 | |
300 if (exps) | |
301 { | |
302 a = new Expressions(); | |
303 a.setDim(exps.dim); | |
304 for (int i = 0; i < a.dim; i++) | |
305 { | |
306 Expression e = cast(Expression)exps.data[i]; | |
307 | |
308 e = e.syntaxCopy(); | |
309 a.data[i] = cast(void*)e; | |
310 } | |
311 } | |
312 return a; | |
313 } | |
314 | |
315 ulong toInteger() | |
316 { | |
317 assert(false); | |
318 } | |
319 | |
320 ulong toUInteger() | |
321 { | |
322 //printf("Expression %s\n", Token.toChars(op)); | |
323 return cast(ulong)toInteger(); | |
324 } | |
325 | |
326 real toReal() | |
327 { | |
328 assert(false); | |
329 } | |
330 | |
331 real toImaginary() | |
332 { | |
333 assert(false); | |
334 } | |
335 | |
336 Complex!(real) toComplex() | |
337 { | |
338 assert(false); | |
339 } | |
340 | |
341 void toCBuffer(OutBuffer buf, HdrGenState* hgs) | |
342 { | |
343 buf.writestring(Token.toChars(op)); | |
344 } | |
345 | |
346 void toMangleBuffer(OutBuffer buf) | |
347 { | |
348 assert(false); | |
349 } | |
350 | |
351 int isLvalue() | |
352 { | |
353 assert(false); | |
354 } | |
355 | |
356 Expression toLvalue(Scope sc, Expression e) | |
357 { | |
358 assert(false); | |
359 } | |
360 | |
361 Expression modifiableLvalue(Scope sc, Expression e) | |
362 { | |
363 //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type.toChars()); | |
364 | |
365 // See if this expression is a modifiable lvalue (i.e. not const) | |
366 version (DMDV2) { | |
367 if (type && (!type.isMutable() || !type.isAssignable())) | |
368 error("%s is not mutable", e.toChars()); | |
369 } | |
370 return toLvalue(sc, e); | |
371 } | |
372 | |
373 /************************************** | |
374 * Do an implicit cast. | |
375 * Issue error if it can't be done. | |
376 */ | |
377 Expression implicitCastTo(Scope sc, Type t) | |
378 { | |
379 //printf("Expression.implicitCastTo(%s of type %s) => %s\n", toChars(), type.toChars(), t.toChars()); | |
380 | |
381 MATCH match = implicitConvTo(t); | |
382 if (match) | |
383 { | |
384 TY tyfrom = type.toBasetype().ty; | |
385 TY tyto = t.toBasetype().ty; | |
386 | |
387 version (DMDV1) { | |
388 if (global.params.warnings && | |
389 Type.impcnvWarn[tyfrom][tyto] && | |
390 op != TOKint64) | |
391 { | |
392 Expression e = optimize(WANT.WANTflags | WANT.WANTvalue); | |
393 | |
394 if (e.op == TOK.TOKint64) | |
395 return e.implicitCastTo(sc, t); | |
396 if (tyfrom == Tint32 && (op == TOKadd || op == TOKmin || op == TOKand || op == TOKor || op == TOKxor)) | |
397 { | |
398 /* This is really only a semi-kludge fix, | |
399 * we really should look at the operands of op | |
400 * and see if they are narrower types. | |
401 * For example, b=b|b and b=b|7 and s=b+b should be allowed, | |
402 * but b=b|i should be an error. | |
403 */ | |
404 ; | |
405 } | |
406 else | |
407 { | |
408 warning("implicit conversion of expression (%s) of type %s to %s can cause loss of data", toChars(), type.toChars(), t.toChars()); | |
409 } | |
410 } | |
411 } | |
412 version (DMDV2) { | |
413 if (match == MATCH.MATCHconst && t == type.constOf()) | |
414 { | |
415 Expression e = copy(); | |
416 e.type = t; | |
417 return e; | |
418 } | |
419 } | |
420 return castTo(sc, t); | |
421 } | |
422 | |
423 Expression e = optimize(WANT.WANTflags | WANT.WANTvalue); | |
424 if (e != this) | |
425 return e.implicitCastTo(sc, t); | |
426 | |
427 static if (false) { | |
428 printf("ty = %d\n", type.ty); | |
429 print(); | |
430 type.print(); | |
431 printf("to:\n"); | |
432 t.print(); | |
433 printf("%p %p type: %s to: %s\n", type.deco, t.deco, type.deco, t.deco); | |
434 //printf("%p %p %p\n", type.nextOf().arrayOf(), type, t); | |
435 fflush(stdout); | |
436 } | |
437 if (!t.deco) { | |
438 /* Can happen with: | |
439 * enum E { One } | |
440 * class A | |
441 * { static void fork(EDG dg) { dg(E.One); } | |
442 * alias void delegate(E) EDG; | |
443 * } | |
444 * Should eventually make it work. | |
445 */ | |
446 error("forward reference to type %s", t.toChars()); | |
447 } else if (t.reliesOnTident()) { | |
448 error("forward reference to type %s", t.reliesOnTident().toChars()); | |
449 } | |
450 | |
451 error("cannot implicitly convert expression (%s) of type %s to %s", toChars(), type.toChars(), t.toChars()); | |
452 return castTo(sc, t); | |
453 } | |
454 | |
455 /******************************************* | |
456 * Return !=0 if we can implicitly convert this to type t. | |
457 * Don't do the actual cast. | |
458 */ | |
459 MATCH implicitConvTo(Type t) | |
460 { | |
461 static if (false) { | |
462 printf("Expression.implicitConvTo(this=%s, type=%s, t=%s)\n", | |
463 toChars(), type.toChars(), t.toChars()); | |
464 } | |
465 //static int nest; if (++nest == 10) halt(); | |
466 if (!type) | |
467 { | |
468 error("%s is not an expression", toChars()); | |
469 type = Type.terror; | |
470 } | |
471 Expression e = optimize(WANT.WANTvalue | WANT.WANTflags); | |
472 if (e.type == t) | |
473 return MATCH.MATCHexact; | |
474 if (e != this) | |
475 { | |
476 //printf("\toptimized to %s of type %s\n", e.toChars(), e.type.toChars()); | |
477 return e.implicitConvTo(t); | |
478 } | |
479 MATCH match = type.implicitConvTo(t); | |
480 if (match != MATCH.MATCHnomatch) | |
481 return match; | |
482 | |
483 /* See if we can do integral narrowing conversions | |
484 */ | |
485 if (type.isintegral() && t.isintegral() && | |
486 type.isTypeBasic() && t.isTypeBasic()) | |
487 { | |
488 IntRange ir = getIntRange(); | |
489 if (ir.imax <= t.sizemask()) | |
490 return MATCH.MATCHconvert; | |
491 } | |
492 | |
493 static if (false) { | |
494 Type tb = t.toBasetype(); | |
495 if (tb.ty == Tdelegate) | |
496 { | |
497 TypeDelegate td = cast(TypeDelegate)tb; | |
498 TypeFunction tf = cast(TypeFunction)td.nextOf(); | |
499 | |
500 if (!tf.varargs && !(tf.arguments && tf.arguments.dim)) | |
501 { | |
502 match = type.implicitConvTo(tf.nextOf()); | |
503 if (match) | |
504 return match; | |
505 if (tf.nextOf().toBasetype().ty == Tvoid) | |
506 return MATCH.MATCHconvert; | |
507 } | |
508 } | |
509 } | |
510 return MATCH.MATCHnomatch; | |
511 } | |
512 | |
513 IntRange getIntRange() | |
514 { | |
515 assert(false); | |
516 } | |
517 | |
518 /************************************** | |
519 * Do an explicit cast. | |
520 */ | |
521 Expression castTo(Scope sc, Type t) | |
522 { | |
523 //printf("Expression.castTo(this=%s, t=%s)\n", toChars(), t.toChars()); | |
524 static if (false) { | |
525 writef("Expression.castTo(this=%s, type=%s, t=%s)\n", | |
526 toChars(), type.toChars(), t.toChars()); | |
527 } | |
528 if (type is t) | |
529 return this; | |
530 Expression e = this; | |
531 Type tb = t.toBasetype(); | |
532 Type typeb = type.toBasetype(); | |
533 if (tb != typeb) | |
534 { | |
535 // Do (type *) cast of (type [dim]) | |
536 if (tb.ty == TY.Tpointer && typeb.ty == TY.Tsarray | |
537 ) | |
538 { | |
539 //printf("Converting [dim] to *\n"); | |
540 | |
541 if (typeb.size(loc) == 0) | |
542 e = new NullExp(loc); | |
543 else | |
544 e = new AddrExp(loc, e); | |
545 } | |
546 else { | |
547 static if (false) { | |
548 if (tb.ty == Tdelegate && type.ty != Tdelegate) | |
549 { | |
550 TypeDelegate td = cast(TypeDelegate)tb; | |
551 TypeFunction tf = cast(TypeFunction)td.nextOf(); | |
552 return toDelegate(sc, tf.nextOf()); | |
553 } | |
554 } | |
555 if (typeb.ty == TY.Tstruct) | |
556 { | |
557 TypeStruct ts = cast(TypeStruct)typeb; | |
558 if (!(tb.ty == TY.Tstruct && ts.sym == (cast(TypeStruct)tb).sym) && | |
559 ts.sym.aliasthis) | |
560 { /* Forward the cast to our alias this member, rewrite to: | |
561 * cast(to)e1.aliasthis | |
562 */ | |
563 Expression e1 = new DotIdExp(loc, this, ts.sym.aliasthis.ident); | |
564 Expression e2 = new CastExp(loc, e1, tb); | |
565 e2 = e2.semantic(sc); | |
566 return e2; | |
567 } | |
568 } | |
569 else if (typeb.ty == TY.Tclass) | |
570 { | |
571 TypeClass ts = cast(TypeClass)typeb; | |
572 if (tb.ty != TY.Tclass && ts.sym.aliasthis) | |
573 { /* Forward the cast to our alias this member, rewrite to: | |
574 * cast(to)e1.aliasthis | |
575 */ | |
576 Expression e1 = new DotIdExp(loc, this, ts.sym.aliasthis.ident); | |
577 Expression e2 = new CastExp(loc, e1, tb); | |
578 e2 = e2.semantic(sc); | |
579 return e2; | |
580 } | |
581 } | |
582 e = new CastExp(loc, e, tb); | |
583 } | |
584 } | |
585 else | |
586 { | |
587 e = e.copy(); // because of COW for assignment to e.type | |
588 } | |
589 | |
590 assert(e != this); | |
591 e.type = t; | |
592 //printf("Returning: %s\n", e.toChars()); | |
593 return e; | |
594 } | |
595 | |
596 /************************************ | |
597 * Detect cases where pointers to the stack can 'escape' the | |
598 * lifetime of the stack frame. | |
599 */ | |
600 void checkEscape() | |
601 { | |
602 } | |
603 | |
604 void checkScalar() | |
605 { | |
606 if (!type.isscalar()) | |
607 error("'%s' is not a scalar, it is a %s", toChars(), type.toChars()); | |
608 | |
609 rvalue(); | |
610 } | |
611 | |
612 void checkNoBool() | |
613 { | |
614 if (type.toBasetype().ty == TY.Tbool) | |
615 error("operation not allowed on bool '%s'", toChars()); | |
616 } | |
617 | |
618 Expression checkIntegral() | |
619 { | |
620 if (!type.isintegral()) | |
621 { | |
622 error("'%s' is not of integral type, it is a %s", toChars(), type.toChars()); | |
623 return new ErrorExp(); | |
624 } | |
625 | |
626 rvalue(); | |
627 return this; | |
628 } | |
629 | |
630 Expression checkArithmetic() | |
631 { | |
632 if (!type.isintegral() && !type.isfloating()) | |
633 { | |
634 error("'%s' is not of arithmetic type, it is a %s", toChars(), type.toChars()); | |
635 return new ErrorExp(); | |
636 } | |
637 | |
638 rvalue(); | |
639 return this; | |
640 } | |
641 | |
642 void checkDeprecated(Scope sc, Dsymbol s) | |
643 { | |
644 s.checkDeprecated(loc, sc); | |
645 } | |
646 | |
647 void checkPurity(Scope sc, FuncDeclaration f) | |
648 { | |
649 static if (true) { | |
650 if (sc.func) | |
651 { | |
652 FuncDeclaration outerfunc = sc.func; | |
653 while (outerfunc.toParent2() && outerfunc.toParent2().isFuncDeclaration()) | |
654 { | |
655 outerfunc = outerfunc.toParent2().isFuncDeclaration(); | |
656 } | |
657 if (outerfunc.isPure() && !sc.intypeof && (!f.isNested() && !f.isPure())) | |
658 error("pure function '%s' cannot call impure function '%s'\n", | |
659 sc.func.toChars(), f.toChars()); | |
660 } | |
661 } else { | |
662 if (sc.func && sc.func.isPure() && !sc.intypeof && !f.isPure()) | |
663 error("pure function '%s' cannot call impure function '%s'\n", | |
664 sc.func.toChars(), .toChars()); | |
665 } | |
666 } | |
667 | |
668 /***************************** | |
669 * Check that expression can be tested for true or false. | |
670 */ | |
671 Expression checkToBoolean() | |
672 { | |
673 // Default is 'yes' - do nothing | |
674 | |
675 debug { | |
676 if (!type) | |
677 dump(0); | |
678 } | |
679 | |
680 if (!type.checkBoolean()) | |
681 { | |
682 error("expression %s of type %s does not have a boolean value", toChars(), type.toChars()); | |
683 } | |
684 | |
685 return this; | |
686 } | |
687 | |
688 Expression checkToPointer() | |
689 { | |
690 Expression e; | |
691 Type tb; | |
692 | |
693 //printf("Expression::checkToPointer()\n"); | |
694 e = this; | |
695 | |
696 // If C static array, convert to pointer | |
697 tb = type.toBasetype(); | |
698 if (tb.ty == Tsarray) | |
699 { | |
700 TypeSArray ts = cast(TypeSArray)tb; | |
701 if (ts.size(loc) == 0) | |
702 e = new NullExp(loc); | |
703 else | |
704 e = new AddrExp(loc, this); | |
705 e.type = ts.next.pointerTo(); | |
706 } | |
707 return e; | |
708 } | |
709 | |
710 Expression addressOf(Scope sc) | |
711 { | |
712 //printf("Expression::addressOf()\n"); | |
713 Expression e = toLvalue(sc, null); | |
714 e = new AddrExp(loc, e); | |
715 e.type = type.pointerTo(); | |
716 return e; | |
717 } | |
718 | |
719 /****************************** | |
720 * If this is a reference, dereference it. | |
721 */ | |
722 Expression deref() | |
723 { | |
724 //printf("Expression::deref()\n"); | |
725 if (type.ty == TY.Treference) | |
726 { | |
727 Expression e = new PtrExp(loc, this); | |
728 e.type = (cast(TypeReference)type).next; | |
729 return e; | |
730 } | |
731 return this; | |
732 } | |
733 | |
734 /*********************************** | |
735 * Do integral promotions (convertchk). | |
736 * Don't convert <array of> to <pointer to> | |
737 */ | |
738 Expression integralPromotions(Scope sc) | |
739 { | |
740 Expression e = this; | |
741 | |
742 //printf("integralPromotions %s %s\n", e.toChars(), e.type.toChars()); | |
743 switch (type.toBasetype().ty) | |
744 { | |
745 case TY.Tvoid: | |
746 error("void has no value"); | |
747 break; | |
748 | |
749 case TY.Tint8: | |
750 case TY.Tuns8: | |
751 case TY.Tint16: | |
752 case TY.Tuns16: | |
753 case TY.Tbit: | |
754 case TY.Tbool: | |
755 case TY.Tchar: | |
756 case TY.Twchar: | |
757 e = e.castTo(sc, Type.tint32); | |
758 break; | |
759 | |
760 case TY.Tdchar: | |
761 e = e.castTo(sc, Type.tuns32); | |
762 break; | |
763 default: | |
764 break; /// | |
765 } | |
766 return e; | |
767 } | |
768 | |
769 Expression toDelegate(Scope sc, Type t) | |
770 { | |
771 assert(false); | |
772 } | |
773 | |
774 void scanForNestedRef(Scope sc) | |
775 { | |
776 assert(false); | |
777 } | |
778 | |
779 Expression optimize(int result) | |
780 { | |
781 //printf("Expression.optimize(result = x%x) %s\n", result, toChars()); | |
782 return this; | |
783 } | |
784 | |
785 Expression interpret(InterState istate) | |
786 { | |
787 assert(false); | |
788 } | |
789 | |
790 int isConst() | |
791 { | |
792 //printf("Expression::isConst(): %s\n", toChars()); | |
793 return 0; | |
794 } | |
795 | |
796 /******************************** | |
797 * Does this expression statically evaluate to a boolean TRUE or FALSE? | |
798 */ | |
799 bool isBool(bool result) | |
800 { | |
801 return false; | |
802 } | |
803 | |
804 int isBit() | |
805 { | |
806 assert(false); | |
807 } | |
808 | |
809 /******************************** | |
810 * Check for expressions that have no use. | |
811 * Input: | |
812 * flag 0 not going to use the result, so issue error message if no | |
813 * side effects | |
814 * 1 the result of the expression is used, but still check | |
815 * for useless subexpressions | |
816 * 2 do not issue error messages, just return !=0 if expression | |
817 * has side effects | |
818 */ | |
819 bool checkSideEffect(int flag) | |
820 { | |
821 if (flag == 0) | |
822 { | |
823 if (op == TOKimport) | |
824 error("%s has no effect", toChars()); | |
825 else | |
826 error("%s has no effect in expression (%s)", | |
827 | |
828 Token.toChars(op), toChars()); | |
829 } | |
830 | |
831 return false; | |
832 } | |
833 | |
834 bool canThrow() | |
835 { | |
836 version (DMDV2) { | |
837 return false; | |
838 } else { | |
839 return true; | |
840 } | |
841 } | |
842 | |
843 int inlineCost(InlineCostState* ics) | |
844 { | |
845 return 1; | |
846 } | |
847 | |
848 Expression doInline(InlineDoState ids) | |
849 { | |
850 //printf("Expression.doInline(%s): %s\n", Token.toChars(op), toChars()); | |
851 return copy(); | |
852 } | |
853 | |
854 Expression inlineScan(InlineScanState* iss) | |
855 { | |
856 return this; | |
857 } | |
858 | |
859 /*********************************** | |
860 * Determine if operands of binary op can be reversed | |
861 * to fit operator overload. | |
862 */ | |
863 | |
864 // For operator overloading | |
865 bool isCommutative() | |
866 { | |
867 return false; // default is no reverse | |
868 } | |
869 | |
870 /*********************************** | |
871 * Get Identifier for operator overload. | |
872 */ | |
873 Identifier opId() | |
874 { | |
875 assert(false); | |
876 } | |
877 | |
878 /*********************************** | |
879 * Get Identifier for reverse operator overload, | |
880 * null if not supported for this operator. | |
881 */ | |
882 Identifier opId_r() | |
883 { | |
884 return null; | |
885 } | |
886 | |
887 // For array ops | |
888 void buildArrayIdent(OutBuffer buf, Expressions arguments) | |
889 { | |
890 assert(false); | |
891 } | |
892 | |
893 Expression buildArrayLoop(Arguments fparams) | |
894 { | |
895 assert(false); | |
896 } | |
897 | |
898 // Back end | |
899 elem* toElem(IRState* irs) | |
900 { | |
901 assert(false); | |
902 } | |
903 | |
904 dt_t** toDt(dt_t** pdt) | |
905 { | |
906 assert(false); | |
907 } | |
908 } |