Mercurial > projects > ldc
comparison dmd/interpret.c @ 1630:44b145be2ef5
Merge dmd 1.056.
author | Robert Clipsham <robert@octarineparrot.com> |
---|---|
date | Sat, 06 Feb 2010 15:53:52 +0000 |
parents | e83f0778c260 |
children | 9bf06e02070b |
comparison
equal
deleted
inserted
replaced
1629:b07d683ba4d0 | 1630:44b145be2ef5 |
---|---|
1 | 1 |
2 // Compiler implementation of the D programming language | 2 // Compiler implementation of the D programming language |
3 // Copyright (c) 1999-2009 by Digital Mars | 3 // Copyright (c) 1999-2010 by Digital Mars |
4 // All Rights Reserved | 4 // All Rights Reserved |
5 // written by Walter Bright | 5 // written by Walter Bright |
6 // http://www.digitalmars.com | 6 // http://www.digitalmars.com |
7 // License for redistribution is by either the Artistic License | 7 // License for redistribution is by either the Artistic License |
8 // in artistic.txt, or the GNU General Public License in gnu.txt. | 8 // in artistic.txt, or the GNU General Public License in gnu.txt. |
50 | 50 |
51 Expression *interpret_length(InterState *istate, Expression *earg); | 51 Expression *interpret_length(InterState *istate, Expression *earg); |
52 Expression *interpret_keys(InterState *istate, Expression *earg, FuncDeclaration *fd); | 52 Expression *interpret_keys(InterState *istate, Expression *earg, FuncDeclaration *fd); |
53 Expression *interpret_values(InterState *istate, Expression *earg, FuncDeclaration *fd); | 53 Expression *interpret_values(InterState *istate, Expression *earg, FuncDeclaration *fd); |
54 | 54 |
55 ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Type *type, Expression *elem, size_t dim); | |
56 | |
55 /************************************* | 57 /************************************* |
56 * Attempt to interpret a function given the arguments. | 58 * Attempt to interpret a function given the arguments. |
57 * Input: | 59 * Input: |
58 * istate state for calling function (NULL if none) | 60 * istate state for calling function (NULL if none) |
59 * arguments function arguments | 61 * arguments function arguments |
90 else if (ident == Id::values) | 92 else if (ident == Id::values) |
91 return interpret_values(istate, thisarg, this); | 93 return interpret_values(istate, thisarg, this); |
92 } | 94 } |
93 #endif | 95 #endif |
94 | 96 |
95 if (cantInterpret || semanticRun == 3) | 97 if (cantInterpret || semanticRun == PASSsemantic3) |
96 return NULL; | 98 return NULL; |
97 | 99 |
98 if (!fbody) | 100 if (!fbody) |
99 { cantInterpret = 1; | 101 { cantInterpret = 1; |
100 return NULL; | 102 return NULL; |
101 } | 103 } |
102 | 104 |
103 if (semanticRun < 3 && scope) | 105 if (semanticRun < PASSsemantic3 && scope) |
104 { | 106 { |
105 semantic3(scope); | 107 semantic3(scope); |
106 if (global.errors) // if errors compiling this function | 108 if (global.errors) // if errors compiling this function |
107 return NULL; | 109 return NULL; |
108 } | 110 } |
109 if (semanticRun < 4) | 111 if (semanticRun < PASSsemantic3done) |
110 return NULL; | 112 return NULL; |
111 | 113 |
112 Type *tb = type->toBasetype(); | 114 Type *tb = type->toBasetype(); |
113 assert(tb->ty == Tfunction); | 115 assert(tb->ty == Tfunction); |
114 TypeFunction *tf = (TypeFunction *)tb; | 116 TypeFunction *tf = (TypeFunction *)tb; |
158 | 160 |
159 for (size_t i = 0; i < dim; i++) | 161 for (size_t i = 0; i < dim; i++) |
160 { Expression *earg = (Expression *)arguments->data[i]; | 162 { Expression *earg = (Expression *)arguments->data[i]; |
161 Parameter *arg = Parameter::getNth(tf->parameters, i); | 163 Parameter *arg = Parameter::getNth(tf->parameters, i); |
162 | 164 |
163 if (arg->storageClass & (STCout | STCref)) | 165 if (arg->storageClass & (STCout | STCref | STClazy)) |
164 { | 166 { |
165 } | 167 } |
166 else | 168 else |
167 { /* Value parameters | 169 { /* Value parameters |
168 */ | 170 */ |
1003 printf("StringExp::interpret() %s\n", toChars()); | 1005 printf("StringExp::interpret() %s\n", toChars()); |
1004 #endif | 1006 #endif |
1005 return this; | 1007 return this; |
1006 } | 1008 } |
1007 | 1009 |
1010 Expression *FuncExp::interpret(InterState *istate) | |
1011 { | |
1012 #if LOG | |
1013 printf("FuncExp::interpret() %s\n", toChars()); | |
1014 #endif | |
1015 return this; | |
1016 } | |
1017 | |
1018 Expression *SymOffExp::interpret(InterState *istate) | |
1019 { | |
1020 #if LOG | |
1021 printf("SymOffExp::interpret() %s\n", toChars()); | |
1022 #endif | |
1023 if (var->isFuncDeclaration() && offset == 0) | |
1024 { | |
1025 return this; | |
1026 } | |
1027 error("Cannot interpret %s at compile time", toChars()); | |
1028 return EXP_CANT_INTERPRET; | |
1029 } | |
1030 | |
1031 Expression *DelegateExp::interpret(InterState *istate) | |
1032 { | |
1033 #if LOG | |
1034 printf("DelegateExp::interpret() %s\n", toChars()); | |
1035 #endif | |
1036 return this; | |
1037 } | |
1038 | |
1008 Expression *getVarExp(Loc loc, InterState *istate, Declaration *d) | 1039 Expression *getVarExp(Loc loc, InterState *istate, Declaration *d) |
1009 { | 1040 { |
1010 Expression *e = EXP_CANT_INTERPRET; | 1041 Expression *e = EXP_CANT_INTERPRET; |
1011 VarDeclaration *v = d->isVarDeclaration(); | 1042 VarDeclaration *v = d->isVarDeclaration(); |
1012 StaticStructInitDeclaration *s = d->isStaticStructInitDeclaration(); | 1043 StaticStructInitDeclaration *s = d->isStaticStructInitDeclaration(); |
1013 if (v) | 1044 if (v) |
1014 { | 1045 { |
1015 #if DMDV2 | 1046 #if DMDV2 |
1047 /* Magic variable __ctfe always returns true when interpreting | |
1048 */ | |
1049 if (v->ident == Id::ctfe) | |
1050 return new IntegerExp(loc, 1, Type::tbool); | |
1051 | |
1016 if ((v->isConst() || v->isImmutable() || v->storage_class & STCmanifest) && v->init && !v->value) | 1052 if ((v->isConst() || v->isImmutable() || v->storage_class & STCmanifest) && v->init && !v->value) |
1017 #else | 1053 #else |
1018 if (v->isConst() && v->init) | 1054 if (v->isConst() && v->init) |
1019 #endif | 1055 #endif |
1020 { e = v->init->toExpression(); | 1056 { e = v->init->toExpression(); |
1021 if (e && !e->type) | 1057 if (e && !e->type) |
1022 e->type = v->type; | 1058 e->type = v->type; |
1059 } | |
1060 else if (v->isCTFE() && !v->value) | |
1061 { | |
1062 if (v->init) | |
1063 { | |
1064 e = v->init->toExpression(); | |
1065 e = e->interpret(istate); | |
1066 } | |
1067 else // This should never happen | |
1068 e = v->type->defaultInitLiteral(); | |
1023 } | 1069 } |
1024 else | 1070 else |
1025 { e = v->value; | 1071 { e = v->value; |
1026 if (!v->isCTFE()) | 1072 if (!v->isCTFE()) |
1027 { error(loc, "static variable %s cannot be read at compile time", v->toChars()); | 1073 { error(loc, "static variable %s cannot be read at compile time", v->toChars()); |
1480 } | 1526 } |
1481 return expsx; | 1527 return expsx; |
1482 } | 1528 } |
1483 | 1529 |
1484 /*************************************** | 1530 /*************************************** |
1485 * Returns oldelems[0..insertpoint] ~ newelems ~ oldelems[insertpoint..$] | 1531 * Returns oldelems[0..insertpoint] ~ newelems ~ oldelems[insertpoint+newelems.length..$] |
1486 */ | 1532 */ |
1487 Expressions *spliceElements(Expressions *oldelems, | 1533 Expressions *spliceElements(Expressions *oldelems, |
1488 Expressions *newelems, size_t insertpoint) | 1534 Expressions *newelems, size_t insertpoint) |
1489 { | 1535 { |
1490 Expressions *expsx = new Expressions(); | 1536 Expressions *expsx = new Expressions(); |
1495 expsx->data[j] = newelems->data[j - insertpoint]; | 1541 expsx->data[j] = newelems->data[j - insertpoint]; |
1496 else | 1542 else |
1497 expsx->data[j] = oldelems->data[j]; | 1543 expsx->data[j] = oldelems->data[j]; |
1498 } | 1544 } |
1499 return expsx; | 1545 return expsx; |
1546 } | |
1547 | |
1548 /*************************************** | |
1549 * Returns oldstr[0..insertpoint] ~ newstr ~ oldstr[insertpoint+newlen..$] | |
1550 */ | |
1551 StringExp *spliceStringExp(StringExp *oldstr, StringExp *newstr, size_t insertpoint) | |
1552 { | |
1553 assert(oldstr->sz==newstr->sz); | |
1554 unsigned char *s; | |
1555 size_t oldlen = oldstr->len; | |
1556 size_t newlen = newstr->len; | |
1557 size_t sz = oldstr->sz; | |
1558 s = (unsigned char *)mem.calloc(oldlen + 1, sz); | |
1559 memcpy(s, oldstr->string, oldlen * sz); | |
1560 memcpy(s + insertpoint * sz, newstr->string, newlen * sz); | |
1561 StringExp *se2 = new StringExp(oldstr->loc, s, oldlen); | |
1562 se2->committed = oldstr->committed; | |
1563 se2->postfix = oldstr->postfix; | |
1564 se2->type = oldstr->type; | |
1565 return se2; | |
1500 } | 1566 } |
1501 | 1567 |
1502 /****************************** | 1568 /****************************** |
1503 * Create an array literal consisting of 'elem' duplicated 'dim' times. | 1569 * Create an array literal consisting of 'elem' duplicated 'dim' times. |
1504 */ | 1570 */ |
1512 ArrayLiteralExp *ae = new ArrayLiteralExp(0, elements); | 1578 ArrayLiteralExp *ae = new ArrayLiteralExp(0, elements); |
1513 ae->type = type; | 1579 ae->type = type; |
1514 return ae; | 1580 return ae; |
1515 } | 1581 } |
1516 | 1582 |
1583 /****************************** | |
1584 * Create a string literal consisting of 'value' duplicated 'dim' times. | |
1585 */ | |
1586 StringExp *createBlockDuplicatedStringLiteral(Type *type, | |
1587 unsigned value, size_t dim, int sz) | |
1588 { | |
1589 unsigned char *s; | |
1590 s = (unsigned char *)mem.calloc(dim + 1, sz); | |
1591 for (int elemi=0; elemi<dim; ++elemi) | |
1592 { | |
1593 switch (sz) | |
1594 { | |
1595 case 1: s[elemi] = value; break; | |
1596 case 2: ((unsigned short *)s)[elemi] = value; break; | |
1597 case 4: ((unsigned *)s)[elemi] = value; break; | |
1598 default: assert(0); | |
1599 } | |
1600 } | |
1601 StringExp *se = new StringExp(0, s, dim); | |
1602 se->type = type; | |
1603 return se; | |
1604 } | |
1517 | 1605 |
1518 /******************************** | 1606 /******************************** |
1519 * Add v to the istate list, unless it already exists there. | 1607 * Add v to the istate list, unless it already exists there. |
1520 */ | 1608 */ |
1521 void addVarToInterstate(InterState *istate, VarDeclaration *v) | 1609 void addVarToInterstate(InterState *istate, VarDeclaration *v) |
1580 } | 1668 } |
1581 | 1669 |
1582 // To reduce code complexity of handling dotvar expressions, | 1670 // To reduce code complexity of handling dotvar expressions, |
1583 // extract the aggregate now. | 1671 // extract the aggregate now. |
1584 Expression *aggregate; | 1672 Expression *aggregate; |
1585 if (e1->op == TOKdotvar) { | 1673 if (e1->op == TOKdotvar) |
1674 { | |
1586 aggregate = ((DotVarExp *)e1)->e1; | 1675 aggregate = ((DotVarExp *)e1)->e1; |
1587 // Get rid of 'this'. | 1676 // Get rid of 'this'. |
1588 if (aggregate->op == TOKthis && istate->localThis) | 1677 if (aggregate->op == TOKthis && istate->localThis) |
1589 aggregate = istate->localThis; | 1678 aggregate = istate->localThis; |
1590 } | 1679 } |
1591 | 1680 if (e1->op == TOKthis && istate->localThis) |
1681 e1 = istate->localThis; | |
1682 | |
1592 /* Assignment to variable of the form: | 1683 /* Assignment to variable of the form: |
1593 * v = e2 | 1684 * v = e2 |
1594 */ | 1685 */ |
1595 if (e1->op == TOKvar) | 1686 if (e1->op == TOKvar) |
1596 { | 1687 { |
1621 e2 = Cast(v->type, v->type, e2); | 1712 e2 = Cast(v->type, v->type, e2); |
1622 } | 1713 } |
1623 if (e2 == EXP_CANT_INTERPRET) | 1714 if (e2 == EXP_CANT_INTERPRET) |
1624 return e2; | 1715 return e2; |
1625 | 1716 |
1626 addVarToInterstate(istate, v); | 1717 if (istate) |
1718 addVarToInterstate(istate, v); | |
1627 v->value = e2; | 1719 v->value = e2; |
1628 e = Cast(type, type, post ? ev : e2); | 1720 e = Cast(type, type, post ? ev : e2); |
1629 } | 1721 } |
1630 } | 1722 } |
1631 else if (e1->op == TOKdotvar && aggregate->op == TOKdotvar) | 1723 else if (e1->op == TOKdotvar && aggregate->op == TOKdotvar) |
1666 * values, it is valid here to use the default initializer. | 1758 * values, it is valid here to use the default initializer. |
1667 * No attempt is made to determine if someone actually relies | 1759 * No attempt is made to determine if someone actually relies |
1668 * on the void value - to do that we'd need a VoidExp. | 1760 * on the void value - to do that we'd need a VoidExp. |
1669 * That's probably a good enhancement idea. | 1761 * That's probably a good enhancement idea. |
1670 */ | 1762 */ |
1671 v->value = v->type->defaultInit(); | 1763 v->value = v->type->defaultInitLiteral(); |
1672 } | 1764 } |
1673 Expression *vie = v->value; | 1765 Expression *vie = v->value; |
1766 assert(vie != EXP_CANT_INTERPRET); | |
1767 | |
1674 if (vie->op == TOKvar) | 1768 if (vie->op == TOKvar) |
1675 { | 1769 { |
1676 Declaration *d = ((VarExp *)vie)->var; | 1770 Declaration *d = ((VarExp *)vie)->var; |
1677 vie = getVarExp(e1->loc, istate, d); | 1771 vie = getVarExp(e1->loc, istate, d); |
1678 } | 1772 } |
1679 if (vie->op != TOKstructliteral) | 1773 if (vie->op != TOKstructliteral) |
1774 { | |
1775 error("Cannot assign %s=%s in CTFE", v->toChars(), vie->toChars()); | |
1680 return EXP_CANT_INTERPRET; | 1776 return EXP_CANT_INTERPRET; |
1777 } | |
1681 StructLiteralExp *se = (StructLiteralExp *)vie; | 1778 StructLiteralExp *se = (StructLiteralExp *)vie; |
1682 VarDeclaration *vf = ((DotVarExp *)e1)->var->isVarDeclaration(); | 1779 VarDeclaration *vf = ((DotVarExp *)e1)->var->isVarDeclaration(); |
1683 if (!vf) | 1780 if (!vf) |
1684 return EXP_CANT_INTERPRET; | 1781 return EXP_CANT_INTERPRET; |
1685 int fieldi = se->getFieldIndex(type, vf->offset); | 1782 int fieldi = se->getFieldIndex(type, vf->offset); |
2013 if (!v || !v->isCTFE()) | 2110 if (!v || !v->isCTFE()) |
2014 { | 2111 { |
2015 error("%s cannot be modified at compile time", v->toChars()); | 2112 error("%s cannot be modified at compile time", v->toChars()); |
2016 return EXP_CANT_INTERPRET; | 2113 return EXP_CANT_INTERPRET; |
2017 } | 2114 } |
2018 // Chase down rebinding of out and ref | 2115 // Chase down rebinding of out and ref |
2019 if (v->value && v->value->op == TOKvar) | 2116 if (v->value && v->value->op == TOKvar) |
2020 { | 2117 { |
2021 VarExp *ve2 = (VarExp *)v->value; | 2118 VarExp *ve2 = (VarExp *)v->value; |
2022 if (ve2->var->isStaticStructInitDeclaration()) | 2119 if (ve2->var->isStaticStructInitDeclaration()) |
2023 { // This can happen if v is a struct initialized to | 2120 { // This can happen if v is a struct initialized to |
2024 // 0 using an __initZ SymbolDeclaration from | 2121 // 0 using an __initZ SymbolDeclaration from |
2025 // TypeStruct::defaultInit() | 2122 // TypeStruct::defaultInit() |
2026 } | 2123 } |
2027 else | 2124 else |
2028 v = ve2->var->isVarDeclaration(); | 2125 v = ve2->var->isVarDeclaration(); |
2029 assert(v); | 2126 assert(v); |
2030 } | 2127 } |
2031 /* Set the $ variable | 2128 /* Set the $ variable |
2032 */ | 2129 */ |
2033 Expression *ee = v->value ? ArrayLength(Type::tsize_t, v->value) | 2130 Expression *ee = v->value ? ArrayLength(Type::tsize_t, v->value) |
2034 : EXP_CANT_INTERPRET; | 2131 : EXP_CANT_INTERPRET; |
2035 if (ee != EXP_CANT_INTERPRET && sexp->lengthVar) | 2132 if (ee != EXP_CANT_INTERPRET && sexp->lengthVar) |
2060 return EXP_CANT_INTERPRET; | 2157 return EXP_CANT_INTERPRET; |
2061 } | 2158 } |
2062 if (v->value->op == TOKarrayliteral) | 2159 if (v->value->op == TOKarrayliteral) |
2063 dim = ((ArrayLiteralExp *)v->value)->elements->dim; | 2160 dim = ((ArrayLiteralExp *)v->value)->elements->dim; |
2064 else if (v->value->op ==TOKstring) | 2161 else if (v->value->op ==TOKstring) |
2065 { | 2162 dim = ((StringExp *)v->value)->len; |
2066 error("String slice assignment is not yet supported in CTFE"); | |
2067 return EXP_CANT_INTERPRET; | |
2068 } | |
2069 } | 2163 } |
2070 else | 2164 else |
2071 { | 2165 { |
2072 error("%s cannot be evaluated at compile time", toChars()); | 2166 error("%s cannot be evaluated at compile time", toChars()); |
2073 return EXP_CANT_INTERPRET; | 2167 return EXP_CANT_INTERPRET; |
2074 } | 2168 } |
2075 int upperbound = upper ? upper->toInteger() : dim; | 2169 int upperbound = upper ? upper->toInteger() : dim; |
2076 int lowerbound = lower ? lower->toInteger() : 0; | 2170 int lowerbound = lower ? lower->toInteger() : 0; |
2077 | 2171 |
2078 ArrayLiteralExp *existing; | |
2079 if (((int)lowerbound < 0) || (upperbound > dim)) | 2172 if (((int)lowerbound < 0) || (upperbound > dim)) |
2080 { | 2173 { |
2081 error("Array bounds [0..%d] exceeded in slice [%d..%d]", dim, lowerbound, upperbound); | 2174 error("Array bounds [0..%d] exceeded in slice [%d..%d]", |
2175 dim, lowerbound, upperbound); | |
2082 return EXP_CANT_INTERPRET; | 2176 return EXP_CANT_INTERPRET; |
2083 } | 2177 } |
2084 if (upperbound-lowerbound != dim) | 2178 // Could either be slice assignment (v[] = e[]), |
2085 { | 2179 // or block assignment (v[] = val). |
2086 // Only modifying part of the array. Must create a new array literal. | 2180 // For the former, we check that the lengths match. |
2087 // If the existing array is uninitialized (this can only happen | 2181 bool isSliceAssignment = (e2->op == TOKarrayliteral) |
2088 // with static arrays), create it. | 2182 || (e2->op == TOKstring); |
2089 if (v->value && v->value->op == TOKarrayliteral) | 2183 size_t srclen = 0; |
2090 existing = (ArrayLiteralExp *)v->value; | 2184 if (e2->op == TOKarrayliteral) |
2091 else | 2185 srclen = ((ArrayLiteralExp *)e2)->elements->dim; |
2092 { | 2186 else if (e2->op == TOKstring) |
2093 // this can only happen with static arrays | 2187 srclen = ((StringExp *)e2)->len; |
2094 existing = createBlockDuplicatedArrayLiteral(v->type, v->type->defaultInit(), dim); | 2188 if (isSliceAssignment && srclen != (upperbound - lowerbound)) |
2095 } | 2189 { |
2096 } | 2190 error("Array length mismatch assigning [0..%d] to [%d..%d]", srclen, lowerbound, upperbound); |
2097 | 2191 return e; |
2192 } | |
2098 if (e2->op == TOKarrayliteral) | 2193 if (e2->op == TOKarrayliteral) |
2099 { | 2194 { |
2100 // Static array assignment from literal | 2195 // Static array assignment from literal |
2101 ArrayLiteralExp *ae = (ArrayLiteralExp *)e2; | 2196 ArrayLiteralExp *ae = (ArrayLiteralExp *)e2; |
2102 if (ae->elements->dim != (upperbound - lowerbound)) | |
2103 { | |
2104 error("Array length mismatch assigning [0..%d] to [%d..%d]", ae->elements->dim, lowerbound, upperbound); | |
2105 return e; | |
2106 } | |
2107 if (upperbound - lowerbound == dim) | 2197 if (upperbound - lowerbound == dim) |
2108 v->value = ae; | 2198 v->value = ae; |
2109 else | 2199 else |
2110 { | 2200 { |
2201 ArrayLiteralExp *existing; | |
2202 // Only modifying part of the array. Must create a new array literal. | |
2203 // If the existing array is uninitialized (this can only happen | |
2204 // with static arrays), create it. | |
2205 if (v->value && v->value->op == TOKarrayliteral) | |
2206 existing = (ArrayLiteralExp *)v->value; | |
2207 else // this can only happen with static arrays | |
2208 existing = createBlockDuplicatedArrayLiteral(v->type, v->type->defaultInit(), dim); | |
2111 // value[] = value[0..lower] ~ ae ~ value[upper..$] | 2209 // value[] = value[0..lower] ~ ae ~ value[upper..$] |
2112 existing->elements = spliceElements(existing->elements, ae->elements, lowerbound); | 2210 existing->elements = spliceElements(existing->elements, ae->elements, lowerbound); |
2113 v->value = existing; | 2211 v->value = existing; |
2114 } | 2212 } |
2115 return e2; | 2213 return e2; |
2116 } | 2214 } |
2215 else if (e2->op == TOKstring) | |
2216 { | |
2217 StringExp *se = (StringExp *)e2; | |
2218 if (upperbound-lowerbound == dim) | |
2219 v->value = e2; | |
2220 else | |
2221 { | |
2222 if (!v->value) | |
2223 v->value = createBlockDuplicatedStringLiteral(se->type, | |
2224 se->type->defaultInit()->toInteger(), dim, se->sz); | |
2225 if (v->value->op==TOKstring) | |
2226 v->value = spliceStringExp((StringExp *)v->value, se, lowerbound); | |
2227 else | |
2228 error("String slice assignment is not yet supported in CTFE"); | |
2229 } | |
2230 return e2; | |
2231 } | |
2117 else if (t->nextOf()->ty == e2->type->ty) | 2232 else if (t->nextOf()->ty == e2->type->ty) |
2118 { | 2233 { |
2119 // Static array block assignment | 2234 // Static array block assignment |
2120 if (upperbound-lowerbound ==dim) | 2235 if (upperbound - lowerbound == dim) |
2121 v->value = createBlockDuplicatedArrayLiteral(v->type, e2, dim); | 2236 v->value = createBlockDuplicatedArrayLiteral(v->type, e2, dim); |
2122 else | 2237 else |
2123 { | 2238 { |
2239 ArrayLiteralExp *existing; | |
2240 // Only modifying part of the array. Must create a new array literal. | |
2241 // If the existing array is uninitialized (this can only happen | |
2242 // with static arrays), create it. | |
2243 if (v->value && v->value->op == TOKarrayliteral) | |
2244 existing = (ArrayLiteralExp *)v->value; | |
2245 else // this can only happen with static arrays | |
2246 existing = createBlockDuplicatedArrayLiteral(v->type, v->type->defaultInit(), dim); | |
2124 // value[] = value[0..lower] ~ ae ~ value[upper..$] | 2247 // value[] = value[0..lower] ~ ae ~ value[upper..$] |
2125 existing->elements = spliceElements(existing->elements, createBlockDuplicatedArrayLiteral(v->type, e2, upperbound-lowerbound)->elements, lowerbound); | 2248 existing->elements = spliceElements(existing->elements, |
2249 createBlockDuplicatedArrayLiteral(v->type, e2, upperbound-lowerbound)->elements, | |
2250 lowerbound); | |
2126 v->value = existing; | 2251 v->value = existing; |
2127 } | 2252 } |
2128 return e2; | |
2129 } | |
2130 else if (e2->op == TOKstring) | |
2131 { | |
2132 StringExp *se = (StringExp *)e2; | |
2133 // This is problematic. char[8] should be storing | |
2134 // values as a string literal, not | |
2135 // as an array literal. Then, for static arrays, we | |
2136 // could do modifications | |
2137 // in-place, with a dramatic memory and speed improvement. | |
2138 error("String slice assignment is not yet supported in CTFE"); | |
2139 return e2; | 2253 return e2; |
2140 } | 2254 } |
2141 else | 2255 else |
2142 { | 2256 { |
2143 error("Slice operation %s cannot be evaluated at compile time", toChars()); | 2257 error("Slice operation %s cannot be evaluated at compile time", toChars()); |
2258 { Expression *e = EXP_CANT_INTERPRET; | 2372 { Expression *e = EXP_CANT_INTERPRET; |
2259 | 2373 |
2260 #if LOG | 2374 #if LOG |
2261 printf("CallExp::interpret() %s\n", toChars()); | 2375 printf("CallExp::interpret() %s\n", toChars()); |
2262 #endif | 2376 #endif |
2263 if (e1->op == TOKdotvar) | 2377 |
2264 { | 2378 Expression * pthis = NULL; |
2265 Expression * pthis = ((DotVarExp*)e1)->e1; | 2379 FuncDeclaration *fd = NULL; |
2266 FuncDeclaration *fd = ((DotVarExp*)e1)->var->isFuncDeclaration(); | 2380 Expression *ecall = e1; |
2267 TypeFunction *tf = fd ? (TypeFunction *)(fd->type) : NULL; | 2381 if (ecall->op == TOKindex) |
2268 if (tf) | 2382 ecall = e1->interpret(istate); |
2269 { // Member function call | 2383 if (ecall->op == TOKdotvar && !((DotVarExp*)ecall)->var->isFuncDeclaration()) |
2270 if(pthis->op == TOKthis) | 2384 ecall = e1->interpret(istate); |
2271 pthis = istate->localThis; | 2385 |
2272 Expression *eresult = fd->interpret(istate, arguments, pthis); | 2386 if (ecall->op == TOKdotvar) |
2387 { // Calling a member function | |
2388 pthis = ((DotVarExp*)e1)->e1; | |
2389 fd = ((DotVarExp*)e1)->var->isFuncDeclaration(); | |
2390 } | |
2391 else if (ecall->op == TOKvar) | |
2392 { | |
2393 VarDeclaration *vd = ((VarExp *)ecall)->var->isVarDeclaration(); | |
2394 if (vd && vd->value) | |
2395 ecall = vd->value; | |
2396 else // Calling a function | |
2397 fd = ((VarExp *)e1)->var->isFuncDeclaration(); | |
2398 } | |
2399 if (ecall->op == TOKdelegate) | |
2400 { // Calling a delegate | |
2401 fd = ((DelegateExp *)ecall)->func; | |
2402 pthis = ((DelegateExp *)ecall)->e1; | |
2403 } | |
2404 else if (ecall->op == TOKfunction) | |
2405 { // Calling a delegate literal | |
2406 fd = ((FuncExp*)ecall)->fd; | |
2407 } | |
2408 else if (ecall->op == TOKstar && ((PtrExp*)ecall)->e1->op==TOKfunction) | |
2409 { // Calling a function literal | |
2410 fd = ((FuncExp*)((PtrExp*)ecall)->e1)->fd; | |
2411 } | |
2412 else if (ecall->op == TOKstar && ((PtrExp*)ecall)->e1->op==TOKvar) | |
2413 { // Calling a function pointer | |
2414 VarDeclaration *vd = ((VarExp *)((PtrExp*)ecall)->e1)->var->isVarDeclaration(); | |
2415 if (vd && vd->value && vd->value->op==TOKsymoff) | |
2416 fd = ((SymOffExp *)vd->value)->var->isFuncDeclaration(); | |
2417 } | |
2418 | |
2419 TypeFunction *tf = fd ? (TypeFunction *)(fd->type) : NULL; | |
2420 if (!tf) | |
2421 { // DAC: I'm not sure if this ever happens | |
2422 //printf("ecall=%s %d %d\n", ecall->toChars(), ecall->op, TOKcall); | |
2423 error("cannot evaluate %s at compile time", toChars()); | |
2424 return EXP_CANT_INTERPRET; | |
2425 } | |
2426 if (pthis && fd) | |
2427 { // Member function call | |
2428 if (pthis->op == TOKthis) | |
2429 pthis = istate->localThis; | |
2430 else if (pthis->op == TOKcomma) | |
2431 pthis = pthis->interpret(istate); | |
2432 Expression *eresult = fd->interpret(istate, arguments, pthis); | |
2433 if (eresult) | |
2434 e = eresult; | |
2435 else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors) | |
2436 e = EXP_VOID_INTERPRET; | |
2437 else | |
2438 error("cannot evaluate %s at compile time", toChars()); | |
2439 return e; | |
2440 } | |
2441 else if (fd) | |
2442 { // function call | |
2443 #if DMDV2 | |
2444 enum BUILTIN b = fd->isBuiltin(); | |
2445 if (b) | |
2446 { Expressions args; | |
2447 args.setDim(arguments->dim); | |
2448 for (size_t i = 0; i < args.dim; i++) | |
2449 { | |
2450 Expression *earg = (Expression *)arguments->data[i]; | |
2451 earg = earg->interpret(istate); | |
2452 if (earg == EXP_CANT_INTERPRET) | |
2453 return earg; | |
2454 args.data[i] = (void *)earg; | |
2455 } | |
2456 e = eval_builtin(b, &args); | |
2457 if (!e) | |
2458 e = EXP_CANT_INTERPRET; | |
2459 } | |
2460 else | |
2461 #endif | |
2462 // Inline .dup | |
2463 if (fd->ident == Id::adDup && arguments && arguments->dim == 2) | |
2464 { | |
2465 e = (Expression *)arguments->data[1]; | |
2466 e = e->interpret(istate); | |
2467 if (e != EXP_CANT_INTERPRET) | |
2468 { | |
2469 e = expType(type, e); | |
2470 } | |
2471 } | |
2472 else | |
2473 { | |
2474 Expression *eresult = fd->interpret(istate, arguments); | |
2273 if (eresult) | 2475 if (eresult) |
2274 e = eresult; | 2476 e = eresult; |
2275 else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors) | 2477 else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors) |
2276 e = EXP_VOID_INTERPRET; | 2478 e = EXP_VOID_INTERPRET; |
2277 else | 2479 else |
2278 error("cannot evaluate %s at compile time", toChars()); | 2480 error("cannot evaluate %s at compile time", toChars()); |
2279 return e; | 2481 } |
2280 } | 2482 } |
2483 else | |
2484 { | |
2281 error("cannot evaluate %s at compile time", toChars()); | 2485 error("cannot evaluate %s at compile time", toChars()); |
2282 return EXP_CANT_INTERPRET; | 2486 return EXP_CANT_INTERPRET; |
2283 } | 2487 } |
2284 if (e1->op == TOKvar) | 2488 return e; |
2285 { | |
2286 FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration(); | |
2287 if (fd) | |
2288 { | |
2289 #if DMDV2 | |
2290 enum BUILTIN b = fd->isBuiltin(); | |
2291 if (b) | |
2292 { Expressions args; | |
2293 args.setDim(arguments->dim); | |
2294 for (size_t i = 0; i < args.dim; i++) | |
2295 { | |
2296 Expression *earg = (Expression *)arguments->data[i]; | |
2297 earg = earg->interpret(istate); | |
2298 if (earg == EXP_CANT_INTERPRET) | |
2299 return earg; | |
2300 args.data[i] = (void *)earg; | |
2301 } | |
2302 e = eval_builtin(b, &args); | |
2303 if (!e) | |
2304 e = EXP_CANT_INTERPRET; | |
2305 } | |
2306 else | |
2307 #endif | |
2308 // Inline .dup | |
2309 if (fd->ident == Id::adDup && arguments && arguments->dim == 2) | |
2310 { | |
2311 e = (Expression *)arguments->data[1]; | |
2312 e = e->interpret(istate); | |
2313 if (e != EXP_CANT_INTERPRET) | |
2314 { | |
2315 e = expType(type, e); | |
2316 } | |
2317 } | |
2318 else | |
2319 { | |
2320 Expression *eresult = fd->interpret(istate, arguments); | |
2321 if (eresult) | |
2322 e = eresult; | |
2323 else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors) | |
2324 e = EXP_VOID_INTERPRET; | |
2325 else | |
2326 error("cannot evaluate %s at compile time", toChars()); | |
2327 } | |
2328 } | |
2329 } | |
2330 return e; | |
2331 } | 2489 } |
2332 | 2490 |
2333 Expression *CommaExp::interpret(InterState *istate) | 2491 Expression *CommaExp::interpret(InterState *istate) |
2334 { | 2492 { |
2335 #if LOG | 2493 #if LOG |
2336 printf("CommaExp::interpret() %s\n", toChars()); | 2494 printf("CommaExp::interpret() %s\n", toChars()); |
2337 #endif | 2495 #endif |
2496 // If the comma returns a temporary variable, it needs to be an lvalue | |
2497 // (this is particularly important for struct constructors) | |
2498 if (e1->op == TOKdeclaration && e2->op == TOKvar | |
2499 && ((DeclarationExp *)e1)->declaration == ((VarExp*)e2)->var) | |
2500 { | |
2501 VarExp* ve = (VarExp *)e2; | |
2502 VarDeclaration *v = ve->var->isVarDeclaration(); | |
2503 if (!v->init && !v->value) | |
2504 v->value = v->type->defaultInitLiteral(); | |
2505 if (!v->value) | |
2506 v->value = v->init->toExpression(); | |
2507 v->value = v->value->interpret(istate); | |
2508 return e2; | |
2509 } | |
2510 | |
2338 Expression *e = e1->interpret(istate); | 2511 Expression *e = e1->interpret(istate); |
2339 if (e != EXP_CANT_INTERPRET) | 2512 if (e != EXP_CANT_INTERPRET) |
2340 e = e2->interpret(istate); | 2513 e = e2->interpret(istate); |
2341 return e; | 2514 return e; |
2342 } | 2515 } |
2514 printf("AssertExp::interpret() %s\n", toChars()); | 2687 printf("AssertExp::interpret() %s\n", toChars()); |
2515 #endif | 2688 #endif |
2516 if( this->e1->op == TOKaddress) | 2689 if( this->e1->op == TOKaddress) |
2517 { // Special case: deal with compiler-inserted assert(&this, "null this") | 2690 { // Special case: deal with compiler-inserted assert(&this, "null this") |
2518 AddrExp *ade = (AddrExp *)this->e1; | 2691 AddrExp *ade = (AddrExp *)this->e1; |
2519 if(ade->e1->op == TOKthis && istate->localThis) | 2692 if (ade->e1->op == TOKthis && istate->localThis) |
2520 return istate->localThis->interpret(istate); | 2693 if (ade->e1->op == TOKdotvar |
2521 } | 2694 && ((DotVarExp *)(istate->localThis))->e1->op == TOKthis) |
2522 if (this->e1->op == TOKthis) | 2695 return getVarExp(loc, istate, ((DotVarExp*)(istate->localThis))->var); |
2523 { | 2696 else |
2524 if(istate->localThis) | 2697 return istate->localThis->interpret(istate); |
2525 return istate->localThis->interpret(istate); | 2698 } |
2526 } | 2699 if (this->e1->op == TOKthis) |
2700 { | |
2701 if (istate->localThis) | |
2702 return istate->localThis->interpret(istate); | |
2703 } | |
2527 e1 = this->e1->interpret(istate); | 2704 e1 = this->e1->interpret(istate); |
2528 if (e1 == EXP_CANT_INTERPRET) | 2705 if (e1 == EXP_CANT_INTERPRET) |
2529 goto Lcant; | 2706 goto Lcant; |
2530 if (e1->isBool(TRUE)) | 2707 if (e1->isBool(TRUE)) |
2531 { | 2708 { |