Mercurial > projects > ldc
comparison dmd/statement.c @ 1587:def7a1d494fd
Merge DMD 1.051
author | Christian Kamm <kamm incasoftware de> |
---|---|
date | Fri, 06 Nov 2009 23:58:01 +0100 |
parents | 05c235309d6f |
children | 207a8a438dea |
comparison
equal
deleted
inserted
replaced
1586:7f728c52e63c | 1587:def7a1d494fd |
---|---|
27 #include "hdrgen.h" | 27 #include "hdrgen.h" |
28 #include "parse.h" | 28 #include "parse.h" |
29 #include "template.h" | 29 #include "template.h" |
30 #include "attrib.h" | 30 #include "attrib.h" |
31 | 31 |
32 extern int os_critsecsize(); | |
33 | |
32 /******************************** Statement ***************************/ | 34 /******************************** Statement ***************************/ |
33 | 35 |
34 Statement::Statement(Loc loc) | 36 Statement::Statement(Loc loc) |
35 : loc(loc) | 37 : loc(loc) |
36 { | 38 { |
139 // TRUE if statement 'comes from' somewhere else, like a goto | 141 // TRUE if statement 'comes from' somewhere else, like a goto |
140 | 142 |
141 int Statement::comeFrom() | 143 int Statement::comeFrom() |
142 { | 144 { |
143 //printf("Statement::comeFrom()\n"); | 145 //printf("Statement::comeFrom()\n"); |
146 return FALSE; | |
147 } | |
148 | |
149 // Return TRUE if statement has no code in it | |
150 int Statement::isEmpty() | |
151 { | |
152 //printf("Statement::isEmpty()\n"); | |
144 return FALSE; | 153 return FALSE; |
145 } | 154 } |
146 | 155 |
147 /**************************************** | 156 /**************************************** |
148 * If this statement has code that needs to run in a finally clause | 157 * If this statement has code that needs to run in a finally clause |
152 * *sentry code executed upon entry to the scope | 161 * *sentry code executed upon entry to the scope |
153 * *sexception code executed upon exit from the scope via exception | 162 * *sexception code executed upon exit from the scope via exception |
154 * *sfinally code executed in finally block | 163 * *sfinally code executed in finally block |
155 */ | 164 */ |
156 | 165 |
157 void Statement::scopeCode(Statement **sentry, Statement **sexception, Statement **sfinally) | 166 void Statement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally) |
158 { | 167 { |
159 //printf("Statement::scopeCode()\n"); | 168 //printf("Statement::scopeCode()\n"); |
160 //print(); | 169 //print(); |
161 *sentry = NULL; | 170 *sentry = NULL; |
162 *sexception = NULL; | 171 *sexception = NULL; |
172 Statements *Statement::flatten(Scope *sc) | 181 Statements *Statement::flatten(Scope *sc) |
173 { | 182 { |
174 return NULL; | 183 return NULL; |
175 } | 184 } |
176 | 185 |
186 | |
187 /******************************** PeelStatement ***************************/ | |
188 | |
189 PeelStatement::PeelStatement(Statement *s) | |
190 : Statement(s->loc) | |
191 { | |
192 this->s = s; | |
193 } | |
194 | |
195 Statement *PeelStatement::semantic(Scope *sc) | |
196 { | |
197 /* "peel" off this wrapper, and don't run semantic() | |
198 * on the result. | |
199 */ | |
200 return s; | |
201 } | |
177 | 202 |
178 /******************************** ExpStatement ***************************/ | 203 /******************************** ExpStatement ***************************/ |
179 | 204 |
180 ExpStatement::ExpStatement(Loc loc, Expression *exp) | 205 ExpStatement::ExpStatement(Loc loc, Expression *exp) |
181 : Statement(loc) | 206 : Statement(loc) |
234 result |= BEthrow; | 259 result |= BEthrow; |
235 } | 260 } |
236 return result; | 261 return result; |
237 } | 262 } |
238 | 263 |
264 int ExpStatement::isEmpty() | |
265 { | |
266 return exp == NULL; | |
267 } | |
268 | |
239 | 269 |
240 /******************************** CompileStatement ***************************/ | 270 /******************************** CompileStatement ***************************/ |
241 | 271 |
242 CompileStatement::CompileStatement(Loc loc, Expression *exp) | 272 CompileStatement::CompileStatement(Loc loc, Expression *exp) |
243 : Statement(loc) | 273 : Statement(loc) |
313 { | 343 { |
314 DeclarationStatement *ds = new DeclarationStatement(loc, exp->syntaxCopy()); | 344 DeclarationStatement *ds = new DeclarationStatement(loc, exp->syntaxCopy()); |
315 return ds; | 345 return ds; |
316 } | 346 } |
317 | 347 |
318 void DeclarationStatement::scopeCode(Statement **sentry, Statement **sexception, Statement **sfinally) | 348 void DeclarationStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally) |
319 { | 349 { |
320 //printf("DeclarationStatement::scopeCode()\n"); | 350 //printf("DeclarationStatement::scopeCode()\n"); |
321 //print(); | 351 //print(); |
322 | 352 |
323 *sentry = NULL; | 353 *sentry = NULL; |
331 DeclarationExp *de = (DeclarationExp *)(exp); | 361 DeclarationExp *de = (DeclarationExp *)(exp); |
332 VarDeclaration *v = de->declaration->isVarDeclaration(); | 362 VarDeclaration *v = de->declaration->isVarDeclaration(); |
333 if (v) | 363 if (v) |
334 { Expression *e; | 364 { Expression *e; |
335 | 365 |
336 e = v->callScopeDtor(); | 366 e = v->callScopeDtor(sc); |
337 if (e) | 367 if (e) |
338 { | 368 { |
339 //printf("dtor is: "); e->print(); | 369 //printf("dtor is: "); e->print(); |
340 *sfinally = new ExpStatement(loc, e); | 370 *sfinally = new ExpStatement(loc, e); |
341 } | 371 } |
405 { | 435 { |
406 Statement *sentry; | 436 Statement *sentry; |
407 Statement *sexception; | 437 Statement *sexception; |
408 Statement *sfinally; | 438 Statement *sfinally; |
409 | 439 |
410 s->scopeCode(&sentry, &sexception, &sfinally); | 440 s->scopeCode(sc, &sentry, &sexception, &sfinally); |
411 if (sentry) | 441 if (sentry) |
412 { | 442 { |
413 sentry = sentry->semantic(sc); | 443 sentry = sentry->semantic(sc); |
414 statements->data[i] = sentry; | 444 statements->data[i] = sentry; |
415 } | 445 } |
553 { | 583 { |
554 //printf("result = x%x\n", result); | 584 //printf("result = x%x\n", result); |
555 //printf("%s\n", s->toChars()); | 585 //printf("%s\n", s->toChars()); |
556 if (!(result & BEfallthru) && !s->comeFrom()) | 586 if (!(result & BEfallthru) && !s->comeFrom()) |
557 { | 587 { |
558 s->warning("statement is not reachable"); | 588 if (s->blockExit() != BEhalt && !s->isEmpty()) |
589 s->warning("statement is not reachable"); | |
559 } | 590 } |
560 | 591 else |
561 result &= ~BEfallthru; | 592 { |
562 result |= s->blockExit(); | 593 result &= ~BEfallthru; |
594 result |= s->blockExit(); | |
595 } | |
563 } | 596 } |
564 } | 597 } |
565 return result; | 598 return result; |
566 } | 599 } |
567 | 600 |
576 continue; | 609 continue; |
577 | 610 |
578 comefrom |= s->comeFrom(); | 611 comefrom |= s->comeFrom(); |
579 } | 612 } |
580 return comefrom; | 613 return comefrom; |
614 } | |
615 | |
616 int CompoundStatement::isEmpty() | |
617 { | |
618 for (int i = 0; i < statements->dim; i++) | |
619 { Statement *s = (Statement *) statements->data[i]; | |
620 if (s && !s->isEmpty()) | |
621 return FALSE; | |
622 } | |
623 return TRUE; | |
581 } | 624 } |
582 | 625 |
583 | 626 |
584 /******************************** CompoundDeclarationStatement ***************************/ | 627 /******************************** CompoundDeclarationStatement ***************************/ |
585 | 628 |
811 { | 854 { |
812 Statement *sentry; | 855 Statement *sentry; |
813 Statement *sexception; | 856 Statement *sexception; |
814 Statement *sfinally; | 857 Statement *sfinally; |
815 | 858 |
816 statement->scopeCode(&sentry, &sexception, &sfinally); | 859 statement->scopeCode(sc, &sentry, &sexception, &sfinally); |
817 if (sfinally) | 860 if (sfinally) |
818 { | 861 { |
819 //printf("adding sfinally\n"); | 862 //printf("adding sfinally\n"); |
820 statement = new CompoundStatement(loc, statement, sfinally); | 863 statement = new CompoundStatement(loc, statement, sfinally); |
821 } | 864 } |
846 { | 889 { |
847 //printf("ScopeStatement::blockExit(%p)\n", statement); | 890 //printf("ScopeStatement::blockExit(%p)\n", statement); |
848 return statement ? statement->blockExit() : BEfallthru; | 891 return statement ? statement->blockExit() : BEfallthru; |
849 } | 892 } |
850 | 893 |
894 | |
851 int ScopeStatement::comeFrom() | 895 int ScopeStatement::comeFrom() |
852 { | 896 { |
853 //printf("ScopeStatement::comeFrom()\n"); | 897 //printf("ScopeStatement::comeFrom()\n"); |
854 return statement ? statement->comeFrom() : FALSE; | 898 return statement ? statement->comeFrom() : FALSE; |
855 } | 899 } |
856 | 900 |
901 int ScopeStatement::isEmpty() | |
902 { | |
903 //printf("ScopeStatement::isEmpty() %d\n", statement ? statement->isEmpty() : TRUE); | |
904 return statement ? statement->isEmpty() : TRUE; | |
905 } | |
906 | |
857 void ScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 907 void ScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
858 { | 908 { |
859 buf->writeByte('{'); | 909 buf->writeByte('{'); |
860 buf->writenl(); | 910 buf->writenl(); |
861 | 911 |
882 } | 932 } |
883 | 933 |
884 | 934 |
885 Statement *WhileStatement::semantic(Scope *sc) | 935 Statement *WhileStatement::semantic(Scope *sc) |
886 { | 936 { |
887 #if 0 | 937 /* Rewrite as a for(;condition;) loop |
888 if (condition->op == TOKmatch) | 938 */ |
889 { | 939 |
890 /* Rewrite while (condition) body as: | 940 Statement *s = new ForStatement(loc, NULL, condition, NULL, body); |
891 * if (condition) | 941 s = s->semantic(sc); |
892 * do | 942 return s; |
893 * body | |
894 * while ((_match = _match.opNext), _match); | |
895 */ | |
896 | |
897 Expression *ew = new IdentifierExp(0, Id::_match); | |
898 ew = new DotIdExp(0, ew, Id::next); | |
899 ew = new AssignExp(0, new IdentifierExp(0, Id::_match), ew); | |
900 ////ew = new EqualExp(TOKnotequal, 0, ew, new NullExp(0)); | |
901 Expression *ev = new IdentifierExp(0, Id::_match); | |
902 //ev = new CastExp(0, ev, Type::tvoidptr); | |
903 ew = new CommaExp(0, ew, ev); | |
904 Statement *sw = new DoStatement(loc, body, ew); | |
905 Statement *si = new IfStatement(loc, condition, sw, NULL); | |
906 return si->semantic(sc); | |
907 } | |
908 #endif | |
909 | |
910 condition = condition->semantic(sc); | |
911 condition = resolveProperties(sc, condition); | |
912 condition = condition->optimize(WANTvalue); | |
913 condition = condition->checkToBoolean(); | |
914 | |
915 sc->noctor++; | |
916 | |
917 Scope *scd = sc->push(); | |
918 scd->sbreak = this; | |
919 scd->scontinue = this; | |
920 if (body) | |
921 body = body->semantic(scd); | |
922 scd->pop(); | |
923 | |
924 sc->noctor--; | |
925 | |
926 return this; | |
927 } | 943 } |
928 | 944 |
929 int WhileStatement::hasBreak() | 945 int WhileStatement::hasBreak() |
930 { | 946 { |
931 return TRUE; | 947 return TRUE; |
936 return TRUE; | 952 return TRUE; |
937 } | 953 } |
938 | 954 |
939 int WhileStatement::usesEH() | 955 int WhileStatement::usesEH() |
940 { | 956 { |
957 assert(0); | |
941 return body ? body->usesEH() : 0; | 958 return body ? body->usesEH() : 0; |
942 } | 959 } |
943 | 960 |
944 int WhileStatement::blockExit() | 961 int WhileStatement::blockExit() |
945 { | 962 { |
963 assert(0); | |
946 //printf("WhileStatement::blockExit(%p)\n", this); | 964 //printf("WhileStatement::blockExit(%p)\n", this); |
947 | 965 |
948 int result = BEnone; | 966 int result = BEnone; |
949 if (condition->canThrow()) | 967 if (condition->canThrow()) |
950 result |= BEthrow; | 968 result |= BEthrow; |
971 } | 989 } |
972 | 990 |
973 | 991 |
974 int WhileStatement::comeFrom() | 992 int WhileStatement::comeFrom() |
975 { | 993 { |
994 assert(0); | |
976 if (body) | 995 if (body) |
977 return body->comeFrom(); | 996 return body->comeFrom(); |
978 return FALSE; | 997 return FALSE; |
979 } | 998 } |
980 | 999 |
1122 condition = condition->checkToBoolean(); | 1141 condition = condition->checkToBoolean(); |
1123 } | 1142 } |
1124 if (increment) | 1143 if (increment) |
1125 { increment = increment->semantic(sc); | 1144 { increment = increment->semantic(sc); |
1126 increment = resolveProperties(sc, increment); | 1145 increment = resolveProperties(sc, increment); |
1146 increment = increment->optimize(0); | |
1127 } | 1147 } |
1128 | 1148 |
1129 sc->sbreak = this; | 1149 sc->sbreak = this; |
1130 sc->scontinue = this; | 1150 sc->scontinue = this; |
1131 if (body) | 1151 if (body) |
1134 | 1154 |
1135 sc->pop(); | 1155 sc->pop(); |
1136 return this; | 1156 return this; |
1137 } | 1157 } |
1138 | 1158 |
1139 void ForStatement::scopeCode(Statement **sentry, Statement **sexception, Statement **sfinally) | 1159 void ForStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally) |
1140 { | 1160 { |
1141 //printf("ForStatement::scopeCode()\n"); | 1161 //printf("ForStatement::scopeCode()\n"); |
1142 //print(); | 1162 //print(); |
1143 if (init) | 1163 if (init) |
1144 init->scopeCode(sentry, sexception, sfinally); | 1164 init->scopeCode(sc, sentry, sexception, sfinally); |
1145 else | 1165 else |
1146 Statement::scopeCode(sentry, sexception, sfinally); | 1166 Statement::scopeCode(sc, sentry, sexception, sfinally); |
1147 } | 1167 } |
1148 | 1168 |
1149 int ForStatement::hasBreak() | 1169 int ForStatement::hasBreak() |
1150 { | 1170 { |
1151 //printf("ForStatement::hasBreak()\n"); | 1171 //printf("ForStatement::hasBreak()\n"); |
1171 return result; | 1191 return result; |
1172 } | 1192 } |
1173 if (condition) | 1193 if (condition) |
1174 { if (condition->canThrow()) | 1194 { if (condition->canThrow()) |
1175 result |= BEthrow; | 1195 result |= BEthrow; |
1196 if (condition->isBool(TRUE)) | |
1197 result &= ~BEfallthru; | |
1198 else if (condition->isBool(FALSE)) | |
1199 return result; | |
1176 } | 1200 } |
1177 else | 1201 else |
1178 result &= ~BEfallthru; // the body must do the exiting | 1202 result &= ~BEfallthru; // the body must do the exiting |
1179 if (body) | 1203 if (body) |
1180 { int r = body->blockExit(); | 1204 { int r = body->blockExit(); |
1350 // Declare value | 1374 // Declare value |
1351 if (arg->storageClass & (STCout | STCref | STClazy)) | 1375 if (arg->storageClass & (STCout | STCref | STClazy)) |
1352 error("no storage class for value %s", arg->ident->toChars()); | 1376 error("no storage class for value %s", arg->ident->toChars()); |
1353 Dsymbol *var; | 1377 Dsymbol *var; |
1354 if (te) | 1378 if (te) |
1355 { | 1379 { Type *tb = e->type->toBasetype(); |
1356 if (e->type->toBasetype()->ty == Tfunction && | 1380 if ((tb->ty == Tfunction || tb->ty == Tsarray) && e->op == TOKvar) |
1357 e->op == TOKvar) | |
1358 { VarExp *ve = (VarExp *)e; | 1381 { VarExp *ve = (VarExp *)e; |
1359 var = new AliasDeclaration(loc, arg->ident, ve->var); | 1382 var = new AliasDeclaration(loc, arg->ident, ve->var); |
1360 } | 1383 } |
1361 else | 1384 else |
1362 { | 1385 { |
1437 } | 1460 } |
1438 | 1461 |
1439 for (size_t i = 0; i < dim; i++) | 1462 for (size_t i = 0; i < dim; i++) |
1440 { // Declare args | 1463 { // Declare args |
1441 Argument *arg = (Argument *)arguments->data[i]; | 1464 Argument *arg = (Argument *)arguments->data[i]; |
1465 Type *argtype = arg->type->semantic(loc, sc); | |
1442 VarDeclaration *var; | 1466 VarDeclaration *var; |
1443 | 1467 |
1444 var = new VarDeclaration(loc, arg->type, arg->ident, NULL); | 1468 var = new VarDeclaration(loc, argtype, arg->ident, NULL); |
1445 var->storage_class |= STCforeach; | 1469 var->storage_class |= STCforeach; |
1446 var->storage_class |= arg->storageClass & (STCin | STCout | STCref); | 1470 var->storage_class |= arg->storageClass & (STCin | STCout | STCref); |
1447 #if 1 | 1471 |
1448 DeclarationExp *de = new DeclarationExp(loc, var); | |
1449 de->semantic(sc); | |
1450 #else | |
1451 var->semantic(sc); | |
1452 if (!sc->insert(var)) | |
1453 error("%s already defined", var->ident->toChars()); | |
1454 #endif | |
1455 if (dim == 2 && i == 0) | 1472 if (dim == 2 && i == 0) |
1456 key = var; | 1473 key = var; |
1457 else | 1474 else |
1458 value = var; | 1475 value = var; |
1476 #if 0 | |
1477 DeclarationExp *de = new DeclarationExp(loc, var); | |
1478 de->semantic(sc); | |
1479 #endif | |
1459 } | 1480 } |
1460 | 1481 |
1461 sc->sbreak = this; | 1482 #if 1 |
1462 sc->scontinue = this; | 1483 { |
1463 body = body->semantic(sc); | 1484 /* Convert to a ForStatement |
1464 | 1485 * foreach (key, value; a) body => |
1486 * for (T[] tmp = a[], size_t key; key < tmp.length; ++key) | |
1487 * { T value = tmp[k]; body } | |
1488 * | |
1489 * foreach_reverse (key, value; a) body => | |
1490 * for (T[] tmp = a[], size_t key = tmp.length; key--; ) | |
1491 * { T value = tmp[k]; body } | |
1492 */ | |
1493 Identifier *id = Lexer::uniqueId("__aggr"); | |
1494 ExpInitializer *ie = new ExpInitializer(loc, new SliceExp(loc, aggr, NULL, NULL)); | |
1495 VarDeclaration *tmp = new VarDeclaration(loc, aggr->type->nextOf()->arrayOf(), id, ie); | |
1496 | |
1497 Expression *tmp_length = new DotIdExp(loc, new VarExp(loc, tmp), Id::length); | |
1498 | |
1499 if (!key) | |
1500 { | |
1501 Identifier *id = Lexer::uniqueId("__key"); | |
1502 key = new VarDeclaration(loc, Type::tsize_t, id, NULL); | |
1503 } | |
1504 if (op == TOKforeach_reverse) | |
1505 key->init = new ExpInitializer(loc, tmp_length); | |
1506 else | |
1507 key->init = new ExpInitializer(loc, new IntegerExp(0)); | |
1508 | |
1509 Statements *cs = new Statements(); | |
1510 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); | |
1511 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key))); | |
1512 Statement *forinit = new CompoundDeclarationStatement(loc, cs); | |
1513 | |
1514 Expression *cond; | |
1515 if (op == TOKforeach_reverse) | |
1516 // key-- | |
1517 cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key)); | |
1518 else | |
1519 // key < tmp.length | |
1520 cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), tmp_length); | |
1521 | |
1522 Expression *increment = NULL; | |
1523 if (op == TOKforeach) | |
1524 // key += 1 | |
1525 increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1)); | |
1526 | |
1527 // T value = tmp[key]; | |
1528 value->init = new ExpInitializer(loc, new IndexExp(loc, new VarExp(loc, tmp), new VarExp(loc, key))); | |
1529 Statement *ds = new DeclarationStatement(loc, new DeclarationExp(loc, value)); | |
1530 | |
1531 body = new CompoundStatement(loc, ds, body); | |
1532 | |
1533 ForStatement *fs = new ForStatement(loc, forinit, cond, increment, body); | |
1534 s = fs->semantic(sc); | |
1535 break; | |
1536 } | |
1537 #else | |
1465 if (!value->type->equals(tab->next)) | 1538 if (!value->type->equals(tab->next)) |
1466 { | 1539 { |
1467 if (aggr->op == TOKstring) | 1540 if (aggr->op == TOKstring) |
1468 aggr = aggr->implicitCastTo(sc, value->type->arrayOf()); | 1541 aggr = aggr->implicitCastTo(sc, value->type->arrayOf()); |
1469 else | 1542 else |
1470 error("foreach: %s is not an array of %s", | 1543 error("foreach: %s is not an array of %s", |
1471 tab->toChars(), value->type->toChars()); | 1544 tab->toChars(), value->type->toChars()); |
1472 } | 1545 } |
1473 | 1546 |
1474 if (key && key->type->ty != Tint32 && key->type->ty != Tuns32) | 1547 if (key) |
1475 { | 1548 { |
1476 if (global.params.is64bit) | 1549 if (key->type->ty != Tint32 && key->type->ty != Tuns32) |
1477 { | 1550 { |
1478 if (key->type->ty != Tint64 && key->type->ty != Tuns64) | 1551 if (global.params.is64bit) |
1479 error("foreach: key type must be int or uint, long or ulong, not %s", key->type->toChars()); | 1552 { |
1553 if (key->type->ty != Tint64 && key->type->ty != Tuns64) | |
1554 error("foreach: key type must be int or uint, long or ulong, not %s", key->type->toChars()); | |
1555 } | |
1556 else | |
1557 error("foreach: key type must be int or uint, not %s", key->type->toChars()); | |
1480 } | 1558 } |
1481 else | 1559 |
1482 error("foreach: key type must be int or uint, not %s", key->type->toChars()); | 1560 if (key->storage_class & (STCout | STCref)) |
1561 error("foreach: key cannot be out or ref"); | |
1483 } | 1562 } |
1484 | 1563 |
1485 if (key && key->storage_class & (STCout | STCref)) | 1564 sc->sbreak = this; |
1486 error("foreach: key cannot be out or ref"); | 1565 sc->scontinue = this; |
1566 body = body->semantic(sc); | |
1487 break; | 1567 break; |
1568 #endif | |
1488 | 1569 |
1489 case Taarray: | 1570 case Taarray: |
1490 taa = (TypeAArray *)tab; | 1571 taa = (TypeAArray *)tab; |
1491 if (dim < 1 || dim > 2) | 1572 if (dim < 1 || dim > 2) |
1492 { | 1573 { |
1502 case Tclass: | 1583 case Tclass: |
1503 case Tstruct: | 1584 case Tstruct: |
1504 #if DMDV2 | 1585 #if DMDV2 |
1505 { /* Look for range iteration, i.e. the properties | 1586 { /* Look for range iteration, i.e. the properties |
1506 * .empty, .next, .retreat, .head and .rear | 1587 * .empty, .next, .retreat, .head and .rear |
1507 * foreach (e; range) { ... } | 1588 * foreach (e; aggr) { ... } |
1508 * translates to: | 1589 * translates to: |
1509 * for (auto __r = range; !__r.empty; __r.next) | 1590 * for (auto __r = aggr[]; !__r.empty; __r.next) |
1510 * { auto e = __r.head; | 1591 * { auto e = __r.head; |
1511 * ... | 1592 * ... |
1512 * } | 1593 * } |
1513 */ | 1594 */ |
1514 if (dim != 1) // only one argument allowed with ranges | 1595 if (dim != 1) // only one argument allowed with ranges |
1521 if (op == TOKforeach) | 1602 if (op == TOKforeach) |
1522 { idhead = Id::Fhead; | 1603 { idhead = Id::Fhead; |
1523 idnext = Id::Fnext; | 1604 idnext = Id::Fnext; |
1524 } | 1605 } |
1525 else | 1606 else |
1526 { idhead = Id::Frear; | 1607 { idhead = Id::Ftoe; |
1527 idnext = Id::Fretreat; | 1608 idnext = Id::Fretreat; |
1528 } | 1609 } |
1529 Dsymbol *shead = search_function(ad, idhead); | 1610 Dsymbol *shead = search_function(ad, idhead); |
1530 if (!shead) | 1611 if (!shead) |
1531 goto Lapply; | 1612 goto Lapply; |
1532 | 1613 |
1533 /* Generate a temporary __r and initialize it with the aggregate. | 1614 /* Generate a temporary __r and initialize it with the aggregate. |
1534 */ | 1615 */ |
1535 Identifier *id = Identifier::generateId("__r"); | 1616 Identifier *id = Identifier::generateId("__r"); |
1536 VarDeclaration *r = new VarDeclaration(loc, NULL, id, new ExpInitializer(loc, aggr)); | 1617 Expression *rinit = new SliceExp(loc, aggr, NULL, NULL); |
1537 r->semantic(sc); | 1618 rinit = rinit->trySemantic(sc); |
1619 if (!rinit) // if application of [] failed | |
1620 rinit = aggr; | |
1621 VarDeclaration *r = new VarDeclaration(loc, NULL, id, new ExpInitializer(loc, rinit)); | |
1622 // r->semantic(sc); | |
1623 //printf("r: %s, init: %s\n", r->toChars(), r->init->toChars()); | |
1538 Statement *init = new DeclarationStatement(loc, r); | 1624 Statement *init = new DeclarationStatement(loc, r); |
1625 //printf("init: %s\n", init->toChars()); | |
1539 | 1626 |
1540 // !__r.empty | 1627 // !__r.empty |
1541 Expression *e = new VarExp(loc, r); | 1628 Expression *e = new VarExp(loc, r); |
1542 e = new DotIdExp(loc, e, Id::Fempty); | 1629 e = new DotIdExp(loc, e, Id::Fempty); |
1543 Expression *condition = new NotExp(loc, e); | 1630 Expression *condition = new NotExp(loc, e); |
1549 /* Declaration statement for e: | 1636 /* Declaration statement for e: |
1550 * auto e = __r.idhead; | 1637 * auto e = __r.idhead; |
1551 */ | 1638 */ |
1552 e = new VarExp(loc, r); | 1639 e = new VarExp(loc, r); |
1553 Expression *einit = new DotIdExp(loc, e, idhead); | 1640 Expression *einit = new DotIdExp(loc, e, idhead); |
1554 einit = einit->semantic(sc); | 1641 // einit = einit->semantic(sc); |
1555 Argument *arg = (Argument *)arguments->data[0]; | 1642 Argument *arg = (Argument *)arguments->data[0]; |
1556 VarDeclaration *ve = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, einit)); | 1643 VarDeclaration *ve = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, einit)); |
1557 ve->storage_class |= STCforeach; | 1644 ve->storage_class |= STCforeach; |
1558 ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STCconst | STCinvariant); | 1645 ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR); |
1559 | 1646 |
1560 DeclarationExp *de = new DeclarationExp(loc, ve); | 1647 DeclarationExp *de = new DeclarationExp(loc, ve); |
1561 | 1648 |
1562 Statement *body = new CompoundStatement(loc, | 1649 Statement *body = new CompoundStatement(loc, |
1563 new DeclarationStatement(loc, de), this->body); | 1650 new DeclarationStatement(loc, de), this->body); |
1564 | 1651 |
1565 s = new ForStatement(loc, init, condition, increment, body); | 1652 s = new ForStatement(loc, init, condition, increment, body); |
1653 #if 0 | |
1654 printf("init: %s\n", init->toChars()); | |
1655 printf("condition: %s\n", condition->toChars()); | |
1656 printf("increment: %s\n", increment->toChars()); | |
1657 printf("body: %s\n", body->toChars()); | |
1658 #endif | |
1566 s = s->semantic(sc); | 1659 s = s->semantic(sc); |
1567 break; | 1660 break; |
1568 } | 1661 } |
1569 #endif | 1662 #endif |
1570 case Tdelegate: | 1663 case Tdelegate: |
1835 break; | 1928 break; |
1836 } | 1929 } |
1837 | 1930 |
1838 default: | 1931 default: |
1839 error("foreach: %s is not an aggregate type", aggr->type->toChars()); | 1932 error("foreach: %s is not an aggregate type", aggr->type->toChars()); |
1933 s = NULL; // error recovery | |
1840 break; | 1934 break; |
1841 } | 1935 } |
1842 sc->noctor--; | 1936 sc->noctor--; |
1843 sc->pop(); | 1937 sc->pop(); |
1844 return s; | 1938 return s; |
1869 { | 1963 { |
1870 result |= body->blockExit() & ~(BEbreak | BEcontinue); | 1964 result |= body->blockExit() & ~(BEbreak | BEcontinue); |
1871 } | 1965 } |
1872 return result; | 1966 return result; |
1873 } | 1967 } |
1968 | |
1874 | 1969 |
1875 int ForeachStatement::comeFrom() | 1970 int ForeachStatement::comeFrom() |
1876 { | 1971 { |
1877 if (body) | 1972 if (body) |
1878 return body->comeFrom(); | 1973 return body->comeFrom(); |
1906 body->toCBuffer(buf, hgs); | 2001 body->toCBuffer(buf, hgs); |
1907 buf->writebyte('}'); | 2002 buf->writebyte('}'); |
1908 buf->writenl(); | 2003 buf->writenl(); |
1909 } | 2004 } |
1910 | 2005 |
2006 /**************************** ForeachRangeStatement ***************************/ | |
2007 | |
2008 #if DMDV2 | |
2009 | |
2010 ForeachRangeStatement::ForeachRangeStatement(Loc loc, enum TOK op, Argument *arg, | |
2011 Expression *lwr, Expression *upr, Statement *body) | |
2012 : Statement(loc) | |
2013 { | |
2014 this->op = op; | |
2015 this->arg = arg; | |
2016 this->lwr = lwr; | |
2017 this->upr = upr; | |
2018 this->body = body; | |
2019 | |
2020 this->key = NULL; | |
2021 } | |
2022 | |
2023 Statement *ForeachRangeStatement::syntaxCopy() | |
2024 { | |
2025 ForeachRangeStatement *s = new ForeachRangeStatement(loc, op, | |
2026 arg->syntaxCopy(), | |
2027 lwr->syntaxCopy(), | |
2028 upr->syntaxCopy(), | |
2029 body ? body->syntaxCopy() : NULL); | |
2030 return s; | |
2031 } | |
2032 | |
2033 Statement *ForeachRangeStatement::semantic(Scope *sc) | |
2034 { | |
2035 //printf("ForeachRangeStatement::semantic() %p\n", this); | |
2036 ScopeDsymbol *sym; | |
2037 Statement *s = this; | |
2038 | |
2039 lwr = lwr->semantic(sc); | |
2040 lwr = resolveProperties(sc, lwr); | |
2041 lwr = lwr->optimize(WANTvalue); | |
2042 if (!lwr->type) | |
2043 { | |
2044 error("invalid range lower bound %s", lwr->toChars()); | |
2045 return this; | |
2046 } | |
2047 | |
2048 upr = upr->semantic(sc); | |
2049 upr = resolveProperties(sc, upr); | |
2050 upr = upr->optimize(WANTvalue); | |
2051 if (!upr->type) | |
2052 { | |
2053 error("invalid range upper bound %s", upr->toChars()); | |
2054 return this; | |
2055 } | |
2056 | |
2057 if (arg->type) | |
2058 { | |
2059 arg->type = arg->type->semantic(loc, sc); | |
2060 lwr = lwr->implicitCastTo(sc, arg->type); | |
2061 upr = upr->implicitCastTo(sc, arg->type); | |
2062 } | |
2063 else | |
2064 { | |
2065 /* Must infer types from lwr and upr | |
2066 */ | |
2067 AddExp ea(loc, lwr, upr); | |
2068 ea.typeCombine(sc); | |
2069 arg->type = ea.type->mutableOf(); | |
2070 lwr = ea.e1; | |
2071 upr = ea.e2; | |
2072 } | |
2073 #if 1 | |
2074 /* Convert to a for loop: | |
2075 * foreach (key; lwr .. upr) => | |
2076 * for (auto key = lwr, auto tmp = upr; key < tmp; ++key) | |
2077 * | |
2078 * foreach_reverse (key; lwr .. upr) => | |
2079 * for (auto tmp = lwr, auto key = upr; key-- > tmp;) | |
2080 */ | |
2081 | |
2082 ExpInitializer *ie = new ExpInitializer(loc, (op == TOKforeach) ? lwr : upr); | |
2083 key = new VarDeclaration(loc, arg->type, arg->ident, ie); | |
2084 | |
2085 Identifier *id = Lexer::uniqueId("__limit"); | |
2086 ie = new ExpInitializer(loc, (op == TOKforeach) ? upr : lwr); | |
2087 VarDeclaration *tmp = new VarDeclaration(loc, arg->type, id, ie); | |
2088 | |
2089 Statements *cs = new Statements(); | |
2090 // Keep order of evaluation as lwr, then upr | |
2091 if (op == TOKforeach) | |
2092 { | |
2093 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key))); | |
2094 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); | |
2095 } | |
2096 else | |
2097 { | |
2098 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); | |
2099 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key))); | |
2100 } | |
2101 Statement *forinit = new CompoundDeclarationStatement(loc, cs); | |
2102 | |
2103 Expression *cond; | |
2104 if (op == TOKforeach_reverse) | |
2105 { // key-- > tmp | |
2106 cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key)); | |
2107 cond = new CmpExp(TOKgt, loc, cond, new VarExp(loc, tmp)); | |
2108 } | |
2109 else | |
2110 // key < tmp | |
2111 cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), new VarExp(loc, tmp)); | |
2112 | |
2113 Expression *increment = NULL; | |
2114 if (op == TOKforeach) | |
2115 // key += 1 | |
2116 increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1)); | |
2117 | |
2118 ForStatement *fs = new ForStatement(loc, forinit, cond, increment, body); | |
2119 s = fs->semantic(sc); | |
2120 return s; | |
2121 #else | |
2122 if (!arg->type->isscalar()) | |
2123 error("%s is not a scalar type", arg->type->toChars()); | |
2124 | |
2125 sym = new ScopeDsymbol(); | |
2126 sym->parent = sc->scopesym; | |
2127 sc = sc->push(sym); | |
2128 | |
2129 sc->noctor++; | |
2130 | |
2131 key = new VarDeclaration(loc, arg->type, arg->ident, NULL); | |
2132 DeclarationExp *de = new DeclarationExp(loc, key); | |
2133 de->semantic(sc); | |
2134 | |
2135 if (key->storage_class) | |
2136 error("foreach range: key cannot have storage class"); | |
2137 | |
2138 sc->sbreak = this; | |
2139 sc->scontinue = this; | |
2140 body = body->semantic(sc); | |
2141 | |
2142 sc->noctor--; | |
2143 sc->pop(); | |
2144 return s; | |
2145 #endif | |
2146 } | |
2147 | |
2148 int ForeachRangeStatement::hasBreak() | |
2149 { | |
2150 return TRUE; | |
2151 } | |
2152 | |
2153 int ForeachRangeStatement::hasContinue() | |
2154 { | |
2155 return TRUE; | |
2156 } | |
2157 | |
2158 int ForeachRangeStatement::usesEH() | |
2159 { | |
2160 assert(0); | |
2161 return body->usesEH(); | |
2162 } | |
2163 | |
2164 int ForeachRangeStatement::blockExit() | |
2165 { | |
2166 assert(0); | |
2167 int result = BEfallthru; | |
2168 | |
2169 if (lwr && lwr->canThrow()) | |
2170 result |= BEthrow; | |
2171 else if (upr && upr->canThrow()) | |
2172 result |= BEthrow; | |
2173 | |
2174 if (body) | |
2175 { | |
2176 result |= body->blockExit() & ~(BEbreak | BEcontinue); | |
2177 } | |
2178 return result; | |
2179 } | |
2180 | |
2181 | |
2182 int ForeachRangeStatement::comeFrom() | |
2183 { | |
2184 assert(0); | |
2185 if (body) | |
2186 return body->comeFrom(); | |
2187 return FALSE; | |
2188 } | |
2189 | |
2190 void ForeachRangeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2191 { | |
2192 buf->writestring(Token::toChars(op)); | |
2193 buf->writestring(" ("); | |
2194 | |
2195 if (arg->type) | |
2196 arg->type->toCBuffer(buf, arg->ident, hgs); | |
2197 else | |
2198 buf->writestring(arg->ident->toChars()); | |
2199 | |
2200 buf->writestring("; "); | |
2201 lwr->toCBuffer(buf, hgs); | |
2202 buf->writestring(" .. "); | |
2203 upr->toCBuffer(buf, hgs); | |
2204 buf->writebyte(')'); | |
2205 buf->writenl(); | |
2206 buf->writebyte('{'); | |
2207 buf->writenl(); | |
2208 if (body) | |
2209 body->toCBuffer(buf, hgs); | |
2210 buf->writebyte('}'); | |
2211 buf->writenl(); | |
2212 } | |
2213 | |
2214 #endif | |
2215 | |
1911 /******************************** IfStatement ***************************/ | 2216 /******************************** IfStatement ***************************/ |
1912 | 2217 |
1913 IfStatement::IfStatement(Loc loc, Argument *arg, Expression *condition, Statement *ifbody, Statement *elsebody) | 2218 IfStatement::IfStatement(Loc loc, Argument *arg, Expression *condition, Statement *ifbody, Statement *elsebody) |
1914 : Statement(loc) | 2219 : Statement(loc) |
1915 { | 2220 { |
2026 result |= BEfallthru; | 2331 result |= BEfallthru; |
2027 } | 2332 } |
2028 //printf("IfStatement::blockExit(%p) = x%x\n", this, result); | 2333 //printf("IfStatement::blockExit(%p) = x%x\n", this, result); |
2029 return result; | 2334 return result; |
2030 } | 2335 } |
2336 | |
2031 | 2337 |
2032 void IfStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 2338 void IfStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
2033 { | 2339 { |
2034 buf->writestring("if ("); | 2340 buf->writestring("if ("); |
2035 if (arg) | 2341 if (arg) |
2179 e = e->semantic(sc); | 2485 e = e->semantic(sc); |
2180 e = e->optimize(WANTvalue | WANTinterpret); | 2486 e = e->optimize(WANTvalue | WANTinterpret); |
2181 if (e->op == TOKstring) | 2487 if (e->op == TOKstring) |
2182 { | 2488 { |
2183 StringExp *se = (StringExp *)e; | 2489 StringExp *se = (StringExp *)e; |
2184 fprintf(stdmsg, "%.*s", (int)se->len, (char*)se->string); | 2490 fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string); |
2185 } | 2491 } |
2186 else | 2492 else |
2187 error("string expected for message, not '%s'", e->toChars()); | 2493 fprintf(stdmsg, e->toChars()); |
2188 } | 2494 } |
2189 fprintf(stdmsg, "\n"); | 2495 fprintf(stdmsg, "\n"); |
2190 } | 2496 } |
2191 } | 2497 } |
2192 else if (ident == Id::lib) | 2498 else if (ident == Id::lib) |
2223 // LDC | 2529 // LDC |
2224 else if (ident == Id::allow_inline) | 2530 else if (ident == Id::allow_inline) |
2225 { | 2531 { |
2226 sc->func->allowInlining = true; | 2532 sc->func->allowInlining = true; |
2227 } | 2533 } |
2228 | 2534 #if DMDV2 |
2535 else if (ident == Id::startaddress) | |
2536 { | |
2537 if (!args || args->dim != 1) | |
2538 error("function name expected for start address"); | |
2539 else | |
2540 { | |
2541 Expression *e = (Expression *)args->data[0]; | |
2542 e = e->semantic(sc); | |
2543 e = e->optimize(WANTvalue | WANTinterpret); | |
2544 args->data[0] = (void *)e; | |
2545 Dsymbol *sa = getDsymbol(e); | |
2546 if (!sa || !sa->isFuncDeclaration()) | |
2547 error("function name expected for start address, not '%s'", e->toChars()); | |
2548 if (body) | |
2549 { | |
2550 body = body->semantic(sc); | |
2551 } | |
2552 return this; | |
2553 } | |
2554 } | |
2555 #endif | |
2229 else | 2556 else |
2230 error("unrecognized pragma(%s)", ident->toChars()); | 2557 error("unrecognized pragma(%s)", ident->toChars()); |
2231 | 2558 |
2232 if (body) | 2559 if (body) |
2233 { | 2560 { |
2251 result |= body->blockExit(); | 2578 result |= body->blockExit(); |
2252 #endif | 2579 #endif |
2253 return result; | 2580 return result; |
2254 } | 2581 } |
2255 | 2582 |
2583 | |
2256 void PragmaStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 2584 void PragmaStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
2257 { | 2585 { |
2258 buf->writestring("pragma ("); | 2586 buf->writestring("pragma ("); |
2259 buf->writestring(ident->toChars()); | 2587 buf->writestring(ident->toChars()); |
2260 if (args && args->dim) | 2588 if (args && args->dim) |
2298 | 2626 |
2299 Statement *StaticAssertStatement::semantic(Scope *sc) | 2627 Statement *StaticAssertStatement::semantic(Scope *sc) |
2300 { | 2628 { |
2301 sa->semantic2(sc); | 2629 sa->semantic2(sc); |
2302 return NULL; | 2630 return NULL; |
2631 } | |
2632 | |
2633 int StaticAssertStatement::blockExit() | |
2634 { | |
2635 return BEfallthru; | |
2303 } | 2636 } |
2304 | 2637 |
2305 void StaticAssertStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 2638 void StaticAssertStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
2306 { | 2639 { |
2307 sa->toCBuffer(buf, hgs); | 2640 sa->toCBuffer(buf, hgs); |
2423 a->push(sc->sw->sdefault); | 2756 a->push(sc->sw->sdefault); |
2424 cs = new CompoundStatement(loc, a); | 2757 cs = new CompoundStatement(loc, a); |
2425 body = cs; | 2758 body = cs; |
2426 } | 2759 } |
2427 | 2760 |
2761 #if DMDV2 | |
2762 if (isFinal) | |
2763 { Type *t = condition->type; | |
2764 while (t->ty == Ttypedef) | |
2765 { // Don't use toBasetype() because that will skip past enums | |
2766 t = ((TypeTypedef *)t)->sym->basetype; | |
2767 } | |
2768 if (condition->type->ty == Tenum) | |
2769 { TypeEnum *te = (TypeEnum *)condition->type; | |
2770 EnumDeclaration *ed = te->toDsymbol(sc)->isEnumDeclaration(); | |
2771 assert(ed); | |
2772 size_t dim = ed->members->dim; | |
2773 for (size_t i = 0; i < dim; i++) | |
2774 { | |
2775 EnumMember *em = ((Dsymbol *)ed->members->data[i])->isEnumMember(); | |
2776 if (em) | |
2777 { | |
2778 for (size_t j = 0; j < cases->dim; j++) | |
2779 { CaseStatement *cs = (CaseStatement *)cases->data[j]; | |
2780 if (cs->exp->equals(em->value)) | |
2781 goto L1; | |
2782 } | |
2783 error("enum member %s not represented in final switch", em->toChars()); | |
2784 } | |
2785 L1: | |
2786 ; | |
2787 } | |
2788 } | |
2789 } | |
2790 #endif | |
2791 | |
2428 sc->pop(); | 2792 sc->pop(); |
2429 return this; | 2793 return this; |
2430 } | 2794 } |
2431 | 2795 |
2432 int SwitchStatement::hasBreak() | 2796 int SwitchStatement::hasBreak() |
2454 else | 2818 else |
2455 result |= BEfallthru; | 2819 result |= BEfallthru; |
2456 | 2820 |
2457 return result; | 2821 return result; |
2458 } | 2822 } |
2823 | |
2459 | 2824 |
2460 void SwitchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 2825 void SwitchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
2461 { | 2826 { |
2462 buf->writestring("switch ("); | 2827 buf->writestring("switch ("); |
2463 condition->toCBuffer(buf, hgs); | 2828 condition->toCBuffer(buf, hgs); |
2569 int CaseStatement::blockExit() | 2934 int CaseStatement::blockExit() |
2570 { | 2935 { |
2571 return statement->blockExit(); | 2936 return statement->blockExit(); |
2572 } | 2937 } |
2573 | 2938 |
2939 | |
2574 int CaseStatement::comeFrom() | 2940 int CaseStatement::comeFrom() |
2575 { | 2941 { |
2576 return TRUE; | 2942 return TRUE; |
2577 } | 2943 } |
2578 | 2944 |
2582 exp->toCBuffer(buf, hgs); | 2948 exp->toCBuffer(buf, hgs); |
2583 buf->writebyte(':'); | 2949 buf->writebyte(':'); |
2584 buf->writenl(); | 2950 buf->writenl(); |
2585 statement->toCBuffer(buf, hgs); | 2951 statement->toCBuffer(buf, hgs); |
2586 } | 2952 } |
2953 | |
2954 /******************************** CaseRangeStatement ***************************/ | |
2955 | |
2956 #if DMDV2 | |
2957 | |
2958 CaseRangeStatement::CaseRangeStatement(Loc loc, Expression *first, | |
2959 Expression *last, Statement *s) | |
2960 : Statement(loc) | |
2961 { | |
2962 this->first = first; | |
2963 this->last = last; | |
2964 this->statement = s; | |
2965 } | |
2966 | |
2967 Statement *CaseRangeStatement::syntaxCopy() | |
2968 { | |
2969 CaseRangeStatement *s = new CaseRangeStatement(loc, | |
2970 first->syntaxCopy(), last->syntaxCopy(), statement->syntaxCopy()); | |
2971 return s; | |
2972 } | |
2973 | |
2974 Statement *CaseRangeStatement::semantic(Scope *sc) | |
2975 { SwitchStatement *sw = sc->sw; | |
2976 | |
2977 //printf("CaseRangeStatement::semantic() %s\n", toChars()); | |
2978 if (sw->isFinal) | |
2979 error("case ranges not allowed in final switch"); | |
2980 | |
2981 first = first->semantic(sc); | |
2982 first = first->implicitCastTo(sc, sw->condition->type); | |
2983 first = first->optimize(WANTvalue | WANTinterpret); | |
2984 dinteger_t fval = first->toInteger(); | |
2985 | |
2986 last = last->semantic(sc); | |
2987 last = last->implicitCastTo(sc, sw->condition->type); | |
2988 last = last->optimize(WANTvalue | WANTinterpret); | |
2989 dinteger_t lval = last->toInteger(); | |
2990 | |
2991 if (lval - fval > 256) | |
2992 { error("more than 256 cases in case range"); | |
2993 lval = fval + 256; | |
2994 } | |
2995 | |
2996 /* This works by replacing the CaseRange with an array of Case's. | |
2997 * | |
2998 * case a: .. case b: s; | |
2999 * => | |
3000 * case a: | |
3001 * [...] | |
3002 * case b: | |
3003 * s; | |
3004 */ | |
3005 | |
3006 Statements *statements = new Statements(); | |
3007 for (dinteger_t i = fval; i <= lval; i++) | |
3008 { | |
3009 Statement *s = statement; | |
3010 if (i != lval) | |
3011 s = new ExpStatement(loc, NULL); | |
3012 Expression *e = new IntegerExp(loc, i, first->type); | |
3013 Statement *cs = new CaseStatement(loc, e, s); | |
3014 statements->push(cs); | |
3015 } | |
3016 Statement *s = new CompoundStatement(loc, statements); | |
3017 s = s->semantic(sc); | |
3018 return s; | |
3019 } | |
3020 | |
3021 void CaseRangeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3022 { | |
3023 buf->writestring("case "); | |
3024 first->toCBuffer(buf, hgs); | |
3025 buf->writestring(": .. case "); | |
3026 last->toCBuffer(buf, hgs); | |
3027 buf->writenl(); | |
3028 statement->toCBuffer(buf, hgs); | |
3029 } | |
3030 | |
3031 #endif | |
2587 | 3032 |
2588 /******************************** DefaultStatement ***************************/ | 3033 /******************************** DefaultStatement ***************************/ |
2589 | 3034 |
2590 DefaultStatement::DefaultStatement(Loc loc, Statement *s) | 3035 DefaultStatement::DefaultStatement(Loc loc, Statement *s) |
2591 : Statement(loc) | 3036 : Statement(loc) |
2638 int DefaultStatement::blockExit() | 3083 int DefaultStatement::blockExit() |
2639 { | 3084 { |
2640 return statement->blockExit(); | 3085 return statement->blockExit(); |
2641 } | 3086 } |
2642 | 3087 |
3088 | |
2643 int DefaultStatement::comeFrom() | 3089 int DefaultStatement::comeFrom() |
2644 { | 3090 { |
2645 return TRUE; | 3091 return TRUE; |
2646 } | 3092 } |
2647 | 3093 |
2675 | 3121 |
2676 int GotoDefaultStatement::blockExit() | 3122 int GotoDefaultStatement::blockExit() |
2677 { | 3123 { |
2678 return BEgoto; | 3124 return BEgoto; |
2679 } | 3125 } |
3126 | |
2680 | 3127 |
2681 void GotoDefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 3128 void GotoDefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
2682 { | 3129 { |
2683 buf->writestring("goto default;\n"); | 3130 buf->writestring("goto default;\n"); |
2684 } | 3131 } |
2723 int GotoCaseStatement::blockExit() | 3170 int GotoCaseStatement::blockExit() |
2724 { | 3171 { |
2725 return BEgoto; | 3172 return BEgoto; |
2726 } | 3173 } |
2727 | 3174 |
3175 | |
2728 void GotoCaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 3176 void GotoCaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
2729 { | 3177 { |
2730 buf->writestring("goto case"); | 3178 buf->writestring("goto case"); |
2731 if (exp) | 3179 if (exp) |
2732 { buf->writebyte(' '); | 3180 { buf->writebyte(' '); |
2745 | 3193 |
2746 int SwitchErrorStatement::blockExit() | 3194 int SwitchErrorStatement::blockExit() |
2747 { | 3195 { |
2748 return BEthrow; | 3196 return BEthrow; |
2749 } | 3197 } |
3198 | |
2750 | 3199 |
2751 void SwitchErrorStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 3200 void SwitchErrorStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
2752 { | 3201 { |
2753 buf->writestring("SwitchErrorStatement::toCBuffer()"); | 3202 buf->writestring("SwitchErrorStatement::toCBuffer()"); |
2754 buf->writenl(); | 3203 buf->writenl(); |
2839 | 3288 |
2840 if (!v || v->isOut() || v->isRef()) | 3289 if (!v || v->isOut() || v->isRef()) |
2841 fd->nrvo_can = 0; | 3290 fd->nrvo_can = 0; |
2842 else if (fd->nrvo_var == NULL) | 3291 else if (fd->nrvo_var == NULL) |
2843 { if (!v->isDataseg() && !v->isParameter() && v->toParent2() == fd) | 3292 { if (!v->isDataseg() && !v->isParameter() && v->toParent2() == fd) |
3293 { //printf("Setting nrvo to %s\n", v->toChars()); | |
2844 fd->nrvo_var = v; | 3294 fd->nrvo_var = v; |
3295 } | |
2845 else | 3296 else |
2846 fd->nrvo_can = 0; | 3297 fd->nrvo_can = 0; |
2847 } | 3298 } |
2848 else if (fd->nrvo_var != v) | 3299 else if (fd->nrvo_var != v) |
2849 fd->nrvo_can = 0; | 3300 fd->nrvo_can = 0; |
2942 s = new ReturnStatement(0, new VarExp(0, fd->vresult)); | 3393 s = new ReturnStatement(0, new VarExp(0, fd->vresult)); |
2943 sc->fes->cases.push(s); | 3394 sc->fes->cases.push(s); |
2944 | 3395 |
2945 // Construct: { vresult = exp; return cases.dim + 1; } | 3396 // Construct: { vresult = exp; return cases.dim + 1; } |
2946 exp = new AssignExp(loc, new VarExp(0, fd->vresult), exp); | 3397 exp = new AssignExp(loc, new VarExp(0, fd->vresult), exp); |
3398 exp->op = TOKconstruct; | |
2947 exp = exp->semantic(sc); | 3399 exp = exp->semantic(sc); |
2948 Statement *s1 = new ExpStatement(loc, exp); | 3400 Statement *s1 = new ExpStatement(loc, exp); |
2949 Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); | 3401 Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); |
2950 s = new CompoundStatement(loc, s1, s2); | 3402 s = new CompoundStatement(loc, s1, s2); |
2951 } | 3403 } |
2958 { | 3410 { |
2959 assert(fd->vresult); | 3411 assert(fd->vresult); |
2960 VarExp *v = new VarExp(0, fd->vresult); | 3412 VarExp *v = new VarExp(0, fd->vresult); |
2961 | 3413 |
2962 exp = new AssignExp(loc, v, exp); | 3414 exp = new AssignExp(loc, v, exp); |
3415 exp->op = TOKconstruct; | |
2963 exp = exp->semantic(sc); | 3416 exp = exp->semantic(sc); |
2964 } | 3417 } |
2965 //exp->dump(0); | 3418 //exp->dump(0); |
2966 //exp->print(); | 3419 //exp->print(); |
2967 exp->checkEscape(); | 3420 exp->checkEscape(); |
2994 return new CompoundStatement(loc, s, gs); | 3447 return new CompoundStatement(loc, s, gs); |
2995 } | 3448 } |
2996 return gs; | 3449 return gs; |
2997 } | 3450 } |
2998 | 3451 |
2999 if (exp && tbret->ty == Tvoid && !fd->isMain()) | 3452 if (exp && tbret->ty == Tvoid && !implicit0) |
3000 { | 3453 { |
3001 /* Replace: | 3454 /* Replace: |
3002 * return exp; | 3455 * return exp; |
3003 * with: | 3456 * with: |
3004 * exp; return; | 3457 * exp; return; |
3005 */ | 3458 */ |
3006 Statement *s = new ExpStatement(loc, exp); | 3459 Statement *s = new ExpStatement(loc, exp); |
3460 exp = NULL; | |
3461 s = s->semantic(sc); | |
3007 loc = 0; | 3462 loc = 0; |
3008 exp = NULL; | |
3009 return new CompoundStatement(loc, s, this); | 3463 return new CompoundStatement(loc, s, this); |
3010 } | 3464 } |
3011 | 3465 |
3012 return this; | 3466 return this; |
3013 } | 3467 } |
3017 | 3471 |
3018 if (exp && exp->canThrow()) | 3472 if (exp && exp->canThrow()) |
3019 result |= BEthrow; | 3473 result |= BEthrow; |
3020 return result; | 3474 return result; |
3021 } | 3475 } |
3476 | |
3022 | 3477 |
3023 void ReturnStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 3478 void ReturnStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3024 { | 3479 { |
3025 buf->printf("return "); | 3480 buf->printf("return "); |
3026 if (exp) | 3481 if (exp) |
3110 { | 3565 { |
3111 //printf("BreakStatement::blockExit(%p) = x%x\n", this, ident ? BEgoto : BEbreak); | 3566 //printf("BreakStatement::blockExit(%p) = x%x\n", this, ident ? BEgoto : BEbreak); |
3112 return ident ? BEgoto : BEbreak; | 3567 return ident ? BEgoto : BEbreak; |
3113 } | 3568 } |
3114 | 3569 |
3570 | |
3115 void BreakStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 3571 void BreakStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3116 { | 3572 { |
3117 buf->writestring("break"); | 3573 buf->writestring("break"); |
3118 if (ident) | 3574 if (ident) |
3119 { buf->writebyte(' '); | 3575 { buf->writebyte(' '); |
3211 int ContinueStatement::blockExit() | 3667 int ContinueStatement::blockExit() |
3212 { | 3668 { |
3213 return ident ? BEgoto : BEcontinue; | 3669 return ident ? BEgoto : BEcontinue; |
3214 } | 3670 } |
3215 | 3671 |
3672 | |
3216 void ContinueStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 3673 void ContinueStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3217 { | 3674 { |
3218 buf->writestring("continue"); | 3675 buf->writestring("continue"); |
3219 if (ident) | 3676 if (ident) |
3220 { buf->writebyte(' '); | 3677 { buf->writebyte(' '); |
3254 } | 3711 } |
3255 | 3712 |
3256 Statement *SynchronizedStatement::semantic(Scope *sc) | 3713 Statement *SynchronizedStatement::semantic(Scope *sc) |
3257 { | 3714 { |
3258 if (exp) | 3715 if (exp) |
3259 { ClassDeclaration *cd; | 3716 { |
3260 | |
3261 exp = exp->semantic(sc); | 3717 exp = exp->semantic(sc); |
3262 exp = resolveProperties(sc, exp); | 3718 exp = resolveProperties(sc, exp); |
3263 cd = exp->type->isClassHandle(); | 3719 ClassDeclaration *cd = exp->type->isClassHandle(); |
3264 if (!cd) | 3720 if (!cd) |
3265 error("can only synchronize on class objects, not '%s'", exp->type->toChars()); | 3721 error("can only synchronize on class objects, not '%s'", exp->type->toChars()); |
3266 else if (cd->isInterfaceDeclaration()) | 3722 else if (cd->isInterfaceDeclaration()) |
3267 { Type *t = new TypeIdentifier(0, Id::Object); | 3723 { /* Cast the interface to an object, as the object has the monitor, |
3724 * not the interface. | |
3725 */ | |
3726 Type *t = new TypeIdentifier(0, Id::Object); | |
3268 | 3727 |
3269 t = t->semantic(0, sc); | 3728 t = t->semantic(0, sc); |
3270 exp = new CastExp(loc, exp, t); | 3729 exp = new CastExp(loc, exp, t); |
3271 exp = exp->semantic(sc); | 3730 exp = exp->semantic(sc); |
3272 } | 3731 } |
3273 } | 3732 |
3733 #if 0 | |
3734 /* Rewrite as: | |
3735 * auto tmp = exp; | |
3736 * _d_monitorenter(tmp); | |
3737 * try { body } finally { _d_monitorexit(tmp); } | |
3738 */ | |
3739 Identifier *id = Lexer::uniqueId("__sync"); | |
3740 ExpInitializer *ie = new ExpInitializer(loc, exp); | |
3741 VarDeclaration *tmp = new VarDeclaration(loc, exp->type, id, ie); | |
3742 | |
3743 Statements *cs = new Statements(); | |
3744 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); | |
3745 | |
3746 FuncDeclaration *fdenter = FuncDeclaration::genCfunc(Type::tvoid, Id::monitorenter); | |
3747 Expression *e = new CallExp(loc, new VarExp(loc, fdenter), new VarExp(loc, tmp)); | |
3748 e->type = Type::tvoid; // do not run semantic on e | |
3749 cs->push(new ExpStatement(loc, e)); | |
3750 | |
3751 FuncDeclaration *fdexit = FuncDeclaration::genCfunc(Type::tvoid, Id::monitorexit); | |
3752 e = new CallExp(loc, new VarExp(loc, fdexit), new VarExp(loc, tmp)); | |
3753 e->type = Type::tvoid; // do not run semantic on e | |
3754 Statement *s = new ExpStatement(loc, e); | |
3755 s = new TryFinallyStatement(loc, body, s); | |
3756 cs->push(s); | |
3757 | |
3758 s = new CompoundStatement(loc, cs); | |
3759 return s->semantic(sc); | |
3760 #endif | |
3761 } | |
3762 #if 0 | |
3763 else | |
3764 { /* Generate our own critical section, then rewrite as: | |
3765 * __gshared byte[CriticalSection.sizeof] critsec; | |
3766 * _d_criticalenter(critsec.ptr); | |
3767 * try { body } finally { _d_criticalexit(critsec.ptr); } | |
3768 */ | |
3769 Identifier *id = Lexer::uniqueId("__critsec"); | |
3770 Type *t = new TypeSArray(Type::tint8, new IntegerExp(PTRSIZE + os_critsecsize())); | |
3771 VarDeclaration *tmp = new VarDeclaration(loc, t, id, NULL); | |
3772 tmp->storage_class |= STCgshared | STCstatic; | |
3773 | |
3774 Statements *cs = new Statements(); | |
3775 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); | |
3776 | |
3777 FuncDeclaration *fdenter = FuncDeclaration::genCfunc(Type::tvoid, Id::criticalenter); | |
3778 Expression *e = new DotIdExp(loc, new VarExp(loc, tmp), Id::ptr); | |
3779 e = e->semantic(sc); | |
3780 e = new CallExp(loc, new VarExp(loc, fdenter), e); | |
3781 e->type = Type::tvoid; // do not run semantic on e | |
3782 cs->push(new ExpStatement(loc, e)); | |
3783 | |
3784 FuncDeclaration *fdexit = FuncDeclaration::genCfunc(Type::tvoid, Id::criticalexit); | |
3785 e = new DotIdExp(loc, new VarExp(loc, tmp), Id::ptr); | |
3786 e = e->semantic(sc); | |
3787 e = new CallExp(loc, new VarExp(loc, fdexit), e); | |
3788 e->type = Type::tvoid; // do not run semantic on e | |
3789 Statement *s = new ExpStatement(loc, e); | |
3790 s = new TryFinallyStatement(loc, body, s); | |
3791 cs->push(s); | |
3792 | |
3793 s = new CompoundStatement(loc, cs); | |
3794 return s->semantic(sc); | |
3795 } | |
3796 #endif | |
3274 if (body) | 3797 if (body) |
3275 { | 3798 { |
3276 Statement* oldScopeExit = sc->enclosingScopeExit; | 3799 Statement* oldScopeExit = sc->enclosingScopeExit; |
3277 sc->enclosingScopeExit = this; | 3800 sc->enclosingScopeExit = this; |
3278 body = body->semantic(sc); | 3801 body = body->semantic(sc); |
3298 | 3821 |
3299 int SynchronizedStatement::blockExit() | 3822 int SynchronizedStatement::blockExit() |
3300 { | 3823 { |
3301 return body ? body->blockExit() : BEfallthru; | 3824 return body ? body->blockExit() : BEfallthru; |
3302 } | 3825 } |
3826 | |
3303 | 3827 |
3304 void SynchronizedStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 3828 void SynchronizedStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3305 { | 3829 { |
3306 buf->writestring("synchronized"); | 3830 buf->writestring("synchronized"); |
3307 if (exp) | 3831 if (exp) |
3416 else | 3940 else |
3417 result |= BEfallthru; | 3941 result |= BEfallthru; |
3418 return result; | 3942 return result; |
3419 } | 3943 } |
3420 | 3944 |
3945 | |
3421 /******************************** TryCatchStatement ***************************/ | 3946 /******************************** TryCatchStatement ***************************/ |
3422 | 3947 |
3423 TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Array *catches) | 3948 TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Array *catches) |
3424 : Statement(loc) | 3949 : Statement(loc) |
3425 { | 3950 { |
3460 | 3985 |
3461 if (c->type->toBasetype()->implicitConvTo(cj->type->toBasetype())) | 3986 if (c->type->toBasetype()->implicitConvTo(cj->type->toBasetype())) |
3462 error("catch at %s hides catch at %s", sj, si); | 3987 error("catch at %s hides catch at %s", sj, si); |
3463 } | 3988 } |
3464 } | 3989 } |
3990 | |
3991 if (!body || body->isEmpty()) | |
3992 { | |
3993 return NULL; | |
3994 } | |
3465 return this; | 3995 return this; |
3466 } | 3996 } |
3467 | 3997 |
3468 int TryCatchStatement::hasBreak() | 3998 int TryCatchStatement::hasBreak() |
3469 { | 3999 { |
3474 { | 4004 { |
3475 return TRUE; | 4005 return TRUE; |
3476 } | 4006 } |
3477 | 4007 |
3478 int TryCatchStatement::blockExit() | 4008 int TryCatchStatement::blockExit() |
3479 { int result; | 4009 { |
3480 | |
3481 assert(body); | 4010 assert(body); |
3482 result = body->blockExit(); | 4011 int result = body->blockExit(); |
3483 | 4012 |
3484 for (size_t i = 0; i < catches->dim; i++) | 4013 for (size_t i = 0; i < catches->dim; i++) |
3485 { | 4014 { |
3486 Catch *c = (Catch *)catches->data[i]; | 4015 Catch *c = (Catch *)catches->data[i]; |
3487 result |= c->blockExit(); | 4016 result |= c->blockExit(); |
3687 int OnScopeStatement::usesEH() | 4216 int OnScopeStatement::usesEH() |
3688 { | 4217 { |
3689 return (tok != TOKon_scope_success); | 4218 return (tok != TOKon_scope_success); |
3690 } | 4219 } |
3691 | 4220 |
3692 void OnScopeStatement::scopeCode(Statement **sentry, Statement **sexception, Statement **sfinally) | 4221 void OnScopeStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally) |
3693 { | 4222 { |
3694 //printf("OnScopeStatement::scopeCode()\n"); | 4223 //printf("OnScopeStatement::scopeCode()\n"); |
3695 //print(); | 4224 //print(); |
3696 *sentry = NULL; | 4225 *sentry = NULL; |
3697 *sexception = NULL; | 4226 *sexception = NULL; |
3768 int ThrowStatement::blockExit() | 4297 int ThrowStatement::blockExit() |
3769 { | 4298 { |
3770 return BEthrow; // obviously | 4299 return BEthrow; // obviously |
3771 } | 4300 } |
3772 | 4301 |
4302 | |
3773 void ThrowStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 4303 void ThrowStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3774 { | 4304 { |
3775 buf->printf("throw "); | 4305 buf->printf("throw "); |
3776 exp->toCBuffer(buf, hgs); | 4306 exp->toCBuffer(buf, hgs); |
3777 buf->writeByte(';'); | 4307 buf->writeByte(';'); |
3824 | 4354 |
3825 int VolatileStatement::blockExit() | 4355 int VolatileStatement::blockExit() |
3826 { | 4356 { |
3827 return statement ? statement->blockExit() : BEfallthru; | 4357 return statement ? statement->blockExit() : BEfallthru; |
3828 } | 4358 } |
4359 | |
3829 | 4360 |
3830 void VolatileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 4361 void VolatileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3831 { | 4362 { |
3832 buf->writestring("volatile"); | 4363 buf->writestring("volatile"); |
3833 if (statement) | 4364 if (statement) |
3890 { | 4421 { |
3891 //printf("GotoStatement::blockExit(%p)\n", this); | 4422 //printf("GotoStatement::blockExit(%p)\n", this); |
3892 return BEgoto; | 4423 return BEgoto; |
3893 } | 4424 } |
3894 | 4425 |
4426 | |
3895 void GotoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 4427 void GotoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3896 { | 4428 { |
3897 buf->writestring("goto "); | 4429 buf->writestring("goto "); |
3898 buf->writestring(ident->toChars()); | 4430 buf->writestring(ident->toChars()); |
3899 buf->writebyte(';'); | 4431 buf->writebyte(';'); |
3981 { | 4513 { |
3982 //printf("LabelStatement::blockExit(%p)\n", this); | 4514 //printf("LabelStatement::blockExit(%p)\n", this); |
3983 return statement ? statement->blockExit() : BEfallthru; | 4515 return statement ? statement->blockExit() : BEfallthru; |
3984 } | 4516 } |
3985 | 4517 |
4518 | |
3986 int LabelStatement::comeFrom() | 4519 int LabelStatement::comeFrom() |
3987 { | 4520 { |
3988 //printf("LabelStatement::comeFrom()\n"); | 4521 //printf("LabelStatement::comeFrom()\n"); |
3989 return TRUE; | 4522 return TRUE; |
3990 } | 4523 } |