Mercurial > projects > ldc
annotate dmd/statement.c @ 1404:11b122f92136
Now that templates instantiations are no longer emitted for all modules that
even blink at them they seem to break due to being linkonce (if compiled with
any optimization level > 0), so let's give them weak linkage instead.
The difference is that unreferenced linkonce symbols can be deleted, while
weak symbols need to be preserved.
author | Frits van Bommel <fvbommel wxs.nl> |
---|---|
date | Thu, 21 May 2009 15:23:28 +0200 |
parents | 8026319762be |
children | 17268b0a3ab0 |
rev | line source |
---|---|
159 | 1 |
2 // Compiler implementation of the D programming language | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
945
diff
changeset
|
3 // Copyright (c) 1999-2009 by Digital Mars |
159 | 4 // All Rights Reserved |
5 // written by Walter Bright | |
6 // http://www.digitalmars.com | |
7 // License for redistribution is by either the Artistic License | |
8 // in artistic.txt, or the GNU General Public License in gnu.txt. | |
9 // See the included readme.txt for details. | |
10 | |
11 #include <stdio.h> | |
12 #include <stdlib.h> | |
13 #include <assert.h> | |
14 | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
945
diff
changeset
|
15 #include "rmem.h" |
159 | 16 |
17 #include "statement.h" | |
18 #include "expression.h" | |
19 #include "cond.h" | |
20 #include "init.h" | |
21 #include "staticassert.h" | |
22 #include "mtype.h" | |
23 #include "scope.h" | |
24 #include "declaration.h" | |
25 #include "aggregate.h" | |
26 #include "id.h" | |
27 #include "hdrgen.h" | |
28 #include "parse.h" | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
29 #include "template.h" |
1195
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
30 #include "attrib.h" |
159 | 31 |
32 /******************************** Statement ***************************/ | |
33 | |
34 Statement::Statement(Loc loc) | |
35 : loc(loc) | |
36 { | |
37 #ifdef _DH | |
38 // If this is an in{} contract scope statement (skip for determining | |
39 // inlineStatus of a function body for header content) | |
40 incontract = 0; | |
41 #endif | |
42 } | |
43 | |
44 Statement *Statement::syntaxCopy() | |
45 { | |
46 assert(0); | |
47 return NULL; | |
48 } | |
49 | |
50 void Statement::print() | |
51 { | |
52 fprintf(stdmsg, "%s\n", toChars()); | |
53 fflush(stdmsg); | |
54 } | |
55 | |
56 char *Statement::toChars() | |
57 { OutBuffer *buf; | |
58 HdrGenState hgs; | |
59 | |
60 buf = new OutBuffer(); | |
61 toCBuffer(buf, &hgs); | |
62 return buf->toChars(); | |
63 } | |
64 | |
65 void Statement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
66 { | |
67 buf->printf("Statement::toCBuffer()"); | |
68 buf->writenl(); | |
69 } | |
70 | |
71 Statement *Statement::semantic(Scope *sc) | |
72 { | |
73 return this; | |
74 } | |
75 | |
76 // Same as semantic(), but do create a new scope | |
77 | |
78 Statement *Statement::semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue) | |
79 { Scope *scd; | |
80 Statement *s; | |
81 | |
82 scd = sc->push(); | |
83 if (sbreak) | |
84 scd->sbreak = sbreak; | |
85 if (scontinue) | |
86 scd->scontinue = scontinue; | |
87 s = semantic(scd); | |
88 scd->pop(); | |
89 return s; | |
90 } | |
91 | |
92 void Statement::error(const char *format, ...) | |
93 { | |
94 va_list ap; | |
95 va_start(ap, format); | |
96 ::verror(loc, format, ap); | |
97 va_end( ap ); | |
98 } | |
99 | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
945
diff
changeset
|
100 void Statement::warning(const char *format, ...) |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
945
diff
changeset
|
101 { |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
945
diff
changeset
|
102 if (global.params.warnings && !global.gag) |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
945
diff
changeset
|
103 { |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
945
diff
changeset
|
104 va_list ap; |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
945
diff
changeset
|
105 va_start(ap, format); |
1124
e7f0c2b48047
Fix a bug where ::warning() was called with a va_list argument instead of an
Frits van Bommel <fvbommel wxs.nl>
parents:
1103
diff
changeset
|
106 ::vwarning(loc, format, ap); |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
945
diff
changeset
|
107 va_end( ap ); |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
945
diff
changeset
|
108 } |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
945
diff
changeset
|
109 } |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
945
diff
changeset
|
110 |
159 | 111 int Statement::hasBreak() |
112 { | |
113 //printf("Statement::hasBreak()\n"); | |
114 return FALSE; | |
115 } | |
116 | |
117 int Statement::hasContinue() | |
118 { | |
119 return FALSE; | |
120 } | |
121 | |
122 // TRUE if statement uses exception handling | |
123 | |
124 int Statement::usesEH() | |
125 { | |
126 return FALSE; | |
127 } | |
128 | |
336 | 129 /* Only valid after semantic analysis |
130 */ | |
131 int Statement::blockExit() | |
132 { | |
133 printf("Statement::blockExit(%p)\n", this); | |
134 printf("%s\n", toChars()); | |
135 assert(0); | |
136 return BEany; | |
137 } | |
138 | |
159 | 139 // TRUE if statement 'comes from' somewhere else, like a goto |
140 | |
141 int Statement::comeFrom() | |
142 { | |
143 //printf("Statement::comeFrom()\n"); | |
144 return FALSE; | |
145 } | |
146 | |
147 /**************************************** | |
148 * If this statement has code that needs to run in a finally clause | |
149 * at the end of the current scope, return that code in the form of | |
150 * a Statement. | |
151 * Output: | |
152 * *sentry code executed upon entry to the scope | |
153 * *sexception code executed upon exit from the scope via exception | |
154 * *sfinally code executed in finally block | |
155 */ | |
156 | |
157 void Statement::scopeCode(Statement **sentry, Statement **sexception, Statement **sfinally) | |
158 { | |
159 //printf("Statement::scopeCode()\n"); | |
160 //print(); | |
161 *sentry = NULL; | |
162 *sexception = NULL; | |
163 *sfinally = NULL; | |
164 } | |
165 | |
166 /********************************* | |
167 * Flatten out the scope by presenting the statement | |
168 * as an array of statements. | |
169 * Returns NULL if no flattening necessary. | |
170 */ | |
171 | |
172 Statements *Statement::flatten(Scope *sc) | |
173 { | |
174 return NULL; | |
175 } | |
176 | |
177 | |
178 /******************************** ExpStatement ***************************/ | |
179 | |
180 ExpStatement::ExpStatement(Loc loc, Expression *exp) | |
181 : Statement(loc) | |
182 { | |
183 this->exp = exp; | |
184 } | |
185 | |
186 Statement *ExpStatement::syntaxCopy() | |
187 { | |
188 Expression *e = exp ? exp->syntaxCopy() : NULL; | |
189 ExpStatement *es = new ExpStatement(loc, e); | |
190 return es; | |
191 } | |
192 | |
193 void ExpStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
194 { | |
195 if (exp) | |
196 exp->toCBuffer(buf, hgs); | |
197 buf->writeByte(';'); | |
198 if (!hgs->FLinit.init) | |
199 buf->writenl(); | |
200 } | |
201 | |
202 Statement *ExpStatement::semantic(Scope *sc) | |
203 { | |
204 if (exp) | |
205 { | |
206 //printf("ExpStatement::semantic() %s\n", exp->toChars()); | |
207 exp = exp->semantic(sc); | |
208 exp = resolveProperties(sc, exp); | |
209 exp->checkSideEffect(0); | |
210 exp = exp->optimize(0); | |
1195
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
211 if (exp->op == TOKdeclaration && !isDeclarationStatement()) |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
212 { Statement *s = new DeclarationStatement(loc, exp); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
213 return s; |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
214 } |
159 | 215 //exp = exp->optimize(isDeclarationStatement() ? WANTvalue : 0); |
216 } | |
217 return this; | |
218 } | |
219 | |
336 | 220 int ExpStatement::blockExit() |
221 { int result = BEfallthru; | |
222 | |
223 if (exp) | |
224 { | |
225 if (exp->op == TOKhalt) | |
226 return BEhalt; | |
227 if (exp->op == TOKassert) | |
228 { AssertExp *a = (AssertExp *)exp; | |
229 | |
230 if (a->e1->isBool(FALSE)) // if it's an assert(0) | |
231 return BEhalt; | |
232 } | |
233 if (exp->canThrow()) | |
234 result |= BEthrow; | |
235 } | |
236 return result; | |
237 } | |
238 | |
159 | 239 |
240 /******************************** CompileStatement ***************************/ | |
241 | |
242 CompileStatement::CompileStatement(Loc loc, Expression *exp) | |
243 : Statement(loc) | |
244 { | |
245 this->exp = exp; | |
246 } | |
247 | |
248 Statement *CompileStatement::syntaxCopy() | |
249 { | |
250 Expression *e = exp->syntaxCopy(); | |
251 CompileStatement *es = new CompileStatement(loc, e); | |
252 return es; | |
253 } | |
254 | |
255 void CompileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
256 { | |
257 buf->writestring("mixin("); | |
258 exp->toCBuffer(buf, hgs); | |
259 buf->writestring(");"); | |
260 if (!hgs->FLinit.init) | |
261 buf->writenl(); | |
262 } | |
263 | |
336 | 264 Statements *CompileStatement::flatten(Scope *sc) |
159 | 265 { |
336 | 266 //printf("CompileStatement::flatten() %s\n", exp->toChars()); |
159 | 267 exp = exp->semantic(sc); |
268 exp = resolveProperties(sc, exp); | |
269 exp = exp->optimize(WANTvalue | WANTinterpret); | |
270 if (exp->op != TOKstring) | |
271 { error("argument to mixin must be a string, not (%s)", exp->toChars()); | |
336 | 272 return NULL; |
159 | 273 } |
274 StringExp *se = (StringExp *)exp; | |
275 se = se->toUTF8(sc); | |
276 Parser p(sc->module, (unsigned char *)se->string, se->len, 0); | |
277 p.loc = loc; | |
278 p.nextToken(); | |
279 | |
336 | 280 Statements *a = new Statements(); |
159 | 281 while (p.token.value != TOKeof) |
282 { | |
283 Statement *s = p.parseStatement(PSsemi | PScurlyscope); | |
336 | 284 a->push(s); |
159 | 285 } |
336 | 286 return a; |
287 } | |
288 | |
289 Statement *CompileStatement::semantic(Scope *sc) | |
290 { | |
291 //printf("CompileStatement::semantic() %s\n", exp->toChars()); | |
292 Statements *a = flatten(sc); | |
293 if (!a) | |
294 return NULL; | |
295 Statement *s = new CompoundStatement(loc, a); | |
159 | 296 return s->semantic(sc); |
297 } | |
298 | |
299 | |
300 /******************************** DeclarationStatement ***************************/ | |
301 | |
302 DeclarationStatement::DeclarationStatement(Loc loc, Dsymbol *declaration) | |
303 : ExpStatement(loc, new DeclarationExp(loc, declaration)) | |
304 { | |
305 } | |
306 | |
307 DeclarationStatement::DeclarationStatement(Loc loc, Expression *exp) | |
308 : ExpStatement(loc, exp) | |
309 { | |
310 } | |
311 | |
312 Statement *DeclarationStatement::syntaxCopy() | |
313 { | |
314 DeclarationStatement *ds = new DeclarationStatement(loc, exp->syntaxCopy()); | |
315 return ds; | |
316 } | |
317 | |
318 void DeclarationStatement::scopeCode(Statement **sentry, Statement **sexception, Statement **sfinally) | |
319 { | |
320 //printf("DeclarationStatement::scopeCode()\n"); | |
321 //print(); | |
322 | |
323 *sentry = NULL; | |
324 *sexception = NULL; | |
325 *sfinally = NULL; | |
326 | |
327 if (exp) | |
328 { | |
329 if (exp->op == TOKdeclaration) | |
330 { | |
331 DeclarationExp *de = (DeclarationExp *)(exp); | |
332 VarDeclaration *v = de->declaration->isVarDeclaration(); | |
333 if (v) | |
334 { Expression *e; | |
335 | |
336 e = v->callAutoDtor(); | |
337 if (e) | |
338 { | |
339 //printf("dtor is: "); e->print(); | |
340 *sfinally = new ExpStatement(loc, e); | |
341 } | |
342 } | |
343 } | |
344 } | |
345 } | |
346 | |
347 void DeclarationStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
348 { | |
349 exp->toCBuffer(buf, hgs); | |
350 } | |
351 | |
352 | |
353 /******************************** CompoundStatement ***************************/ | |
354 | |
355 CompoundStatement::CompoundStatement(Loc loc, Statements *s) | |
356 : Statement(loc) | |
357 { | |
358 statements = s; | |
359 } | |
360 | |
361 CompoundStatement::CompoundStatement(Loc loc, Statement *s1, Statement *s2) | |
362 : Statement(loc) | |
363 { | |
364 statements = new Statements(); | |
365 statements->reserve(2); | |
366 statements->push(s1); | |
367 statements->push(s2); | |
368 } | |
369 | |
370 Statement *CompoundStatement::syntaxCopy() | |
371 { | |
372 Statements *a = new Statements(); | |
373 a->setDim(statements->dim); | |
374 for (size_t i = 0; i < statements->dim; i++) | |
375 { Statement *s = (Statement *)statements->data[i]; | |
376 if (s) | |
377 s = s->syntaxCopy(); | |
378 a->data[i] = s; | |
379 } | |
380 CompoundStatement *cs = new CompoundStatement(loc, a); | |
381 return cs; | |
382 } | |
383 | |
384 | |
385 Statement *CompoundStatement::semantic(Scope *sc) | |
386 { Statement *s; | |
387 | |
388 //printf("CompoundStatement::semantic(this = %p, sc = %p)\n", this, sc); | |
389 | |
390 for (size_t i = 0; i < statements->dim; ) | |
391 { | |
392 s = (Statement *) statements->data[i]; | |
393 if (s) | |
394 { Statements *a = s->flatten(sc); | |
395 | |
396 if (a) | |
397 { | |
398 statements->remove(i); | |
399 statements->insert(i, a); | |
400 continue; | |
401 } | |
402 s = s->semantic(sc); | |
403 statements->data[i] = s; | |
404 if (s) | |
405 { | |
406 Statement *sentry; | |
407 Statement *sexception; | |
408 Statement *sfinally; | |
409 | |
410 s->scopeCode(&sentry, &sexception, &sfinally); | |
411 if (sentry) | |
412 { | |
413 sentry = sentry->semantic(sc); | |
414 statements->data[i] = sentry; | |
415 } | |
416 if (sexception) | |
417 { | |
418 if (i + 1 == statements->dim && !sfinally) | |
419 { | |
420 #if 1 | |
421 sexception = sexception->semantic(sc); | |
422 #else | |
423 statements->push(sexception); | |
424 if (sfinally) | |
425 // Assume sexception does not throw | |
426 statements->push(sfinally); | |
427 #endif | |
428 } | |
429 else | |
430 { | |
431 /* Rewrite: | |
432 * s; s1; s2; | |
433 * As: | |
434 * s; | |
435 * try { s1; s2; } | |
436 * catch (Object __o) | |
437 * { sexception; throw __o; } | |
438 */ | |
439 Statement *body; | |
440 Statements *a = new Statements(); | |
441 | |
442 for (int j = i + 1; j < statements->dim; j++) | |
443 { | |
444 a->push(statements->data[j]); | |
445 } | |
446 body = new CompoundStatement(0, a); | |
447 body = new ScopeStatement(0, body); | |
448 | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
449 Identifier *id = Lexer::uniqueId("__o"); |
159 | 450 |
451 Statement *handler = new ThrowStatement(0, new IdentifierExp(0, id)); | |
452 handler = new CompoundStatement(0, sexception, handler); | |
453 | |
454 Array *catches = new Array(); | |
455 Catch *ctch = new Catch(0, NULL, id, handler); | |
456 catches->push(ctch); | |
457 s = new TryCatchStatement(0, body, catches); | |
458 | |
459 if (sfinally) | |
460 s = new TryFinallyStatement(0, s, sfinally); | |
461 s = s->semantic(sc); | |
462 statements->setDim(i + 1); | |
463 statements->push(s); | |
464 break; | |
465 } | |
466 } | |
467 else if (sfinally) | |
468 { | |
469 if (0 && i + 1 == statements->dim) | |
470 { | |
471 statements->push(sfinally); | |
472 } | |
473 else | |
474 { | |
475 /* Rewrite: | |
476 * s; s1; s2; | |
477 * As: | |
478 * s; try { s1; s2; } finally { sfinally; } | |
479 */ | |
480 Statement *body; | |
481 Statements *a = new Statements(); | |
482 | |
483 for (int j = i + 1; j < statements->dim; j++) | |
484 { | |
485 a->push(statements->data[j]); | |
486 } | |
487 body = new CompoundStatement(0, a); | |
488 s = new TryFinallyStatement(0, body, sfinally); | |
489 s = s->semantic(sc); | |
490 statements->setDim(i + 1); | |
491 statements->push(s); | |
492 break; | |
493 } | |
494 } | |
495 } | |
496 } | |
497 i++; | |
498 } | |
232
092468448d25
[svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents:
215
diff
changeset
|
499 if (statements->dim == 1 && !isAsmBlockStatement()) |
336 | 500 { |
501 return (Statement *)statements->data[0]; | |
502 } | |
159 | 503 return this; |
504 } | |
505 | |
506 Statements *CompoundStatement::flatten(Scope *sc) | |
507 { | |
508 return statements; | |
509 } | |
510 | |
511 ReturnStatement *CompoundStatement::isReturnStatement() | |
336 | 512 { |
159 | 513 ReturnStatement *rs = NULL; |
514 | |
336 | 515 for (int i = 0; i < statements->dim; i++) |
516 { Statement *s = (Statement *) statements->data[i]; | |
159 | 517 if (s) |
518 { | |
519 rs = s->isReturnStatement(); | |
520 if (rs) | |
521 break; | |
522 } | |
523 } | |
524 return rs; | |
525 } | |
526 | |
527 void CompoundStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
336 | 528 { |
529 for (int i = 0; i < statements->dim; i++) | |
530 { Statement *s = (Statement *) statements->data[i]; | |
159 | 531 if (s) |
532 s->toCBuffer(buf, hgs); | |
533 } | |
534 } | |
535 | |
536 int CompoundStatement::usesEH() | |
537 { | |
538 for (int i = 0; i < statements->dim; i++) | |
336 | 539 { Statement *s = (Statement *) statements->data[i]; |
159 | 540 if (s && s->usesEH()) |
541 return TRUE; | |
542 } | |
543 return FALSE; | |
544 } | |
545 | |
336 | 546 int CompoundStatement::blockExit() |
547 { | |
548 //printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim); | |
549 int result = BEfallthru; | |
550 for (size_t i = 0; i < statements->dim; i++) | |
551 { Statement *s = (Statement *) statements->data[i]; | |
552 if (s) | |
553 { | |
554 //printf("result = x%x\n", result); | |
555 //printf("%s\n", s->toChars()); | |
556 if (!(result & BEfallthru) && !s->comeFrom()) | |
557 { | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
945
diff
changeset
|
558 s->warning("statement is not reachable"); |
336 | 559 } |
560 | |
561 result &= ~BEfallthru; | |
562 result |= s->blockExit(); | |
563 } | |
564 } | |
565 return result; | |
566 } | |
567 | |
159 | 568 int CompoundStatement::comeFrom() |
569 { int comefrom = FALSE; | |
570 | |
571 //printf("CompoundStatement::comeFrom()\n"); | |
572 for (int i = 0; i < statements->dim; i++) | |
573 { Statement *s = (Statement *)statements->data[i]; | |
574 | |
575 if (!s) | |
576 continue; | |
577 | |
578 comefrom |= s->comeFrom(); | |
579 } | |
580 return comefrom; | |
581 } | |
582 | |
583 | |
1195
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
584 /******************************** CompoundDeclarationStatement ***************************/ |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
585 |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
586 CompoundDeclarationStatement::CompoundDeclarationStatement(Loc loc, Statements *s) |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
587 : CompoundStatement(loc, s) |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
588 { |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
589 statements = s; |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
590 } |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
591 |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
592 Statement *CompoundDeclarationStatement::syntaxCopy() |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
593 { |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
594 Statements *a = new Statements(); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
595 a->setDim(statements->dim); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
596 for (size_t i = 0; i < statements->dim; i++) |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
597 { Statement *s = (Statement *)statements->data[i]; |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
598 if (s) |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
599 s = s->syntaxCopy(); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
600 a->data[i] = s; |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
601 } |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
602 CompoundDeclarationStatement *cs = new CompoundDeclarationStatement(loc, a); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
603 return cs; |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
604 } |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
605 |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
606 void CompoundDeclarationStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
607 { |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
608 int nwritten = 0; |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
609 for (int i = 0; i < statements->dim; i++) |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
610 { Statement *s = (Statement *) statements->data[i]; |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
611 if (s) |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
612 { DeclarationStatement *ds = s->isDeclarationStatement(); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
613 assert(ds); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
614 DeclarationExp *de = (DeclarationExp *)ds->exp; |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
615 assert(de->op == TOKdeclaration); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
616 Declaration *d = de->declaration->isDeclaration(); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
617 assert(d); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
618 VarDeclaration *v = d->isVarDeclaration(); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
619 if (v) |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
620 { |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
621 /* This essentially copies the part of VarDeclaration::toCBuffer() |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
622 * that does not print the type. |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
623 * Should refactor this. |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
624 */ |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
625 if (nwritten) |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
626 { |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
627 buf->writeByte(','); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
628 buf->writestring(v->ident->toChars()); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
629 } |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
630 else |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
631 { |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
632 StorageClassDeclaration::stcToCBuffer(buf, v->storage_class); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
633 if (v->type) |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
634 v->type->toCBuffer(buf, v->ident, hgs); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
635 else |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
636 buf->writestring(v->ident->toChars()); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
637 } |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
638 |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
639 if (v->init) |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
640 { buf->writestring(" = "); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
641 #if DMDV2 |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
642 ExpInitializer *ie = v->init->isExpInitializer(); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
643 if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit)) |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
644 ((AssignExp *)ie->exp)->e2->toCBuffer(buf, hgs); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
645 else |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
646 #endif |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
647 v->init->toCBuffer(buf, hgs); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
648 } |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
649 } |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
650 else |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
651 d->toCBuffer(buf, hgs); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
652 nwritten++; |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
653 } |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
654 } |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
655 buf->writeByte(';'); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
656 if (!hgs->FLinit.init) |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
657 buf->writenl(); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
658 } |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
659 |
159 | 660 /**************************** UnrolledLoopStatement ***************************/ |
661 | |
662 UnrolledLoopStatement::UnrolledLoopStatement(Loc loc, Statements *s) | |
663 : Statement(loc) | |
664 { | |
665 statements = s; | |
666 } | |
667 | |
668 Statement *UnrolledLoopStatement::syntaxCopy() | |
669 { | |
670 Statements *a = new Statements(); | |
671 a->setDim(statements->dim); | |
672 for (size_t i = 0; i < statements->dim; i++) | |
673 { Statement *s = (Statement *)statements->data[i]; | |
674 if (s) | |
675 s = s->syntaxCopy(); | |
676 a->data[i] = s; | |
677 } | |
678 UnrolledLoopStatement *cs = new UnrolledLoopStatement(loc, a); | |
679 return cs; | |
680 } | |
681 | |
682 | |
683 Statement *UnrolledLoopStatement::semantic(Scope *sc) | |
684 { | |
685 //printf("UnrolledLoopStatement::semantic(this = %p, sc = %p)\n", this, sc); | |
686 | |
687 sc->noctor++; | |
688 Scope *scd = sc->push(); | |
689 scd->sbreak = this; | |
690 scd->scontinue = this; | |
691 | |
692 for (size_t i = 0; i < statements->dim; i++) | |
693 { | |
694 Statement *s = (Statement *) statements->data[i]; | |
695 if (s) | |
696 { | |
697 s = s->semantic(scd); | |
698 statements->data[i] = s; | |
699 } | |
700 } | |
701 | |
702 scd->pop(); | |
703 sc->noctor--; | |
704 return this; | |
705 } | |
706 | |
707 void UnrolledLoopStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
708 { | |
709 buf->writestring("unrolled {"); | |
710 buf->writenl(); | |
711 | |
712 for (size_t i = 0; i < statements->dim; i++) | |
713 { Statement *s; | |
714 | |
715 s = (Statement *) statements->data[i]; | |
716 if (s) | |
717 s->toCBuffer(buf, hgs); | |
718 } | |
719 | |
720 buf->writeByte('}'); | |
721 buf->writenl(); | |
722 } | |
723 | |
724 int UnrolledLoopStatement::hasBreak() | |
725 { | |
726 return TRUE; | |
727 } | |
728 | |
729 int UnrolledLoopStatement::hasContinue() | |
730 { | |
731 return TRUE; | |
732 } | |
733 | |
734 int UnrolledLoopStatement::usesEH() | |
735 { | |
736 for (size_t i = 0; i < statements->dim; i++) | |
336 | 737 { Statement *s = (Statement *) statements->data[i]; |
159 | 738 if (s && s->usesEH()) |
739 return TRUE; | |
740 } | |
741 return FALSE; | |
742 } | |
743 | |
336 | 744 int UnrolledLoopStatement::blockExit() |
745 { | |
746 int result = BEfallthru; | |
747 for (size_t i = 0; i < statements->dim; i++) | |
748 { Statement *s = (Statement *) statements->data[i]; | |
749 if (s) | |
750 { | |
751 int r = s->blockExit(); | |
752 result |= r & ~(BEbreak | BEcontinue); | |
753 } | |
754 } | |
755 return result; | |
756 } | |
757 | |
159 | 758 int UnrolledLoopStatement::comeFrom() |
759 { int comefrom = FALSE; | |
760 | |
761 //printf("UnrolledLoopStatement::comeFrom()\n"); | |
762 for (size_t i = 0; i < statements->dim; i++) | |
763 { Statement *s = (Statement *)statements->data[i]; | |
764 | |
765 if (!s) | |
766 continue; | |
767 | |
768 comefrom |= s->comeFrom(); | |
769 } | |
770 return comefrom; | |
771 } | |
772 | |
773 | |
774 /******************************** ScopeStatement ***************************/ | |
775 | |
776 ScopeStatement::ScopeStatement(Loc loc, Statement *s) | |
777 : Statement(loc) | |
778 { | |
779 this->statement = s; | |
780 } | |
781 | |
782 Statement *ScopeStatement::syntaxCopy() | |
783 { | |
784 Statement *s; | |
785 | |
786 s = statement ? statement->syntaxCopy() : NULL; | |
787 s = new ScopeStatement(loc, s); | |
788 return s; | |
789 } | |
790 | |
791 | |
792 Statement *ScopeStatement::semantic(Scope *sc) | |
793 { ScopeDsymbol *sym; | |
794 | |
795 //printf("ScopeStatement::semantic(sc = %p)\n", sc); | |
796 if (statement) | |
797 { Statements *a; | |
798 | |
799 sym = new ScopeDsymbol(); | |
800 sym->parent = sc->scopesym; | |
801 sc = sc->push(sym); | |
802 | |
803 a = statement->flatten(sc); | |
804 if (a) | |
805 { | |
806 statement = new CompoundStatement(loc, a); | |
807 } | |
808 | |
809 statement = statement->semantic(sc); | |
810 if (statement) | |
811 { | |
812 Statement *sentry; | |
813 Statement *sexception; | |
814 Statement *sfinally; | |
815 | |
816 statement->scopeCode(&sentry, &sexception, &sfinally); | |
817 if (sfinally) | |
818 { | |
819 //printf("adding sfinally\n"); | |
820 statement = new CompoundStatement(loc, statement, sfinally); | |
821 } | |
822 } | |
823 | |
824 sc->pop(); | |
825 } | |
826 return this; | |
827 } | |
828 | |
829 int ScopeStatement::hasBreak() | |
830 { | |
831 //printf("ScopeStatement::hasBreak() %s\n", toChars()); | |
832 return statement ? statement->hasBreak() : FALSE; | |
833 } | |
834 | |
835 int ScopeStatement::hasContinue() | |
836 { | |
837 return statement ? statement->hasContinue() : FALSE; | |
838 } | |
839 | |
840 int ScopeStatement::usesEH() | |
841 { | |
842 return statement ? statement->usesEH() : FALSE; | |
843 } | |
844 | |
336 | 845 int ScopeStatement::blockExit() |
846 { | |
847 //printf("ScopeStatement::blockExit(%p)\n", statement); | |
848 return statement ? statement->blockExit() : BEfallthru; | |
849 } | |
850 | |
159 | 851 int ScopeStatement::comeFrom() |
852 { | |
853 //printf("ScopeStatement::comeFrom()\n"); | |
854 return statement ? statement->comeFrom() : FALSE; | |
855 } | |
856 | |
857 void ScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
858 { | |
859 buf->writeByte('{'); | |
860 buf->writenl(); | |
861 | |
862 if (statement) | |
863 statement->toCBuffer(buf, hgs); | |
864 | |
865 buf->writeByte('}'); | |
866 buf->writenl(); | |
867 } | |
868 | |
869 /******************************** WhileStatement ***************************/ | |
870 | |
871 WhileStatement::WhileStatement(Loc loc, Expression *c, Statement *b) | |
872 : Statement(loc) | |
873 { | |
874 condition = c; | |
875 body = b; | |
876 } | |
877 | |
878 Statement *WhileStatement::syntaxCopy() | |
879 { | |
880 WhileStatement *s = new WhileStatement(loc, condition->syntaxCopy(), body ? body->syntaxCopy() : NULL); | |
881 return s; | |
882 } | |
883 | |
884 | |
885 Statement *WhileStatement::semantic(Scope *sc) | |
886 { | |
887 #if 0 | |
888 if (condition->op == TOKmatch) | |
889 { | |
890 /* Rewrite while (condition) body as: | |
891 * if (condition) | |
892 * do | |
893 * body | |
894 * while ((_match = _match.opNext), _match); | |
895 */ | |
896 | |
897 Expression *ew = new IdentifierExp(0, Id::_match); | |
898 ew = new DotIdExp(0, ew, Id::next); | |
899 ew = new AssignExp(0, new IdentifierExp(0, Id::_match), ew); | |
900 ////ew = new EqualExp(TOKnotequal, 0, ew, new NullExp(0)); | |
901 Expression *ev = new IdentifierExp(0, Id::_match); | |
902 //ev = new CastExp(0, ev, Type::tvoidptr); | |
903 ew = new CommaExp(0, ew, ev); | |
904 Statement *sw = new DoStatement(loc, body, ew); | |
905 Statement *si = new IfStatement(loc, condition, sw, NULL); | |
906 return si->semantic(sc); | |
907 } | |
908 #endif | |
909 | |
910 condition = condition->semantic(sc); | |
911 condition = resolveProperties(sc, condition); | |
912 condition = condition->optimize(WANTvalue); | |
913 condition = condition->checkToBoolean(); | |
914 | |
915 sc->noctor++; | |
916 | |
917 Scope *scd = sc->push(); | |
918 scd->sbreak = this; | |
919 scd->scontinue = this; | |
920 if (body) | |
921 body = body->semantic(scd); | |
922 scd->pop(); | |
923 | |
924 sc->noctor--; | |
925 | |
926 return this; | |
927 } | |
928 | |
929 int WhileStatement::hasBreak() | |
930 { | |
931 return TRUE; | |
932 } | |
933 | |
934 int WhileStatement::hasContinue() | |
935 { | |
936 return TRUE; | |
937 } | |
938 | |
939 int WhileStatement::usesEH() | |
940 { | |
941 return body ? body->usesEH() : 0; | |
942 } | |
943 | |
336 | 944 int WhileStatement::blockExit() |
945 { | |
946 //printf("WhileStatement::blockExit(%p)\n", this); | |
947 | |
948 int result = BEnone; | |
949 if (condition->canThrow()) | |
950 result |= BEthrow; | |
951 if (condition->isBool(TRUE)) | |
952 { | |
953 if (body) | |
954 { result |= body->blockExit(); | |
955 if (result & BEbreak) | |
956 result |= BEfallthru; | |
957 } | |
958 } | |
959 else if (condition->isBool(FALSE)) | |
960 { | |
961 result |= BEfallthru; | |
962 } | |
963 else | |
964 { | |
965 if (body) | |
966 result |= body->blockExit(); | |
967 result |= BEfallthru; | |
968 } | |
969 result &= ~(BEbreak | BEcontinue); | |
970 return result; | |
971 } | |
972 | |
1195
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
973 |
159 | 974 int WhileStatement::comeFrom() |
975 { | |
976 if (body) | |
977 return body->comeFrom(); | |
978 return FALSE; | |
979 } | |
980 | |
981 void WhileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
982 { | |
983 buf->writestring("while ("); | |
984 condition->toCBuffer(buf, hgs); | |
985 buf->writebyte(')'); | |
986 buf->writenl(); | |
987 if (body) | |
988 body->toCBuffer(buf, hgs); | |
989 } | |
990 | |
991 /******************************** DoStatement ***************************/ | |
992 | |
993 DoStatement::DoStatement(Loc loc, Statement *b, Expression *c) | |
994 : Statement(loc) | |
995 { | |
996 body = b; | |
997 condition = c; | |
998 } | |
999 | |
1000 Statement *DoStatement::syntaxCopy() | |
1001 { | |
1002 DoStatement *s = new DoStatement(loc, body ? body->syntaxCopy() : NULL, condition->syntaxCopy()); | |
1003 return s; | |
1004 } | |
1005 | |
1006 | |
1007 Statement *DoStatement::semantic(Scope *sc) | |
1008 { | |
1009 sc->noctor++; | |
1010 if (body) | |
1011 body = body->semanticScope(sc, this, this); | |
1012 sc->noctor--; | |
1013 condition = condition->semantic(sc); | |
1014 condition = resolveProperties(sc, condition); | |
1015 condition = condition->optimize(WANTvalue); | |
1016 | |
1017 condition = condition->checkToBoolean(); | |
1018 | |
1019 return this; | |
1020 } | |
1021 | |
1022 int DoStatement::hasBreak() | |
1023 { | |
1024 return TRUE; | |
1025 } | |
1026 | |
1027 int DoStatement::hasContinue() | |
1028 { | |
1029 return TRUE; | |
1030 } | |
1031 | |
1032 int DoStatement::usesEH() | |
1033 { | |
1034 return body ? body->usesEH() : 0; | |
1035 } | |
1036 | |
336 | 1037 int DoStatement::blockExit() |
1038 { int result; | |
1039 | |
1040 if (body) | |
1041 { result = body->blockExit(); | |
1042 if (result == BEbreak) | |
1043 return BEfallthru; | |
1044 if (result & BEcontinue) | |
1045 result |= BEfallthru; | |
1046 } | |
1047 else | |
1048 result = BEfallthru; | |
1049 if (result & BEfallthru) | |
1050 { if (condition->canThrow()) | |
1051 result |= BEthrow; | |
1052 if (!(result & BEbreak) && condition->isBool(TRUE)) | |
1053 result &= ~BEfallthru; | |
1054 } | |
1055 result &= ~(BEbreak | BEcontinue); | |
1056 return result; | |
1057 } | |
1058 | |
1195
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
1059 |
159 | 1060 int DoStatement::comeFrom() |
1061 { | |
1062 if (body) | |
1063 return body->comeFrom(); | |
1064 return FALSE; | |
1065 } | |
1066 | |
1067 void DoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1068 { | |
1069 buf->writestring("do"); | |
1070 buf->writenl(); | |
1071 if (body) | |
1072 body->toCBuffer(buf, hgs); | |
1073 buf->writestring("while ("); | |
1074 condition->toCBuffer(buf, hgs); | |
1075 buf->writebyte(')'); | |
1076 } | |
1077 | |
1078 /******************************** ForStatement ***************************/ | |
1079 | |
1080 ForStatement::ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body) | |
1081 : Statement(loc) | |
1082 { | |
1083 this->init = init; | |
1084 this->condition = condition; | |
1085 this->increment = increment; | |
1086 this->body = body; | |
1087 } | |
1088 | |
1089 Statement *ForStatement::syntaxCopy() | |
1090 { | |
1091 Statement *i = NULL; | |
1092 if (init) | |
1093 i = init->syntaxCopy(); | |
1094 Expression *c = NULL; | |
1095 if (condition) | |
1096 c = condition->syntaxCopy(); | |
1097 Expression *inc = NULL; | |
1098 if (increment) | |
1099 inc = increment->syntaxCopy(); | |
1100 ForStatement *s = new ForStatement(loc, i, c, inc, body->syntaxCopy()); | |
1101 return s; | |
1102 } | |
1103 | |
1104 Statement *ForStatement::semantic(Scope *sc) | |
1105 { | |
1106 ScopeDsymbol *sym = new ScopeDsymbol(); | |
1107 sym->parent = sc->scopesym; | |
1108 sc = sc->push(sym); | |
1109 if (init) | |
1110 init = init->semantic(sc); | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
945
diff
changeset
|
1111 #if 0 |
159 | 1112 if (!condition) |
1113 // Use a default value | |
1114 condition = new IntegerExp(loc, 1, Type::tboolean); | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
945
diff
changeset
|
1115 #endif |
159 | 1116 sc->noctor++; |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1117 if (condition) |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1118 { |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1119 condition = condition->semantic(sc); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1120 condition = resolveProperties(sc, condition); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1121 condition = condition->optimize(WANTvalue); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1122 condition = condition->checkToBoolean(); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1123 } |
159 | 1124 if (increment) |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1125 { increment = increment->semantic(sc); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1126 increment = resolveProperties(sc, increment); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1127 } |
159 | 1128 |
1129 sc->sbreak = this; | |
1130 sc->scontinue = this; | |
1367
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1358
diff
changeset
|
1131 if (body) |
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1358
diff
changeset
|
1132 body = body->semantic(sc); |
159 | 1133 sc->noctor--; |
1134 | |
1135 sc->pop(); | |
1136 return this; | |
1137 } | |
1138 | |
1139 void ForStatement::scopeCode(Statement **sentry, Statement **sexception, Statement **sfinally) | |
1140 { | |
1141 //printf("ForStatement::scopeCode()\n"); | |
1142 //print(); | |
1143 if (init) | |
1144 init->scopeCode(sentry, sexception, sfinally); | |
1145 else | |
1146 Statement::scopeCode(sentry, sexception, sfinally); | |
1147 } | |
1148 | |
1149 int ForStatement::hasBreak() | |
1150 { | |
1151 //printf("ForStatement::hasBreak()\n"); | |
1152 return TRUE; | |
1153 } | |
1154 | |
1155 int ForStatement::hasContinue() | |
1156 { | |
1157 return TRUE; | |
1158 } | |
1159 | |
1160 int ForStatement::usesEH() | |
1161 { | |
1162 return (init && init->usesEH()) || body->usesEH(); | |
1163 } | |
1164 | |
336 | 1165 int ForStatement::blockExit() |
1166 { int result = BEfallthru; | |
1167 | |
1168 if (init) | |
1169 { result = init->blockExit(); | |
1170 if (!(result & BEfallthru)) | |
1171 return result; | |
1172 } | |
1173 if (condition) | |
1174 { if (condition->canThrow()) | |
1175 result |= BEthrow; | |
1176 } | |
1177 else | |
1178 result &= ~BEfallthru; // the body must do the exiting | |
1179 if (body) | |
1180 { int r = body->blockExit(); | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
945
diff
changeset
|
1181 if (r & (BEbreak | BEgoto)) |
336 | 1182 result |= BEfallthru; |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
945
diff
changeset
|
1183 result |= r & ~(BEfallthru | BEbreak | BEcontinue); |
336 | 1184 } |
1185 if (increment && increment->canThrow()) | |
1186 result |= BEthrow; | |
1187 return result; | |
1188 } | |
1189 | |
1195
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
1190 |
159 | 1191 int ForStatement::comeFrom() |
1192 { | |
1193 //printf("ForStatement::comeFrom()\n"); | |
1194 if (body) | |
1195 { int result = body->comeFrom(); | |
1196 //printf("result = %d\n", result); | |
1197 return result; | |
1198 } | |
1199 return FALSE; | |
1200 } | |
1201 | |
1202 void ForStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1203 { | |
1204 buf->writestring("for ("); | |
1205 if (init) | |
1206 { | |
1207 hgs->FLinit.init++; | |
1208 init->toCBuffer(buf, hgs); | |
1209 hgs->FLinit.init--; | |
1210 } | |
1211 else | |
1212 buf->writebyte(';'); | |
1213 if (condition) | |
1214 { buf->writebyte(' '); | |
1215 condition->toCBuffer(buf, hgs); | |
1216 } | |
1217 buf->writebyte(';'); | |
1218 if (increment) | |
1219 { buf->writebyte(' '); | |
1220 increment->toCBuffer(buf, hgs); | |
1221 } | |
1222 buf->writebyte(')'); | |
1223 buf->writenl(); | |
1224 buf->writebyte('{'); | |
1225 buf->writenl(); | |
1226 body->toCBuffer(buf, hgs); | |
1227 buf->writebyte('}'); | |
1228 buf->writenl(); | |
1229 } | |
1230 | |
1231 /******************************** ForeachStatement ***************************/ | |
1232 | |
1233 ForeachStatement::ForeachStatement(Loc loc, enum TOK op, Arguments *arguments, | |
1234 Expression *aggr, Statement *body) | |
1235 : Statement(loc) | |
1236 { | |
1237 this->op = op; | |
1238 this->arguments = arguments; | |
1239 this->aggr = aggr; | |
1240 this->body = body; | |
1241 | |
1242 this->key = NULL; | |
1243 this->value = NULL; | |
1244 | |
1245 this->func = NULL; | |
1246 } | |
1247 | |
1248 Statement *ForeachStatement::syntaxCopy() | |
1249 { | |
1250 Arguments *args = Argument::arraySyntaxCopy(arguments); | |
1251 Expression *exp = aggr->syntaxCopy(); | |
1252 ForeachStatement *s = new ForeachStatement(loc, op, args, exp, | |
1253 body ? body->syntaxCopy() : NULL); | |
1254 return s; | |
1255 } | |
1256 | |
1257 Statement *ForeachStatement::semantic(Scope *sc) | |
1258 { | |
1259 //printf("ForeachStatement::semantic() %p\n", this); | |
1260 ScopeDsymbol *sym; | |
1261 Statement *s = this; | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1262 size_t dim = arguments->dim; |
159 | 1263 TypeAArray *taa = NULL; |
1264 | |
1265 Type *tn = NULL; | |
1266 Type *tnv = NULL; | |
1267 | |
1268 func = sc->func; | |
1269 if (func->fes) | |
1270 func = func->fes->func; | |
1271 | |
1272 aggr = aggr->semantic(sc); | |
1273 aggr = resolveProperties(sc, aggr); | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1274 aggr = aggr->optimize(WANTvalue); |
159 | 1275 if (!aggr->type) |
1276 { | |
1277 error("invalid foreach aggregate %s", aggr->toChars()); | |
1278 return this; | |
1279 } | |
1280 | |
1358
78038e540342
Fix overload resolution issue in dmd bug 313/314 fix.
Christian Kamm <kamm incasoftware de>
parents:
1195
diff
changeset
|
1281 inferApplyArgTypes(op, arguments, aggr, sc->module); |
159 | 1282 |
1283 /* Check for inference errors | |
1284 */ | |
1285 if (dim != arguments->dim) | |
1286 { | |
1287 //printf("dim = %d, arguments->dim = %d\n", dim, arguments->dim); | |
1288 error("cannot uniquely infer foreach argument types"); | |
1289 return this; | |
1290 } | |
1291 | |
1292 Type *tab = aggr->type->toBasetype(); | |
1293 | |
1294 if (tab->ty == Ttuple) // don't generate new scope for tuple loops | |
1295 { | |
1296 if (dim < 1 || dim > 2) | |
1297 { | |
1298 error("only one (value) or two (key,value) arguments for tuple foreach"); | |
1299 return s; | |
1300 } | |
1301 | |
1302 TypeTuple *tuple = (TypeTuple *)tab; | |
1303 Statements *statements = new Statements(); | |
1304 //printf("aggr: op = %d, %s\n", aggr->op, aggr->toChars()); | |
1305 size_t n; | |
1306 TupleExp *te = NULL; | |
1307 if (aggr->op == TOKtuple) // expression tuple | |
1308 { te = (TupleExp *)aggr; | |
1309 n = te->exps->dim; | |
1310 } | |
1311 else if (aggr->op == TOKtype) // type tuple | |
1312 { | |
1313 n = Argument::dim(tuple->arguments); | |
1314 } | |
1315 else | |
1316 assert(0); | |
1317 for (size_t j = 0; j < n; j++) | |
1318 { size_t k = (op == TOKforeach) ? j : n - 1 - j; | |
1319 Expression *e; | |
1320 Type *t; | |
1321 if (te) | |
1322 e = (Expression *)te->exps->data[k]; | |
1323 else | |
1324 t = Argument::getNth(tuple->arguments, k)->type; | |
1325 Argument *arg = (Argument *)arguments->data[0]; | |
1326 Statements *st = new Statements(); | |
1327 | |
1328 if (dim == 2) | |
1329 { // Declare key | |
1330 if (arg->storageClass & (STCout | STCref | STClazy)) | |
1331 error("no storage class for key %s", arg->ident->toChars()); | |
1332 TY keyty = arg->type->ty; | |
1195
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
1333 if (keyty != Tint32 && keyty != Tuns32) |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
1334 { |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
1335 if (global.params.is64bit) |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
1336 { |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
1337 if (keyty != Tint64 && keyty != Tuns64) |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
1338 error("foreach: key type must be int or uint, long or ulong, not %s", arg->type->toChars()); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
1339 } |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
1340 else |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
1341 error("foreach: key type must be int or uint, not %s", arg->type->toChars()); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
1342 } |
159 | 1343 Initializer *ie = new ExpInitializer(0, new IntegerExp(k)); |
1344 VarDeclaration *var = new VarDeclaration(loc, arg->type, arg->ident, ie); | |
1345 var->storage_class |= STCconst; | |
1346 DeclarationExp *de = new DeclarationExp(loc, var); | |
1347 st->push(new ExpStatement(loc, de)); | |
1348 arg = (Argument *)arguments->data[1]; // value | |
1349 } | |
1350 // Declare value | |
1351 if (arg->storageClass & (STCout | STCref | STClazy)) | |
1352 error("no storage class for value %s", arg->ident->toChars()); | |
1353 Dsymbol *var; | |
1354 if (te) | |
1355 { | |
1356 if (e->type->toBasetype()->ty == Tfunction && | |
1357 e->op == TOKvar) | |
1358 { VarExp *ve = (VarExp *)e; | |
1359 var = new AliasDeclaration(loc, arg->ident, ve->var); | |
1360 } | |
1361 else | |
1362 { | |
1363 arg->type = e->type; | |
1364 Initializer *ie = new ExpInitializer(0, e); | |
1365 VarDeclaration *v = new VarDeclaration(loc, arg->type, arg->ident, ie); | |
1366 if (e->isConst()) | |
1367 v->storage_class |= STCconst; | |
1368 var = v; | |
1369 } | |
1370 } | |
1371 else | |
1372 { | |
1373 var = new AliasDeclaration(loc, arg->ident, t); | |
1374 } | |
1375 DeclarationExp *de = new DeclarationExp(loc, var); | |
1376 st->push(new ExpStatement(loc, de)); | |
1377 | |
1378 st->push(body->syntaxCopy()); | |
1379 s = new CompoundStatement(loc, st); | |
1380 s = new ScopeStatement(loc, s); | |
1381 statements->push(s); | |
1382 } | |
1383 | |
1384 s = new UnrolledLoopStatement(loc, statements); | |
1385 s = s->semantic(sc); | |
1386 return s; | |
1387 } | |
1388 | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1389 for (size_t i = 0; i < dim; i++) |
159 | 1390 { Argument *arg = (Argument *)arguments->data[i]; |
1391 if (!arg->type) | |
1392 { | |
1393 error("cannot infer type for %s", arg->ident->toChars()); | |
1394 return this; | |
1395 } | |
1396 } | |
1397 | |
1398 sym = new ScopeDsymbol(); | |
1399 sym->parent = sc->scopesym; | |
1400 sc = sc->push(sym); | |
1401 | |
1402 sc->noctor++; | |
1403 | |
1404 switch (tab->ty) | |
1405 { | |
1406 case Tarray: | |
1407 case Tsarray: | |
1408 if (dim < 1 || dim > 2) | |
1409 { | |
1410 error("only one or two arguments for array foreach"); | |
1411 break; | |
1412 } | |
1413 | |
1414 /* Look for special case of parsing char types out of char type | |
1415 * array. | |
1416 */ | |
1417 tn = tab->nextOf()->toBasetype(); | |
1418 if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar) | |
1419 { Argument *arg; | |
1420 | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1421 int i = (dim == 1) ? 0 : 1; // index of value |
159 | 1422 arg = (Argument *)arguments->data[i]; |
1423 arg->type = arg->type->semantic(loc, sc); | |
1424 tnv = arg->type->toBasetype(); | |
1425 if (tnv->ty != tn->ty && | |
1426 (tnv->ty == Tchar || tnv->ty == Twchar || tnv->ty == Tdchar)) | |
1427 { | |
1428 if (arg->storageClass & STCref) | |
1429 error("foreach: value of UTF conversion cannot be ref"); | |
1430 if (dim == 2) | |
1431 { arg = (Argument *)arguments->data[0]; | |
1432 if (arg->storageClass & STCref) | |
1433 error("foreach: key cannot be ref"); | |
1434 } | |
1435 goto Lapply; | |
1436 } | |
1437 } | |
1438 | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1439 for (size_t i = 0; i < dim; i++) |
159 | 1440 { // Declare args |
1441 Argument *arg = (Argument *)arguments->data[i]; | |
1442 VarDeclaration *var; | |
1443 | |
1444 var = new VarDeclaration(loc, arg->type, arg->ident, NULL); | |
1445 var->storage_class |= STCforeach; | |
1446 var->storage_class |= arg->storageClass & (STCin | STCout | STCref); | |
1447 #if 1 | |
1448 DeclarationExp *de = new DeclarationExp(loc, var); | |
1449 de->semantic(sc); | |
1450 #else | |
1451 var->semantic(sc); | |
1452 if (!sc->insert(var)) | |
1453 error("%s already defined", var->ident->toChars()); | |
1454 #endif | |
1455 if (dim == 2 && i == 0) | |
1456 key = var; | |
1457 else | |
1458 value = var; | |
1459 } | |
1460 | |
1461 sc->sbreak = this; | |
1462 sc->scontinue = this; | |
1463 body = body->semantic(sc); | |
1464 | |
1465 if (!value->type->equals(tab->next)) | |
1466 { | |
1467 if (aggr->op == TOKstring) | |
1468 aggr = aggr->implicitCastTo(sc, value->type->arrayOf()); | |
1469 else | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1470 error("foreach: %s is not an array of %s", |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1471 tab->toChars(), value->type->toChars()); |
159 | 1472 } |
1473 | |
1195
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
1474 if (key && key->type->ty != Tint32 && key->type->ty != Tuns32) |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
1475 { |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
1476 if (global.params.is64bit) |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
1477 { |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
1478 if (key->type->ty != Tint64 && key->type->ty != Tuns64) |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
1479 error("foreach: key type must be int or uint, long or ulong, not %s", key->type->toChars()); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
1480 } |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
1481 else |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
1482 error("foreach: key type must be int or uint, not %s", key->type->toChars()); |
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1164
diff
changeset
|
1483 } |
159 | 1484 |
1485 if (key && key->storage_class & (STCout | STCref)) | |
1486 error("foreach: key cannot be out or ref"); | |
1487 break; | |
1488 | |
1489 case Taarray: | |
1490 taa = (TypeAArray *)tab; | |
1491 if (dim < 1 || dim > 2) | |
1492 { | |
1493 error("only one or two arguments for associative array foreach"); | |
1494 break; | |
1495 } | |
1496 if (op == TOKforeach_reverse) | |
1497 { | |
1498 error("no reverse iteration on associative arrays"); | |
1499 } | |
1500 goto Lapply; | |
1501 | |
1502 case Tclass: | |
1503 case Tstruct: | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1504 #if DMDV2 |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1505 { /* Look for range iteration, i.e. the properties |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1506 * .empty, .next, .retreat, .head and .rear |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1507 * foreach (e; range) { ... } |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1508 * translates to: |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1509 * for (auto __r = range; !__r.empty; __r.next) |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1510 * { auto e = __r.head; |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1511 * ... |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1512 * } |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1513 */ |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1514 if (dim != 1) // only one argument allowed with ranges |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1515 goto Lapply; |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1516 AggregateDeclaration *ad = (tab->ty == Tclass) |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1517 ? (AggregateDeclaration *)((TypeClass *)tab)->sym |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1518 : (AggregateDeclaration *)((TypeStruct *)tab)->sym; |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1519 Identifier *idhead; |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1520 Identifier *idnext; |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1521 if (op == TOKforeach) |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1522 { idhead = Id::Fhead; |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1523 idnext = Id::Fnext; |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1524 } |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1525 else |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1526 { idhead = Id::Frear; |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1527 idnext = Id::Fretreat; |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1528 } |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1529 Dsymbol *shead = search_function(ad, idhead); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1530 if (!shead) |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1531 goto Lapply; |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1532 |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1533 /* Generate a temporary __r and initialize it with the aggregate. |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1534 */ |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1535 Identifier *id = Identifier::generateId("__r"); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1536 VarDeclaration *r = new VarDeclaration(loc, NULL, id, new ExpInitializer(loc, aggr)); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1537 r->semantic(sc); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1538 Statement *init = new DeclarationStatement(loc, r); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1539 |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1540 // !__r.empty |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1541 Expression *e = new VarExp(loc, r); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1542 e = new DotIdExp(loc, e, Id::Fempty); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1543 Expression *condition = new NotExp(loc, e); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1544 |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1545 // __r.next |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1546 e = new VarExp(loc, r); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1547 Expression *increment = new DotIdExp(loc, e, idnext); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1548 |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1549 /* Declaration statement for e: |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1550 * auto e = __r.idhead; |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1551 */ |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1552 e = new VarExp(loc, r); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1553 Expression *einit = new DotIdExp(loc, e, idhead); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1554 einit = einit->semantic(sc); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1555 Argument *arg = (Argument *)arguments->data[0]; |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1556 VarDeclaration *ve = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, einit)); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1557 ve->storage_class |= STCforeach; |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1558 ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STCconst | STCinvariant); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1559 |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1560 DeclarationExp *de = new DeclarationExp(loc, ve); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1561 |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1562 Statement *body = new CompoundStatement(loc, |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1563 new DeclarationStatement(loc, de), this->body); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1564 |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1565 s = new ForStatement(loc, init, condition, increment, body); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1566 s = s->semantic(sc); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1567 break; |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1568 } |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1569 #endif |
159 | 1570 case Tdelegate: |
1571 Lapply: | |
1572 { FuncDeclaration *fdapply; | |
1573 Arguments *args; | |
1574 Expression *ec; | |
1575 Expression *e; | |
1576 FuncLiteralDeclaration *fld; | |
1577 Argument *a; | |
1578 Type *t; | |
1579 Expression *flde; | |
1580 Identifier *id; | |
1581 Type *tret; | |
719
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1582 TypeDelegate* dgty; |
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1583 TypeDelegate* dgty2; |
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1584 TypeDelegate* fldeTy; |
159 | 1585 |
1586 tret = func->type->nextOf(); | |
1587 | |
1588 // Need a variable to hold value from any return statements in body. | |
1589 if (!sc->func->vresult && tret && tret != Type::tvoid) | |
1590 { VarDeclaration *v; | |
1591 | |
1592 v = new VarDeclaration(loc, tret, Id::result, NULL); | |
1593 v->noauto = 1; | |
1594 v->semantic(sc); | |
1595 if (!sc->insert(v)) | |
1596 assert(0); | |
1597 v->parent = sc->func; | |
1598 sc->func->vresult = v; | |
1599 } | |
1600 | |
1601 /* Turn body into the function literal: | |
1602 * int delegate(ref T arg) { body } | |
1603 */ | |
1604 args = new Arguments(); | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1605 for (size_t i = 0; i < dim; i++) |
159 | 1606 { Argument *arg = (Argument *)arguments->data[i]; |
1607 | |
1608 arg->type = arg->type->semantic(loc, sc); | |
1609 if (arg->storageClass & STCref) | |
1610 id = arg->ident; | |
1611 else | |
1612 { // Make a copy of the ref argument so it isn't | |
1613 // a reference. | |
1614 VarDeclaration *v; | |
1615 Initializer *ie; | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1616 |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
1617 id = Lexer::uniqueId("__applyArg", i); |
159 | 1618 |
1619 ie = new ExpInitializer(0, new IdentifierExp(0, id)); | |
1620 v = new VarDeclaration(0, arg->type, arg->ident, ie); | |
1621 s = new DeclarationStatement(0, v); | |
1622 body = new CompoundStatement(loc, s, body); | |
1623 } | |
1624 a = new Argument(STCref, arg->type, id, NULL); | |
1625 args->push(a); | |
1626 } | |
1627 t = new TypeFunction(args, Type::tint32, 0, LINKd); | |
1628 fld = new FuncLiteralDeclaration(loc, 0, t, TOKdelegate, this); | |
1629 fld->fbody = body; | |
1630 flde = new FuncExp(loc, fld); | |
1631 flde = flde->semantic(sc); | |
1632 | |
1633 // Resolve any forward referenced goto's | |
1634 for (int i = 0; i < gotos.dim; i++) | |
1635 { CompoundStatement *cs = (CompoundStatement *)gotos.data[i]; | |
1636 GotoStatement *gs = (GotoStatement *)cs->statements->data[0]; | |
1637 | |
1638 if (!gs->label->statement) | |
1639 { // 'Promote' it to this scope, and replace with a return | |
1640 cases.push(gs); | |
1641 s = new ReturnStatement(0, new IntegerExp(cases.dim + 1)); | |
1642 cs->statements->data[0] = (void *)s; | |
1643 } | |
1644 } | |
1645 | |
1646 if (tab->ty == Taarray) | |
1647 { | |
1648 // Check types | |
1649 Argument *arg = (Argument *)arguments->data[0]; | |
1650 if (dim == 2) | |
1651 { | |
1652 if (arg->storageClass & STCref) | |
1653 error("foreach: index cannot be ref"); | |
1654 if (!arg->type->equals(taa->index)) | |
1655 error("foreach: index must be type %s, not %s", taa->index->toChars(), arg->type->toChars()); | |
1656 arg = (Argument *)arguments->data[1]; | |
1657 } | |
1658 if (!arg->type->equals(taa->nextOf())) | |
1659 error("foreach: value must be type %s, not %s", taa->nextOf()->toChars(), arg->type->toChars()); | |
1660 | |
1661 /* Call: | |
1662 * _aaApply(aggr, keysize, flde) | |
1663 */ | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
510
diff
changeset
|
1664 //LDC: Build arguments. |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
380
diff
changeset
|
1665 static FuncDeclaration *aaApply2_fd = NULL; |
719
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1666 static TypeDelegate* aaApply2_dg; |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
380
diff
changeset
|
1667 if(!aaApply2_fd) { |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
380
diff
changeset
|
1668 Arguments* args = new Arguments; |
715
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1669 args->push(new Argument(STCin, Type::tvoid->pointerTo(), NULL, NULL)); |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
380
diff
changeset
|
1670 args->push(new Argument(STCin, Type::tsize_t, NULL, NULL)); |
378
d8234836b40f
Get rid of runTimeHack and instead add proper argument info to the frontend
Christian Kamm <kamm incasoftware de>
parents:
353
diff
changeset
|
1671 Arguments* dgargs = new Arguments; |
d8234836b40f
Get rid of runTimeHack and instead add proper argument info to the frontend
Christian Kamm <kamm incasoftware de>
parents:
353
diff
changeset
|
1672 dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL)); |
d8234836b40f
Get rid of runTimeHack and instead add proper argument info to the frontend
Christian Kamm <kamm incasoftware de>
parents:
353
diff
changeset
|
1673 dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL)); |
719
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1674 aaApply2_dg = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd)); |
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1675 args->push(new Argument(STCin, aaApply2_dg, NULL, NULL)); |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
380
diff
changeset
|
1676 aaApply2_fd = FuncDeclaration::genCfunc(args, Type::tindex, "_aaApply2"); |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
380
diff
changeset
|
1677 } |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
380
diff
changeset
|
1678 static FuncDeclaration *aaApply_fd = NULL; |
719
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1679 static TypeDelegate* aaApply_dg; |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
380
diff
changeset
|
1680 if(!aaApply_fd) { |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
380
diff
changeset
|
1681 Arguments* args = new Arguments; |
715
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1682 args->push(new Argument(STCin, Type::tvoid->pointerTo(), NULL, NULL)); |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
380
diff
changeset
|
1683 args->push(new Argument(STCin, Type::tsize_t, NULL, NULL)); |
378
d8234836b40f
Get rid of runTimeHack and instead add proper argument info to the frontend
Christian Kamm <kamm incasoftware de>
parents:
353
diff
changeset
|
1684 Arguments* dgargs = new Arguments; |
d8234836b40f
Get rid of runTimeHack and instead add proper argument info to the frontend
Christian Kamm <kamm incasoftware de>
parents:
353
diff
changeset
|
1685 dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL)); |
719
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1686 aaApply_dg = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd)); |
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1687 args->push(new Argument(STCin, aaApply_dg, NULL, NULL)); |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
380
diff
changeset
|
1688 aaApply_fd = FuncDeclaration::genCfunc(args, Type::tindex, "_aaApply"); |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
380
diff
changeset
|
1689 } |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
380
diff
changeset
|
1690 if (dim == 2) { |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
380
diff
changeset
|
1691 fdapply = aaApply2_fd; |
719
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1692 fldeTy = aaApply2_dg; |
389
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
380
diff
changeset
|
1693 } else { |
722f5e90c39c
Made setup for runtime calls in dmd frontend allocate less.
Christian Kamm <kamm incasoftware de>
parents:
380
diff
changeset
|
1694 fdapply = aaApply_fd; |
719
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1695 fldeTy = aaApply_dg; |
378
d8234836b40f
Get rid of runTimeHack and instead add proper argument info to the frontend
Christian Kamm <kamm incasoftware de>
parents:
353
diff
changeset
|
1696 } |
159 | 1697 ec = new VarExp(0, fdapply); |
1698 Expressions *exps = new Expressions(); | |
1699 exps->push(aggr); | |
1700 size_t keysize = taa->key->size(); | |
765
f08e0ff8d28c
Fixed 32bit assumption in statement.c when calling aaApply(2).
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
719
diff
changeset
|
1701 keysize = (keysize + (PTRSIZE-1)) & ~(PTRSIZE-1); |
159 | 1702 exps->push(new IntegerExp(0, keysize, Type::tsize_t)); |
719
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1703 |
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1704 // LDC paint delegate argument to the type runtime expects |
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1705 if (!fldeTy->equals(flde->type)) |
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1706 { |
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1707 flde = new CastExp(loc, flde, flde->type); |
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1708 flde->type = fldeTy; |
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1709 } |
159 | 1710 exps->push(flde); |
1711 e = new CallExp(loc, ec, exps); | |
1712 e->type = Type::tindex; // don't run semantic() on e | |
1713 } | |
1714 else if (tab->ty == Tarray || tab->ty == Tsarray) | |
1715 { | |
1716 /* Call: | |
1717 * _aApply(aggr, flde) | |
1718 */ | |
1719 static char fntab[9][3] = | |
1720 { "cc","cw","cd", | |
1721 "wc","cc","wd", | |
1722 "dc","dw","dd" | |
1723 }; | |
1724 char fdname[7+1+2+ sizeof(dim)*3 + 1]; | |
1725 int flag; | |
1726 | |
1727 switch (tn->ty) | |
1728 { | |
1729 case Tchar: flag = 0; break; | |
1730 case Twchar: flag = 3; break; | |
1731 case Tdchar: flag = 6; break; | |
1732 default: assert(0); | |
1733 } | |
1734 switch (tnv->ty) | |
1735 { | |
1736 case Tchar: flag += 0; break; | |
1737 case Twchar: flag += 1; break; | |
1738 case Tdchar: flag += 2; break; | |
1739 default: assert(0); | |
1740 } | |
1741 const char *r = (op == TOKforeach_reverse) ? "R" : ""; | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
945
diff
changeset
|
1742 int j = sprintf(fdname, "_aApply%s%.*s%zu", r, 2, fntab[flag], dim); |
159 | 1743 assert(j < sizeof(fdname)); |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
510
diff
changeset
|
1744 //LDC: Build arguments. |
378
d8234836b40f
Get rid of runTimeHack and instead add proper argument info to the frontend
Christian Kamm <kamm incasoftware de>
parents:
353
diff
changeset
|
1745 Arguments* args = new Arguments; |
715
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1746 args->push(new Argument(STCin, tn->arrayOf(), NULL, NULL)); |
378
d8234836b40f
Get rid of runTimeHack and instead add proper argument info to the frontend
Christian Kamm <kamm incasoftware de>
parents:
353
diff
changeset
|
1747 if (dim == 2) { |
d8234836b40f
Get rid of runTimeHack and instead add proper argument info to the frontend
Christian Kamm <kamm incasoftware de>
parents:
353
diff
changeset
|
1748 Arguments* dgargs = new Arguments; |
d8234836b40f
Get rid of runTimeHack and instead add proper argument info to the frontend
Christian Kamm <kamm incasoftware de>
parents:
353
diff
changeset
|
1749 dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL)); |
d8234836b40f
Get rid of runTimeHack and instead add proper argument info to the frontend
Christian Kamm <kamm incasoftware de>
parents:
353
diff
changeset
|
1750 dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL)); |
719
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1751 dgty = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd)); |
378
d8234836b40f
Get rid of runTimeHack and instead add proper argument info to the frontend
Christian Kamm <kamm incasoftware de>
parents:
353
diff
changeset
|
1752 args->push(new Argument(STCin, dgty, NULL, NULL)); |
d8234836b40f
Get rid of runTimeHack and instead add proper argument info to the frontend
Christian Kamm <kamm incasoftware de>
parents:
353
diff
changeset
|
1753 fdapply = FuncDeclaration::genCfunc(args, Type::tindex, fdname); |
d8234836b40f
Get rid of runTimeHack and instead add proper argument info to the frontend
Christian Kamm <kamm incasoftware de>
parents:
353
diff
changeset
|
1754 } else { |
d8234836b40f
Get rid of runTimeHack and instead add proper argument info to the frontend
Christian Kamm <kamm incasoftware de>
parents:
353
diff
changeset
|
1755 Arguments* dgargs = new Arguments; |
d8234836b40f
Get rid of runTimeHack and instead add proper argument info to the frontend
Christian Kamm <kamm incasoftware de>
parents:
353
diff
changeset
|
1756 dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL)); |
719
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1757 dgty = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd)); |
378
d8234836b40f
Get rid of runTimeHack and instead add proper argument info to the frontend
Christian Kamm <kamm incasoftware de>
parents:
353
diff
changeset
|
1758 args->push(new Argument(STCin, dgty, NULL, NULL)); |
d8234836b40f
Get rid of runTimeHack and instead add proper argument info to the frontend
Christian Kamm <kamm incasoftware de>
parents:
353
diff
changeset
|
1759 fdapply = FuncDeclaration::genCfunc(args, Type::tindex, fdname); |
d8234836b40f
Get rid of runTimeHack and instead add proper argument info to the frontend
Christian Kamm <kamm incasoftware de>
parents:
353
diff
changeset
|
1760 } |
159 | 1761 |
1762 ec = new VarExp(0, fdapply); | |
1763 Expressions *exps = new Expressions(); | |
1764 if (tab->ty == Tsarray) | |
1765 aggr = aggr->castTo(sc, tn->arrayOf()); | |
715
30b42a283c8e
Removed TypeOpaque from DMD.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1766 exps->push(aggr); |
719
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1767 |
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1768 // LDC paint delegate argument to the type runtime expects |
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1769 if (!dgty->equals(flde->type)) |
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1770 { |
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1771 flde = new CastExp(loc, flde, flde->type); |
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1772 flde->type = dgty; |
7261ff0f95ff
Implemented first class delegates. closes #101
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
715
diff
changeset
|
1773 } |
159 | 1774 exps->push(flde); |
1775 e = new CallExp(loc, ec, exps); | |
1776 e->type = Type::tindex; // don't run semantic() on e | |
1777 } | |
1778 else if (tab->ty == Tdelegate) | |
1779 { | |
1780 /* Call: | |
1781 * aggr(flde) | |
1782 */ | |
1783 Expressions *exps = new Expressions(); | |
1784 exps->push(flde); | |
1785 e = new CallExp(loc, aggr, exps); | |
1786 e = e->semantic(sc); | |
1787 if (e->type != Type::tint32) | |
1788 error("opApply() function for %s must return an int", tab->toChars()); | |
1789 } | |
1790 else | |
1791 { | |
1792 /* Call: | |
1793 * aggr.apply(flde) | |
1794 */ | |
1795 ec = new DotIdExp(loc, aggr, | |
1796 (op == TOKforeach_reverse) ? Id::applyReverse | |
1797 : Id::apply); | |
1798 Expressions *exps = new Expressions(); | |
1799 exps->push(flde); | |
1800 e = new CallExp(loc, ec, exps); | |
1801 e = e->semantic(sc); | |
1802 if (e->type != Type::tint32) | |
1803 error("opApply() function for %s must return an int", tab->toChars()); | |
1804 } | |
1805 | |
1806 if (!cases.dim) | |
1807 // Easy case, a clean exit from the loop | |
1808 s = new ExpStatement(loc, e); | |
1809 else | |
1810 { // Construct a switch statement around the return value | |
1811 // of the apply function. | |
1812 Statements *a = new Statements(); | |
1813 | |
1814 // default: break; takes care of cases 0 and 1 | |
1815 s = new BreakStatement(0, NULL); | |
1816 s = new DefaultStatement(0, s); | |
1817 a->push(s); | |
1818 | |
1819 // cases 2... | |
1820 for (int i = 0; i < cases.dim; i++) | |
1821 { | |
1822 s = (Statement *)cases.data[i]; | |
1823 s = new CaseStatement(0, new IntegerExp(i + 2), s); | |
1824 a->push(s); | |
1825 } | |
1826 | |
1827 s = new CompoundStatement(loc, a); | |
1828 s = new SwitchStatement(loc, e, s); | |
1829 s = s->semantic(sc); | |
1830 } | |
1831 break; | |
1832 } | |
1833 | |
1834 default: | |
1835 error("foreach: %s is not an aggregate type", aggr->type->toChars()); | |
1836 break; | |
1837 } | |
1838 sc->noctor--; | |
1839 sc->pop(); | |
1840 return s; | |
1841 } | |
1842 | |
1843 int ForeachStatement::hasBreak() | |
1844 { | |
1845 return TRUE; | |
1846 } | |
1847 | |
1848 int ForeachStatement::hasContinue() | |
1849 { | |
1850 return TRUE; | |
1851 } | |
1852 | |
1853 int ForeachStatement::usesEH() | |
1854 { | |
1855 return body->usesEH(); | |
1856 } | |
1857 | |
336 | 1858 int ForeachStatement::blockExit() |
1859 { int result = BEfallthru; | |
1860 | |
1861 if (aggr->canThrow()) | |
1862 result |= BEthrow; | |
1863 | |
1864 if (body) | |
1865 { | |
1866 result |= body->blockExit() & ~(BEbreak | BEcontinue); | |
1867 } | |
1868 return result; | |
1869 } | |
1870 | |
159 | 1871 int ForeachStatement::comeFrom() |
1872 { | |
1873 if (body) | |
1874 return body->comeFrom(); | |
1875 return FALSE; | |
1876 } | |
1877 | |
1878 void ForeachStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1879 { | |
1880 buf->writestring(Token::toChars(op)); | |
1881 buf->writestring(" ("); | |
1882 for (int i = 0; i < arguments->dim; i++) | |
1883 { | |
1884 Argument *a = (Argument *)arguments->data[i]; | |
1885 if (i) | |
1886 buf->writestring(", "); | |
1887 if (a->storageClass & STCref) | |
1888 buf->writestring((global.params.Dversion == 1) | |
1889 ? (char*)"inout " : (char*)"ref "); | |
1890 if (a->type) | |
1891 a->type->toCBuffer(buf, a->ident, hgs); | |
1892 else | |
1893 buf->writestring(a->ident->toChars()); | |
1894 } | |
1895 buf->writestring("; "); | |
1896 aggr->toCBuffer(buf, hgs); | |
1897 buf->writebyte(')'); | |
1898 buf->writenl(); | |
1899 buf->writebyte('{'); | |
1900 buf->writenl(); | |
1901 if (body) | |
1902 body->toCBuffer(buf, hgs); | |
1903 buf->writebyte('}'); | |
1904 buf->writenl(); | |
1905 } | |
1906 | |
1907 /******************************** IfStatement ***************************/ | |
1908 | |
1909 IfStatement::IfStatement(Loc loc, Argument *arg, Expression *condition, Statement *ifbody, Statement *elsebody) | |
1910 : Statement(loc) | |
1911 { | |
1912 this->arg = arg; | |
1913 this->condition = condition; | |
1914 this->ifbody = ifbody; | |
1915 this->elsebody = elsebody; | |
1916 this->match = NULL; | |
1917 } | |
1918 | |
1919 Statement *IfStatement::syntaxCopy() | |
1920 { | |
1921 Statement *i = NULL; | |
1922 if (ifbody) | |
1923 i = ifbody->syntaxCopy(); | |
1924 | |
1925 Statement *e = NULL; | |
1926 if (elsebody) | |
1927 e = elsebody->syntaxCopy(); | |
1928 | |
1929 Argument *a = arg ? arg->syntaxCopy() : NULL; | |
1930 IfStatement *s = new IfStatement(loc, a, condition->syntaxCopy(), i, e); | |
1931 return s; | |
1932 } | |
1933 | |
1934 Statement *IfStatement::semantic(Scope *sc) | |
1935 { | |
1936 condition = condition->semantic(sc); | |
1937 condition = resolveProperties(sc, condition); | |
1938 condition = condition->checkToBoolean(); | |
1939 | |
1940 // If we can short-circuit evaluate the if statement, don't do the | |
1941 // semantic analysis of the skipped code. | |
1942 // This feature allows a limited form of conditional compilation. | |
1943 condition = condition->optimize(WANTflags); | |
1944 | |
1945 // Evaluate at runtime | |
1946 unsigned cs0 = sc->callSuper; | |
1947 unsigned cs1; | |
1948 | |
1949 Scope *scd; | |
1950 if (arg) | |
1951 { /* Declare arg, which we will set to be the | |
1952 * result of condition. | |
1953 */ | |
1954 ScopeDsymbol *sym = new ScopeDsymbol(); | |
1955 sym->parent = sc->scopesym; | |
1956 scd = sc->push(sym); | |
1957 | |
1958 Type *t = arg->type ? arg->type : condition->type; | |
1959 match = new VarDeclaration(loc, t, arg->ident, NULL); | |
1960 match->noauto = 1; | |
1961 match->semantic(scd); | |
1962 if (!scd->insert(match)) | |
1963 assert(0); | |
1964 match->parent = sc->func; | |
1965 | |
1966 /* Generate: | |
1967 * (arg = condition) | |
1968 */ | |
1969 VarExp *v = new VarExp(0, match); | |
1970 condition = new AssignExp(loc, v, condition); | |
1971 condition = condition->semantic(scd); | |
1972 } | |
1973 else | |
1974 scd = sc->push(); | |
1975 ifbody = ifbody->semantic(scd); | |
1976 scd->pop(); | |
1977 | |
1978 cs1 = sc->callSuper; | |
1979 sc->callSuper = cs0; | |
1980 if (elsebody) | |
1981 elsebody = elsebody->semanticScope(sc, NULL, NULL); | |
1982 sc->mergeCallSuper(loc, cs1); | |
1983 | |
1984 return this; | |
1985 } | |
1986 | |
1987 int IfStatement::usesEH() | |
1988 { | |
1989 return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH()); | |
1990 } | |
1991 | |
336 | 1992 int IfStatement::blockExit() |
1993 { | |
1994 //printf("IfStatement::blockExit(%p)\n", this); | |
1995 | |
1996 int result = BEnone; | |
1997 if (condition->canThrow()) | |
1998 result |= BEthrow; | |
1999 if (condition->isBool(TRUE)) | |
2000 { | |
2001 if (ifbody) | |
2002 result |= ifbody->blockExit(); | |
2003 else | |
2004 result |= BEfallthru; | |
2005 } | |
2006 else if (condition->isBool(FALSE)) | |
2007 { | |
2008 if (elsebody) | |
2009 result |= elsebody->blockExit(); | |
2010 else | |
2011 result |= BEfallthru; | |
2012 } | |
2013 else | |
2014 { | |
2015 if (ifbody) | |
2016 result |= ifbody->blockExit(); | |
2017 else | |
2018 result |= BEfallthru; | |
2019 if (elsebody) | |
2020 result |= elsebody->blockExit(); | |
2021 else | |
2022 result |= BEfallthru; | |
2023 } | |
2024 //printf("IfStatement::blockExit(%p) = x%x\n", this, result); | |
2025 return result; | |
2026 } | |
2027 | |
159 | 2028 void IfStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
2029 { | |
2030 buf->writestring("if ("); | |
2031 if (arg) | |
2032 { | |
2033 if (arg->type) | |
2034 arg->type->toCBuffer(buf, arg->ident, hgs); | |
2035 else | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
389
diff
changeset
|
2036 { buf->writestring("auto "); |
159 | 2037 buf->writestring(arg->ident->toChars()); |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
389
diff
changeset
|
2038 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
389
diff
changeset
|
2039 buf->writestring(" = "); |
159 | 2040 } |
2041 condition->toCBuffer(buf, hgs); | |
2042 buf->writebyte(')'); | |
2043 buf->writenl(); | |
2044 ifbody->toCBuffer(buf, hgs); | |
2045 if (elsebody) | |
2046 { buf->writestring("else"); | |
2047 buf->writenl(); | |
2048 elsebody->toCBuffer(buf, hgs); | |
2049 } | |
2050 } | |
2051 | |
2052 /******************************** ConditionalStatement ***************************/ | |
2053 | |
2054 ConditionalStatement::ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody) | |
2055 : Statement(loc) | |
2056 { | |
2057 this->condition = condition; | |
2058 this->ifbody = ifbody; | |
2059 this->elsebody = elsebody; | |
2060 } | |
2061 | |
2062 Statement *ConditionalStatement::syntaxCopy() | |
2063 { | |
2064 Statement *e = NULL; | |
2065 if (elsebody) | |
2066 e = elsebody->syntaxCopy(); | |
2067 ConditionalStatement *s = new ConditionalStatement(loc, | |
2068 condition->syntaxCopy(), ifbody->syntaxCopy(), e); | |
2069 return s; | |
2070 } | |
2071 | |
2072 Statement *ConditionalStatement::semantic(Scope *sc) | |
2073 { | |
2074 //printf("ConditionalStatement::semantic()\n"); | |
2075 | |
2076 // If we can short-circuit evaluate the if statement, don't do the | |
2077 // semantic analysis of the skipped code. | |
2078 // This feature allows a limited form of conditional compilation. | |
2079 if (condition->include(sc, NULL)) | |
2080 { | |
2081 ifbody = ifbody->semantic(sc); | |
2082 return ifbody; | |
2083 } | |
2084 else | |
2085 { | |
2086 if (elsebody) | |
2087 elsebody = elsebody->semantic(sc); | |
2088 return elsebody; | |
2089 } | |
2090 } | |
2091 | |
2092 Statements *ConditionalStatement::flatten(Scope *sc) | |
2093 { | |
2094 Statement *s; | |
2095 | |
2096 if (condition->include(sc, NULL)) | |
2097 s = ifbody; | |
2098 else | |
2099 s = elsebody; | |
2100 | |
2101 Statements *a = new Statements(); | |
2102 a->push(s); | |
2103 return a; | |
2104 } | |
2105 | |
2106 int ConditionalStatement::usesEH() | |
2107 { | |
2108 return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH()); | |
2109 } | |
2110 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
389
diff
changeset
|
2111 int ConditionalStatement::blockExit() |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
389
diff
changeset
|
2112 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
389
diff
changeset
|
2113 int result = ifbody->blockExit(); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
389
diff
changeset
|
2114 if (elsebody) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
389
diff
changeset
|
2115 result |= elsebody->blockExit(); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
389
diff
changeset
|
2116 return result; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
389
diff
changeset
|
2117 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
389
diff
changeset
|
2118 |
159 | 2119 void ConditionalStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
2120 { | |
2121 condition->toCBuffer(buf, hgs); | |
2122 buf->writenl(); | |
336 | 2123 buf->writeByte('{'); |
2124 buf->writenl(); | |
159 | 2125 if (ifbody) |
2126 ifbody->toCBuffer(buf, hgs); | |
336 | 2127 buf->writeByte('}'); |
2128 buf->writenl(); | |
159 | 2129 if (elsebody) |
2130 { | |
2131 buf->writestring("else"); | |
2132 buf->writenl(); | |
336 | 2133 buf->writeByte('{'); |
2134 buf->writenl(); | |
159 | 2135 elsebody->toCBuffer(buf, hgs); |
336 | 2136 buf->writeByte('}'); |
2137 buf->writenl(); | |
159 | 2138 } |
2139 buf->writenl(); | |
2140 } | |
2141 | |
2142 | |
2143 /******************************** PragmaStatement ***************************/ | |
2144 | |
2145 PragmaStatement::PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body) | |
2146 : Statement(loc) | |
2147 { | |
2148 this->ident = ident; | |
2149 this->args = args; | |
2150 this->body = body; | |
2151 } | |
2152 | |
2153 Statement *PragmaStatement::syntaxCopy() | |
2154 { | |
2155 Statement *b = NULL; | |
2156 if (body) | |
2157 b = body->syntaxCopy(); | |
2158 PragmaStatement *s = new PragmaStatement(loc, | |
2159 ident, Expression::arraySyntaxCopy(args), b); | |
2160 return s; | |
2161 } | |
2162 | |
2163 Statement *PragmaStatement::semantic(Scope *sc) | |
2164 { // Should be merged with PragmaDeclaration | |
2165 //printf("PragmaStatement::semantic() %s\n", toChars()); | |
2166 //printf("body = %p\n", body); | |
2167 if (ident == Id::msg) | |
2168 { | |
2169 if (args) | |
2170 { | |
2171 for (size_t i = 0; i < args->dim; i++) | |
2172 { | |
2173 Expression *e = (Expression *)args->data[i]; | |
2174 | |
2175 e = e->semantic(sc); | |
2176 e = e->optimize(WANTvalue | WANTinterpret); | |
2177 if (e->op == TOKstring) | |
2178 { | |
2179 StringExp *se = (StringExp *)e; | |
794
661384d6a936
Fix warnings on x86-64. By fvbommel.
Christian Kamm <kamm incasoftware de>
parents:
765
diff
changeset
|
2180 fprintf(stdmsg, "%.*s", (int)se->len, (char*)se->string); |
159 | 2181 } |
2182 else | |
2183 error("string expected for message, not '%s'", e->toChars()); | |
2184 } | |
2185 fprintf(stdmsg, "\n"); | |
2186 } | |
2187 } | |
2188 else if (ident == Id::lib) | |
2189 { | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
2190 #if 1 |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
2191 /* Should this be allowed? |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
2192 */ |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
2193 error("pragma(lib) not allowed as statement"); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
2194 #else |
159 | 2195 if (!args || args->dim != 1) |
2196 error("string expected for library name"); | |
2197 else | |
2198 { | |
2199 Expression *e = (Expression *)args->data[0]; | |
2200 | |
2201 e = e->semantic(sc); | |
2202 e = e->optimize(WANTvalue | WANTinterpret); | |
2203 args->data[0] = (void *)e; | |
2204 if (e->op != TOKstring) | |
2205 error("string expected for library name, not '%s'", e->toChars()); | |
2206 else if (global.params.verbose) | |
2207 { | |
2208 StringExp *se = (StringExp *)e; | |
2209 char *name = (char *)mem.malloc(se->len + 1); | |
2210 memcpy(name, se->string, se->len); | |
2211 name[se->len] = 0; | |
2212 printf("library %s\n", name); | |
2213 mem.free(name); | |
2214 } | |
2215 } | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
2216 #endif |
159 | 2217 } |
945
03d7c4aac654
SWITCHED TO LLVM 2.5 !
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
908
diff
changeset
|
2218 |
03d7c4aac654
SWITCHED TO LLVM 2.5 !
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
908
diff
changeset
|
2219 // LDC |
03d7c4aac654
SWITCHED TO LLVM 2.5 !
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
908
diff
changeset
|
2220 else if (ident == Id::allow_inline) |
03d7c4aac654
SWITCHED TO LLVM 2.5 !
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
908
diff
changeset
|
2221 { |
03d7c4aac654
SWITCHED TO LLVM 2.5 !
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
908
diff
changeset
|
2222 sc->func->allowInlining = true; |
03d7c4aac654
SWITCHED TO LLVM 2.5 !
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
908
diff
changeset
|
2223 } |
03d7c4aac654
SWITCHED TO LLVM 2.5 !
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
908
diff
changeset
|
2224 |
159 | 2225 else |
2226 error("unrecognized pragma(%s)", ident->toChars()); | |
2227 | |
2228 if (body) | |
2229 { | |
2230 body = body->semantic(sc); | |
2231 } | |
2232 return body; | |
2233 } | |
2234 | |
2235 int PragmaStatement::usesEH() | |
2236 { | |
2237 return body && body->usesEH(); | |
2238 } | |
2239 | |
336 | 2240 int PragmaStatement::blockExit() |
2241 { | |
2242 int result = BEfallthru; | |
2243 #if 0 // currently, no code is generated for Pragma's, so it's just fallthru | |
2244 if (arrayExpressionCanThrow(args)) | |
2245 result |= BEthrow; | |
2246 if (body) | |
2247 result |= body->blockExit(); | |
2248 #endif | |
2249 return result; | |
2250 } | |
2251 | |
159 | 2252 void PragmaStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
2253 { | |
2254 buf->writestring("pragma ("); | |
2255 buf->writestring(ident->toChars()); | |
2256 if (args && args->dim) | |
2257 { | |
2258 buf->writestring(", "); | |
2259 argsToCBuffer(buf, args, hgs); | |
2260 } | |
2261 buf->writeByte(')'); | |
2262 if (body) | |
2263 { | |
2264 buf->writenl(); | |
2265 buf->writeByte('{'); | |
2266 buf->writenl(); | |
2267 | |
2268 body->toCBuffer(buf, hgs); | |
2269 | |
2270 buf->writeByte('}'); | |
2271 buf->writenl(); | |
2272 } | |
2273 else | |
2274 { | |
2275 buf->writeByte(';'); | |
2276 buf->writenl(); | |
2277 } | |
2278 } | |
2279 | |
2280 | |
2281 /******************************** StaticAssertStatement ***************************/ | |
2282 | |
2283 StaticAssertStatement::StaticAssertStatement(StaticAssert *sa) | |
2284 : Statement(sa->loc) | |
2285 { | |
2286 this->sa = sa; | |
2287 } | |
2288 | |
2289 Statement *StaticAssertStatement::syntaxCopy() | |
2290 { | |
2291 StaticAssertStatement *s = new StaticAssertStatement((StaticAssert *)sa->syntaxCopy(NULL)); | |
2292 return s; | |
2293 } | |
2294 | |
2295 Statement *StaticAssertStatement::semantic(Scope *sc) | |
2296 { | |
2297 sa->semantic2(sc); | |
2298 return NULL; | |
2299 } | |
2300 | |
2301 void StaticAssertStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2302 { | |
2303 sa->toCBuffer(buf, hgs); | |
2304 } | |
2305 | |
2306 | |
2307 /******************************** SwitchStatement ***************************/ | |
2308 | |
2309 SwitchStatement::SwitchStatement(Loc loc, Expression *c, Statement *b) | |
2310 : Statement(loc) | |
2311 { | |
2312 condition = c; | |
2313 body = b; | |
2314 sdefault = NULL; | |
2315 cases = NULL; | |
2316 hasNoDefault = 0; | |
1159
c6d6a68bb5db
Add back some enclosing scope-exit information to the frontend to produce
Christian Kamm <kamm incasoftware de>
parents:
1141
diff
changeset
|
2317 // LDC |
c6d6a68bb5db
Add back some enclosing scope-exit information to the frontend to produce
Christian Kamm <kamm incasoftware de>
parents:
1141
diff
changeset
|
2318 enclosingScopeExit = NULL; |
159 | 2319 } |
2320 | |
2321 Statement *SwitchStatement::syntaxCopy() | |
2322 { | |
2323 SwitchStatement *s = new SwitchStatement(loc, | |
2324 condition->syntaxCopy(), body->syntaxCopy()); | |
2325 return s; | |
2326 } | |
2327 | |
2328 Statement *SwitchStatement::semantic(Scope *sc) | |
2329 { | |
2330 //printf("SwitchStatement::semantic(%p)\n", this); | |
2331 assert(!cases); // ensure semantic() is only run once | |
2332 | |
1159
c6d6a68bb5db
Add back some enclosing scope-exit information to the frontend to produce
Christian Kamm <kamm incasoftware de>
parents:
1141
diff
changeset
|
2333 // LDC |
c6d6a68bb5db
Add back some enclosing scope-exit information to the frontend to produce
Christian Kamm <kamm incasoftware de>
parents:
1141
diff
changeset
|
2334 enclosingScopeExit = sc->enclosingScopeExit; |
c6d6a68bb5db
Add back some enclosing scope-exit information to the frontend to produce
Christian Kamm <kamm incasoftware de>
parents:
1141
diff
changeset
|
2335 |
159 | 2336 condition = condition->semantic(sc); |
2337 condition = resolveProperties(sc, condition); | |
2338 if (condition->type->isString()) | |
2339 { | |
2340 // If it's not an array, cast it to one | |
2341 if (condition->type->ty != Tarray) | |
2342 { | |
2343 condition = condition->implicitCastTo(sc, condition->type->nextOf()->arrayOf()); | |
2344 } | |
2345 } | |
2346 else | |
2347 { condition = condition->integralPromotions(sc); | |
2348 condition->checkIntegral(); | |
2349 } | |
2350 condition = condition->optimize(WANTvalue); | |
2351 | |
2352 sc = sc->push(); | |
2353 sc->sbreak = this; | |
2354 sc->sw = this; | |
2355 | |
2356 cases = new Array(); | |
2357 sc->noctor++; // BUG: should use Scope::mergeCallSuper() for each case instead | |
2358 body = body->semantic(sc); | |
2359 sc->noctor--; | |
2360 | |
2361 // Resolve any goto case's with exp | |
2362 for (int i = 0; i < gotoCases.dim; i++) | |
2363 { | |
2364 GotoCaseStatement *gcs = (GotoCaseStatement *)gotoCases.data[i]; | |
2365 | |
2366 if (!gcs->exp) | |
2367 { | |
2368 gcs->error("no case statement following goto case;"); | |
2369 break; | |
2370 } | |
2371 | |
2372 for (Scope *scx = sc; scx; scx = scx->enclosing) | |
2373 { | |
2374 if (!scx->sw) | |
2375 continue; | |
2376 for (int j = 0; j < scx->sw->cases->dim; j++) | |
2377 { | |
2378 CaseStatement *cs = (CaseStatement *)scx->sw->cases->data[j]; | |
2379 | |
2380 if (cs->exp->equals(gcs->exp)) | |
2381 { | |
2382 gcs->cs = cs; | |
2383 goto Lfoundcase; | |
2384 } | |
2385 } | |
2386 } | |
2387 gcs->error("case %s not found", gcs->exp->toChars()); | |
2388 | |
2389 Lfoundcase: | |
2390 ; | |
2391 } | |
2392 | |
2393 if (!sc->sw->sdefault) | |
2394 { hasNoDefault = 1; | |
2395 | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
945
diff
changeset
|
2396 warning("switch statement has no default"); |
159 | 2397 |
2398 // Generate runtime error if the default is hit | |
2399 Statements *a = new Statements(); | |
2400 CompoundStatement *cs; | |
2401 Statement *s; | |
2402 | |
2403 if (global.params.useSwitchError) | |
2404 s = new SwitchErrorStatement(loc); | |
2405 else | |
2406 { Expression *e = new HaltExp(loc); | |
2407 s = new ExpStatement(loc, e); | |
2408 } | |
2409 | |
2410 a->reserve(4); | |
2411 a->push(body); | |
901 | 2412 |
2413 // LDC needs semantic to be run on break | |
2414 Statement *breakstmt = new BreakStatement(loc, NULL); | |
2415 breakstmt->semantic(sc); | |
2416 a->push(breakstmt); | |
2417 | |
159 | 2418 sc->sw->sdefault = new DefaultStatement(loc, s); |
2419 a->push(sc->sw->sdefault); | |
2420 cs = new CompoundStatement(loc, a); | |
2421 body = cs; | |
2422 } | |
2423 | |
2424 sc->pop(); | |
2425 return this; | |
2426 } | |
2427 | |
2428 int SwitchStatement::hasBreak() | |
2429 { | |
2430 return TRUE; | |
2431 } | |
2432 | |
2433 int SwitchStatement::usesEH() | |
2434 { | |
2435 return body ? body->usesEH() : 0; | |
2436 } | |
2437 | |
336 | 2438 int SwitchStatement::blockExit() |
2439 { int result = BEnone; | |
2440 if (condition->canThrow()) | |
2441 result |= BEthrow; | |
2442 | |
2443 if (body) | |
2444 { result |= body->blockExit(); | |
2445 if (result & BEbreak) | |
2446 { result |= BEfallthru; | |
2447 result &= ~BEbreak; | |
2448 } | |
2449 } | |
2450 else | |
2451 result |= BEfallthru; | |
2452 | |
2453 return result; | |
2454 } | |
2455 | |
159 | 2456 void SwitchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
2457 { | |
2458 buf->writestring("switch ("); | |
2459 condition->toCBuffer(buf, hgs); | |
2460 buf->writebyte(')'); | |
2461 buf->writenl(); | |
2462 if (body) | |
2463 { | |
2464 if (!body->isScopeStatement()) | |
2465 { buf->writebyte('{'); | |
2466 buf->writenl(); | |
2467 body->toCBuffer(buf, hgs); | |
2468 buf->writebyte('}'); | |
2469 buf->writenl(); | |
2470 } | |
2471 else | |
2472 { | |
2473 body->toCBuffer(buf, hgs); | |
2474 } | |
2475 } | |
2476 } | |
2477 | |
2478 /******************************** CaseStatement ***************************/ | |
2479 | |
2480 CaseStatement::CaseStatement(Loc loc, Expression *exp, Statement *s) | |
2481 : Statement(loc) | |
2482 { | |
2483 this->exp = exp; | |
2484 this->statement = s; | |
2485 cblock = NULL; | |
2486 bodyBB = NULL; | |
262
88252a1af660
[svn r280] Fixed a bunch of issues with switch statements. Ended up a bit far reaching...
lindquist
parents:
232
diff
changeset
|
2487 llvmIdx = NULL; |
1159
c6d6a68bb5db
Add back some enclosing scope-exit information to the frontend to produce
Christian Kamm <kamm incasoftware de>
parents:
1141
diff
changeset
|
2488 // LDC |
c6d6a68bb5db
Add back some enclosing scope-exit information to the frontend to produce
Christian Kamm <kamm incasoftware de>
parents:
1141
diff
changeset
|
2489 enclosingScopeExit = NULL; |
159 | 2490 } |
2491 | |
2492 Statement *CaseStatement::syntaxCopy() | |
2493 { | |
2494 CaseStatement *s = new CaseStatement(loc, exp->syntaxCopy(), statement->syntaxCopy()); | |
2495 return s; | |
2496 } | |
2497 | |
2498 Statement *CaseStatement::semantic(Scope *sc) | |
2499 { SwitchStatement *sw = sc->sw; | |
2500 | |
2501 //printf("CaseStatement::semantic() %s\n", toChars()); | |
1159
c6d6a68bb5db
Add back some enclosing scope-exit information to the frontend to produce
Christian Kamm <kamm incasoftware de>
parents:
1141
diff
changeset
|
2502 |
159 | 2503 exp = exp->semantic(sc); |
2504 if (sw) | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
2505 { |
1164
166042b48c28
Fix bug in CaseStatement::semantic when there's no enclosing switch.
Christian Kamm <kamm incasoftware de>
parents:
1159
diff
changeset
|
2506 // LDC |
166042b48c28
Fix bug in CaseStatement::semantic when there's no enclosing switch.
Christian Kamm <kamm incasoftware de>
parents:
1159
diff
changeset
|
2507 enclosingScopeExit = sc->enclosingScopeExit; |
166042b48c28
Fix bug in CaseStatement::semantic when there's no enclosing switch.
Christian Kamm <kamm incasoftware de>
parents:
1159
diff
changeset
|
2508 if (enclosingScopeExit != sw->enclosingScopeExit) |
166042b48c28
Fix bug in CaseStatement::semantic when there's no enclosing switch.
Christian Kamm <kamm incasoftware de>
parents:
1159
diff
changeset
|
2509 { |
166042b48c28
Fix bug in CaseStatement::semantic when there's no enclosing switch.
Christian Kamm <kamm incasoftware de>
parents:
1159
diff
changeset
|
2510 error("case must be inside the same try, synchronized or volatile level as switch"); |
166042b48c28
Fix bug in CaseStatement::semantic when there's no enclosing switch.
Christian Kamm <kamm incasoftware de>
parents:
1159
diff
changeset
|
2511 } |
166042b48c28
Fix bug in CaseStatement::semantic when there's no enclosing switch.
Christian Kamm <kamm incasoftware de>
parents:
1159
diff
changeset
|
2512 |
159 | 2513 exp = exp->implicitCastTo(sc, sw->condition->type); |
2514 exp = exp->optimize(WANTvalue | WANTinterpret); | |
2515 if (exp->op != TOKstring && exp->op != TOKint64) | |
2516 { | |
2517 error("case must be a string or an integral constant, not %s", exp->toChars()); | |
2518 exp = new IntegerExp(0); | |
2519 } | |
2520 | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
2521 for (int i = 0; i < sw->cases->dim; i++) |
159 | 2522 { |
2523 CaseStatement *cs = (CaseStatement *)sw->cases->data[i]; | |
2524 | |
2525 //printf("comparing '%s' with '%s'\n", exp->toChars(), cs->exp->toChars()); | |
2526 if (cs->exp->equals(exp)) | |
2527 { error("duplicate case %s in switch statement", exp->toChars()); | |
2528 break; | |
2529 } | |
2530 } | |
2531 | |
2532 sw->cases->push(this); | |
2533 | |
2534 // Resolve any goto case's with no exp to this case statement | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
2535 for (size_t i = 0; i < sw->gotoCases.dim; i++) |
159 | 2536 { |
2537 GotoCaseStatement *gcs = (GotoCaseStatement *)sw->gotoCases.data[i]; | |
2538 | |
2539 if (!gcs->exp) | |
2540 { | |
2541 gcs->cs = this; | |
2542 sw->gotoCases.remove(i); // remove from array | |
2543 } | |
2544 } | |
2545 } | |
2546 else | |
2547 error("case not in switch statement"); | |
2548 statement = statement->semantic(sc); | |
2549 return this; | |
2550 } | |
2551 | |
2552 int CaseStatement::compare(Object *obj) | |
2553 { | |
2554 // Sort cases so we can do an efficient lookup | |
2555 CaseStatement *cs2 = (CaseStatement *)(obj); | |
2556 | |
2557 return exp->compare(cs2->exp); | |
2558 } | |
2559 | |
2560 int CaseStatement::usesEH() | |
2561 { | |
2562 return statement->usesEH(); | |
2563 } | |
2564 | |
336 | 2565 int CaseStatement::blockExit() |
2566 { | |
2567 return statement->blockExit(); | |
2568 } | |
2569 | |
159 | 2570 int CaseStatement::comeFrom() |
2571 { | |
2572 return TRUE; | |
2573 } | |
2574 | |
2575 void CaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2576 { | |
2577 buf->writestring("case "); | |
2578 exp->toCBuffer(buf, hgs); | |
2579 buf->writebyte(':'); | |
2580 buf->writenl(); | |
2581 statement->toCBuffer(buf, hgs); | |
2582 } | |
2583 | |
2584 /******************************** DefaultStatement ***************************/ | |
2585 | |
2586 DefaultStatement::DefaultStatement(Loc loc, Statement *s) | |
2587 : Statement(loc) | |
2588 { | |
2589 this->statement = s; | |
2590 #if IN_GCC | |
2591 + cblock = NULL; | |
2592 #endif | |
2593 bodyBB = NULL; | |
1159
c6d6a68bb5db
Add back some enclosing scope-exit information to the frontend to produce
Christian Kamm <kamm incasoftware de>
parents:
1141
diff
changeset
|
2594 // LDC |
c6d6a68bb5db
Add back some enclosing scope-exit information to the frontend to produce
Christian Kamm <kamm incasoftware de>
parents:
1141
diff
changeset
|
2595 enclosingScopeExit = NULL; |
159 | 2596 } |
2597 | |
2598 Statement *DefaultStatement::syntaxCopy() | |
2599 { | |
2600 DefaultStatement *s = new DefaultStatement(loc, statement->syntaxCopy()); | |
2601 return s; | |
2602 } | |
2603 | |
2604 Statement *DefaultStatement::semantic(Scope *sc) | |
2605 { | |
336 | 2606 //printf("DefaultStatement::semantic()\n"); |
1159
c6d6a68bb5db
Add back some enclosing scope-exit information to the frontend to produce
Christian Kamm <kamm incasoftware de>
parents:
1141
diff
changeset
|
2607 |
159 | 2608 if (sc->sw) |
2609 { | |
2610 if (sc->sw->sdefault) | |
2611 { | |
2612 error("switch statement already has a default"); | |
2613 } | |
2614 sc->sw->sdefault = this; | |
1159
c6d6a68bb5db
Add back some enclosing scope-exit information to the frontend to produce
Christian Kamm <kamm incasoftware de>
parents:
1141
diff
changeset
|
2615 |
c6d6a68bb5db
Add back some enclosing scope-exit information to the frontend to produce
Christian Kamm <kamm incasoftware de>
parents:
1141
diff
changeset
|
2616 // LDC |
c6d6a68bb5db
Add back some enclosing scope-exit information to the frontend to produce
Christian Kamm <kamm incasoftware de>
parents:
1141
diff
changeset
|
2617 enclosingScopeExit = sc->enclosingScopeExit; |
c6d6a68bb5db
Add back some enclosing scope-exit information to the frontend to produce
Christian Kamm <kamm incasoftware de>
parents:
1141
diff
changeset
|
2618 if (enclosingScopeExit != sc->sw->enclosingScopeExit) |
c6d6a68bb5db
Add back some enclosing scope-exit information to the frontend to produce
Christian Kamm <kamm incasoftware de>
parents:
1141
diff
changeset
|
2619 { |
c6d6a68bb5db
Add back some enclosing scope-exit information to the frontend to produce
Christian Kamm <kamm incasoftware de>
parents:
1141
diff
changeset
|
2620 error("default must be inside the same try, synchronized or volatile level as switch"); |
c6d6a68bb5db
Add back some enclosing scope-exit information to the frontend to produce
Christian Kamm <kamm incasoftware de>
parents:
1141
diff
changeset
|
2621 } |
159 | 2622 } |
2623 else | |
2624 error("default not in switch statement"); | |
2625 statement = statement->semantic(sc); | |
2626 return this; | |
2627 } | |
2628 | |
2629 int DefaultStatement::usesEH() | |
2630 { | |
2631 return statement->usesEH(); | |
2632 } | |
2633 | |
336 | 2634 int DefaultStatement::blockExit() |
2635 { | |
2636 return statement->blockExit(); | |
2637 } | |
2638 | |
159 | 2639 int DefaultStatement::comeFrom() |
2640 { | |
2641 return TRUE; | |
2642 } | |
2643 | |
2644 void DefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2645 { | |
2646 buf->writestring("default:\n"); | |
2647 statement->toCBuffer(buf, hgs); | |
2648 } | |
2649 | |
2650 /******************************** GotoDefaultStatement ***************************/ | |
2651 | |
2652 GotoDefaultStatement::GotoDefaultStatement(Loc loc) | |
2653 : Statement(loc) | |
2654 { | |
2655 sw = NULL; | |
2656 } | |
2657 | |
2658 Statement *GotoDefaultStatement::syntaxCopy() | |
2659 { | |
2660 GotoDefaultStatement *s = new GotoDefaultStatement(loc); | |
2661 return s; | |
2662 } | |
2663 | |
2664 Statement *GotoDefaultStatement::semantic(Scope *sc) | |
2665 { | |
2666 sw = sc->sw; | |
2667 if (!sw) | |
2668 error("goto default not in switch statement"); | |
2669 return this; | |
2670 } | |
2671 | |
336 | 2672 int GotoDefaultStatement::blockExit() |
2673 { | |
2674 return BEgoto; | |
2675 } | |
2676 | |
159 | 2677 void GotoDefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
2678 { | |
2679 buf->writestring("goto default;\n"); | |
2680 } | |
2681 | |
2682 /******************************** GotoCaseStatement ***************************/ | |
2683 | |
2684 GotoCaseStatement::GotoCaseStatement(Loc loc, Expression *exp) | |
2685 : Statement(loc) | |
2686 { | |
2687 cs = NULL; | |
2688 this->exp = exp; | |
2689 sw = NULL; | |
2690 } | |
2691 | |
2692 Statement *GotoCaseStatement::syntaxCopy() | |
2693 { | |
2694 Expression *e = exp ? exp->syntaxCopy() : NULL; | |
2695 GotoCaseStatement *s = new GotoCaseStatement(loc, e); | |
2696 return s; | |
2697 } | |
2698 | |
2699 Statement *GotoCaseStatement::semantic(Scope *sc) | |
2700 { | |
2701 if (exp) | |
2702 exp = exp->semantic(sc); | |
2703 | |
2704 if (!sc->sw) | |
2705 error("goto case not in switch statement"); | |
2706 else | |
2707 { | |
2708 sw = sc->sw; | |
2709 sc->sw->gotoCases.push(this); | |
2710 if (exp) | |
2711 { | |
2712 exp = exp->implicitCastTo(sc, sc->sw->condition->type); | |
2713 exp = exp->optimize(WANTvalue); | |
2714 } | |
2715 } | |
2716 return this; | |
2717 } | |
2718 | |
336 | 2719 int GotoCaseStatement::blockExit() |
2720 { | |
2721 return BEgoto; | |
2722 } | |
2723 | |
159 | 2724 void GotoCaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
2725 { | |
2726 buf->writestring("goto case"); | |
2727 if (exp) | |
2728 { buf->writebyte(' '); | |
2729 exp->toCBuffer(buf, hgs); | |
2730 } | |
2731 buf->writebyte(';'); | |
2732 buf->writenl(); | |
2733 } | |
2734 | |
2735 /******************************** SwitchErrorStatement ***************************/ | |
2736 | |
2737 SwitchErrorStatement::SwitchErrorStatement(Loc loc) | |
2738 : Statement(loc) | |
2739 { | |
2740 } | |
2741 | |
336 | 2742 int SwitchErrorStatement::blockExit() |
2743 { | |
2744 return BEthrow; | |
2745 } | |
2746 | |
159 | 2747 void SwitchErrorStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
2748 { | |
2749 buf->writestring("SwitchErrorStatement::toCBuffer()"); | |
2750 buf->writenl(); | |
2751 } | |
2752 | |
2753 /******************************** ReturnStatement ***************************/ | |
2754 | |
2755 ReturnStatement::ReturnStatement(Loc loc, Expression *exp) | |
2756 : Statement(loc) | |
2757 { | |
2758 this->exp = exp; | |
2759 } | |
2760 | |
2761 Statement *ReturnStatement::syntaxCopy() | |
2762 { | |
2763 Expression *e = NULL; | |
2764 if (exp) | |
2765 e = exp->syntaxCopy(); | |
2766 ReturnStatement *s = new ReturnStatement(loc, e); | |
2767 return s; | |
2768 } | |
2769 | |
2770 Statement *ReturnStatement::semantic(Scope *sc) | |
2771 { | |
2772 //printf("ReturnStatement::semantic() %s\n", toChars()); | |
2773 | |
2774 FuncDeclaration *fd = sc->parent->isFuncDeclaration(); | |
2775 Scope *scx = sc; | |
2776 int implicit0 = 0; | |
2777 | |
2778 if (sc->fes) | |
2779 { | |
2780 // Find scope of function foreach is in | |
2781 for (; 1; scx = scx->enclosing) | |
2782 { | |
2783 assert(scx); | |
2784 if (scx->func != fd) | |
2785 { fd = scx->func; // fd is now function enclosing foreach | |
2786 break; | |
2787 } | |
2788 } | |
2789 } | |
2790 | |
2791 Type *tret = fd->type->nextOf(); | |
2792 if (fd->tintro) | |
336 | 2793 /* We'll be implicitly casting the return expression to tintro |
2794 */ | |
159 | 2795 tret = fd->tintro->nextOf(); |
2796 Type *tbret = NULL; | |
2797 | |
2798 if (tret) | |
2799 tbret = tret->toBasetype(); | |
2800 | |
2801 // main() returns 0, even if it returns void | |
2802 if (!exp && (!tbret || tbret->ty == Tvoid) && fd->isMain()) | |
2803 { implicit0 = 1; | |
2804 exp = new IntegerExp(0); | |
2805 } | |
2806 | |
2807 if (sc->incontract || scx->incontract) | |
2808 error("return statements cannot be in contracts"); | |
1141
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
2809 if (sc->enclosingFinally || scx->enclosingFinally) |
159 | 2810 error("return statements cannot be in finally, scope(exit) or scope(success) bodies"); |
2811 | |
2812 if (fd->isCtorDeclaration()) | |
2813 { | |
2814 // Constructors implicitly do: | |
2815 // return this; | |
2816 if (exp && exp->op != TOKthis) | |
2817 error("cannot return expression from constructor"); | |
2818 exp = new ThisExp(0); | |
2819 } | |
2820 | |
2821 if (!exp) | |
2822 fd->nrvo_can = 0; | |
2823 | |
2824 if (exp) | |
2825 { | |
2826 fd->hasReturnExp |= 1; | |
2827 | |
2828 exp = exp->semantic(sc); | |
2829 exp = resolveProperties(sc, exp); | |
2830 exp = exp->optimize(WANTvalue); | |
2831 | |
2832 if (fd->nrvo_can && exp->op == TOKvar) | |
2833 { VarExp *ve = (VarExp *)exp; | |
2834 VarDeclaration *v = ve->var->isVarDeclaration(); | |
2835 | |
2836 if (!v || v->isOut() || v->isRef()) | |
2837 fd->nrvo_can = 0; | |
2838 else if (fd->nrvo_var == NULL) | |
2839 { if (!v->isDataseg() && !v->isParameter() && v->toParent2() == fd) | |
2840 fd->nrvo_var = v; | |
2841 else | |
2842 fd->nrvo_can = 0; | |
2843 } | |
2844 else if (fd->nrvo_var != v) | |
2845 fd->nrvo_can = 0; | |
2846 } | |
2847 else | |
2848 fd->nrvo_can = 0; | |
2849 | |
2850 if (fd->returnLabel && tbret->ty != Tvoid) | |
2851 { | |
2852 } | |
2853 else if (fd->inferRetType) | |
2854 { | |
2855 if (fd->type->nextOf()) | |
2856 { | |
2857 if (!exp->type->equals(fd->type->nextOf())) | |
2858 error("mismatched function return type inference of %s and %s", | |
2859 exp->type->toChars(), fd->type->nextOf()->toChars()); | |
2860 } | |
2861 else | |
2862 { | |
2863 fd->type->next = exp->type; | |
2864 fd->type = fd->type->semantic(loc, sc); | |
2865 if (!fd->tintro) | |
2866 { tret = fd->type->nextOf(); | |
2867 tbret = tret->toBasetype(); | |
2868 } | |
2869 } | |
2870 } | |
2871 else if (tbret->ty != Tvoid) | |
2872 { | |
2873 exp = exp->implicitCastTo(sc, tret); | |
2874 } | |
2875 } | |
2876 else if (fd->inferRetType) | |
2877 { | |
2878 if (fd->type->nextOf()) | |
2879 { | |
2880 if (fd->type->nextOf()->ty != Tvoid) | |
2881 error("mismatched function return type inference of void and %s", | |
2882 fd->type->nextOf()->toChars()); | |
2883 } | |
2884 else | |
2885 { | |
2886 fd->type->next = Type::tvoid; | |
2887 fd->type = fd->type->semantic(loc, sc); | |
2888 if (!fd->tintro) | |
2889 { tret = Type::tvoid; | |
2890 tbret = tret; | |
2891 } | |
2892 } | |
2893 } | |
2894 else if (tbret->ty != Tvoid) // if non-void return | |
2895 error("return expression expected"); | |
2896 | |
2897 if (sc->fes) | |
2898 { | |
2899 Statement *s; | |
2900 | |
2901 if (exp && !implicit0) | |
2902 { | |
2903 exp = exp->implicitCastTo(sc, tret); | |
2904 } | |
2905 if (!exp || exp->op == TOKint64 || exp->op == TOKfloat64 || | |
2906 exp->op == TOKimaginary80 || exp->op == TOKcomplex80 || | |
2907 exp->op == TOKthis || exp->op == TOKsuper || exp->op == TOKnull || | |
2908 exp->op == TOKstring) | |
2909 { | |
2910 sc->fes->cases.push(this); | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
2911 // Construct: return cases.dim+1; |
159 | 2912 s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); |
2913 } | |
2914 else if (fd->type->nextOf()->toBasetype() == Type::tvoid) | |
2915 { | |
2916 s = new ReturnStatement(0, NULL); | |
2917 sc->fes->cases.push(s); | |
2918 | |
2919 // Construct: { exp; return cases.dim + 1; } | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
2920 Statement *s1 = new ExpStatement(loc, exp); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
2921 Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); |
159 | 2922 s = new CompoundStatement(loc, s1, s2); |
2923 } | |
2924 else | |
2925 { | |
2926 // Construct: return vresult; | |
2927 if (!fd->vresult) | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
2928 { // Declare vresult |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
2929 VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL); |
159 | 2930 v->noauto = 1; |
2931 v->semantic(scx); | |
2932 if (!scx->insert(v)) | |
2933 assert(0); | |
2934 v->parent = fd; | |
2935 fd->vresult = v; | |
2936 } | |
2937 | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
2938 s = new ReturnStatement(0, new VarExp(0, fd->vresult)); |
159 | 2939 sc->fes->cases.push(s); |
2940 | |
2941 // Construct: { vresult = exp; return cases.dim + 1; } | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
2942 exp = new AssignExp(loc, new VarExp(0, fd->vresult), exp); |
159 | 2943 exp = exp->semantic(sc); |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
2944 Statement *s1 = new ExpStatement(loc, exp); |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
2945 Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); |
159 | 2946 s = new CompoundStatement(loc, s1, s2); |
2947 } | |
2948 return s; | |
2949 } | |
2950 | |
2951 if (exp) | |
2952 { | |
2953 if (fd->returnLabel && tbret->ty != Tvoid) | |
2954 { | |
2955 assert(fd->vresult); | |
2956 VarExp *v = new VarExp(0, fd->vresult); | |
2957 | |
2958 exp = new AssignExp(loc, v, exp); | |
2959 exp = exp->semantic(sc); | |
2960 } | |
2961 //exp->dump(0); | |
2962 //exp->print(); | |
2963 exp->checkEscape(); | |
2964 } | |
2965 | |
2966 /* BUG: need to issue an error on: | |
2967 * this | |
2968 * { if (x) return; | |
2969 * super(); | |
2970 * } | |
2971 */ | |
2972 | |
2973 if (sc->callSuper & CSXany_ctor && | |
2974 !(sc->callSuper & (CSXthis_ctor | CSXsuper_ctor))) | |
2975 error("return without calling constructor"); | |
2976 | |
2977 sc->callSuper |= CSXreturn; | |
2978 | |
2979 // See if all returns are instead to be replaced with a goto returnLabel; | |
2980 if (fd->returnLabel) | |
2981 { | |
2982 GotoStatement *gs = new GotoStatement(loc, Id::returnLabel); | |
2983 | |
2984 gs->label = fd->returnLabel; | |
2985 if (exp) | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
2986 { /* Replace: return exp; |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
2987 * with: exp; goto returnLabel; |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
2988 */ |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
2989 Statement *s = new ExpStatement(0, exp); |
159 | 2990 return new CompoundStatement(loc, s, gs); |
2991 } | |
2992 return gs; | |
2993 } | |
2994 | |
2995 if (exp && tbret->ty == Tvoid && !fd->isMain()) | |
336 | 2996 { |
2997 /* Replace: | |
2998 * return exp; | |
2999 * with: | |
3000 * exp; return; | |
3001 */ | |
3002 Statement *s = new ExpStatement(loc, exp); | |
159 | 3003 loc = 0; |
3004 exp = NULL; | |
3005 return new CompoundStatement(loc, s, this); | |
3006 } | |
3007 | |
3008 return this; | |
3009 } | |
3010 | |
336 | 3011 int ReturnStatement::blockExit() |
3012 { int result = BEreturn; | |
3013 | |
3014 if (exp && exp->canThrow()) | |
3015 result |= BEthrow; | |
3016 return result; | |
3017 } | |
3018 | |
159 | 3019 void ReturnStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3020 { | |
3021 buf->printf("return "); | |
3022 if (exp) | |
3023 exp->toCBuffer(buf, hgs); | |
3024 buf->writeByte(';'); | |
3025 buf->writenl(); | |
3026 } | |
3027 | |
3028 /******************************** BreakStatement ***************************/ | |
3029 | |
3030 BreakStatement::BreakStatement(Loc loc, Identifier *ident) | |
3031 : Statement(loc) | |
3032 { | |
3033 this->ident = ident; | |
3034 } | |
3035 | |
3036 Statement *BreakStatement::syntaxCopy() | |
3037 { | |
3038 BreakStatement *s = new BreakStatement(loc, ident); | |
3039 return s; | |
3040 } | |
3041 | |
3042 Statement *BreakStatement::semantic(Scope *sc) | |
3043 { | |
336 | 3044 //printf("BreakStatement::semantic()\n"); |
159 | 3045 // If: |
3046 // break Identifier; | |
3047 if (ident) | |
3048 { | |
3049 Scope *scx; | |
3050 FuncDeclaration *thisfunc = sc->func; | |
3051 | |
3052 for (scx = sc; scx; scx = scx->enclosing) | |
3053 { | |
3054 LabelStatement *ls; | |
3055 | |
3056 if (scx->func != thisfunc) // if in enclosing function | |
3057 { | |
3058 if (sc->fes) // if this is the body of a foreach | |
3059 { | |
3060 /* Post this statement to the fes, and replace | |
3061 * it with a return value that caller will put into | |
3062 * a switch. Caller will figure out where the break | |
3063 * label actually is. | |
3064 * Case numbers start with 2, not 0, as 0 is continue | |
3065 * and 1 is break. | |
3066 */ | |
3067 Statement *s; | |
3068 sc->fes->cases.push(this); | |
3069 s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); | |
3070 return s; | |
3071 } | |
3072 break; // can't break to it | |
3073 } | |
3074 | |
3075 ls = scx->slabel; | |
3076 if (ls && ls->ident == ident) | |
3077 { | |
3078 Statement *s = ls->statement; | |
3079 | |
3080 if (!s->hasBreak()) | |
3081 error("label '%s' has no break", ident->toChars()); | |
1141
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3082 if (ls->enclosingFinally != sc->enclosingFinally) |
159 | 3083 error("cannot break out of finally block"); |
3084 | |
3085 this->target = ls; | |
3086 return this; | |
3087 } | |
3088 } | |
3089 error("enclosing label '%s' for break not found", ident->toChars()); | |
3090 } | |
3091 else if (!sc->sbreak) | |
3092 { | |
3093 if (sc->fes) | |
3094 { Statement *s; | |
3095 | |
3096 // Replace break; with return 1; | |
3097 s = new ReturnStatement(0, new IntegerExp(1)); | |
3098 return s; | |
3099 } | |
3100 error("break is not inside a loop or switch"); | |
3101 } | |
3102 return this; | |
3103 } | |
3104 | |
336 | 3105 int BreakStatement::blockExit() |
3106 { | |
3107 //printf("BreakStatement::blockExit(%p) = x%x\n", this, ident ? BEgoto : BEbreak); | |
3108 return ident ? BEgoto : BEbreak; | |
3109 } | |
3110 | |
159 | 3111 void BreakStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3112 { | |
3113 buf->writestring("break"); | |
3114 if (ident) | |
3115 { buf->writebyte(' '); | |
3116 buf->writestring(ident->toChars()); | |
3117 } | |
3118 buf->writebyte(';'); | |
3119 buf->writenl(); | |
3120 } | |
3121 | |
3122 /******************************** ContinueStatement ***************************/ | |
3123 | |
3124 ContinueStatement::ContinueStatement(Loc loc, Identifier *ident) | |
3125 : Statement(loc) | |
3126 { | |
3127 this->ident = ident; | |
3128 } | |
3129 | |
3130 Statement *ContinueStatement::syntaxCopy() | |
3131 { | |
3132 ContinueStatement *s = new ContinueStatement(loc, ident); | |
3133 return s; | |
3134 } | |
3135 | |
3136 Statement *ContinueStatement::semantic(Scope *sc) | |
3137 { | |
3138 //printf("ContinueStatement::semantic() %p\n", this); | |
3139 if (ident) | |
3140 { | |
3141 Scope *scx; | |
3142 FuncDeclaration *thisfunc = sc->func; | |
3143 | |
3144 for (scx = sc; scx; scx = scx->enclosing) | |
3145 { | |
3146 LabelStatement *ls; | |
3147 | |
3148 if (scx->func != thisfunc) // if in enclosing function | |
3149 { | |
3150 if (sc->fes) // if this is the body of a foreach | |
3151 { | |
3152 for (; scx; scx = scx->enclosing) | |
3153 { | |
3154 ls = scx->slabel; | |
3155 if (ls && ls->ident == ident && ls->statement == sc->fes) | |
3156 { | |
3157 // Replace continue ident; with return 0; | |
3158 return new ReturnStatement(0, new IntegerExp(0)); | |
3159 } | |
3160 } | |
3161 | |
3162 /* Post this statement to the fes, and replace | |
3163 * it with a return value that caller will put into | |
3164 * a switch. Caller will figure out where the break | |
3165 * label actually is. | |
3166 * Case numbers start with 2, not 0, as 0 is continue | |
3167 * and 1 is break. | |
3168 */ | |
3169 Statement *s; | |
3170 sc->fes->cases.push(this); | |
3171 s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); | |
3172 return s; | |
3173 } | |
3174 break; // can't continue to it | |
3175 } | |
3176 | |
3177 ls = scx->slabel; | |
3178 if (ls && ls->ident == ident) | |
3179 { | |
3180 Statement *s = ls->statement; | |
3181 | |
3182 if (!s->hasContinue()) | |
3183 error("label '%s' has no continue", ident->toChars()); | |
1141
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3184 if (ls->enclosingFinally != sc->enclosingFinally) |
159 | 3185 error("cannot continue out of finally block"); |
3186 | |
3187 this->target = ls; | |
3188 return this; | |
3189 } | |
3190 } | |
3191 error("enclosing label '%s' for continue not found", ident->toChars()); | |
3192 } | |
3193 else if (!sc->scontinue) | |
3194 { | |
3195 if (sc->fes) | |
3196 { Statement *s; | |
3197 | |
3198 // Replace continue; with return 0; | |
3199 s = new ReturnStatement(0, new IntegerExp(0)); | |
3200 return s; | |
3201 } | |
3202 error("continue is not inside a loop"); | |
3203 } | |
3204 return this; | |
3205 } | |
3206 | |
336 | 3207 int ContinueStatement::blockExit() |
3208 { | |
3209 return ident ? BEgoto : BEcontinue; | |
3210 } | |
3211 | |
159 | 3212 void ContinueStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3213 { | |
3214 buf->writestring("continue"); | |
3215 if (ident) | |
3216 { buf->writebyte(' '); | |
3217 buf->writestring(ident->toChars()); | |
3218 } | |
3219 buf->writebyte(';'); | |
3220 buf->writenl(); | |
3221 } | |
3222 | |
3223 /******************************** SynchronizedStatement ***************************/ | |
3224 | |
3225 SynchronizedStatement::SynchronizedStatement(Loc loc, Expression *exp, Statement *body) | |
3226 : Statement(loc) | |
3227 { | |
3228 this->exp = exp; | |
3229 this->body = body; | |
3230 this->esync = NULL; | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
510
diff
changeset
|
3231 // LDC |
309 | 3232 this->llsync = NULL; |
159 | 3233 } |
3234 | |
3235 SynchronizedStatement::SynchronizedStatement(Loc loc, elem *esync, Statement *body) | |
3236 : Statement(loc) | |
3237 { | |
3238 this->exp = NULL; | |
3239 this->body = body; | |
3240 this->esync = esync; | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
510
diff
changeset
|
3241 // LDC |
309 | 3242 this->llsync = NULL; |
159 | 3243 } |
3244 | |
3245 Statement *SynchronizedStatement::syntaxCopy() | |
3246 { | |
3247 Expression *e = exp ? exp->syntaxCopy() : NULL; | |
3248 SynchronizedStatement *s = new SynchronizedStatement(loc, e, body ? body->syntaxCopy() : NULL); | |
3249 return s; | |
3250 } | |
3251 | |
3252 Statement *SynchronizedStatement::semantic(Scope *sc) | |
3253 { | |
3254 if (exp) | |
3255 { ClassDeclaration *cd; | |
3256 | |
3257 exp = exp->semantic(sc); | |
3258 exp = resolveProperties(sc, exp); | |
3259 cd = exp->type->isClassHandle(); | |
3260 if (!cd) | |
3261 error("can only synchronize on class objects, not '%s'", exp->type->toChars()); | |
3262 else if (cd->isInterfaceDeclaration()) | |
3263 { Type *t = new TypeIdentifier(0, Id::Object); | |
3264 | |
3265 t = t->semantic(0, sc); | |
3266 exp = new CastExp(loc, exp, t); | |
3267 exp = exp->semantic(sc); | |
3268 } | |
3269 } | |
3270 if (body) | |
309 | 3271 { |
1141
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3272 Statement* oldScopeExit = sc->enclosingScopeExit; |
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3273 sc->enclosingScopeExit = this; |
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3274 body = body->semantic(sc); |
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3275 sc->enclosingScopeExit = oldScopeExit; |
309 | 3276 } |
159 | 3277 return this; |
3278 } | |
3279 | |
3280 int SynchronizedStatement::hasBreak() | |
3281 { | |
3282 return FALSE; //TRUE; | |
3283 } | |
3284 | |
3285 int SynchronizedStatement::hasContinue() | |
3286 { | |
3287 return FALSE; //TRUE; | |
3288 } | |
3289 | |
3290 int SynchronizedStatement::usesEH() | |
3291 { | |
3292 return TRUE; | |
3293 } | |
3294 | |
336 | 3295 int SynchronizedStatement::blockExit() |
3296 { | |
3297 return body ? body->blockExit() : BEfallthru; | |
3298 } | |
3299 | |
159 | 3300 void SynchronizedStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3301 { | |
3302 buf->writestring("synchronized"); | |
3303 if (exp) | |
3304 { buf->writebyte('('); | |
3305 exp->toCBuffer(buf, hgs); | |
3306 buf->writebyte(')'); | |
3307 } | |
3308 if (body) | |
3309 { | |
3310 buf->writebyte(' '); | |
3311 body->toCBuffer(buf, hgs); | |
3312 } | |
3313 } | |
3314 | |
3315 /******************************** WithStatement ***************************/ | |
3316 | |
3317 WithStatement::WithStatement(Loc loc, Expression *exp, Statement *body) | |
3318 : Statement(loc) | |
3319 { | |
3320 this->exp = exp; | |
3321 this->body = body; | |
3322 wthis = NULL; | |
3323 } | |
3324 | |
3325 Statement *WithStatement::syntaxCopy() | |
3326 { | |
3327 WithStatement *s = new WithStatement(loc, exp->syntaxCopy(), body ? body->syntaxCopy() : NULL); | |
3328 return s; | |
3329 } | |
3330 | |
3331 Statement *WithStatement::semantic(Scope *sc) | |
3332 { ScopeDsymbol *sym; | |
3333 Initializer *init; | |
3334 | |
3335 //printf("WithStatement::semantic()\n"); | |
3336 exp = exp->semantic(sc); | |
3337 exp = resolveProperties(sc, exp); | |
3338 if (exp->op == TOKimport) | |
3339 { ScopeExp *es = (ScopeExp *)exp; | |
3340 | |
3341 sym = es->sds; | |
3342 } | |
3343 else if (exp->op == TOKtype) | |
3344 { TypeExp *es = (TypeExp *)exp; | |
3345 | |
3346 sym = es->type->toDsymbol(sc)->isScopeDsymbol(); | |
3347 if (!sym) | |
3348 { error("%s has no members", es->toChars()); | |
3349 body = body->semantic(sc); | |
3350 return this; | |
3351 } | |
3352 } | |
3353 else | |
3354 { Type *t = exp->type; | |
3355 | |
3356 assert(t); | |
3357 t = t->toBasetype(); | |
3358 if (t->isClassHandle()) | |
3359 { | |
3360 init = new ExpInitializer(loc, exp); | |
3361 wthis = new VarDeclaration(loc, exp->type, Id::withSym, init); | |
3362 wthis->semantic(sc); | |
3363 | |
3364 sym = new WithScopeSymbol(this); | |
3365 sym->parent = sc->scopesym; | |
3366 } | |
3367 else if (t->ty == Tstruct) | |
3368 { | |
3369 Expression *e = exp->addressOf(sc); | |
3370 init = new ExpInitializer(loc, e); | |
3371 wthis = new VarDeclaration(loc, e->type, Id::withSym, init); | |
3372 wthis->semantic(sc); | |
3373 sym = new WithScopeSymbol(this); | |
3374 sym->parent = sc->scopesym; | |
3375 } | |
3376 else | |
3377 { error("with expressions must be class objects, not '%s'", exp->type->toChars()); | |
3378 return NULL; | |
3379 } | |
3380 } | |
3381 sc = sc->push(sym); | |
3382 | |
3383 if (body) | |
3384 body = body->semantic(sc); | |
3385 | |
3386 sc->pop(); | |
3387 | |
3388 return this; | |
3389 } | |
3390 | |
3391 void WithStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3392 { | |
3393 buf->writestring("with ("); | |
3394 exp->toCBuffer(buf, hgs); | |
3395 buf->writestring(")\n"); | |
3396 if (body) | |
3397 body->toCBuffer(buf, hgs); | |
3398 } | |
3399 | |
3400 int WithStatement::usesEH() | |
3401 { | |
3402 return body ? body->usesEH() : 0; | |
3403 } | |
3404 | |
336 | 3405 int WithStatement::blockExit() |
3406 { | |
3407 int result = BEnone; | |
3408 if (exp->canThrow()) | |
3409 result = BEthrow; | |
3410 if (body) | |
3411 result |= body->blockExit(); | |
3412 else | |
3413 result |= BEfallthru; | |
3414 return result; | |
3415 } | |
3416 | |
159 | 3417 /******************************** TryCatchStatement ***************************/ |
3418 | |
3419 TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Array *catches) | |
3420 : Statement(loc) | |
3421 { | |
3422 this->body = body; | |
3423 this->catches = catches; | |
3424 } | |
3425 | |
3426 Statement *TryCatchStatement::syntaxCopy() | |
3427 { | |
3428 Array *a = new Array(); | |
3429 a->setDim(catches->dim); | |
3430 for (int i = 0; i < a->dim; i++) | |
3431 { Catch *c; | |
3432 | |
3433 c = (Catch *)catches->data[i]; | |
3434 c = c->syntaxCopy(); | |
3435 a->data[i] = c; | |
3436 } | |
3437 TryCatchStatement *s = new TryCatchStatement(loc, body->syntaxCopy(), a); | |
3438 return s; | |
3439 } | |
3440 | |
3441 Statement *TryCatchStatement::semantic(Scope *sc) | |
3442 { | |
3443 body = body->semanticScope(sc, NULL /*this*/, NULL); | |
3444 | |
336 | 3445 /* Even if body is NULL, still do semantic analysis on catches |
3446 */ | |
3447 for (size_t i = 0; i < catches->dim; i++) | |
3448 { Catch *c = (Catch *)catches->data[i]; | |
159 | 3449 c->semantic(sc); |
3450 | |
3451 // Determine if current catch 'hides' any previous catches | |
336 | 3452 for (size_t j = 0; j < i; j++) |
159 | 3453 { Catch *cj = (Catch *)catches->data[j]; |
3454 char *si = c->loc.toChars(); | |
3455 char *sj = cj->loc.toChars(); | |
3456 | |
3457 if (c->type->toBasetype()->implicitConvTo(cj->type->toBasetype())) | |
3458 error("catch at %s hides catch at %s", sj, si); | |
3459 } | |
3460 } | |
3461 return this; | |
3462 } | |
3463 | |
3464 int TryCatchStatement::hasBreak() | |
3465 { | |
3466 return FALSE; //TRUE; | |
3467 } | |
3468 | |
3469 int TryCatchStatement::usesEH() | |
3470 { | |
3471 return TRUE; | |
3472 } | |
3473 | |
336 | 3474 int TryCatchStatement::blockExit() |
3475 { int result; | |
3476 | |
3477 assert(body); | |
3478 result = body->blockExit(); | |
3479 | |
3480 for (size_t i = 0; i < catches->dim; i++) | |
3481 { | |
3482 Catch *c = (Catch *)catches->data[i]; | |
3483 result |= c->blockExit(); | |
3484 } | |
3485 return result; | |
3486 } | |
3487 | |
159 | 3488 void TryCatchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3489 { | |
3490 buf->writestring("try"); | |
3491 buf->writenl(); | |
3492 if (body) | |
3493 body->toCBuffer(buf, hgs); | |
336 | 3494 for (size_t i = 0; i < catches->dim; i++) |
159 | 3495 { |
3496 Catch *c = (Catch *)catches->data[i]; | |
3497 c->toCBuffer(buf, hgs); | |
3498 } | |
3499 } | |
3500 | |
3501 /******************************** Catch ***************************/ | |
3502 | |
3503 Catch::Catch(Loc loc, Type *t, Identifier *id, Statement *handler) | |
3504 { | |
3505 //printf("Catch(%s, loc = %s)\n", id->toChars(), loc.toChars()); | |
3506 this->loc = loc; | |
3507 this->type = t; | |
3508 this->ident = id; | |
3509 this->handler = handler; | |
3510 var = NULL; | |
3511 } | |
3512 | |
3513 Catch *Catch::syntaxCopy() | |
3514 { | |
3515 Catch *c = new Catch(loc, | |
3516 (type ? type->syntaxCopy() : NULL), | |
3517 ident, | |
3518 (handler ? handler->syntaxCopy() : NULL)); | |
3519 return c; | |
3520 } | |
3521 | |
3522 void Catch::semantic(Scope *sc) | |
3523 { ScopeDsymbol *sym; | |
3524 | |
3525 //printf("Catch::semantic(%s)\n", ident->toChars()); | |
3526 | |
3527 #ifndef IN_GCC | |
1141
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3528 if (sc->enclosingFinally) |
159 | 3529 { |
3530 /* This is because the _d_local_unwind() gets the stack munged | |
3531 * up on this. The workaround is to place any try-catches into | |
3532 * a separate function, and call that. | |
3533 * To fix, have the compiler automatically convert the finally | |
3534 * body into a nested function. | |
3535 */ | |
3536 error(loc, "cannot put catch statement inside finally block"); | |
3537 } | |
3538 #endif | |
3539 | |
3540 sym = new ScopeDsymbol(); | |
3541 sym->parent = sc->scopesym; | |
3542 sc = sc->push(sym); | |
3543 | |
3544 if (!type) | |
3545 type = new TypeIdentifier(0, Id::Object); | |
3546 type = type->semantic(loc, sc); | |
3547 if (!type->toBasetype()->isClassHandle()) | |
3548 error("can only catch class objects, not '%s'", type->toChars()); | |
3549 else if (ident) | |
3550 { | |
3551 var = new VarDeclaration(loc, type, ident, NULL); | |
3552 var->parent = sc->parent; | |
3553 sc->insert(var); | |
3554 } | |
3555 handler = handler->semantic(sc); | |
3556 | |
3557 sc->pop(); | |
3558 } | |
3559 | |
336 | 3560 int Catch::blockExit() |
3561 { | |
3562 return handler ? handler->blockExit() : BEfallthru; | |
3563 } | |
3564 | |
159 | 3565 void Catch::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3566 { | |
3567 buf->writestring("catch"); | |
3568 if (type) | |
3569 { buf->writebyte('('); | |
3570 type->toCBuffer(buf, ident, hgs); | |
3571 buf->writebyte(')'); | |
3572 } | |
3573 buf->writenl(); | |
3574 buf->writebyte('{'); | |
3575 buf->writenl(); | |
336 | 3576 if (handler) |
3577 handler->toCBuffer(buf, hgs); | |
159 | 3578 buf->writebyte('}'); |
3579 buf->writenl(); | |
3580 } | |
3581 | |
3582 /****************************** TryFinallyStatement ***************************/ | |
3583 | |
3584 TryFinallyStatement::TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody) | |
3585 : Statement(loc) | |
3586 { | |
3587 this->body = body; | |
3588 this->finalbody = finalbody; | |
3589 } | |
3590 | |
3591 Statement *TryFinallyStatement::syntaxCopy() | |
3592 { | |
3593 TryFinallyStatement *s = new TryFinallyStatement(loc, | |
3594 body->syntaxCopy(), finalbody->syntaxCopy()); | |
3595 return s; | |
3596 } | |
3597 | |
3598 Statement *TryFinallyStatement::semantic(Scope *sc) | |
3599 { | |
3600 //printf("TryFinallyStatement::semantic()\n"); | |
3601 | |
1141
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3602 Statement* oldScopeExit = sc->enclosingScopeExit; |
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3603 sc->enclosingScopeExit = this; |
159 | 3604 body = body->semantic(sc); |
1141
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3605 sc->enclosingScopeExit = oldScopeExit; |
159 | 3606 |
3607 sc = sc->push(); | |
1141
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3608 sc->enclosingFinally = this; |
159 | 3609 sc->sbreak = NULL; |
3610 sc->scontinue = NULL; // no break or continue out of finally block | |
3611 finalbody = finalbody->semantic(sc); | |
3612 sc->pop(); | |
3613 return this; | |
3614 } | |
3615 | |
3616 void TryFinallyStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3617 { | |
3618 buf->printf("try\n{\n"); | |
3619 body->toCBuffer(buf, hgs); | |
3620 buf->printf("}\nfinally\n{\n"); | |
3621 finalbody->toCBuffer(buf, hgs); | |
3622 buf->writeByte('}'); | |
3623 buf->writenl(); | |
3624 } | |
3625 | |
3626 int TryFinallyStatement::hasBreak() | |
3627 { | |
3628 return FALSE; //TRUE; | |
3629 } | |
3630 | |
3631 int TryFinallyStatement::hasContinue() | |
3632 { | |
3633 return FALSE; //TRUE; | |
3634 } | |
3635 | |
3636 int TryFinallyStatement::usesEH() | |
3637 { | |
3638 return TRUE; | |
3639 } | |
3640 | |
336 | 3641 int TryFinallyStatement::blockExit() |
3642 { | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3643 if (body) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3644 return body->blockExit(); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3645 return BEfallthru; |
336 | 3646 } |
3647 | |
159 | 3648 |
3649 /****************************** OnScopeStatement ***************************/ | |
3650 | |
3651 OnScopeStatement::OnScopeStatement(Loc loc, TOK tok, Statement *statement) | |
3652 : Statement(loc) | |
3653 { | |
3654 this->tok = tok; | |
3655 this->statement = statement; | |
3656 } | |
3657 | |
3658 Statement *OnScopeStatement::syntaxCopy() | |
3659 { | |
3660 OnScopeStatement *s = new OnScopeStatement(loc, | |
3661 tok, statement->syntaxCopy()); | |
3662 return s; | |
3663 } | |
3664 | |
3665 Statement *OnScopeStatement::semantic(Scope *sc) | |
3666 { | |
3667 /* semantic is called on results of scopeCode() */ | |
3668 return this; | |
3669 } | |
3670 | |
336 | 3671 int OnScopeStatement::blockExit() |
3672 { // At this point, this statement is just an empty placeholder | |
3673 return BEfallthru; | |
3674 } | |
3675 | |
159 | 3676 void OnScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3677 { | |
3678 buf->writestring(Token::toChars(tok)); | |
3679 buf->writebyte(' '); | |
3680 statement->toCBuffer(buf, hgs); | |
3681 } | |
3682 | |
3683 int OnScopeStatement::usesEH() | |
3684 { | |
3685 return (tok != TOKon_scope_success); | |
3686 } | |
3687 | |
3688 void OnScopeStatement::scopeCode(Statement **sentry, Statement **sexception, Statement **sfinally) | |
3689 { | |
3690 //printf("OnScopeStatement::scopeCode()\n"); | |
3691 //print(); | |
3692 *sentry = NULL; | |
3693 *sexception = NULL; | |
3694 *sfinally = NULL; | |
3695 switch (tok) | |
3696 { | |
3697 case TOKon_scope_exit: | |
3698 *sfinally = statement; | |
3699 break; | |
3700 | |
3701 case TOKon_scope_failure: | |
3702 *sexception = statement; | |
3703 break; | |
3704 | |
3705 case TOKon_scope_success: | |
3706 { | |
3707 /* Create: | |
3708 * sentry: int x = 0; | |
3709 * sexception: x = 1; | |
3710 * sfinally: if (!x) statement; | |
3711 */ | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
794
diff
changeset
|
3712 Identifier *id = Lexer::uniqueId("__os"); |
159 | 3713 |
3714 ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(0)); | |
3715 VarDeclaration *v = new VarDeclaration(loc, Type::tint32, id, ie); | |
3716 *sentry = new DeclarationStatement(loc, v); | |
3717 | |
3718 Expression *e = new IntegerExp(1); | |
3719 e = new AssignExp(0, new VarExp(0, v), e); | |
3720 *sexception = new ExpStatement(0, e); | |
3721 | |
3722 e = new VarExp(0, v); | |
3723 e = new NotExp(0, e); | |
3724 *sfinally = new IfStatement(0, NULL, e, statement, NULL); | |
3725 | |
3726 break; | |
3727 } | |
3728 | |
3729 default: | |
3730 assert(0); | |
3731 } | |
3732 } | |
3733 | |
3734 /******************************** ThrowStatement ***************************/ | |
3735 | |
3736 ThrowStatement::ThrowStatement(Loc loc, Expression *exp) | |
3737 : Statement(loc) | |
3738 { | |
3739 this->exp = exp; | |
3740 } | |
3741 | |
3742 Statement *ThrowStatement::syntaxCopy() | |
3743 { | |
3744 ThrowStatement *s = new ThrowStatement(loc, exp->syntaxCopy()); | |
3745 return s; | |
3746 } | |
3747 | |
3748 Statement *ThrowStatement::semantic(Scope *sc) | |
3749 { | |
3750 //printf("ThrowStatement::semantic()\n"); | |
3751 | |
3752 FuncDeclaration *fd = sc->parent->isFuncDeclaration(); | |
3753 fd->hasReturnExp |= 2; | |
3754 | |
3755 if (sc->incontract) | |
3756 error("Throw statements cannot be in contracts"); | |
3757 exp = exp->semantic(sc); | |
3758 exp = resolveProperties(sc, exp); | |
3759 if (!exp->type->toBasetype()->isClassHandle()) | |
3760 error("can only throw class objects, not type %s", exp->type->toChars()); | |
3761 return this; | |
3762 } | |
3763 | |
336 | 3764 int ThrowStatement::blockExit() |
3765 { | |
3766 return BEthrow; // obviously | |
3767 } | |
3768 | |
159 | 3769 void ThrowStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3770 { | |
3771 buf->printf("throw "); | |
3772 exp->toCBuffer(buf, hgs); | |
3773 buf->writeByte(';'); | |
3774 buf->writenl(); | |
3775 } | |
3776 | |
3777 /******************************** VolatileStatement **************************/ | |
3778 | |
3779 VolatileStatement::VolatileStatement(Loc loc, Statement *statement) | |
3780 : Statement(loc) | |
3781 { | |
3782 this->statement = statement; | |
3783 } | |
3784 | |
3785 Statement *VolatileStatement::syntaxCopy() | |
3786 { | |
3787 VolatileStatement *s = new VolatileStatement(loc, | |
3788 statement ? statement->syntaxCopy() : NULL); | |
3789 return s; | |
3790 } | |
3791 | |
3792 Statement *VolatileStatement::semantic(Scope *sc) | |
3793 { | |
309 | 3794 if (statement) |
3795 { | |
1141
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3796 Statement* oldScopeExit = sc->enclosingScopeExit; |
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3797 sc->enclosingScopeExit = this; |
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3798 statement = statement->semantic(sc); |
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3799 sc->enclosingScopeExit = oldScopeExit; |
309 | 3800 } |
159 | 3801 return this; |
3802 } | |
3803 | |
3804 Statements *VolatileStatement::flatten(Scope *sc) | |
3805 { | |
3806 Statements *a; | |
3807 | |
3808 a = statement ? statement->flatten(sc) : NULL; | |
3809 if (a) | |
3810 { for (int i = 0; i < a->dim; i++) | |
3811 { Statement *s = (Statement *)a->data[i]; | |
3812 | |
3813 s = new VolatileStatement(loc, s); | |
3814 a->data[i] = s; | |
3815 } | |
3816 } | |
3817 | |
3818 return a; | |
3819 } | |
3820 | |
336 | 3821 int VolatileStatement::blockExit() |
3822 { | |
3823 return statement ? statement->blockExit() : BEfallthru; | |
3824 } | |
3825 | |
159 | 3826 void VolatileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3827 { | |
3828 buf->writestring("volatile"); | |
3829 if (statement) | |
3830 { if (statement->isScopeStatement()) | |
3831 buf->writenl(); | |
3832 else | |
3833 buf->writebyte(' '); | |
3834 statement->toCBuffer(buf, hgs); | |
3835 } | |
3836 } | |
3837 | |
3838 | |
3839 /******************************** GotoStatement ***************************/ | |
3840 | |
3841 GotoStatement::GotoStatement(Loc loc, Identifier *ident) | |
3842 : Statement(loc) | |
3843 { | |
3844 this->ident = ident; | |
3845 this->label = NULL; | |
1141
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3846 this->enclosingFinally = NULL; |
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3847 this->enclosingScopeExit = NULL; |
159 | 3848 } |
3849 | |
3850 Statement *GotoStatement::syntaxCopy() | |
3851 { | |
3852 GotoStatement *s = new GotoStatement(loc, ident); | |
3853 return s; | |
3854 } | |
3855 | |
3856 Statement *GotoStatement::semantic(Scope *sc) | |
3857 { FuncDeclaration *fd = sc->parent->isFuncDeclaration(); | |
3858 | |
3859 //printf("GotoStatement::semantic()\n"); | |
1141
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3860 enclosingFinally = sc->enclosingFinally; |
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3861 enclosingScopeExit = sc->enclosingScopeExit; |
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3862 |
159 | 3863 label = fd->searchLabel(ident); |
3864 if (!label->statement && sc->fes) | |
3865 { | |
3866 /* Either the goto label is forward referenced or it | |
3867 * is in the function that the enclosing foreach is in. | |
3868 * Can't know yet, so wrap the goto in a compound statement | |
3869 * so we can patch it later, and add it to a 'look at this later' | |
3870 * list. | |
3871 */ | |
3872 Statements *a = new Statements(); | |
3873 Statement *s; | |
3874 | |
3875 a->push(this); | |
3876 s = new CompoundStatement(loc, a); | |
3877 sc->fes->gotos.push(s); // 'look at this later' list | |
3878 return s; | |
3879 } | |
1141
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3880 if (label->statement && label->statement->enclosingFinally != sc->enclosingFinally) |
159 | 3881 error("cannot goto in or out of finally block"); |
3882 return this; | |
3883 } | |
3884 | |
336 | 3885 int GotoStatement::blockExit() |
3886 { | |
3887 //printf("GotoStatement::blockExit(%p)\n", this); | |
3888 return BEgoto; | |
3889 } | |
3890 | |
159 | 3891 void GotoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3892 { | |
3893 buf->writestring("goto "); | |
3894 buf->writestring(ident->toChars()); | |
3895 buf->writebyte(';'); | |
3896 buf->writenl(); | |
3897 } | |
3898 | |
3899 /******************************** LabelStatement ***************************/ | |
3900 | |
3901 LabelStatement::LabelStatement(Loc loc, Identifier *ident, Statement *statement) | |
3902 : Statement(loc) | |
3903 { | |
3904 this->ident = ident; | |
3905 this->statement = statement; | |
1141
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3906 this->enclosingFinally = NULL; |
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3907 this->enclosingScopeExit = NULL; |
159 | 3908 this->lblock = NULL; |
3909 this->isReturnLabel = 0; | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
304
diff
changeset
|
3910 this->asmLabel = false; |
159 | 3911 } |
3912 | |
3913 Statement *LabelStatement::syntaxCopy() | |
3914 { | |
3915 LabelStatement *s = new LabelStatement(loc, ident, statement->syntaxCopy()); | |
3916 return s; | |
3917 } | |
3918 | |
3919 Statement *LabelStatement::semantic(Scope *sc) | |
3920 { LabelDsymbol *ls; | |
3921 FuncDeclaration *fd = sc->parent->isFuncDeclaration(); | |
3922 | |
3923 //printf("LabelStatement::semantic()\n"); | |
3924 ls = fd->searchLabel(ident); | |
3925 if (ls->statement) | |
3926 error("Label '%s' already defined", ls->toChars()); | |
3927 else | |
3928 ls->statement = this; | |
1141
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3929 |
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3930 enclosingFinally = sc->enclosingFinally; |
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3931 enclosingScopeExit = sc->enclosingScopeExit; |
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1133
diff
changeset
|
3932 |
159 | 3933 sc = sc->push(); |
3934 sc->scopesym = sc->enclosing->scopesym; | |
3935 sc->callSuper |= CSXlabel; | |
3936 sc->slabel = this; | |
3937 if (statement) | |
3938 statement = statement->semantic(sc); | |
3939 sc->pop(); | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
304
diff
changeset
|
3940 |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
510
diff
changeset
|
3941 // LDC put in labmap |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
304
diff
changeset
|
3942 fd->labmap[ident->toChars()] = this; |
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
304
diff
changeset
|
3943 |
159 | 3944 return this; |
3945 } | |
3946 | |
3947 Statements *LabelStatement::flatten(Scope *sc) | |
3948 { | |
3949 Statements *a = NULL; | |
3950 | |
3951 if (statement) | |
3952 { | |
3953 a = statement->flatten(sc); | |
3954 if (a) | |
3955 { | |
3956 if (!a->dim) | |
3957 { | |
3958 a->push(new ExpStatement(loc, NULL)); | |
3959 } | |
3960 Statement *s = (Statement *)a->data[0]; | |
3961 | |
3962 s = new LabelStatement(loc, ident, s); | |
3963 a->data[0] = s; | |
3964 } | |
3965 } | |
3966 | |
3967 return a; | |
3968 } | |
3969 | |
3970 | |
3971 int LabelStatement::usesEH() | |
3972 { | |
3973 return statement ? statement->usesEH() : FALSE; | |
3974 } | |
3975 | |
336 | 3976 int LabelStatement::blockExit() |
3977 { | |
3978 //printf("LabelStatement::blockExit(%p)\n", this); | |
3979 return statement ? statement->blockExit() : BEfallthru; | |
3980 } | |
3981 | |
159 | 3982 int LabelStatement::comeFrom() |
3983 { | |
3984 //printf("LabelStatement::comeFrom()\n"); | |
3985 return TRUE; | |
3986 } | |
3987 | |
3988 void LabelStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3989 { | |
3990 buf->writestring(ident->toChars()); | |
3991 buf->writebyte(':'); | |
3992 buf->writenl(); | |
3993 if (statement) | |
3994 statement->toCBuffer(buf, hgs); | |
3995 } | |
3996 | |
3997 | |
3998 /******************************** LabelDsymbol ***************************/ | |
3999 | |
4000 LabelDsymbol::LabelDsymbol(Identifier *ident) | |
4001 : Dsymbol(ident) | |
4002 { | |
4003 statement = NULL; | |
4004 } | |
4005 | |
4006 LabelDsymbol *LabelDsymbol::isLabel() // is this a LabelDsymbol()? | |
4007 { | |
4008 return this; | |
4009 } |