comparison dmd/CompoundStatement.d @ 0:10317f0c89a5

Initial commit
author korDen
date Sat, 24 Oct 2009 08:42:06 +0400
parents
children 3f834bed4f13
comparison
equal deleted inserted replaced
-1:000000000000 0:10317f0c89a5
1 module dmd.CompoundStatement;
2
3 import dmd.Loc;
4 import dmd.Statement;
5 import dmd.Array;
6 import dmd.TryCatchStatement;
7 import dmd.TryFinallyStatement;
8 import dmd.Catch;
9 import dmd.ScopeStatement;
10 import dmd.Identifier;
11 import dmd.Lexer;
12 import dmd.ThrowStatement;
13 import dmd.IdentifierExp;
14 import dmd.Scope;
15 import dmd.OutBuffer;
16 import dmd.HdrGenState;
17 import dmd.ArrayTypes;
18 import dmd.ReturnStatement;
19 import dmd.Expression;
20 import dmd.InterState;
21 import dmd.InlineDoState;
22 import dmd.InlineCostState;
23 import dmd.InlineScanState;
24 import dmd.IfStatement;
25 import dmd.IRState;
26 import dmd.BE;
27 import dmd.Util;
28
29 class CompoundStatement : Statement
30 {
31 Statements statements;
32
33 this(Loc loc, Statements s)
34 {
35 super(loc);
36 statements = s;
37 }
38
39 this(Loc loc, Statement s1, Statement s2)
40 {
41 super(loc);
42
43 statements = new Statements();
44 statements.reserve(2);
45 statements.push(cast(void*)s1);
46 statements.push(cast(void*)s2);
47 }
48
49 Statement syntaxCopy()
50 {
51 Statements a = new Statements();
52 a.setDim(statements.dim);
53
54 for (size_t i = 0; i < statements.dim; i++)
55 {
56 Statement s = cast(Statement)statements.data[i];
57 if (s)
58 s = s.syntaxCopy();
59 a.data[i] = cast(void*)s;
60 }
61
62 return new CompoundStatement(loc, a);
63 }
64
65 void toCBuffer(OutBuffer buf, HdrGenState* hgs)
66 {
67 assert(false);
68 }
69
70 static int indent = 0;
71 static int depth = 0;
72
73 Statement semantic(Scope sc)
74 {
75 Statement s;
76
77 //printf("CompoundStatement.semantic(this = %p, sc = %p)\n", this, sc);
78
79 for (size_t i = 0; i < statements.dim; )
80 {
81 s = cast(Statement) statements.data[i];
82 if (s)
83 {
84 Statements a = s.flatten(sc);
85
86 if (a)
87 {
88 statements.remove(i);
89 statements.insert(i, a);
90 continue;
91 }
92
93 s = s.semantic(sc);
94
95 statements.data[i] = cast(void*)s;
96 if (s)
97 {
98 Statement sentry;
99 Statement sexception;
100 Statement sfinally;
101
102 s.scopeCode(sc, &sentry, &sexception, &sfinally);
103 if (sentry)
104 {
105 sentry = sentry.semantic(sc);
106 if (s.isDeclarationStatement())
107 {
108 statements.insert(i, cast(void*)sentry);
109 i++;
110 }
111 else
112 statements.data[i] = cast(void*)sentry;
113 }
114 if (sexception)
115 {
116 if (i + 1 == statements.dim && !sfinally)
117 {
118 static if (true) {
119 sexception = sexception.semantic(sc);
120 } else {
121 statements.push(sexception);
122 if (sfinally)
123 // Assume sexception does not throw
124 statements.push(sfinally);
125 }
126 }
127 else
128 {
129 /* Rewrite:
130 * s; s1; s2;
131 * As:
132 * s;
133 * try { s1; s2; }
134 * catch (Object __o)
135 * { sexception; throw __o; }
136 */
137 Statement body_;
138 Statements aa = new Statements();
139
140 for (int j = i + 1; j < statements.dim; j++)
141 {
142 aa.push(statements.data[j]);
143 }
144 body_ = new CompoundStatement(Loc(0), aa);
145 body_ = new ScopeStatement(Loc(0), body_);
146
147 Identifier id = Lexer.uniqueId("__o");
148
149 Statement handler = new ThrowStatement(Loc(0), new IdentifierExp(Loc(0), id));
150 handler = new CompoundStatement(Loc(0), sexception, handler);
151
152 Array catches = new Array();
153 Catch ctch = new Catch(Loc(0), null, id, handler);
154 catches.push(cast(void*)ctch);
155 s = new TryCatchStatement(Loc(0), body_, catches);
156
157 if (sfinally)
158 s = new TryFinallyStatement(Loc(0), s, sfinally);
159 s = s.semantic(sc);
160 statements.setDim(i + 1);
161 statements.push(cast(void*)s);
162 break;
163 }
164 }
165 else if (sfinally)
166 {
167 if (0 && i + 1 == statements.dim)
168 {
169 statements.push(cast(void*)sfinally);
170 }
171 else
172 {
173 /* Rewrite:
174 * s; s1; s2;
175 * As:
176 * s; try { s1; s2; } finally { sfinally; }
177 */
178 Statement body_;
179 Statements aa = new Statements();
180
181 for (int j = i + 1; j < statements.dim; j++)
182 {
183 aa.push(statements.data[j]);
184 }
185 body_ = new CompoundStatement(Loc(0), aa);
186 s = new TryFinallyStatement(Loc(0), body_, sfinally);
187 s = s.semantic(sc);
188 statements.setDim(i + 1);
189 statements.push(cast(void*)s);
190 break;
191 }
192 }
193 }
194 }
195 i++;
196 }
197 if (statements.dim == 1)
198 {
199 return cast(Statement)statements.data[0];
200 }
201 return this;
202 }
203
204 bool usesEH()
205 {
206 assert(false);
207 }
208
209 BE blockExit()
210 {
211 //printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim);
212 BE result = BE.BEfallthru;
213 for (size_t i = 0; i < statements.dim; i++)
214 { Statement s = cast(Statement)statements.data[i];
215 if (s)
216 {
217 //printf("result = x%x\n", result);
218 //printf("%s\n", s->toChars());
219 if (!(result & BE.BEfallthru) && !s.comeFrom())
220 {
221 if (s.blockExit() != BE.BEhalt)
222 s.warning("statement is not reachable");
223 }
224
225 result &= ~BE.BEfallthru;
226 result |= s.blockExit();
227 }
228 }
229
230 return result;
231 }
232
233 bool comeFrom()
234 {
235 assert(false);
236 }
237
238 bool isEmpty()
239 {
240 for (int i = 0; i < statements.dim; i++)
241 {
242 Statement s = cast(Statement) statements.data[i];
243 if (s && !s.isEmpty())
244 return false;
245 }
246 return true;
247 }
248
249 Statements flatten(Scope sc)
250 {
251 return statements;
252 }
253
254 ReturnStatement isReturnStatement()
255 {
256 ReturnStatement rs = null;
257
258 for (int i = 0; i < statements.dim; i++)
259 {
260 Statement s = cast(Statement) statements.data[i];
261 if (s)
262 {
263 rs = s.isReturnStatement();
264 if (rs)
265 break;
266 }
267 }
268 return rs;
269 }
270
271 Expression interpret(InterState* istate)
272 {
273 assert(false);
274 }
275
276 int inlineCost(InlineCostState* ics)
277 {
278 int cost = 0;
279
280 for (size_t i = 0; i < statements.dim; i++)
281 {
282 Statement s = cast(Statement)statements.data[i];
283 if (s)
284 {
285 cost += s.inlineCost(ics);
286 if (cost >= COST_MAX)
287 break;
288 }
289 }
290
291 return cost;
292 }
293
294 Expression doInline(InlineDoState ids)
295 {
296 Expression e = null;
297
298 //printf("CompoundStatement.doInline() %d\n", statements.dim);
299 for (size_t i = 0; i < statements.dim; i++)
300 {
301 Statement s = cast(Statement)statements.data[i];
302 if (s)
303 {
304 Expression e2 = s.doInline(ids);
305 e = Expression.combine(e, e2);
306 if (s.isReturnStatement())
307 break;
308
309 /* Check for:
310 * if (condition)
311 * return exp1;
312 * else
313 * return exp2;
314 */
315 IfStatement ifs = s.isIfStatement();
316 if (ifs && ifs.elsebody && ifs.ifbody &&
317 ifs.ifbody.isReturnStatement() &&
318 ifs.elsebody.isReturnStatement()
319 )
320 break;
321 }
322 }
323 return e;
324 }
325
326 Statement inlineScan(InlineScanState* iss)
327 {
328 for (size_t i = 0; i < statements.dim; i++)
329 {
330 Statement s = cast(Statement) statements.data[i];
331 if (s)
332 statements.data[i] = cast(void*)s.inlineScan(iss);
333 }
334
335 return this;
336 }
337
338 void toIR(IRState* irs)
339 {
340 if (statements)
341 {
342 size_t dim = statements.dim;
343 for (size_t i = 0 ; i < dim ; i++)
344 {
345 Statement s = cast(Statement)statements.data[i];
346 if (s !is null)
347 {
348 s.toIR(irs);
349 }
350 }
351 }
352 }
353
354 CompoundStatement isCompoundStatement() { return this; }
355 }