Mercurial > projects > ddmd
annotate dmd/EqualExp.d @ 115:6caaf0256da1
+ interpretation of (non-assign) binary expressions
+ BinExp.isunsigned
+ EqualExp.isBit
author | Trass3r |
---|---|
date | Thu, 02 Sep 2010 01:29:29 +0200 |
parents | e28b18c23469 |
children | 60bb0fe4563e |
rev | line source |
---|---|
72 | 1 module dmd.EqualExp; |
2 | |
114 | 3 import dmd.common; |
79 | 4 import dmd.ErrorExp; |
72 | 5 import dmd.Expression; |
0 | 6 import dmd.Id; |
72 | 7 import dmd.Identifier; |
8 import dmd.InterState; | |
9 import dmd.Loc; | |
10 import dmd.Scope; | |
11 import dmd.IRState; | |
12 import dmd.BinExp; | |
0 | 13 import dmd.TOK; |
14 import dmd.Type; | |
15 import dmd.AddrExp; | |
16 import dmd.VarExp; | |
17 import dmd.IntegerExp; | |
18 import dmd.TY; | |
19 import dmd.Token; | |
20 import dmd.NotExp; | |
21 import dmd.WANT; | |
72 | 22 import dmd.GlobalExpressions; |
23 | |
0 | 24 import dmd.backend.elem; |
25 import dmd.backend.OPER; | |
26 import dmd.backend.Util; | |
27 import dmd.backend.TYM; | |
28 import dmd.backend.RTLSYM; | |
29 | |
30 import dmd.codegen.Util; | |
31 | |
32 import dmd.expression.util.arrayTypeCompatible; | |
33 import dmd.expression.Util; | |
72 | 34 import dmd.expression.Equal; |
35 | |
0 | 36 class EqualExp : BinExp |
37 { | |
38 this(TOK op, Loc loc, Expression e1, Expression e2) | |
39 { | |
40 super(loc, op, EqualExp.sizeof, e1, e2); | |
41 assert(op == TOK.TOKequal || op == TOK.TOKnotequal); | |
42 } | |
43 | |
72 | 44 override Expression semantic(Scope sc) |
0 | 45 { |
46 Expression e; | |
47 | |
48 //printf("EqualExp.semantic('%s')\n", toChars()); | |
49 if (type) | |
50 return this; | |
51 | |
52 BinExp.semanticp(sc); | |
53 | |
54 /* Before checking for operator overloading, check to see if we're | |
55 * comparing the addresses of two statics. If so, we can just see | |
56 * if they are the same symbol. | |
57 */ | |
58 if (e1.op == TOK.TOKaddress && e2.op == TOK.TOKaddress) | |
59 { | |
60 AddrExp ae1 = cast(AddrExp)e1; | |
61 AddrExp ae2 = cast(AddrExp)e2; | |
62 | |
63 if (ae1.e1.op == TOK.TOKvar && ae2.e1.op == TOK.TOKvar) | |
64 { | |
65 VarExp ve1 = cast(VarExp)ae1.e1; | |
66 VarExp ve2 = cast(VarExp)ae2.e1; | |
67 | |
68 if (ve1.var == ve2.var /*|| ve1.var.toSymbol() == ve2.var.toSymbol()*/) | |
69 { | |
70 // They are the same, result is 'true' for ==, 'false' for != | |
71 e = new IntegerExp(loc, (op == TOK.TOKequal), Type.tboolean); | |
72 return e; | |
73 } | |
74 } | |
75 } | |
76 | |
79 | 77 Type t1 = e1.type.toBasetype(); |
78 Type t2 = e2.type.toBasetype(); | |
79 if (t1.ty == TY.Tclass && e2.op == TOK.TOKnull || t2.ty == TY.Tclass && e1.op == TOK.TOKnull) | |
0 | 80 { |
81 error("use '%s' instead of '%s' when comparing with null", | |
82 Token.toChars(op == TOK.TOKequal ? TOK.TOKidentity : TOK.TOKnotidentity), | |
83 Token.toChars(op)); | |
84 } | |
85 | |
86 //if (e2.op != TOKnull) | |
87 { | |
88 e = op_overload(sc); | |
89 if (e) | |
90 { | |
91 if (op == TOK.TOKnotequal) | |
92 { | |
93 e = new NotExp(e.loc, e); | |
94 e = e.semantic(sc); | |
95 } | |
96 | |
97 return e; | |
98 } | |
99 } | |
100 | |
79 | 101 // Disallow comparing T[]==T and T==T[] |
102 if (e1.op == TOKslice && t1.ty == Tarray && e2.implicitConvTo(t1.nextOf()) || | |
103 e2.op == TOKslice && t2.ty == Tarray && e1.implicitConvTo(t2.nextOf())) | |
104 { | |
105 incompatibleTypes(); | |
106 return new ErrorExp(); | |
107 } | |
108 | |
0 | 109 e = typeCombine(sc); |
110 type = Type.tboolean; | |
111 | |
112 // Special handling for array comparisons | |
113 if (!arrayTypeCompatible(loc, e1.type, e2.type)) | |
114 { | |
115 if (e1.type != e2.type && e1.type.isfloating() && e2.type.isfloating()) | |
116 { | |
117 // Cast both to complex | |
118 e1 = e1.castTo(sc, Type.tcomplex80); | |
119 e2 = e2.castTo(sc, Type.tcomplex80); | |
120 } | |
121 } | |
122 | |
123 return e; | |
124 } | |
125 | |
72 | 126 override Expression optimize(int result) |
0 | 127 { |
128 Expression e; | |
129 | |
130 //printf("EqualExp::optimize(result = %x) %s\n", result, toChars()); | |
131 e1 = e1.optimize(WANTvalue | (result & WANTinterpret)); | |
132 e2 = e2.optimize(WANTvalue | (result & WANTinterpret)); | |
133 e = this; | |
134 | |
135 Expression e1 = fromConstInitializer(result, this.e1); | |
136 Expression e2 = fromConstInitializer(result, this.e2); | |
137 | |
138 e = Equal(op, type, e1, e2); | |
139 if (e is EXP_CANT_INTERPRET) | |
140 e = this; | |
141 return e; | |
142 } | |
143 | |
72 | 144 override Expression interpret(InterState istate) |
0 | 145 { |
115
6caaf0256da1
+ interpretation of (non-assign) binary expressions
Trass3r
parents:
114
diff
changeset
|
146 return interpretCommon2(istate, &Equal); |
0 | 147 } |
148 | |
115
6caaf0256da1
+ interpretation of (non-assign) binary expressions
Trass3r
parents:
114
diff
changeset
|
149 override bool isBit() |
0 | 150 { |
115
6caaf0256da1
+ interpretation of (non-assign) binary expressions
Trass3r
parents:
114
diff
changeset
|
151 return true; |
0 | 152 } |
153 | |
72 | 154 override bool isCommutative() |
0 | 155 { |
156 return true; | |
157 } | |
158 | |
72 | 159 override Identifier opId() |
0 | 160 { |
161 return Id.eq; | |
162 } | |
163 | |
72 | 164 override elem* toElem(IRState* irs) |
0 | 165 { |
166 //printf("EqualExp::toElem() %s\n", toChars()); | |
167 elem* e; | |
168 OPER eop; | |
169 Type t1 = e1.type.toBasetype(); | |
170 Type t2 = e2.type.toBasetype(); | |
171 | |
172 switch (op) | |
173 { | |
174 case TOKequal: eop = OPeqeq; break; | |
175 case TOKnotequal: eop = OPne; break; | |
176 default: | |
177 dump(0); | |
178 assert(0); | |
179 } | |
180 | |
181 //printf("EqualExp::toElem()\n"); | |
182 if (t1.ty == Tstruct) | |
183 { // Do bit compare of struct's | |
184 elem* es1; | |
185 elem* es2; | |
186 elem* ecount; | |
187 | |
188 es1 = e1.toElem(irs); | |
189 es2 = e2.toElem(irs); | |
190 static if (true) { | |
191 es1 = addressElem(es1, t1); | |
192 es2 = addressElem(es2, t2); | |
193 } else { | |
194 es1 = el_una(OPaddr, TYnptr, es1); | |
195 es2 = el_una(OPaddr, TYnptr, es2); | |
196 } | |
197 e = el_param(es1, es2); | |
198 ecount = el_long(TYint, t1.size()); | |
199 e = el_bin(OPmemcmp, TYint, e, ecount); | |
200 e = el_bin(eop, TYint, e, el_long(TYint, 0)); | |
201 el_setLoc(e,loc); | |
202 } | |
203 /// static if (false) { | |
204 /// else if (t1.ty == Tclass && t2.ty == Tclass) | |
205 /// { | |
206 /// elem *ec1; | |
207 /// elem *ec2; | |
208 /// | |
209 /// ec1 = e1.toElem(irs); | |
210 /// ec2 = e2.toElem(irs); | |
211 /// e = el_bin(OPcall,TYint,el_var(rtlsym[RTLSYM_OBJ_EQ]),el_param(ec1, ec2)); | |
212 /// } | |
213 /// } | |
214 else if ((t1.ty == Tarray || t1.ty == Tsarray) && | |
215 (t2.ty == Tarray || t2.ty == Tsarray)) | |
216 { | |
217 elem* ea1; | |
218 elem* ea2; | |
219 elem* ep; | |
220 Type telement = t1.nextOf().toBasetype(); | |
221 int rtlfunc; | |
222 | |
223 ea1 = e1.toElem(irs); | |
224 ea1 = array_toDarray(t1, ea1); | |
225 ea2 = e2.toElem(irs); | |
226 ea2 = array_toDarray(t2, ea2); | |
227 | |
228 version (DMDV2) { | |
229 ep = el_params(telement.arrayOf().getInternalTypeInfo(null).toElem(irs), | |
230 ea2, ea1, null); | |
231 rtlfunc = RTLSYM_ARRAYEQ2; | |
232 } else { | |
233 ep = el_params(telement.getInternalTypeInfo(null).toElem(irs), ea2, ea1, null); | |
234 rtlfunc = RTLSYM_ARRAYEQ; | |
235 } | |
236 e = el_bin(OPcall, TYint, el_var(rtlsym[rtlfunc]), ep); | |
237 if (op == TOKnotequal) | |
238 e = el_bin(OPxor, TYint, e, el_long(TYint, 1)); | |
239 el_setLoc(e,loc); | |
240 } | |
241 else | |
242 e = toElemBin(irs, eop); | |
243 | |
244 return e; | |
245 } | |
246 } | |
247 |