Mercurial > projects > ddmd
annotate dmd/CondExp.d @ 178:e3afd1303184
Many small bugs fixed
Made all classes derive from TObject to detect memory leaks (functionality is disabled for now)
Began work on overriding backend memory allocations (to avoid memory leaks)
author | korDen |
---|---|
date | Sun, 17 Oct 2010 07:42:00 +0400 |
parents | af1bebfd96a4 |
children | b0d41ff5e0df |
rev | line source |
---|---|
0 | 1 module dmd.CondExp; |
2 | |
114 | 3 import dmd.common; |
0 | 4 import dmd.BinExp; |
5 import dmd.Loc; | |
123 | 6 import dmd.PtrExp; |
0 | 7 import dmd.MATCH; |
8 import dmd.Expression; | |
129 | 9 import dmd.GlobalExpressions; |
0 | 10 import dmd.Scope; |
11 import dmd.InterState; | |
12 import dmd.OutBuffer; | |
13 import dmd.HdrGenState; | |
14 import dmd.Type; | |
15 import dmd.InlineCostState; | |
16 import dmd.InlineDoState; | |
17 import dmd.InlineScanState; | |
18 import dmd.IRState; | |
19 import dmd.TOK; | |
20 import dmd.TY; | |
21 import dmd.WANT; | |
50 | 22 import dmd.PREC; |
0 | 23 import dmd.Global; |
24 | |
25 import dmd.backend.elem; | |
26 import dmd.backend.Util; | |
27 import dmd.backend.OPER; | |
28 import dmd.backend.mTY; | |
29 import dmd.backend.TYM; | |
30 import dmd.codegen.Util; | |
31 | |
50 | 32 import dmd.expression.Util; |
33 | |
0 | 34 class CondExp : BinExp |
35 { | |
36 Expression econd; | |
37 | |
38 this(Loc loc, Expression econd, Expression e1, Expression e2) | |
39 { | |
178 | 40 register(); |
0 | 41 super(loc, TOK.TOKquestion, CondExp.sizeof, e1, e2); |
42 this.econd = econd; | |
43 } | |
44 | |
72 | 45 override Expression syntaxCopy() |
0 | 46 { |
43 | 47 return new CondExp(loc, econd.syntaxCopy(), e1.syntaxCopy(), e2.syntaxCopy()); |
0 | 48 } |
49 | |
72 | 50 override Expression semantic(Scope sc) |
0 | 51 { |
52 Type t1; | |
53 Type t2; | |
54 uint cs0; | |
55 uint cs1; | |
56 | |
57 version (LOGSEMANTIC) { | |
58 printf("CondExp.semantic('%s')\n", toChars()); | |
59 } | |
60 if (type) | |
61 return this; | |
62 | |
63 econd = econd.semantic(sc); | |
64 econd = resolveProperties(sc, econd); | |
65 econd = econd.checkToPointer(); | |
66 econd = econd.checkToBoolean(); | |
67 | |
68 static if (false) { | |
69 /* this cannot work right because the types of e1 and e2 | |
70 * both contribute to the type of the result. | |
71 */ | |
72 if (sc.flags & SCOPEstaticif) | |
73 { | |
74 /* If in static if, don't evaluate what we don't have to. | |
75 */ | |
76 econd = econd.optimize(WANTflags); | |
77 if (econd.isBool(TRUE)) | |
78 { | |
79 e1 = e1.semantic(sc); | |
80 e1 = resolveProperties(sc, e1); | |
81 return e1; | |
82 } | |
83 else if (econd.isBool(FALSE)) | |
84 { | |
85 e2 = e2.semantic(sc); | |
86 e2 = resolveProperties(sc, e2); | |
87 return e2; | |
88 } | |
89 } | |
90 } | |
91 | |
92 cs0 = sc.callSuper; | |
93 e1 = e1.semantic(sc); | |
94 e1 = resolveProperties(sc, e1); | |
95 cs1 = sc.callSuper; | |
96 sc.callSuper = cs0; | |
97 e2 = e2.semantic(sc); | |
98 e2 = resolveProperties(sc, e2); | |
99 sc.mergeCallSuper(loc, cs1); | |
100 | |
101 // If either operand is void, the result is void | |
102 t1 = e1.type; | |
103 t2 = e2.type; | |
104 if (t1.ty == Tvoid || t2.ty == Tvoid) | |
105 type = Type.tvoid; | |
106 else if (t1 == t2) | |
107 type = t1; | |
108 else | |
109 { | |
110 typeCombine(sc); | |
111 switch (e1.type.toBasetype().ty) | |
112 { | |
113 case Tcomplex32: | |
114 case Tcomplex64: | |
115 case Tcomplex80: | |
116 e2 = e2.castTo(sc, e1.type); | |
117 break; | |
118 default: | |
119 break; | |
120 } | |
121 switch (e2.type.toBasetype().ty) | |
122 { | |
123 case Tcomplex32: | |
124 case Tcomplex64: | |
125 case Tcomplex80: | |
126 e1 = e1.castTo(sc, e2.type); | |
127 break; | |
128 default: | |
129 break; | |
130 } | |
131 if (type.toBasetype().ty == Tarray) | |
132 { | |
133 e1 = e1.castTo(sc, type); | |
134 e2 = e2.castTo(sc, type); | |
135 } | |
136 } | |
137 static if (false) { | |
138 printf("res: %s\n", type.toChars()); | |
139 printf("e1 : %s\n", e1.type.toChars()); | |
140 printf("e2 : %s\n", e2.type.toChars()); | |
141 } | |
142 return this; | |
143 } | |
144 | |
72 | 145 override Expression optimize(int result) |
0 | 146 { |
147 Expression e; | |
148 | |
149 econd = econd.optimize(WANTflags | (result & WANTinterpret)); | |
150 if (econd.isBool(true)) | |
151 e = e1.optimize(result); | |
152 else if (econd.isBool(false)) | |
153 e = e2.optimize(result); | |
154 else | |
155 { | |
156 e1 = e1.optimize(result); | |
157 e2 = e2.optimize(result); | |
158 e = this; | |
159 } | |
160 | |
161 return e; | |
162 } | |
163 | |
72 | 164 override Expression interpret(InterState istate) |
0 | 165 { |
129 | 166 version (LOG) { |
167 printf("CondExp.interpret() %.*s\n", toChars()); | |
168 } | |
169 Expression e = econd.interpret(istate); | |
170 if (e !is EXP_CANT_INTERPRET) | |
171 { | |
172 if (e.isBool(true)) | |
173 e = e1.interpret(istate); | |
174 else if (e.isBool(false)) | |
175 e = e2.interpret(istate); | |
176 else | |
177 e = EXP_CANT_INTERPRET; | |
178 } | |
179 return e; | |
0 | 180 } |
181 | |
72 | 182 override void checkEscape() |
0 | 183 { |
184 e1.checkEscape(); | |
185 e2.checkEscape(); | |
186 } | |
187 | |
135 | 188 override void checkEscapeRef() |
189 { | |
190 e1.checkEscapeRef(); | |
191 e2.checkEscapeRef(); | |
192 } | |
193 | |
72 | 194 override int isLvalue() |
0 | 195 { |
123 | 196 return e1.isLvalue() && e2.isLvalue(); |
0 | 197 } |
198 | |
123 | 199 override Expression toLvalue(Scope sc, Expression ex) |
0 | 200 { |
123 | 201 PtrExp e; |
202 | |
203 // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2) | |
204 e = new PtrExp(loc, this, type); | |
205 | |
206 e1 = e1.addressOf(sc); | |
207 //e1 = e1.toLvalue(sc, null); | |
208 | |
209 e2 = e2.addressOf(sc); | |
210 //e2 = e2.toLvalue(sc, null); | |
211 | |
212 typeCombine(sc); | |
213 | |
214 type = e2.type; | |
215 return e; | |
0 | 216 } |
217 | |
72 | 218 override Expression modifiableLvalue(Scope sc, Expression e) |
0 | 219 { |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
220 //error("conditional expression %s is not a modifiable lvalue", toChars()); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
221 e1 = e1.modifiableLvalue(sc, e1); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
222 e2 = e2.modifiableLvalue(sc, e1); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
223 return toLvalue(sc, this); |
0 | 224 } |
225 | |
72 | 226 override Expression checkToBoolean() |
0 | 227 { |
123 | 228 e1 = e1.checkToBoolean(); |
229 e2 = e2.checkToBoolean(); | |
230 return this; | |
0 | 231 } |
232 | |
72 | 233 override bool checkSideEffect(int flag) |
0 | 234 { |
64 | 235 if (flag == 2) |
236 { | |
237 return econd.checkSideEffect(2) || e1.checkSideEffect(2) || e2.checkSideEffect(2); | |
238 } | |
239 else | |
240 { | |
241 econd.checkSideEffect(1); | |
242 e1.checkSideEffect(flag); | |
243 return e2.checkSideEffect(flag); | |
244 } | |
0 | 245 } |
246 | |
72 | 247 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 248 { |
50 | 249 expToCBuffer(buf, hgs, econd, PREC_oror); |
250 buf.writestring(" ? "); | |
251 expToCBuffer(buf, hgs, e1, PREC_expr); | |
252 buf.writestring(" : "); | |
253 expToCBuffer(buf, hgs, e2, PREC_cond); | |
0 | 254 } |
255 | |
72 | 256 override MATCH implicitConvTo(Type t) |
0 | 257 { |
258 MATCH m1 = e1.implicitConvTo(t); | |
259 MATCH m2 = e2.implicitConvTo(t); | |
260 //printf("CondExp: m1 %d m2 %d\n", m1, m2); | |
261 | |
262 // Pick the worst match | |
263 return (m1 < m2) ? m1 : m2; | |
264 } | |
265 | |
72 | 266 override Expression castTo(Scope sc, Type t) |
0 | 267 { |
268 Expression e = this; | |
269 | |
270 if (type !is t) | |
271 { | |
272 if (1 || e1.op == TOKstring || e2.op == TOKstring) | |
273 { | |
274 e = new CondExp(loc, econd, e1.castTo(sc, t), e2.castTo(sc, t)); | |
275 e.type = t; | |
276 } | |
277 else | |
278 e = Expression.castTo(sc, t); | |
279 } | |
280 return e; | |
281 } | |
282 | |
72 | 283 override void scanForNestedRef(Scope sc) |
0 | 284 { |
285 assert(false); | |
286 } | |
287 | |
72 | 288 override bool canThrow() |
0 | 289 { |
290 return econd.canThrow() || e1.canThrow() || e2.canThrow(); | |
291 } | |
292 | |
72 | 293 override int inlineCost(InlineCostState* ics) |
0 | 294 { |
295 return 1 + e1.inlineCost(ics) + e2.inlineCost(ics) + econd.inlineCost(ics); | |
296 } | |
297 | |
72 | 298 override Expression doInline(InlineDoState ids) |
0 | 299 { |
300 CondExp ce = cast(CondExp)copy(); | |
301 | |
302 ce.econd = econd.doInline(ids); | |
303 ce.e1 = e1.doInline(ids); | |
304 ce.e2 = e2.doInline(ids); | |
305 return ce; | |
306 } | |
307 | |
72 | 308 override Expression inlineScan(InlineScanState* iss) |
0 | 309 { |
310 econd = econd.inlineScan(iss); | |
311 e1 = e1.inlineScan(iss); | |
312 e2 = e2.inlineScan(iss); | |
313 return this; | |
314 } | |
315 | |
72 | 316 override elem* toElem(IRState* irs) |
0 | 317 { |
318 elem* eleft; | |
319 elem* eright; | |
320 | |
321 elem* ec = econd.toElem(irs); | |
322 | |
323 eleft = e1.toElem(irs); | |
324 tym_t ty = eleft.Ety; | |
325 if (global.params.cov && e1.loc.linnum) | |
326 eleft = el_combine(incUsageElem(irs, e1.loc), eleft); | |
327 | |
328 eright = e2.toElem(irs); | |
329 if (global.params.cov && e2.loc.linnum) | |
330 eright = el_combine(incUsageElem(irs, e2.loc), eright); | |
331 | |
332 elem* e = el_bin(OPcond, ty, ec, el_bin(OPcolon, ty, eleft, eright)); | |
333 if (tybasic(ty) == TYstruct) | |
334 e.Enumbytes = cast(uint)e1.type.size(); | |
335 | |
336 el_setLoc(e, loc); | |
337 return e; | |
338 } | |
72 | 339 } |