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