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