Mercurial > projects > ddmd
annotate dmd/CmpExp.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 | e3afd1303184 |
rev | line source |
---|---|
72 | 1 module dmd.CmpExp; |
2 | |
114 | 3 import dmd.common; |
72 | 4 import dmd.Expression; |
5 import dmd.Identifier; | |
6 import dmd.backend.elem; | |
7 import dmd.InterState; | |
8 import dmd.Loc; | |
9 import dmd.TOK; | |
10 import dmd.Scope; | |
11 import dmd.IRState; | |
0 | 12 import dmd.Type; |
13 import dmd.Id; | |
14 import dmd.TY; | |
15 import dmd.ErrorExp; | |
16 import dmd.IntegerExp; | |
17 import dmd.MATCH; | |
18 import dmd.BinExp; | |
19 import dmd.WANT; | |
20 import dmd.GlobalExpressions; | |
21 | |
22 import dmd.expression.Util; | |
23 import dmd.codegen.Util; | |
24 import dmd.expression.Cmp; | |
25 | |
26 import dmd.backend.Util; | |
27 import dmd.backend.RTLSYM; | |
28 import dmd.backend.TYM; | |
29 import dmd.backend.OPER; | |
72 | 30 import dmd.backend.rel; |
31 | |
0 | 32 class CmpExp : BinExp |
33 { | |
34 this(TOK op, Loc loc, Expression e1, Expression e2) | |
72 | 35 { |
0 | 36 super(loc, op, CmpExp.sizeof, e1, e2); |
37 } | |
38 | |
72 | 39 override Expression semantic(Scope sc) |
0 | 40 { |
41 Expression e; | |
42 | |
43 version (LOGSEMANTIC) { | |
44 printf("CmpExp.semantic('%s')\n", toChars()); | |
45 } | |
46 if (type) | |
47 return this; | |
48 | |
49 BinExp.semanticp(sc); | |
50 | |
79 | 51 Type t1 = e1.type.toBasetype(); |
52 Type t2 = e2.type.toBasetype(); | |
53 if (t1.ty == Tclass && e2.op == TOKnull || | |
54 t2.ty == Tclass && e1.op == TOKnull) | |
0 | 55 { |
56 error("do not use null when comparing class types"); | |
57 } | |
58 | |
59 e = op_overload(sc); | |
60 if (e) | |
61 { | |
62 if (!e.type.isscalar() && e.type.equals(e1.type)) | |
63 { | |
64 error("recursive opCmp expansion"); | |
65 e = new ErrorExp(); | |
66 } | |
67 else | |
68 { | |
69 e = new CmpExp(op, loc, e, new IntegerExp(loc, 0, Type.tint32)); | |
70 e = e.semantic(sc); | |
71 } | |
72 return e; | |
73 } | |
74 | |
79 | 75 // Disallow comparing T[]==T and T==T[] |
76 if (e1.op == TOKslice && t1.ty == Tarray && e2.implicitConvTo(t1.nextOf()) || | |
77 e2.op == TOKslice && t2.ty == Tarray && e1.implicitConvTo(t2.nextOf())) | |
78 { | |
79 incompatibleTypes(); | |
80 return new ErrorExp(); | |
81 } | |
82 | |
0 | 83 typeCombine(sc); |
84 type = Type.tboolean; | |
85 | |
86 // Special handling for array comparisons | |
87 t1 = e1.type.toBasetype(); | |
88 t2 = e2.type.toBasetype(); | |
89 if ((t1.ty == Tarray || t1.ty == Tsarray || t1.ty == Tpointer) && | |
90 (t2.ty == Tarray || t2.ty == Tsarray || t2.ty == Tpointer)) | |
91 { | |
92 if (t1.nextOf().implicitConvTo(t2.nextOf()) < MATCHconst && | |
93 t2.nextOf().implicitConvTo(t1.nextOf()) < MATCHconst && | |
94 (t1.nextOf().ty != Tvoid && t2.nextOf().ty != Tvoid)) | |
95 error("array comparison type mismatch, %s vs %s", t1.nextOf().toChars(), t2.nextOf().toChars()); | |
96 e = this; | |
97 } | |
98 else if (t1.ty == Tstruct || t2.ty == Tstruct || | |
99 (t1.ty == Tclass && t2.ty == Tclass)) | |
100 { | |
101 if (t2.ty == Tstruct) | |
102 error("need member function opCmp() for %s %s to compare", t2.toDsymbol(sc).kind(), t2.toChars()); | |
103 else | |
104 error("need member function opCmp() for %s %s to compare", t1.toDsymbol(sc).kind(), t1.toChars()); | |
105 e = this; | |
106 } | |
107 /// static if (true) { | |
108 else if (t1.iscomplex() || t2.iscomplex()) | |
109 { | |
110 error("compare not defined for complex operands"); | |
111 e = new ErrorExp(); | |
112 } | |
113 /// } | |
114 else | |
115 { | |
116 e1.rvalue(); | |
117 e2.rvalue(); | |
118 e = this; | |
119 } | |
120 | |
121 //printf("CmpExp: %s, type = %s\n", e.toChars(), e.type.toChars()); | |
122 return e; | |
123 } | |
124 | |
72 | 125 override Expression optimize(int result) |
0 | 126 { |
127 Expression e; | |
128 | |
129 //printf("CmpExp::optimize() %s\n", toChars()); | |
130 e1 = e1.optimize(WANTvalue | (result & WANTinterpret)); | |
131 e2 = e2.optimize(WANTvalue | (result & WANTinterpret)); | |
132 | |
133 Expression e1 = fromConstInitializer(result, this.e1); | |
134 Expression e2 = fromConstInitializer(result, this.e2); | |
135 | |
136 e = Cmp(op, type, e1, e2); | |
137 if (e is EXP_CANT_INTERPRET) | |
138 e = this; | |
139 return e; | |
140 } | |
141 | |
72 | 142 override Expression interpret(InterState istate) |
0 | 143 { |
115
6caaf0256da1
+ interpretation of (non-assign) binary expressions
Trass3r
parents:
114
diff
changeset
|
144 return interpretCommon2(istate, &Cmp); |
0 | 145 } |
146 | |
72 | 147 override int isBit() |
0 | 148 { |
149 assert(false); | |
150 } | |
151 | |
72 | 152 override bool isCommutative() |
0 | 153 { |
154 return true; | |
155 } | |
156 | |
72 | 157 override Identifier opId() |
0 | 158 { |
159 return Id.cmp; | |
160 } | |
161 | |
72 | 162 override elem* toElem(IRState* irs) |
0 | 163 { |
164 elem *e; | |
165 OPER eop; | |
166 Type t1 = e1.type.toBasetype(); | |
167 Type t2 = e2.type.toBasetype(); | |
168 | |
169 switch (op) | |
170 { | |
171 case TOKlt: eop = OPlt; break; | |
172 case TOKgt: eop = OPgt; break; | |
173 case TOKle: eop = OPle; break; | |
174 case TOKge: eop = OPge; break; | |
175 case TOKequal: eop = OPeqeq; break; | |
176 case TOKnotequal: eop = OPne; break; | |
177 | |
178 // NCEG floating point compares | |
179 case TOKunord: eop = OPunord; break; | |
180 case TOKlg: eop = OPlg; break; | |
181 case TOKleg: eop = OPleg; break; | |
182 case TOKule: eop = OPule; break; | |
183 case TOKul: eop = OPul; break; | |
184 case TOKuge: eop = OPuge; break; | |
185 case TOKug: eop = OPug; break; | |
186 case TOKue: eop = OPue; break; | |
187 default: | |
188 dump(0); | |
189 assert(0); | |
190 } | |
191 if (!t1.isfloating()) | |
192 { | |
193 // Convert from floating point compare to equivalent | |
194 // integral compare | |
195 eop = cast(OPER)rel_integral(eop); | |
196 } | |
197 if (cast(int)eop > 1 && t1.ty == Tclass && t2.ty == Tclass) | |
198 { | |
199 static if (true) { | |
200 assert(0); | |
201 } else { | |
202 elem *ec1; | |
203 elem *ec2; | |
204 | |
205 ec1 = e1.toElem(irs); | |
206 ec2 = e2.toElem(irs); | |
207 e = el_bin(OPcall,TYint,el_var(rtlsym[RTLSYM_OBJ_CMP]),el_param(ec1, ec2)); | |
208 e = el_bin(eop, TYint, e, el_long(TYint, 0)); | |
209 } | |
210 } | |
211 else if (cast(int)eop > 1 && | |
212 (t1.ty == Tarray || t1.ty == Tsarray) && | |
213 (t2.ty == Tarray || t2.ty == Tsarray)) | |
214 { | |
215 elem* ea1; | |
216 elem* ea2; | |
217 elem* ep; | |
218 Type telement = t1.nextOf().toBasetype(); | |
219 int rtlfunc; | |
220 | |
221 ea1 = e1.toElem(irs); | |
222 ea1 = array_toDarray(t1, ea1); | |
223 ea2 = e2.toElem(irs); | |
224 ea2 = array_toDarray(t2, ea2); | |
225 | |
226 version (DMDV2) { | |
227 ep = el_params(telement.arrayOf().getInternalTypeInfo(null).toElem(irs), | |
228 ea2, ea1, null); | |
229 rtlfunc = RTLSYM_ARRAYCMP2; | |
230 } else { | |
231 ep = el_params(telement.getInternalTypeInfo(null).toElem(irs), ea2, ea1, null); | |
232 rtlfunc = RTLSYM_ARRAYCMP; | |
233 } | |
234 e = el_bin(OPcall, TYint, el_var(rtlsym[rtlfunc]), ep); | |
235 e = el_bin(eop, TYint, e, el_long(TYint, 0)); | |
236 el_setLoc(e,loc); | |
237 } | |
238 else | |
239 { | |
240 if (cast(int)eop <= 1) | |
241 { | |
242 /* The result is determinate, create: | |
243 * (e1 , e2) , eop | |
244 */ | |
245 e = toElemBin(irs,OPcomma); | |
246 e = el_bin(OPcomma,e.Ety,e,el_long(e.Ety,cast(int)eop)); | |
247 } | |
248 else | |
249 e = toElemBin(irs,eop); | |
250 } | |
251 return e; | |
252 } | |
253 } | |
254 |