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 }