Mercurial > projects > ddmd
annotate dmd/ForStatement.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 |
---|---|
0 | 1 module dmd.ForStatement; |
2 | |
114 | 3 import dmd.common; |
0 | 4 import dmd.Statement; |
5 import dmd.Expression; | |
123 | 6 import dmd.GlobalExpressions; |
0 | 7 import dmd.Loc; |
8 import dmd.Scope; | |
9 import dmd.InterState; | |
10 import dmd.OutBuffer; | |
11 import dmd.HdrGenState; | |
12 import dmd.InlineScanState; | |
13 import dmd.WANT; | |
14 import dmd.ScopeDsymbol; | |
15 import dmd.IRState; | |
16 import dmd.BE; | |
17 | |
18 import dmd.backend.Blockx; | |
19 import dmd.backend.block; | |
20 import dmd.backend.Util; | |
21 import dmd.backend.BC; | |
22 | |
187
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
178
diff
changeset
|
23 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
|
24 |
0 | 25 class ForStatement : Statement |
26 { | |
187
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
178
diff
changeset
|
27 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
|
28 |
0 | 29 Statement init; |
30 Expression condition; | |
31 Expression increment; | |
32 Statement body_; | |
33 | |
34 this(Loc loc, Statement init, Expression condition, Expression increment, Statement body_) | |
35 { | |
178 | 36 register(); |
0 | 37 super(loc); |
38 | |
39 this.init = init; | |
40 this.condition = condition; | |
41 this.increment = increment; | |
42 this.body_ = body_; | |
43 } | |
44 | |
72 | 45 override Statement syntaxCopy() |
0 | 46 { |
47 Statement i = null; | |
48 if (init) | |
49 i = init.syntaxCopy(); | |
50 Expression c = null; | |
51 if (condition) | |
52 c = condition.syntaxCopy(); | |
53 Expression inc = null; | |
54 if (increment) | |
55 inc = increment.syntaxCopy(); | |
56 ForStatement s = new ForStatement(loc, i, c, inc, body_.syntaxCopy()); | |
57 return s; | |
58 } | |
59 | |
72 | 60 override Statement semantic(Scope sc) |
0 | 61 { |
62 ScopeDsymbol sym = new ScopeDsymbol(); | |
63 sym.parent = sc.scopesym; | |
64 sc = sc.push(sym); | |
65 if (init) | |
66 init = init.semantic(sc); | |
67 sc.noctor++; | |
68 if (condition) | |
69 { | |
70 condition = condition.semantic(sc); | |
71 condition = resolveProperties(sc, condition); | |
72 condition = condition.optimize(WANTvalue); | |
73 condition = condition.checkToBoolean(); | |
74 } | |
75 if (increment) | |
76 { | |
77 increment = increment.semantic(sc); | |
78 increment = resolveProperties(sc, increment); | |
79 | 79 increment = increment.optimize(0); |
0 | 80 } |
81 | |
82 sc.sbreak = this; | |
83 sc.scontinue = this; | |
84 if (body_) | |
85 body_ = body_.semantic(sc); | |
86 sc.noctor--; | |
87 | |
88 sc.pop(); | |
89 return this; | |
90 } | |
91 | |
72 | 92 override void scopeCode(Scope sc, Statement* sentry, Statement* sexception, Statement* sfinally) |
0 | 93 { |
94 //printf("ForStatement::scopeCode()\n"); | |
95 //print(); | |
96 if (init) | |
97 init.scopeCode(sc, sentry, sexception, sfinally); | |
98 else | |
99 Statement.scopeCode(sc, sentry, sexception, sfinally); | |
100 } | |
101 | |
72 | 102 override bool hasBreak() |
0 | 103 { |
104 //printf("ForStatement.hasBreak()\n"); | |
105 return true; | |
106 } | |
107 | |
72 | 108 override bool hasContinue() |
0 | 109 { |
110 return true; | |
111 } | |
112 | |
72 | 113 override bool usesEH() |
0 | 114 { |
115 return (init && init.usesEH()) || body_.usesEH(); | |
116 } | |
117 | |
72 | 118 override BE blockExit() |
0 | 119 { |
120 BE result = BE.BEfallthru; | |
121 | |
122 if (init) | |
123 { | |
124 result = init.blockExit(); | |
125 if (!(result & BE.BEfallthru)) | |
126 return result; | |
127 } | |
128 if (condition) | |
129 { | |
130 if (condition.canThrow()) | |
131 result |= BE.BEthrow; | |
132 if (condition.isBool(true)) | |
133 result &= ~BE.BEfallthru; | |
134 else if (condition.isBool(false)) | |
135 return result; | |
136 } | |
137 else | |
138 result &= ~BE.BEfallthru; // the body must do the exiting | |
139 if (body_) | |
140 { | |
141 int r = body_.blockExit(); | |
142 if (r & (BE.BEbreak | BE.BEgoto)) | |
143 result |= BE.BEfallthru; | |
144 result |= r & ~(BE.BEfallthru | BE.BEbreak | BE.BEcontinue); | |
145 } | |
146 if (increment && increment.canThrow()) | |
147 result |= BE.BEthrow; | |
148 return result; | |
149 } | |
150 | |
72 | 151 override bool comeFrom() |
0 | 152 { |
153 //printf("ForStatement.comeFrom()\n"); | |
154 if (body_) | |
155 { | |
156 bool result = body_.comeFrom(); | |
157 //printf("result = %d\n", result); | |
158 return result; | |
159 } | |
160 return false; | |
161 } | |
162 | |
72 | 163 override Expression interpret(InterState istate) |
0 | 164 { |
123 | 165 version (LOG) { |
166 printf("ForStatement.interpret()\n"); | |
167 } | |
168 if (istate.start == this) | |
169 istate.start = null; | |
170 | |
171 Expression e; | |
172 | |
173 if (init) | |
174 { | |
175 e = init.interpret(istate); | |
176 if (e is EXP_CANT_INTERPRET) | |
177 return e; | |
178 assert(!e); | |
179 } | |
180 | |
181 if (istate.start) | |
182 { | |
183 e = body_ ? body_.interpret(istate) : null; | |
184 if (istate.start) | |
185 return null; | |
186 if (e is EXP_CANT_INTERPRET) | |
187 return e; | |
188 if (e is EXP_BREAK_INTERPRET) | |
189 return null; | |
190 if (e is EXP_CONTINUE_INTERPRET) | |
191 goto Lcontinue; | |
192 if (e) | |
193 return e; | |
194 } | |
195 | |
196 while (true) | |
197 { | |
198 if (!condition) | |
199 goto Lhead; | |
200 e = condition.interpret(istate); | |
201 if (e is EXP_CANT_INTERPRET) | |
202 break; | |
203 if (!e.isConst()) | |
204 { | |
205 e = EXP_CANT_INTERPRET; | |
206 break; | |
207 } | |
208 if (e.isBool(true)) | |
209 { | |
210 Lhead: | |
211 e = body_ ? body_.interpret(istate) : null; | |
212 if (e is EXP_CANT_INTERPRET) | |
213 break; | |
214 if (e is EXP_BREAK_INTERPRET) | |
215 { | |
216 e = null; | |
217 break; | |
218 } | |
219 if (e && e !is EXP_CONTINUE_INTERPRET) | |
220 break; | |
221 Lcontinue: | |
222 if (increment) | |
223 { | |
224 e = increment.interpret(istate); | |
225 if (e is EXP_CANT_INTERPRET) | |
226 break; | |
227 } | |
228 } | |
229 else if (e.isBool(false)) | |
230 { | |
231 e = null; | |
232 break; | |
233 } | |
234 else | |
235 assert(0); | |
236 } | |
237 return e; | |
0 | 238 } |
239 | |
72 | 240 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 241 { |
242 buf.writestring("for ("); | |
243 if (init) | |
244 { | |
245 hgs.FLinit.init++; | |
246 init.toCBuffer(buf, hgs); | |
247 hgs.FLinit.init--; | |
248 } | |
249 else | |
250 buf.writebyte(';'); | |
251 if (condition) | |
252 { buf.writebyte(' '); | |
253 condition.toCBuffer(buf, hgs); | |
254 } | |
255 buf.writebyte(';'); | |
256 if (increment) | |
257 { | |
258 buf.writebyte(' '); | |
259 increment.toCBuffer(buf, hgs); | |
260 } | |
261 buf.writebyte(')'); | |
262 buf.writenl(); | |
263 buf.writebyte('{'); | |
264 buf.writenl(); | |
265 body_.toCBuffer(buf, hgs); | |
266 buf.writebyte('}'); | |
267 buf.writenl(); | |
268 } | |
269 | |
72 | 270 override Statement inlineScan(InlineScanState* iss) |
0 | 271 { |
272 if (init) | |
273 init = init.inlineScan(iss); | |
274 if (condition) | |
275 condition = condition.inlineScan(iss); | |
276 if (increment) | |
277 increment = increment.inlineScan(iss); | |
278 if (body_) | |
279 body_ = body_.inlineScan(iss); | |
280 return this; | |
281 } | |
282 | |
72 | 283 override void toIR(IRState* irs) |
0 | 284 { |
285 Blockx* blx = irs.blx; | |
286 | |
287 IRState mystate = IRState(irs,this); | |
288 mystate.breakBlock = block_calloc(blx); | |
289 mystate.contBlock = block_calloc(blx); | |
290 | |
291 if (init) | |
292 init.toIR(&mystate); | |
293 block* bpre = blx.curblock; | |
294 block_next(blx,BCgoto,null); | |
295 block* bcond = blx.curblock; | |
296 list_append(&bpre.Bsucc, bcond); | |
297 list_append(&mystate.contBlock.Bsucc, bcond); | |
298 if (condition) | |
299 { | |
300 incUsage(irs, condition.loc); | |
301 block_appendexp(bcond, condition.toElem(&mystate)); | |
302 block_next(blx,BCiftrue,null); | |
303 list_append(&bcond.Bsucc, blx.curblock); | |
304 list_append(&bcond.Bsucc, mystate.breakBlock); | |
305 } | |
306 else | |
307 { | |
308 /* No conditional, it's a straight goto | |
309 */ | |
310 block_next(blx,BCgoto,null); | |
311 list_append(&bcond.Bsucc, blx.curblock); | |
312 } | |
313 | |
314 if (body_) | |
315 body_.toIR(&mystate); | |
316 /* End of the body goes to the continue block | |
317 */ | |
318 list_append(&blx.curblock.Bsucc, mystate.contBlock); | |
319 block_next(blx, BCgoto, mystate.contBlock); | |
320 | |
321 if (increment) | |
322 { | |
323 incUsage(irs, increment.loc); | |
324 block_appendexp(mystate.contBlock, increment.toElem(&mystate)); | |
325 } | |
326 | |
327 /* The 'break' block follows the for statement. | |
328 */ | |
329 block_next(blx,BCgoto, mystate.breakBlock); | |
330 } | |
72 | 331 } |