Mercurial > projects > ldc
comparison dmd/statement.c @ 846:bc982f1ad106
Merged DMD 1.037 frontend
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Sat, 13 Dec 2008 13:15:31 +0100 |
parents | 661384d6a936 |
children | 330f999ade44 |
comparison
equal
deleted
inserted
replaced
845:d128381e086e | 846:bc982f1ad106 |
---|---|
24 #include "declaration.h" | 24 #include "declaration.h" |
25 #include "aggregate.h" | 25 #include "aggregate.h" |
26 #include "id.h" | 26 #include "id.h" |
27 #include "hdrgen.h" | 27 #include "hdrgen.h" |
28 #include "parse.h" | 28 #include "parse.h" |
29 #include "template.h" | |
29 | 30 |
30 /******************************** Statement ***************************/ | 31 /******************************** Statement ***************************/ |
31 | 32 |
32 Statement::Statement(Loc loc) | 33 Statement::Statement(Loc loc) |
33 : loc(loc) | 34 : loc(loc) |
449 a->push(statements->data[j]); | 450 a->push(statements->data[j]); |
450 } | 451 } |
451 body = new CompoundStatement(0, a); | 452 body = new CompoundStatement(0, a); |
452 body = new ScopeStatement(0, body); | 453 body = new ScopeStatement(0, body); |
453 | 454 |
454 static int num; | 455 Identifier *id = Lexer::uniqueId("__o"); |
455 char name[3 + sizeof(num) * 3 + 1]; | |
456 sprintf(name, "__o%d", ++num); | |
457 Identifier *id = Lexer::idPool(name); | |
458 | 456 |
459 Statement *handler = new ThrowStatement(0, new IdentifierExp(0, id)); | 457 Statement *handler = new ThrowStatement(0, new IdentifierExp(0, id)); |
460 handler = new CompoundStatement(0, sexception, handler); | 458 handler = new CompoundStatement(0, sexception, handler); |
461 | 459 |
462 Array *catches = new Array(); | 460 Array *catches = new Array(); |
1105 init = init->semantic(sc); | 1103 init = init->semantic(sc); |
1106 if (!condition) | 1104 if (!condition) |
1107 // Use a default value | 1105 // Use a default value |
1108 condition = new IntegerExp(loc, 1, Type::tboolean); | 1106 condition = new IntegerExp(loc, 1, Type::tboolean); |
1109 sc->noctor++; | 1107 sc->noctor++; |
1110 condition = condition->semantic(sc); | 1108 if (condition) |
1111 condition = resolveProperties(sc, condition); | 1109 { |
1112 condition = condition->optimize(WANTvalue); | 1110 condition = condition->semantic(sc); |
1113 condition = condition->checkToBoolean(); | 1111 condition = resolveProperties(sc, condition); |
1112 condition = condition->optimize(WANTvalue); | |
1113 condition = condition->checkToBoolean(); | |
1114 } | |
1114 if (increment) | 1115 if (increment) |
1115 increment = increment->semantic(sc); | 1116 { increment = increment->semantic(sc); |
1117 increment = resolveProperties(sc, increment); | |
1118 } | |
1116 | 1119 |
1117 sc->sbreak = this; | 1120 sc->sbreak = this; |
1118 sc->scontinue = this; | 1121 sc->scontinue = this; |
1119 body = body->semantic(sc); | 1122 body = body->semantic(sc); |
1120 sc->noctor--; | 1123 sc->noctor--; |
1255 Statement *ForeachStatement::semantic(Scope *sc) | 1258 Statement *ForeachStatement::semantic(Scope *sc) |
1256 { | 1259 { |
1257 //printf("ForeachStatement::semantic() %p\n", this); | 1260 //printf("ForeachStatement::semantic() %p\n", this); |
1258 ScopeDsymbol *sym; | 1261 ScopeDsymbol *sym; |
1259 Statement *s = this; | 1262 Statement *s = this; |
1260 int dim = arguments->dim; | 1263 size_t dim = arguments->dim; |
1261 int i; | |
1262 TypeAArray *taa = NULL; | 1264 TypeAArray *taa = NULL; |
1263 | 1265 |
1264 Type *tn = NULL; | 1266 Type *tn = NULL; |
1265 Type *tnv = NULL; | 1267 Type *tnv = NULL; |
1266 | 1268 |
1270 if (func->fes) | 1272 if (func->fes) |
1271 func = func->fes->func; | 1273 func = func->fes->func; |
1272 | 1274 |
1273 aggr = aggr->semantic(sc); | 1275 aggr = aggr->semantic(sc); |
1274 aggr = resolveProperties(sc, aggr); | 1276 aggr = resolveProperties(sc, aggr); |
1277 aggr = aggr->optimize(WANTvalue); | |
1275 if (!aggr->type) | 1278 if (!aggr->type) |
1276 { | 1279 { |
1277 error("invalid foreach aggregate %s", aggr->toChars()); | 1280 error("invalid foreach aggregate %s", aggr->toChars()); |
1278 return this; | 1281 return this; |
1279 } | 1282 } |
1385 s = new UnrolledLoopStatement(loc, statements); | 1388 s = new UnrolledLoopStatement(loc, statements); |
1386 s = s->semantic(sc); | 1389 s = s->semantic(sc); |
1387 return s; | 1390 return s; |
1388 } | 1391 } |
1389 | 1392 |
1390 for (i = 0; i < dim; i++) | 1393 for (size_t i = 0; i < dim; i++) |
1391 { Argument *arg = (Argument *)arguments->data[i]; | 1394 { Argument *arg = (Argument *)arguments->data[i]; |
1392 if (!arg->type) | 1395 if (!arg->type) |
1393 { | 1396 { |
1394 error("cannot infer type for %s", arg->ident->toChars()); | 1397 error("cannot infer type for %s", arg->ident->toChars()); |
1395 return this; | 1398 return this; |
1417 */ | 1420 */ |
1418 tn = tab->nextOf()->toBasetype(); | 1421 tn = tab->nextOf()->toBasetype(); |
1419 if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar) | 1422 if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar) |
1420 { Argument *arg; | 1423 { Argument *arg; |
1421 | 1424 |
1422 i = (dim == 1) ? 0 : 1; // index of value | 1425 int i = (dim == 1) ? 0 : 1; // index of value |
1423 arg = (Argument *)arguments->data[i]; | 1426 arg = (Argument *)arguments->data[i]; |
1424 arg->type = arg->type->semantic(loc, sc); | 1427 arg->type = arg->type->semantic(loc, sc); |
1425 tnv = arg->type->toBasetype(); | 1428 tnv = arg->type->toBasetype(); |
1426 if (tnv->ty != tn->ty && | 1429 if (tnv->ty != tn->ty && |
1427 (tnv->ty == Tchar || tnv->ty == Twchar || tnv->ty == Tdchar)) | 1430 (tnv->ty == Tchar || tnv->ty == Twchar || tnv->ty == Tdchar)) |
1435 } | 1438 } |
1436 goto Lapply; | 1439 goto Lapply; |
1437 } | 1440 } |
1438 } | 1441 } |
1439 | 1442 |
1440 for (i = 0; i < dim; i++) | 1443 for (size_t i = 0; i < dim; i++) |
1441 { // Declare args | 1444 { // Declare args |
1442 Argument *arg = (Argument *)arguments->data[i]; | 1445 Argument *arg = (Argument *)arguments->data[i]; |
1443 VarDeclaration *var; | 1446 VarDeclaration *var; |
1444 | 1447 |
1445 var = new VarDeclaration(loc, arg->type, arg->ident, NULL); | 1448 var = new VarDeclaration(loc, arg->type, arg->ident, NULL); |
1466 if (!value->type->equals(tab->next)) | 1469 if (!value->type->equals(tab->next)) |
1467 { | 1470 { |
1468 if (aggr->op == TOKstring) | 1471 if (aggr->op == TOKstring) |
1469 aggr = aggr->implicitCastTo(sc, value->type->arrayOf()); | 1472 aggr = aggr->implicitCastTo(sc, value->type->arrayOf()); |
1470 else | 1473 else |
1471 error("foreach: %s is not an array of %s", tab->toChars(), value->type->toChars()); | 1474 error("foreach: %s is not an array of %s", |
1475 tab->toChars(), value->type->toChars()); | |
1472 } | 1476 } |
1473 | 1477 |
1474 if (key) | 1478 if (key) |
1475 { | 1479 { |
1476 if (global.params.is64bit) | 1480 if (global.params.is64bit) |
1503 } | 1507 } |
1504 goto Lapply; | 1508 goto Lapply; |
1505 | 1509 |
1506 case Tclass: | 1510 case Tclass: |
1507 case Tstruct: | 1511 case Tstruct: |
1512 #if DMDV2 | |
1513 { /* Look for range iteration, i.e. the properties | |
1514 * .empty, .next, .retreat, .head and .rear | |
1515 * foreach (e; range) { ... } | |
1516 * translates to: | |
1517 * for (auto __r = range; !__r.empty; __r.next) | |
1518 * { auto e = __r.head; | |
1519 * ... | |
1520 * } | |
1521 */ | |
1522 if (dim != 1) // only one argument allowed with ranges | |
1523 goto Lapply; | |
1524 AggregateDeclaration *ad = (tab->ty == Tclass) | |
1525 ? (AggregateDeclaration *)((TypeClass *)tab)->sym | |
1526 : (AggregateDeclaration *)((TypeStruct *)tab)->sym; | |
1527 Identifier *idhead; | |
1528 Identifier *idnext; | |
1529 if (op == TOKforeach) | |
1530 { idhead = Id::Fhead; | |
1531 idnext = Id::Fnext; | |
1532 } | |
1533 else | |
1534 { idhead = Id::Frear; | |
1535 idnext = Id::Fretreat; | |
1536 } | |
1537 Dsymbol *shead = search_function(ad, idhead); | |
1538 if (!shead) | |
1539 goto Lapply; | |
1540 | |
1541 /* Generate a temporary __r and initialize it with the aggregate. | |
1542 */ | |
1543 Identifier *id = Identifier::generateId("__r"); | |
1544 VarDeclaration *r = new VarDeclaration(loc, NULL, id, new ExpInitializer(loc, aggr)); | |
1545 r->semantic(sc); | |
1546 Statement *init = new DeclarationStatement(loc, r); | |
1547 | |
1548 // !__r.empty | |
1549 Expression *e = new VarExp(loc, r); | |
1550 e = new DotIdExp(loc, e, Id::Fempty); | |
1551 Expression *condition = new NotExp(loc, e); | |
1552 | |
1553 // __r.next | |
1554 e = new VarExp(loc, r); | |
1555 Expression *increment = new DotIdExp(loc, e, idnext); | |
1556 | |
1557 /* Declaration statement for e: | |
1558 * auto e = __r.idhead; | |
1559 */ | |
1560 e = new VarExp(loc, r); | |
1561 Expression *einit = new DotIdExp(loc, e, idhead); | |
1562 einit = einit->semantic(sc); | |
1563 Argument *arg = (Argument *)arguments->data[0]; | |
1564 VarDeclaration *ve = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, einit)); | |
1565 ve->storage_class |= STCforeach; | |
1566 ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STCconst | STCinvariant); | |
1567 | |
1568 DeclarationExp *de = new DeclarationExp(loc, ve); | |
1569 | |
1570 Statement *body = new CompoundStatement(loc, | |
1571 new DeclarationStatement(loc, de), this->body); | |
1572 | |
1573 s = new ForStatement(loc, init, condition, increment, body); | |
1574 s = s->semantic(sc); | |
1575 break; | |
1576 } | |
1577 #endif | |
1508 case Tdelegate: | 1578 case Tdelegate: |
1509 Lapply: | 1579 Lapply: |
1510 { FuncDeclaration *fdapply; | 1580 { FuncDeclaration *fdapply; |
1511 Arguments *args; | 1581 Arguments *args; |
1512 Expression *ec; | 1582 Expression *ec; |
1538 | 1608 |
1539 /* Turn body into the function literal: | 1609 /* Turn body into the function literal: |
1540 * int delegate(ref T arg) { body } | 1610 * int delegate(ref T arg) { body } |
1541 */ | 1611 */ |
1542 args = new Arguments(); | 1612 args = new Arguments(); |
1543 for (i = 0; i < dim; i++) | 1613 for (size_t i = 0; i < dim; i++) |
1544 { Argument *arg = (Argument *)arguments->data[i]; | 1614 { Argument *arg = (Argument *)arguments->data[i]; |
1545 | 1615 |
1546 arg->type = arg->type->semantic(loc, sc); | 1616 arg->type = arg->type->semantic(loc, sc); |
1547 if (arg->storageClass & STCref) | 1617 if (arg->storageClass & STCref) |
1548 id = arg->ident; | 1618 id = arg->ident; |
1549 else | 1619 else |
1550 { // Make a copy of the ref argument so it isn't | 1620 { // Make a copy of the ref argument so it isn't |
1551 // a reference. | 1621 // a reference. |
1552 VarDeclaration *v; | 1622 VarDeclaration *v; |
1553 Initializer *ie; | 1623 Initializer *ie; |
1554 char applyArg[10 + sizeof(i)*3 + 1]; | 1624 |
1555 | 1625 id = Lexer::uniqueId("__applyArg", i); |
1556 sprintf(applyArg, "__applyArg%d", i); | |
1557 id = Lexer::idPool(applyArg); | |
1558 | 1626 |
1559 ie = new ExpInitializer(0, new IdentifierExp(0, id)); | 1627 ie = new ExpInitializer(0, new IdentifierExp(0, id)); |
1560 v = new VarDeclaration(0, arg->type, arg->ident, ie); | 1628 v = new VarDeclaration(0, arg->type, arg->ident, ie); |
1561 s = new DeclarationStatement(0, v); | 1629 s = new DeclarationStatement(0, v); |
1562 body = new CompoundStatement(loc, s, body); | 1630 body = new CompoundStatement(loc, s, body); |
2143 fprintf(stdmsg, "\n"); | 2211 fprintf(stdmsg, "\n"); |
2144 } | 2212 } |
2145 } | 2213 } |
2146 else if (ident == Id::lib) | 2214 else if (ident == Id::lib) |
2147 { | 2215 { |
2216 #if 1 | |
2217 /* Should this be allowed? | |
2218 */ | |
2219 error("pragma(lib) not allowed as statement"); | |
2220 #else | |
2148 if (!args || args->dim != 1) | 2221 if (!args || args->dim != 1) |
2149 error("string expected for library name"); | 2222 error("string expected for library name"); |
2150 else | 2223 else |
2151 { | 2224 { |
2152 Expression *e = (Expression *)args->data[0]; | 2225 Expression *e = (Expression *)args->data[0]; |
2164 name[se->len] = 0; | 2237 name[se->len] = 0; |
2165 printf("library %s\n", name); | 2238 printf("library %s\n", name); |
2166 mem.free(name); | 2239 mem.free(name); |
2167 } | 2240 } |
2168 } | 2241 } |
2242 #endif | |
2169 } | 2243 } |
2170 else | 2244 else |
2171 error("unrecognized pragma(%s)", ident->toChars()); | 2245 error("unrecognized pragma(%s)", ident->toChars()); |
2172 | 2246 |
2173 if (body) | 2247 if (body) |
2452 { SwitchStatement *sw = sc->sw; | 2526 { SwitchStatement *sw = sc->sw; |
2453 | 2527 |
2454 //printf("CaseStatement::semantic() %s\n", toChars()); | 2528 //printf("CaseStatement::semantic() %s\n", toChars()); |
2455 exp = exp->semantic(sc); | 2529 exp = exp->semantic(sc); |
2456 if (sw) | 2530 if (sw) |
2457 { int i; | 2531 { |
2458 | |
2459 exp = exp->implicitCastTo(sc, sw->condition->type); | 2532 exp = exp->implicitCastTo(sc, sw->condition->type); |
2460 exp = exp->optimize(WANTvalue | WANTinterpret); | 2533 exp = exp->optimize(WANTvalue | WANTinterpret); |
2461 if (exp->op != TOKstring && exp->op != TOKint64) | 2534 if (exp->op != TOKstring && exp->op != TOKint64) |
2462 { | 2535 { |
2463 error("case must be a string or an integral constant, not %s", exp->toChars()); | 2536 error("case must be a string or an integral constant, not %s", exp->toChars()); |
2464 exp = new IntegerExp(0); | 2537 exp = new IntegerExp(0); |
2465 } | 2538 } |
2466 | 2539 |
2467 for (i = 0; i < sw->cases->dim; i++) | 2540 for (int i = 0; i < sw->cases->dim; i++) |
2468 { | 2541 { |
2469 CaseStatement *cs = (CaseStatement *)sw->cases->data[i]; | 2542 CaseStatement *cs = (CaseStatement *)sw->cases->data[i]; |
2470 | 2543 |
2471 //printf("comparing '%s' with '%s'\n", exp->toChars(), cs->exp->toChars()); | 2544 //printf("comparing '%s' with '%s'\n", exp->toChars(), cs->exp->toChars()); |
2472 if (cs->exp->equals(exp)) | 2545 if (cs->exp->equals(exp)) |
2476 } | 2549 } |
2477 | 2550 |
2478 sw->cases->push(this); | 2551 sw->cases->push(this); |
2479 | 2552 |
2480 // Resolve any goto case's with no exp to this case statement | 2553 // Resolve any goto case's with no exp to this case statement |
2481 for (i = 0; i < sw->gotoCases.dim; i++) | 2554 for (size_t i = 0; i < sw->gotoCases.dim; i++) |
2482 { | 2555 { |
2483 GotoCaseStatement *gcs = (GotoCaseStatement *)sw->gotoCases.data[i]; | 2556 GotoCaseStatement *gcs = (GotoCaseStatement *)sw->gotoCases.data[i]; |
2484 | 2557 |
2485 if (!gcs->exp) | 2558 if (!gcs->exp) |
2486 { | 2559 { |
2873 exp->op == TOKimaginary80 || exp->op == TOKcomplex80 || | 2946 exp->op == TOKimaginary80 || exp->op == TOKcomplex80 || |
2874 exp->op == TOKthis || exp->op == TOKsuper || exp->op == TOKnull || | 2947 exp->op == TOKthis || exp->op == TOKsuper || exp->op == TOKnull || |
2875 exp->op == TOKstring) | 2948 exp->op == TOKstring) |
2876 { | 2949 { |
2877 sc->fes->cases.push(this); | 2950 sc->fes->cases.push(this); |
2951 // Construct: return cases.dim+1; | |
2878 s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); | 2952 s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); |
2879 } | 2953 } |
2880 else if (fd->type->nextOf()->toBasetype() == Type::tvoid) | 2954 else if (fd->type->nextOf()->toBasetype() == Type::tvoid) |
2881 { | 2955 { |
2882 Statement *s1; | |
2883 Statement *s2; | |
2884 | |
2885 s = new ReturnStatement(0, NULL); | 2956 s = new ReturnStatement(0, NULL); |
2886 sc->fes->cases.push(s); | 2957 sc->fes->cases.push(s); |
2887 | 2958 |
2888 // Construct: { exp; return cases.dim + 1; } | 2959 // Construct: { exp; return cases.dim + 1; } |
2889 s1 = new ExpStatement(loc, exp); | 2960 Statement *s1 = new ExpStatement(loc, exp); |
2890 s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); | 2961 Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); |
2891 s = new CompoundStatement(loc, s1, s2); | 2962 s = new CompoundStatement(loc, s1, s2); |
2892 } | 2963 } |
2893 else | 2964 else |
2894 { | 2965 { |
2895 VarExp *v; | |
2896 Statement *s1; | |
2897 Statement *s2; | |
2898 | |
2899 // Construct: return vresult; | 2966 // Construct: return vresult; |
2900 if (!fd->vresult) | 2967 if (!fd->vresult) |
2901 { VarDeclaration *v; | 2968 { // Declare vresult |
2902 | 2969 VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL); |
2903 v = new VarDeclaration(loc, tret, Id::result, NULL); | |
2904 v->noauto = 1; | 2970 v->noauto = 1; |
2905 v->semantic(scx); | 2971 v->semantic(scx); |
2906 if (!scx->insert(v)) | 2972 if (!scx->insert(v)) |
2907 assert(0); | 2973 assert(0); |
2908 v->parent = fd; | 2974 v->parent = fd; |
2909 fd->vresult = v; | 2975 fd->vresult = v; |
2910 } | 2976 } |
2911 | 2977 |
2912 v = new VarExp(0, fd->vresult); | 2978 s = new ReturnStatement(0, new VarExp(0, fd->vresult)); |
2913 s = new ReturnStatement(0, v); | |
2914 sc->fes->cases.push(s); | 2979 sc->fes->cases.push(s); |
2915 | 2980 |
2916 // Construct: { vresult = exp; return cases.dim + 1; } | 2981 // Construct: { vresult = exp; return cases.dim + 1; } |
2917 v = new VarExp(0, fd->vresult); | 2982 exp = new AssignExp(loc, new VarExp(0, fd->vresult), exp); |
2918 exp = new AssignExp(loc, v, exp); | |
2919 exp = exp->semantic(sc); | 2983 exp = exp->semantic(sc); |
2920 s1 = new ExpStatement(loc, exp); | 2984 Statement *s1 = new ExpStatement(loc, exp); |
2921 s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); | 2985 Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); |
2922 s = new CompoundStatement(loc, s1, s2); | 2986 s = new CompoundStatement(loc, s1, s2); |
2923 } | 2987 } |
2924 return s; | 2988 return s; |
2925 } | 2989 } |
2926 | 2990 |
2957 { | 3021 { |
2958 GotoStatement *gs = new GotoStatement(loc, Id::returnLabel); | 3022 GotoStatement *gs = new GotoStatement(loc, Id::returnLabel); |
2959 | 3023 |
2960 gs->label = fd->returnLabel; | 3024 gs->label = fd->returnLabel; |
2961 if (exp) | 3025 if (exp) |
2962 { Statement *s; | 3026 { /* Replace: return exp; |
2963 | 3027 * with: exp; goto returnLabel; |
2964 s = new ExpStatement(0, exp); | 3028 */ |
3029 Statement *s = new ExpStatement(0, exp); | |
2965 return new CompoundStatement(loc, s, gs); | 3030 return new CompoundStatement(loc, s, gs); |
2966 } | 3031 } |
2967 return gs; | 3032 return gs; |
2968 } | 3033 } |
2969 | 3034 |
3737 /* Create: | 3802 /* Create: |
3738 * sentry: int x = 0; | 3803 * sentry: int x = 0; |
3739 * sexception: x = 1; | 3804 * sexception: x = 1; |
3740 * sfinally: if (!x) statement; | 3805 * sfinally: if (!x) statement; |
3741 */ | 3806 */ |
3742 static int num; | 3807 Identifier *id = Lexer::uniqueId("__os"); |
3743 char name[5 + sizeof(num) * 3 + 1]; | |
3744 sprintf(name, "__osf%d", ++num); | |
3745 Identifier *id = Lexer::idPool(name); | |
3746 | 3808 |
3747 ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(0)); | 3809 ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(0)); |
3748 VarDeclaration *v = new VarDeclaration(loc, Type::tint32, id, ie); | 3810 VarDeclaration *v = new VarDeclaration(loc, Type::tint32, id, ie); |
3749 *sentry = new DeclarationStatement(loc, v); | 3811 *sentry = new DeclarationStatement(loc, v); |
3750 | 3812 |