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