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