Mercurial > projects > ldc
comparison dmd/interpret.c @ 1587:def7a1d494fd
Merge DMD 1.051
author | Christian Kamm <kamm incasoftware de> |
---|---|
date | Fri, 06 Nov 2009 23:58:01 +0100 |
parents | 8026319762be |
children | 8aa756a00228 |
comparison
equal
deleted
inserted
replaced
1586:7f728c52e63c | 1587:def7a1d494fd |
---|---|
1 | 1 |
2 // Compiler implementation of the D programming language | 2 // Compiler implementation of the D programming language |
3 // Copyright (c) 1999-2008 by Digital Mars | 3 // Copyright (c) 1999-2009 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. |
32 InterState *caller; // calling function's InterState | 32 InterState *caller; // calling function's InterState |
33 FuncDeclaration *fd; // function being interpreted | 33 FuncDeclaration *fd; // function being interpreted |
34 Dsymbols vars; // variables used in this function | 34 Dsymbols vars; // variables used in this function |
35 Statement *start; // if !=NULL, start execution at this statement | 35 Statement *start; // if !=NULL, start execution at this statement |
36 Statement *gotoTarget; // target of EXP_GOTO_INTERPRET result | 36 Statement *gotoTarget; // target of EXP_GOTO_INTERPRET result |
37 Expression *localThis; // value of 'this', or NULL if none | |
37 | 38 |
38 InterState(); | 39 InterState(); |
39 }; | 40 }; |
40 | 41 |
41 InterState::InterState() | 42 InterState::InterState() |
48 Expression *interpret_aaValues(InterState *istate, Expressions *arguments); | 49 Expression *interpret_aaValues(InterState *istate, Expressions *arguments); |
49 | 50 |
50 /************************************* | 51 /************************************* |
51 * Attempt to interpret a function given the arguments. | 52 * Attempt to interpret a function given the arguments. |
52 * Input: | 53 * Input: |
53 * istate state for calling function (NULL if none) | 54 * istate state for calling function (NULL if none) |
55 * arguments function arguments | |
56 * thisarg 'this', if a needThis() function, NULL if not. | |
57 * | |
54 * Return result expression if successful, NULL if not. | 58 * Return result expression if successful, NULL if not. |
55 */ | 59 */ |
56 | 60 |
57 Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments) | 61 Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments, Expression *thisarg) |
58 { | 62 { |
59 #if LOG | 63 #if LOG |
60 printf("\n********\nFuncDeclaration::interpret(istate = %p) %s\n", istate, toChars()); | 64 printf("\n********\nFuncDeclaration::interpret(istate = %p) %s\n", istate, toChars()); |
61 printf("cantInterpret = %d, semanticRun = %d\n", cantInterpret, semanticRun); | 65 printf("cantInterpret = %d, semanticRun = %d\n", cantInterpret, semanticRun); |
62 #endif | 66 #endif |
70 return interpret_aaValues(istate, arguments); | 74 return interpret_aaValues(istate, arguments); |
71 | 75 |
72 if (cantInterpret || semanticRun == 3) | 76 if (cantInterpret || semanticRun == 3) |
73 return NULL; | 77 return NULL; |
74 | 78 |
75 if (needThis() || isNested() || !fbody) | 79 if (!fbody) |
76 { cantInterpret = 1; | 80 { cantInterpret = 1; |
77 return NULL; | 81 return NULL; |
78 } | 82 } |
79 | 83 |
80 if (semanticRun < 3 && scope) | 84 if (semanticRun < 3 && scope) |
88 | 92 |
89 Type *tb = type->toBasetype(); | 93 Type *tb = type->toBasetype(); |
90 assert(tb->ty == Tfunction); | 94 assert(tb->ty == Tfunction); |
91 TypeFunction *tf = (TypeFunction *)tb; | 95 TypeFunction *tf = (TypeFunction *)tb; |
92 Type *tret = tf->next->toBasetype(); | 96 Type *tret = tf->next->toBasetype(); |
93 if (tf->varargs /*|| tret->ty == Tvoid*/) | 97 if (tf->varargs) |
94 { cantInterpret = 1; | 98 { cantInterpret = 1; |
99 error("Variadic functions are not yet implemented in CTFE"); | |
95 return NULL; | 100 return NULL; |
96 } | 101 } |
97 | 102 |
103 // Ensure there are no lazy parameters | |
98 if (tf->parameters) | 104 if (tf->parameters) |
99 { size_t dim = Argument::dim(tf->parameters); | 105 { size_t dim = Argument::dim(tf->parameters); |
100 for (size_t i = 0; i < dim; i++) | 106 for (size_t i = 0; i < dim; i++) |
101 { Argument *arg = Argument::getNth(tf->parameters, i); | 107 { Argument *arg = Argument::getNth(tf->parameters, i); |
102 if (arg->storageClass & STClazy) | 108 if (arg->storageClass & STClazy) |
107 } | 113 } |
108 | 114 |
109 InterState istatex; | 115 InterState istatex; |
110 istatex.caller = istate; | 116 istatex.caller = istate; |
111 istatex.fd = this; | 117 istatex.fd = this; |
118 istatex.localThis = thisarg; | |
112 | 119 |
113 Expressions vsave; // place to save previous parameter values | 120 Expressions vsave; // place to save previous parameter values |
114 size_t dim = 0; | 121 size_t dim = 0; |
122 if (needThis() && !thisarg) | |
123 { cantInterpret = 1; | |
124 // error, no this. Prevent segfault. | |
125 error("need 'this' to access member %s", toChars()); | |
126 return NULL; | |
127 } | |
115 if (arguments) | 128 if (arguments) |
116 { | 129 { |
117 dim = arguments->dim; | 130 dim = arguments->dim; |
118 assert(!dim || parameters->dim == dim); | 131 assert(!dim || (parameters && (parameters->dim == dim))); |
119 vsave.setDim(dim); | 132 vsave.setDim(dim); |
120 | 133 |
121 /* Evaluate all the arguments to the function, | 134 /* Evaluate all the arguments to the function, |
122 * store the results in eargs[] | 135 * store the results in eargs[] |
123 */ | 136 */ |
142 */ | 155 */ |
143 earg = ((AddrExp *)earg)->e1; | 156 earg = ((AddrExp *)earg)->e1; |
144 } | 157 } |
145 earg = earg->interpret(istate ? istate : &istatex); | 158 earg = earg->interpret(istate ? istate : &istatex); |
146 if (earg == EXP_CANT_INTERPRET) | 159 if (earg == EXP_CANT_INTERPRET) |
160 { cantInterpret = 1; | |
147 return NULL; | 161 return NULL; |
162 } | |
148 } | 163 } |
149 eargs.data[i] = earg; | 164 eargs.data[i] = earg; |
150 } | 165 } |
151 | 166 |
152 for (size_t i = 0; i < dim; i++) | 167 for (size_t i = 0; i < dim; i++) |
155 VarDeclaration *v = (VarDeclaration *)parameters->data[i]; | 170 VarDeclaration *v = (VarDeclaration *)parameters->data[i]; |
156 vsave.data[i] = v->value; | 171 vsave.data[i] = v->value; |
157 #if LOG | 172 #if LOG |
158 printf("arg[%d] = %s\n", i, earg->toChars()); | 173 printf("arg[%d] = %s\n", i, earg->toChars()); |
159 #endif | 174 #endif |
160 if (arg->storageClass & (STCout | STCref)) | 175 if (arg->storageClass & (STCout | STCref) && earg->op==TOKvar) |
161 { | 176 { |
162 /* Bind out or ref parameter to the corresponding | 177 /* Bind out or ref parameter to the corresponding |
163 * variable v2 | 178 * variable v2 |
164 */ | 179 */ |
165 if (!istate || earg->op != TOKvar) | 180 if (!istate) |
181 { cantInterpret = 1; | |
182 error("%s cannot be by passed by reference at compile time", earg->toChars()); | |
166 return NULL; // can't bind to non-interpreted vars | 183 return NULL; // can't bind to non-interpreted vars |
167 | 184 } |
185 // We need to chase down all of the the passed parameters until | |
186 // we find something that isn't a TOKvar, then create a variable | |
187 // containg that expression. | |
168 VarDeclaration *v2; | 188 VarDeclaration *v2; |
169 while (1) | 189 while (1) |
170 { | 190 { |
171 VarExp *ve = (VarExp *)earg; | 191 VarExp *ve = (VarExp *)earg; |
172 v2 = ve->var->isVarDeclaration(); | 192 v2 = ve->var->isVarDeclaration(); |
173 if (!v2) | 193 if (!v2) |
194 { cantInterpret = 1; | |
174 return NULL; | 195 return NULL; |
196 } | |
175 if (!v2->value || v2->value->op != TOKvar) | 197 if (!v2->value || v2->value->op != TOKvar) |
176 break; | 198 break; |
199 //TODO | |
200 #ifdef IN_DMD | |
201 if (((VarExp *)v2->value)->var->isSymbolDeclaration()) | |
202 { // This can happen if v is a struct initialized to | |
203 // 0 using an __initZ SymbolDeclaration from | |
204 // TypeStruct::defaultInit() | |
205 break; // eg default-initialized variable | |
206 } | |
207 #endif | |
177 earg = v2->value; | 208 earg = v2->value; |
178 } | 209 } |
179 | 210 |
180 v->value = new VarExp(earg->loc, v2); | 211 v->value = new VarExp(earg->loc, v2); |
181 | 212 |
189 break; | 220 break; |
190 } | 221 } |
191 } | 222 } |
192 } | 223 } |
193 else | 224 else |
194 { /* Value parameters | 225 { // Value parameters and non-trivial references |
195 */ | |
196 v->value = earg; | 226 v->value = earg; |
197 } | 227 } |
198 #if LOG | 228 #if LOG |
199 printf("interpreted arg[%d] = %s\n", i, earg->toChars()); | 229 printf("interpreted arg[%d] = %s\n", i, earg->toChars()); |
200 #endif | 230 #endif |
231 } | |
232 } | |
233 // Don't restore the value of 'this' upon function return | |
234 if (needThis() && thisarg->op==TOKvar) { | |
235 VarDeclaration *thisvar = ((VarExp *)(thisarg))->var->isVarDeclaration(); | |
236 for (size_t i = 0; i < istate->vars.dim; i++) | |
237 { VarDeclaration *v = (VarDeclaration *)istate->vars.data[i]; | |
238 if (v == thisvar) | |
239 { istate->vars.data[i] = NULL; | |
240 break; | |
241 } | |
201 } | 242 } |
202 } | 243 } |
203 | 244 |
204 /* Save the values of the local variables used | 245 /* Save the values of the local variables used |
205 */ | 246 */ |
206 Expressions valueSaves; | 247 Expressions valueSaves; |
207 if (istate) | 248 if (istate && !isNested()) |
208 { | 249 { |
209 //printf("saving local variables...\n"); | 250 //printf("saving local variables...\n"); |
210 valueSaves.setDim(istate->vars.dim); | 251 valueSaves.setDim(istate->vars.dim); |
211 for (size_t i = 0; i < istate->vars.dim; i++) | 252 for (size_t i = 0; i < istate->vars.dim; i++) |
212 { VarDeclaration *v = (VarDeclaration *)istate->vars.data[i]; | 253 { VarDeclaration *v = (VarDeclaration *)istate->vars.data[i]; |
218 } | 259 } |
219 } | 260 } |
220 } | 261 } |
221 | 262 |
222 Expression *e = NULL; | 263 Expression *e = NULL; |
223 | |
224 while (1) | 264 while (1) |
225 { | 265 { |
226 e = fbody->interpret(&istatex); | 266 e = fbody->interpret(&istatex); |
227 if (e == EXP_CANT_INTERPRET) | 267 if (e == EXP_CANT_INTERPRET) |
228 { | 268 { |
244 istatex.gotoTarget = NULL; | 284 istatex.gotoTarget = NULL; |
245 } | 285 } |
246 else | 286 else |
247 break; | 287 break; |
248 } | 288 } |
249 | |
250 /* Restore the parameter values | 289 /* Restore the parameter values |
251 */ | 290 */ |
252 for (size_t i = 0; i < dim; i++) | 291 for (size_t i = 0; i < dim; i++) |
253 { | 292 { |
254 VarDeclaration *v = (VarDeclaration *)parameters->data[i]; | 293 VarDeclaration *v = (VarDeclaration *)parameters->data[i]; |
255 v->value = (Expression *)vsave.data[i]; | 294 v->value = (Expression *)vsave.data[i]; |
256 } | 295 } |
257 | 296 |
258 if (istate) | 297 if (istate && !isNested()) |
259 { | 298 { |
260 /* Restore the variable values | 299 /* Restore the variable values |
261 */ | 300 */ |
262 //printf("restoring local variables...\n"); | 301 //printf("restoring local variables...\n"); |
263 for (size_t i = 0; i < istate->vars.dim; i++) | 302 for (size_t i = 0; i < istate->vars.dim; i++) |
266 { v->value = (Expression *)valueSaves.data[i]; | 305 { v->value = (Expression *)valueSaves.data[i]; |
267 //printf("\trestoring [%d] %s = %s\n", i, v->toChars(), v->value ? v->value->toChars() : ""); | 306 //printf("\trestoring [%d] %s = %s\n", i, v->toChars(), v->value ? v->value->toChars() : ""); |
268 } | 307 } |
269 } | 308 } |
270 } | 309 } |
271 | |
272 return e; | 310 return e; |
273 } | 311 } |
274 | 312 |
275 /******************************** Statement ***************************/ | 313 /******************************** Statement ***************************/ |
276 | 314 |
476 return NULL; | 514 return NULL; |
477 if (e == EXP_CANT_INTERPRET) | 515 if (e == EXP_CANT_INTERPRET) |
478 return e; | 516 return e; |
479 if (e == EXP_BREAK_INTERPRET) | 517 if (e == EXP_BREAK_INTERPRET) |
480 return NULL; | 518 return NULL; |
481 if (e != EXP_CONTINUE_INTERPRET) | 519 if (e && e != EXP_CONTINUE_INTERPRET) |
482 return e; | 520 return e; |
483 } | 521 } |
484 | 522 |
485 while (1) | 523 while (1) |
486 { | 524 { |
756 { | 794 { |
757 key->value = elwr; | 795 key->value = elwr; |
758 | 796 |
759 while (1) | 797 while (1) |
760 { | 798 { |
761 e = Cmp(TOKlt, key->value->type, key->value, upr); | 799 e = Cmp(TOKlt, key->value->type, key->value, eupr); |
762 if (e == EXP_CANT_INTERPRET) | 800 if (e == EXP_CANT_INTERPRET) |
763 break; | 801 break; |
764 if (e->isBool(TRUE) == FALSE) | 802 if (e->isBool(TRUE) == FALSE) |
765 { e = NULL; | 803 { e = NULL; |
766 break; | 804 break; |
771 break; | 809 break; |
772 if (e == EXP_BREAK_INTERPRET) | 810 if (e == EXP_BREAK_INTERPRET) |
773 { e = NULL; | 811 { e = NULL; |
774 break; | 812 break; |
775 } | 813 } |
776 e = Add(key->value->type, key->value, new IntegerExp(loc, 1, key->value->type)); | 814 if (e == NULL || e == EXP_CONTINUE_INTERPRET) |
777 if (e == EXP_CANT_INTERPRET) | 815 { e = Add(key->value->type, key->value, new IntegerExp(loc, 1, key->value->type)); |
778 break; | 816 if (e == EXP_CANT_INTERPRET) |
779 key->value = e; | 817 break; |
818 key->value = e; | |
819 } | |
820 else | |
821 break; | |
780 } | 822 } |
781 } | 823 } |
782 else // TOKforeach_reverse | 824 else // TOKforeach_reverse |
783 { | 825 { |
784 key->value = eupr; | 826 key->value = eupr; |
785 | 827 |
786 while (1) | 828 do |
787 { | 829 { |
788 e = Cmp(TOKgt, key->value->type, key->value, lwr); | 830 e = Cmp(TOKgt, key->value->type, key->value, elwr); |
789 if (e == EXP_CANT_INTERPRET) | 831 if (e == EXP_CANT_INTERPRET) |
790 break; | 832 break; |
791 if (e->isBool(TRUE) == FALSE) | 833 if (e->isBool(TRUE) == FALSE) |
792 { e = NULL; | 834 { e = NULL; |
793 break; | 835 break; |
803 break; | 845 break; |
804 if (e == EXP_BREAK_INTERPRET) | 846 if (e == EXP_BREAK_INTERPRET) |
805 { e = NULL; | 847 { e = NULL; |
806 break; | 848 break; |
807 } | 849 } |
808 } | 850 } while (e == NULL || e == EXP_CONTINUE_INTERPRET); |
809 } | 851 } |
810 key->value = keysave; | 852 key->value = keysave; |
811 return e; | 853 return e; |
812 } | 854 } |
813 #endif | 855 #endif |
944 #if LOG | 986 #if LOG |
945 printf("Expression::interpret() %s\n", toChars()); | 987 printf("Expression::interpret() %s\n", toChars()); |
946 printf("type = %s\n", type->toChars()); | 988 printf("type = %s\n", type->toChars()); |
947 dump(0); | 989 dump(0); |
948 #endif | 990 #endif |
991 error("Cannot interpret %s at compile time", toChars()); | |
992 return EXP_CANT_INTERPRET; | |
993 } | |
994 | |
995 Expression *ThisExp::interpret(InterState *istate) | |
996 { | |
997 if (istate->localThis) | |
998 return istate->localThis->interpret(istate); | |
949 return EXP_CANT_INTERPRET; | 999 return EXP_CANT_INTERPRET; |
950 } | 1000 } |
951 | 1001 |
952 Expression *NullExp::interpret(InterState *istate) | 1002 Expression *NullExp::interpret(InterState *istate) |
953 { | 1003 { |
989 VarDeclaration *v = d->isVarDeclaration(); | 1039 VarDeclaration *v = d->isVarDeclaration(); |
990 StaticStructInitDeclaration *s = d->isStaticStructInitDeclaration(); | 1040 StaticStructInitDeclaration *s = d->isStaticStructInitDeclaration(); |
991 if (v) | 1041 if (v) |
992 { | 1042 { |
993 #if DMDV2 | 1043 #if DMDV2 |
994 if ((v->isConst() || v->isInvariant()) && v->init && !v->value) | 1044 if ((v->isConst() || v->isInvariant() || v->storage_class & STCmanifest) && v->init && !v->value) |
995 #else | 1045 #else |
996 if (v->isConst() && v->init) | 1046 if (v->isConst() && v->init) |
997 #endif | 1047 #endif |
998 { e = v->init->toExpression(); | 1048 { e = v->init->toExpression(); |
999 if (e && !e->type) | 1049 if (e && !e->type) |
1000 e->type = v->type; | 1050 e->type = v->type; |
1001 } | 1051 } |
1002 else | 1052 else |
1003 { e = v->value; | 1053 { e = v->value; |
1004 if (!e) | 1054 if (v->isDataseg()) |
1055 { error(loc, "static variable %s cannot be read at compile time", v->toChars()); | |
1056 e = EXP_CANT_INTERPRET; | |
1057 } | |
1058 else if (!e) | |
1005 error(loc, "variable %s is used before initialization", v->toChars()); | 1059 error(loc, "variable %s is used before initialization", v->toChars()); |
1006 else if (e != EXP_CANT_INTERPRET) | 1060 else if (e != EXP_CANT_INTERPRET) |
1007 e = e->interpret(istate); | 1061 e = e->interpret(istate); |
1008 } | 1062 } |
1009 if (!e) | 1063 if (!e) |
1058 } | 1112 } |
1059 else if (declaration->isAttribDeclaration() || | 1113 else if (declaration->isAttribDeclaration() || |
1060 declaration->isTemplateMixin() || | 1114 declaration->isTemplateMixin() || |
1061 declaration->isTupleDeclaration()) | 1115 declaration->isTupleDeclaration()) |
1062 { // These can be made to work, too lazy now | 1116 { // These can be made to work, too lazy now |
1117 error("Declaration %s is not yet implemented in CTFE", toChars()); | |
1118 | |
1063 e = EXP_CANT_INTERPRET; | 1119 e = EXP_CANT_INTERPRET; |
1064 } | 1120 } |
1065 else | 1121 else |
1066 { // Others should not contain executable code, so are trivial to evaluate | 1122 { // Others should not contain executable code, so are trivial to evaluate |
1067 e = NULL; | 1123 e = NULL; |
1068 } | 1124 } |
1069 #if LOG | 1125 #if LOG |
1070 printf("-DeclarationExp::interpret(): %p\n", e); | 1126 printf("-DeclarationExp::interpret(%s): %p\n", toChars(), e); |
1071 #endif | 1127 #endif |
1072 return e; | 1128 return e; |
1073 } | 1129 } |
1074 | 1130 |
1075 Expression *TupleExp::interpret(InterState *istate) | 1131 Expression *TupleExp::interpret(InterState *istate) |
1255 printf("StructLiteralExp::interpret() %s\n", toChars()); | 1311 printf("StructLiteralExp::interpret() %s\n", toChars()); |
1256 #endif | 1312 #endif |
1257 /* We don't know how to deal with overlapping fields | 1313 /* We don't know how to deal with overlapping fields |
1258 */ | 1314 */ |
1259 if (sd->hasUnions) | 1315 if (sd->hasUnions) |
1260 return EXP_CANT_INTERPRET; | 1316 { error("Unions with overlapping fields are not yet supported in CTFE"); |
1317 return EXP_CANT_INTERPRET; | |
1318 } | |
1261 | 1319 |
1262 if (elements) | 1320 if (elements) |
1263 { | 1321 { |
1264 for (size_t i = 0; i < elements->dim; i++) | 1322 for (size_t i = 0; i < elements->dim; i++) |
1265 { Expression *e = (Expression *)elements->data[i]; | 1323 { Expression *e = (Expression *)elements->data[i]; |
1427 | 1485 |
1428 BIN_INTERPRET2(Equal) | 1486 BIN_INTERPRET2(Equal) |
1429 BIN_INTERPRET2(Identity) | 1487 BIN_INTERPRET2(Identity) |
1430 BIN_INTERPRET2(Cmp) | 1488 BIN_INTERPRET2(Cmp) |
1431 | 1489 |
1490 /* Helper functions for BinExp::interpretAssignCommon | |
1491 */ | |
1492 | |
1493 /*************************************** | |
1494 * Duplicate the elements array, then set field 'indexToChange' = newelem. | |
1495 */ | |
1496 Expressions *changeOneElement(Expressions *oldelems, size_t indexToChange, void *newelem) | |
1497 { | |
1498 Expressions *expsx = new Expressions(); | |
1499 expsx->setDim(oldelems->dim); | |
1500 for (size_t j = 0; j < expsx->dim; j++) | |
1501 { | |
1502 if (j == indexToChange) | |
1503 expsx->data[j] = newelem; | |
1504 else | |
1505 expsx->data[j] = oldelems->data[j]; | |
1506 } | |
1507 return expsx; | |
1508 } | |
1509 | |
1510 /*************************************** | |
1511 * Returns oldelems[0..insertpoint] ~ newelems ~ oldelems[insertpoint..$] | |
1512 */ | |
1513 Expressions *spliceElements(Expressions *oldelems, | |
1514 Expressions *newelems, size_t insertpoint) | |
1515 { | |
1516 Expressions *expsx = new Expressions(); | |
1517 expsx->setDim(oldelems->dim); | |
1518 for (size_t j = 0; j < expsx->dim; j++) | |
1519 { | |
1520 if (j >= insertpoint && j < insertpoint + newelems->dim) | |
1521 expsx->data[j] = newelems->data[j - insertpoint]; | |
1522 else | |
1523 expsx->data[j] = oldelems->data[j]; | |
1524 } | |
1525 return expsx; | |
1526 } | |
1527 | |
1528 /****************************** | |
1529 * Create an array literal consisting of 'elem' duplicated 'dim' times. | |
1530 */ | |
1531 ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Type *type, | |
1532 Expression *elem, size_t dim) | |
1533 { | |
1534 Expressions *elements = new Expressions(); | |
1535 elements->setDim(dim); | |
1536 for (size_t i = 0; i < dim; i++) | |
1537 elements->data[i] = elem; | |
1538 ArrayLiteralExp *ae = new ArrayLiteralExp(0, elements); | |
1539 ae->type = type; | |
1540 return ae; | |
1541 } | |
1542 | |
1543 | |
1544 /******************************** | |
1545 * Necessary because defaultInit() for a struct is a VarExp, not a StructLiteralExp. | |
1546 */ | |
1547 StructLiteralExp *createDefaultInitStructLiteral(Loc loc, StructDeclaration *sym) | |
1548 { | |
1549 Expressions *structelems = new Expressions(); | |
1550 structelems->setDim(sym->fields.dim); | |
1551 for (size_t j = 0; j < structelems->dim; j++) | |
1552 { | |
1553 structelems->data[j] = ((VarDeclaration *)(sym->fields.data[j]))->type->defaultInit(); | |
1554 } | |
1555 StructLiteralExp *structinit = new StructLiteralExp(loc, sym, structelems); | |
1556 // Why doesn't the StructLiteralExp constructor do this, when | |
1557 // sym->type != NULL ? | |
1558 structinit->type = sym->type; | |
1559 return structinit; | |
1560 } | |
1561 | |
1562 /******************************** | |
1563 * Add v to the istate list, unless it already exists there. | |
1564 */ | |
1565 void addVarToInterstate(InterState *istate, VarDeclaration *v) | |
1566 { | |
1567 if (!v->isParameter()) | |
1568 { | |
1569 for (size_t i = 0; 1; i++) | |
1570 { | |
1571 if (i == istate->vars.dim) | |
1572 { istate->vars.push(v); | |
1573 //printf("\tadding %s to istate\n", v->toChars()); | |
1574 break; | |
1575 } | |
1576 if (v == (VarDeclaration *)istate->vars.data[i]) | |
1577 break; | |
1578 } | |
1579 } | |
1580 } | |
1581 | |
1432 Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post) | 1582 Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post) |
1433 { | 1583 { |
1434 #if LOG | 1584 #if LOG |
1435 printf("BinExp::interpretAssignCommon() %s\n", toChars()); | 1585 printf("BinExp::interpretAssignCommon() %s\n", toChars()); |
1436 #endif | 1586 #endif |
1447 if (e1 == EXP_CANT_INTERPRET) | 1597 if (e1 == EXP_CANT_INTERPRET) |
1448 return e1; | 1598 return e1; |
1449 Expression *e2 = this->e2->interpret(istate); | 1599 Expression *e2 = this->e2->interpret(istate); |
1450 if (e2 == EXP_CANT_INTERPRET) | 1600 if (e2 == EXP_CANT_INTERPRET) |
1451 return e2; | 1601 return e2; |
1452 | 1602 |
1603 // Chase down rebinding of out and ref. | |
1604 if (e1->op == TOKvar) | |
1605 { | |
1606 VarExp *ve = (VarExp *)e1; | |
1607 VarDeclaration *v = ve->var->isVarDeclaration(); | |
1608 if (v && v->value && v->value->op == TOKvar) | |
1609 { | |
1610 VarExp *ve2 = (VarExp *)v->value; | |
1611 //TODO | |
1612 #ifdef IN_DMD | |
1613 if (ve2->var->isSymbolDeclaration()) | |
1614 { // This can happen if v is a struct initialized to | |
1615 // 0 using an __initZ SymbolDeclaration from | |
1616 // TypeStruct::defaultInit() | |
1617 } | |
1618 else | |
1619 #endif | |
1620 e1 = v->value; | |
1621 } | |
1622 else if (v && v->value && (v->value->op==TOKindex || v->value->op == TOKdotvar)) | |
1623 { | |
1624 // It is no longer be a TOKvar, eg when a[4] is passed by ref. | |
1625 e1 = v->value; | |
1626 } | |
1627 } | |
1628 | |
1629 // To reduce code complexity of handling dotvar expressions, | |
1630 // extract the aggregate now. | |
1631 Expression *aggregate; | |
1632 if (e1->op == TOKdotvar) { | |
1633 aggregate = ((DotVarExp *)e1)->e1; | |
1634 // Get rid of 'this'. | |
1635 if (aggregate->op == TOKthis && istate->localThis) | |
1636 aggregate = istate->localThis; | |
1637 } | |
1638 | |
1453 /* Assignment to variable of the form: | 1639 /* Assignment to variable of the form: |
1454 * v = e2 | 1640 * v = e2 |
1455 */ | 1641 */ |
1456 if (e1->op == TOKvar) | 1642 if (e1->op == TOKvar) |
1457 { | 1643 { |
1458 VarExp *ve = (VarExp *)e1; | 1644 VarExp *ve = (VarExp *)e1; |
1459 VarDeclaration *v = ve->var->isVarDeclaration(); | 1645 VarDeclaration *v = ve->var->isVarDeclaration(); |
1646 assert(v); | |
1647 if (v && v->isDataseg()) | |
1648 { // Can't modify global or static data | |
1649 error("%s cannot be modified at compile time", v->toChars()); | |
1650 return EXP_CANT_INTERPRET; | |
1651 } | |
1460 if (v && !v->isDataseg()) | 1652 if (v && !v->isDataseg()) |
1461 { | 1653 { |
1462 /* Chase down rebinding of out and ref | |
1463 */ | |
1464 if (v->value && v->value->op == TOKvar) | |
1465 { | |
1466 VarExp *ve2 = (VarExp *)v->value; | |
1467 if (ve2->var->isStaticStructInitDeclaration()) | |
1468 { | |
1469 /* This can happen if v is a struct initialized to | |
1470 * 0 using an StaticStructInitDeclaration from | |
1471 * TypeStruct::defaultInit() | |
1472 */ | |
1473 } | |
1474 else | |
1475 v = ve2->var->isVarDeclaration(); | |
1476 assert(v); | |
1477 } | |
1478 | |
1479 Expression *ev = v->value; | 1654 Expression *ev = v->value; |
1480 if (fp && !ev) | 1655 if (fp && !ev) |
1481 { error("variable %s is used before initialization", v->toChars()); | 1656 { error("variable %s is used before initialization", v->toChars()); |
1482 return e; | 1657 return e; |
1483 } | 1658 } |
1490 { | 1665 { |
1491 e2 = v->type->defaultInit(); | 1666 e2 = v->type->defaultInit(); |
1492 } | 1667 } |
1493 e2 = Cast(v->type, v->type, e2); | 1668 e2 = Cast(v->type, v->type, e2); |
1494 } | 1669 } |
1495 if (e2 != EXP_CANT_INTERPRET) | 1670 if (e2 == EXP_CANT_INTERPRET) |
1496 { | 1671 return e2; |
1497 if (!v->isParameter()) | 1672 |
1498 { | 1673 addVarToInterstate(istate, v); |
1499 for (size_t i = 0; 1; i++) | 1674 v->value = e2; |
1500 { | 1675 e = Cast(type, type, post ? ev : e2); |
1501 if (i == istate->vars.dim) | 1676 } |
1502 { istate->vars.push(v); | 1677 } |
1503 //printf("\tadding %s to istate\n", v->toChars()); | 1678 else if (e1->op == TOKdotvar && aggregate->op == TOKdotvar) |
1504 break; | 1679 { // eg v.u.var = e2, v[3].u.var = e2, etc. |
1505 } | 1680 error("Nested struct assignment %s is not yet supported in CTFE", toChars()); |
1506 if (v == (VarDeclaration *)istate->vars.data[i]) | |
1507 break; | |
1508 } | |
1509 } | |
1510 v->value = e2; | |
1511 e = Cast(type, type, post ? ev : e2); | |
1512 } | |
1513 } | |
1514 } | 1681 } |
1515 /* Assignment to struct member of the form: | 1682 /* Assignment to struct member of the form: |
1516 * v.var = e2 | 1683 * v.var = e2 |
1517 */ | 1684 */ |
1518 else if (e1->op == TOKdotvar && ((DotVarExp *)e1)->e1->op == TOKvar) | 1685 else if (e1->op == TOKdotvar && aggregate->op == TOKvar) |
1519 { VarExp *ve = (VarExp *)((DotVarExp *)e1)->e1; | 1686 { VarDeclaration *v = ((VarExp *)aggregate)->var->isVarDeclaration(); |
1520 VarDeclaration *v = ve->var->isVarDeclaration(); | |
1521 | 1687 |
1522 if (v->isDataseg()) | 1688 if (v->isDataseg()) |
1689 { // Can't modify global or static data | |
1690 error("%s cannot be modified at compile time", v->toChars()); | |
1523 return EXP_CANT_INTERPRET; | 1691 return EXP_CANT_INTERPRET; |
1692 } else { | |
1693 // Chase down rebinding of out and ref | |
1694 if (v->value && v->value->op == TOKvar) | |
1695 { | |
1696 VarExp *ve2 = (VarExp *)v->value; | |
1697 //TODO | |
1698 #ifdef IN_DMD | |
1699 if (ve2->var->isSymbolDeclaration()) | |
1700 { // This can happen if v is a struct initialized to | |
1701 // 0 using an __initZ SymbolDeclaration from | |
1702 // TypeStruct::defaultInit() | |
1703 } | |
1704 else | |
1705 #endif | |
1706 v = ve2->var->isVarDeclaration(); | |
1707 assert(v); | |
1708 } | |
1709 } | |
1524 if (fp && !v->value) | 1710 if (fp && !v->value) |
1525 { error("variable %s is used before initialization", v->toChars()); | 1711 { error("variable %s is used before initialization", v->toChars()); |
1526 return e; | 1712 return e; |
1527 } | 1713 } |
1528 if (v->value == NULL && v->init->isVoidInitializer()) | 1714 if (v->value == NULL && v->init->isVoidInitializer()) |
1555 else | 1741 else |
1556 e2 = Cast(type, type, e2); | 1742 e2 = Cast(type, type, e2); |
1557 if (e2 == EXP_CANT_INTERPRET) | 1743 if (e2 == EXP_CANT_INTERPRET) |
1558 return e2; | 1744 return e2; |
1559 | 1745 |
1560 if (!v->isParameter()) | 1746 addVarToInterstate(istate, v); |
1561 { | |
1562 for (size_t i = 0; 1; i++) | |
1563 { | |
1564 if (i == istate->vars.dim) | |
1565 { istate->vars.push(v); | |
1566 break; | |
1567 } | |
1568 if (v == (VarDeclaration *)istate->vars.data[i]) | |
1569 break; | |
1570 } | |
1571 } | |
1572 | 1747 |
1573 /* Create new struct literal reflecting updated fieldi | 1748 /* Create new struct literal reflecting updated fieldi |
1574 */ | 1749 */ |
1575 Expressions *expsx = new Expressions(); | 1750 Expressions *expsx = changeOneElement(se->elements, fieldi, e2); |
1576 expsx->setDim(se->elements->dim); | |
1577 for (size_t j = 0; j < expsx->dim; j++) | |
1578 { | |
1579 if (j == fieldi) | |
1580 expsx->data[j] = (void *)e2; | |
1581 else | |
1582 expsx->data[j] = se->elements->data[j]; | |
1583 } | |
1584 v->value = new StructLiteralExp(se->loc, se->sd, expsx); | 1751 v->value = new StructLiteralExp(se->loc, se->sd, expsx); |
1585 v->value->type = se->type; | 1752 v->value->type = se->type; |
1586 | 1753 |
1587 e = Cast(type, type, post ? ev : e2); | 1754 e = Cast(type, type, post ? ev : e2); |
1588 } | 1755 } |
1592 else if (e1->op == TOKstar && ((PtrExp *)e1)->e1->op == TOKsymoff) | 1759 else if (e1->op == TOKstar && ((PtrExp *)e1)->e1->op == TOKsymoff) |
1593 { SymOffExp *soe = (SymOffExp *)((PtrExp *)e1)->e1; | 1760 { SymOffExp *soe = (SymOffExp *)((PtrExp *)e1)->e1; |
1594 VarDeclaration *v = soe->var->isVarDeclaration(); | 1761 VarDeclaration *v = soe->var->isVarDeclaration(); |
1595 | 1762 |
1596 if (v->isDataseg()) | 1763 if (v->isDataseg()) |
1764 { | |
1765 error("%s cannot be modified at compile time", v->toChars()); | |
1597 return EXP_CANT_INTERPRET; | 1766 return EXP_CANT_INTERPRET; |
1767 } | |
1598 if (fp && !v->value) | 1768 if (fp && !v->value) |
1599 { error("variable %s is used before initialization", v->toChars()); | 1769 { error("variable %s is used before initialization", v->toChars()); |
1600 return e; | 1770 return e; |
1601 } | 1771 } |
1602 Expression *vie = v->value; | 1772 Expression *vie = v->value; |
1617 else | 1787 else |
1618 e2 = Cast(type, type, e2); | 1788 e2 = Cast(type, type, e2); |
1619 if (e2 == EXP_CANT_INTERPRET) | 1789 if (e2 == EXP_CANT_INTERPRET) |
1620 return e2; | 1790 return e2; |
1621 | 1791 |
1622 if (!v->isParameter()) | 1792 addVarToInterstate(istate, v); |
1623 { | |
1624 for (size_t i = 0; 1; i++) | |
1625 { | |
1626 if (i == istate->vars.dim) | |
1627 { istate->vars.push(v); | |
1628 break; | |
1629 } | |
1630 if (v == (VarDeclaration *)istate->vars.data[i]) | |
1631 break; | |
1632 } | |
1633 } | |
1634 | 1793 |
1635 /* Create new struct literal reflecting updated fieldi | 1794 /* Create new struct literal reflecting updated fieldi |
1636 */ | 1795 */ |
1637 Expressions *expsx = new Expressions(); | 1796 Expressions *expsx = changeOneElement(se->elements, fieldi, e2); |
1638 expsx->setDim(se->elements->dim); | |
1639 for (size_t j = 0; j < expsx->dim; j++) | |
1640 { | |
1641 if (j == fieldi) | |
1642 expsx->data[j] = (void *)e2; | |
1643 else | |
1644 expsx->data[j] = se->elements->data[j]; | |
1645 } | |
1646 v->value = new StructLiteralExp(se->loc, se->sd, expsx); | 1797 v->value = new StructLiteralExp(se->loc, se->sd, expsx); |
1647 v->value->type = se->type; | 1798 v->value->type = se->type; |
1648 | 1799 |
1649 e = Cast(type, type, post ? ev : e2); | 1800 e = Cast(type, type, post ? ev : e2); |
1650 } | 1801 } |
1653 */ | 1804 */ |
1654 else if (e1->op == TOKindex && ((IndexExp *)e1)->e1->op == TOKvar) | 1805 else if (e1->op == TOKindex && ((IndexExp *)e1)->e1->op == TOKvar) |
1655 { IndexExp *ie = (IndexExp *)e1; | 1806 { IndexExp *ie = (IndexExp *)e1; |
1656 VarExp *ve = (VarExp *)ie->e1; | 1807 VarExp *ve = (VarExp *)ie->e1; |
1657 VarDeclaration *v = ve->var->isVarDeclaration(); | 1808 VarDeclaration *v = ve->var->isVarDeclaration(); |
1658 | |
1659 if (!v || v->isDataseg()) | 1809 if (!v || v->isDataseg()) |
1810 { | |
1811 error("%s cannot be modified at compile time", v ? v->toChars(): "void"); | |
1660 return EXP_CANT_INTERPRET; | 1812 return EXP_CANT_INTERPRET; |
1813 } | |
1814 if (v->value && v->value->op == TOKvar) | |
1815 { | |
1816 VarExp *ve2 = (VarExp *)v->value; | |
1817 // TODO | |
1818 #ifdef IN_DMD | |
1819 if (ve2->var->isSymbolDeclaration()) | |
1820 { // This can happen if v is a struct initialized to | |
1821 // 0 using an __initZ SymbolDeclaration from | |
1822 // TypeStruct::defaultInit() | |
1823 } | |
1824 else | |
1825 #endif | |
1826 v = ve2->var->isVarDeclaration(); | |
1827 assert(v); | |
1828 } | |
1661 if (!v->value) | 1829 if (!v->value) |
1662 { | 1830 { |
1663 if (fp) | 1831 if (fp) |
1664 { error("variable %s is used before initialization", v->toChars()); | 1832 { error("variable %s is used before initialization", v->toChars()); |
1665 return e; | 1833 return e; |
1673 * What we should do is fill the array literal with | 1841 * What we should do is fill the array literal with |
1674 * NULL data, so use-before-initialized can be detected. | 1842 * NULL data, so use-before-initialized can be detected. |
1675 * But we're too lazy at the moment to do it, as that | 1843 * But we're too lazy at the moment to do it, as that |
1676 * involves redoing Index() and whoever calls it. | 1844 * involves redoing Index() and whoever calls it. |
1677 */ | 1845 */ |
1678 Expression *ev = v->type->defaultInit(); | 1846 |
1679 size_t dim = ((TypeSArray *)t)->dim->toInteger(); | 1847 size_t dim = ((TypeSArray *)t)->dim->toInteger(); |
1680 Expressions *elements = new Expressions(); | 1848 v->value = createBlockDuplicatedArrayLiteral(v->type, |
1681 elements->setDim(dim); | 1849 v->type->defaultInit(), dim); |
1682 for (size_t i = 0; i < dim; i++) | |
1683 elements->data[i] = (void *)ev; | |
1684 ArrayLiteralExp *ae = new ArrayLiteralExp(0, elements); | |
1685 ae->type = v->type; | |
1686 v->value = ae; | |
1687 } | 1850 } |
1688 else | 1851 else |
1689 return EXP_CANT_INTERPRET; | 1852 return EXP_CANT_INTERPRET; |
1690 } | 1853 } |
1691 | 1854 |
1696 ae = (ArrayLiteralExp *)v->value; | 1859 ae = (ArrayLiteralExp *)v->value; |
1697 else if (v->value->op == TOKassocarrayliteral) | 1860 else if (v->value->op == TOKassocarrayliteral) |
1698 aae = (AssocArrayLiteralExp *)v->value; | 1861 aae = (AssocArrayLiteralExp *)v->value; |
1699 else if (v->value->op == TOKstring) | 1862 else if (v->value->op == TOKstring) |
1700 se = (StringExp *)v->value; | 1863 se = (StringExp *)v->value; |
1864 else if (v->value->op == TOKnull) | |
1865 { | |
1866 // This would be a runtime segfault | |
1867 error("Cannot index null array %s", v->toChars()); | |
1868 return EXP_CANT_INTERPRET; | |
1869 } | |
1701 else | 1870 else |
1702 return EXP_CANT_INTERPRET; | 1871 return EXP_CANT_INTERPRET; |
1703 | 1872 |
1873 /* Set the $ variable | |
1874 */ | |
1875 Expression *ee = ArrayLength(Type::tsize_t, v->value); | |
1876 if (ee != EXP_CANT_INTERPRET && ie->lengthVar) | |
1877 ie->lengthVar->value = ee; | |
1704 Expression *index = ie->e2->interpret(istate); | 1878 Expression *index = ie->e2->interpret(istate); |
1705 if (index == EXP_CANT_INTERPRET) | 1879 if (index == EXP_CANT_INTERPRET) |
1706 return EXP_CANT_INTERPRET; | 1880 return EXP_CANT_INTERPRET; |
1707 Expression *ev; | 1881 Expression *ev; |
1708 if (fp || ae || se) // not for aae, because key might not be there | 1882 if (fp || ae || se) // not for aae, because key might not be there |
1716 e2 = (*fp)(type, ev, e2); | 1890 e2 = (*fp)(type, ev, e2); |
1717 else | 1891 else |
1718 e2 = Cast(type, type, e2); | 1892 e2 = Cast(type, type, e2); |
1719 if (e2 == EXP_CANT_INTERPRET) | 1893 if (e2 == EXP_CANT_INTERPRET) |
1720 return e2; | 1894 return e2; |
1721 | 1895 |
1722 if (!v->isParameter()) | 1896 addVarToInterstate(istate, v); |
1723 { | |
1724 for (size_t i = 0; 1; i++) | |
1725 { | |
1726 if (i == istate->vars.dim) | |
1727 { istate->vars.push(v); | |
1728 break; | |
1729 } | |
1730 if (v == (VarDeclaration *)istate->vars.data[i]) | |
1731 break; | |
1732 } | |
1733 } | |
1734 | |
1735 if (ae) | 1897 if (ae) |
1736 { | 1898 { |
1737 /* Create new array literal reflecting updated elem | 1899 /* Create new array literal reflecting updated elem |
1738 */ | 1900 */ |
1739 int elemi = index->toInteger(); | 1901 int elemi = index->toInteger(); |
1740 Expressions *expsx = new Expressions(); | 1902 Expressions *expsx = changeOneElement(ae->elements, elemi, e2); |
1741 expsx->setDim(ae->elements->dim); | |
1742 for (size_t j = 0; j < expsx->dim; j++) | |
1743 { | |
1744 if (j == elemi) | |
1745 expsx->data[j] = (void *)e2; | |
1746 else | |
1747 expsx->data[j] = ae->elements->data[j]; | |
1748 } | |
1749 v->value = new ArrayLiteralExp(ae->loc, expsx); | 1903 v->value = new ArrayLiteralExp(ae->loc, expsx); |
1750 v->value->type = ae->type; | 1904 v->value->type = ae->type; |
1751 } | 1905 } |
1752 else if (aae) | 1906 else if (aae) |
1753 { | 1907 { |
1806 else | 1960 else |
1807 assert(0); | 1961 assert(0); |
1808 | 1962 |
1809 e = Cast(type, type, post ? ev : e2); | 1963 e = Cast(type, type, post ? ev : e2); |
1810 } | 1964 } |
1965 | |
1966 /* Assignment to struct element in array, of the form: | |
1967 * a[i].var = e2 | |
1968 */ | |
1969 else if (e1->op == TOKdotvar && aggregate->op == TOKindex && | |
1970 ((IndexExp *)aggregate)->e1->op == TOKvar) | |
1971 { | |
1972 IndexExp * ie = (IndexExp *)aggregate; | |
1973 VarExp *ve = (VarExp *)(ie->e1); | |
1974 VarDeclaration *v = ve->var->isVarDeclaration(); | |
1975 if (!v || v->isDataseg()) | |
1976 { | |
1977 error("%s cannot be modified at compile time", v ? v->toChars(): "void"); | |
1978 return EXP_CANT_INTERPRET; | |
1979 } | |
1980 Type *t = ve->type->toBasetype(); | |
1981 ArrayLiteralExp *ae = (ArrayLiteralExp *)v->value; | |
1982 if (!ae) | |
1983 { | |
1984 // assignment to one element in an uninitialized (static) array. | |
1985 // This is quite difficult, because defaultInit() for a struct is a VarExp, | |
1986 // not a StructLiteralExp. | |
1987 Type *t = v->type->toBasetype(); | |
1988 if (t->ty != Tsarray) | |
1989 { | |
1990 error("Cannot index an uninitialized variable"); | |
1991 return EXP_CANT_INTERPRET; | |
1992 } | |
1993 | |
1994 Type *telem = ((TypeSArray *)t)->nextOf()->toBasetype(); | |
1995 if (telem->ty != Tstruct) { return EXP_CANT_INTERPRET; } | |
1996 | |
1997 // Create a default struct literal... | |
1998 StructDeclaration *sym = ((TypeStruct *)telem)->sym; | |
1999 StructLiteralExp *structinit = createDefaultInitStructLiteral(v->loc, sym); | |
2000 | |
2001 // ... and use to create a blank array literal | |
2002 size_t dim = ((TypeSArray *)t)->dim->toInteger(); | |
2003 ae = createBlockDuplicatedArrayLiteral(v->type, structinit, dim); | |
2004 v->value = ae; | |
2005 } | |
2006 if ((Expression *)(ae->elements) == EXP_CANT_INTERPRET) | |
2007 { | |
2008 // Note that this would be a runtime segfault | |
2009 error("Cannot index null array %s", v->toChars()); | |
2010 return EXP_CANT_INTERPRET; | |
2011 } | |
2012 // Set the $ variable | |
2013 Expression *ee = ArrayLength(Type::tsize_t, v->value); | |
2014 if (ee != EXP_CANT_INTERPRET && ie->lengthVar) | |
2015 ie->lengthVar->value = ee; | |
2016 // Determine the index, and check that it's OK. | |
2017 Expression *index = ie->e2->interpret(istate); | |
2018 if (index == EXP_CANT_INTERPRET) | |
2019 return EXP_CANT_INTERPRET; | |
2020 | |
2021 int elemi = index->toInteger(); | |
2022 if (elemi >= ae->elements->dim) | |
2023 { | |
2024 error("array index %d is out of bounds %s[0..%d]", elemi, | |
2025 v->toChars(), ae->elements->dim); | |
2026 return EXP_CANT_INTERPRET; | |
2027 } | |
2028 // Get old element | |
2029 Expression *vie = (Expression *)(ae->elements->data[elemi]); | |
2030 if (vie->op != TOKstructliteral) | |
2031 return EXP_CANT_INTERPRET; | |
2032 | |
2033 // Work out which field needs to be changed | |
2034 StructLiteralExp *se = (StructLiteralExp *)vie; | |
2035 VarDeclaration *vf = ((DotVarExp *)e1)->var->isVarDeclaration(); | |
2036 if (!vf) | |
2037 return EXP_CANT_INTERPRET; | |
2038 | |
2039 int fieldi = se->getFieldIndex(type, vf->offset); | |
2040 if (fieldi == -1) | |
2041 return EXP_CANT_INTERPRET; | |
2042 | |
2043 Expression *ev = se->getField(type, vf->offset); | |
2044 if (fp) | |
2045 e2 = (*fp)(type, ev, e2); | |
2046 else | |
2047 e2 = Cast(type, type, e2); | |
2048 if (e2 == EXP_CANT_INTERPRET) | |
2049 return e2; | |
2050 | |
2051 // Create new struct literal reflecting updated field | |
2052 Expressions *expsx = changeOneElement(se->elements, fieldi, e2); | |
2053 Expression * newstruct = new StructLiteralExp(se->loc, se->sd, expsx); | |
2054 | |
2055 // Create new array literal reflecting updated struct elem | |
2056 ae->elements = changeOneElement(ae->elements, elemi, newstruct); | |
2057 return ae; | |
2058 } | |
2059 /* Slice assignment, initialization of static arrays | |
2060 * a[] = e | |
2061 */ | |
2062 else if (e1->op == TOKslice && ((SliceExp *)e1)->e1->op==TOKvar) | |
2063 { | |
2064 SliceExp * sexp = (SliceExp *)e1; | |
2065 VarExp *ve = (VarExp *)(sexp->e1); | |
2066 VarDeclaration *v = ve->var->isVarDeclaration(); | |
2067 if (!v || v->isDataseg()) | |
2068 { | |
2069 error("%s cannot be modified at compile time", v->toChars()); | |
2070 return EXP_CANT_INTERPRET; | |
2071 } | |
2072 // Chase down rebinding of out and ref | |
2073 if (v->value && v->value->op == TOKvar) | |
2074 { | |
2075 VarExp *ve2 = (VarExp *)v->value; | |
2076 // TODO | |
2077 #ifdef IN_DMD | |
2078 if (ve2->var->isSymbolDeclaration()) | |
2079 { // This can happen if v is a struct initialized to | |
2080 // 0 using an __initZ SymbolDeclaration from | |
2081 // TypeStruct::defaultInit() | |
2082 } | |
2083 else | |
2084 #endif | |
2085 v = ve2->var->isVarDeclaration(); | |
2086 assert(v); | |
2087 } | |
2088 /* Set the $ variable | |
2089 */ | |
2090 Expression *ee = v->value ? ArrayLength(Type::tsize_t, v->value) | |
2091 : EXP_CANT_INTERPRET; | |
2092 if (ee != EXP_CANT_INTERPRET && sexp->lengthVar) | |
2093 sexp->lengthVar->value = ee; | |
2094 Expression *upper = NULL; | |
2095 Expression *lower = NULL; | |
2096 if (sexp->upr) | |
2097 { | |
2098 upper = sexp->upr->interpret(istate); | |
2099 if (upper == EXP_CANT_INTERPRET) | |
2100 return EXP_CANT_INTERPRET; | |
2101 } | |
2102 if (sexp->lwr) | |
2103 { | |
2104 lower = sexp->lwr->interpret(istate); | |
2105 if (lower == EXP_CANT_INTERPRET) | |
2106 return EXP_CANT_INTERPRET; | |
2107 } | |
2108 Type *t = v->type->toBasetype(); | |
2109 size_t dim; | |
2110 if (t->ty == Tsarray) | |
2111 dim = ((TypeSArray *)t)->dim->toInteger(); | |
2112 else if (t->ty == Tarray) | |
2113 { | |
2114 if (!v->value || v->value->op == TOKnull) | |
2115 { | |
2116 error("cannot assign to null array %s", v->toChars()); | |
2117 return EXP_CANT_INTERPRET; | |
2118 } | |
2119 if (v->value->op == TOKarrayliteral) | |
2120 dim = ((ArrayLiteralExp *)v->value)->elements->dim; | |
2121 else if (v->value->op ==TOKstring) | |
2122 { | |
2123 error("String slice assignment is not yet supported in CTFE"); | |
2124 return EXP_CANT_INTERPRET; | |
2125 } | |
2126 } | |
2127 else | |
2128 { | |
2129 error("%s cannot be evaluated at compile time", toChars()); | |
2130 return EXP_CANT_INTERPRET; | |
2131 } | |
2132 int upperbound = upper ? upper->toInteger() : dim; | |
2133 int lowerbound = lower ? lower->toInteger() : 0; | |
2134 | |
2135 ArrayLiteralExp *existing; | |
2136 if (((int)lowerbound < 0) || (upperbound > dim)) | |
2137 { | |
2138 error("Array bounds [0..%d] exceeded in slice [%d..%d]", dim, lowerbound, upperbound); | |
2139 return EXP_CANT_INTERPRET; | |
2140 } | |
2141 if (upperbound-lowerbound != dim) | |
2142 { | |
2143 // Only modifying part of the array. Must create a new array literal. | |
2144 // If the existing array is uninitialized (this can only happen | |
2145 // with static arrays), create it. | |
2146 if (v->value && v->value->op == TOKarrayliteral) | |
2147 existing = (ArrayLiteralExp *)v->value; | |
2148 else | |
2149 { | |
2150 // this can only happen with static arrays | |
2151 existing = createBlockDuplicatedArrayLiteral(v->type, v->type->defaultInit(), dim); | |
2152 } | |
2153 } | |
2154 | |
2155 if (e2->op == TOKarrayliteral) | |
2156 { | |
2157 // Static array assignment from literal | |
2158 ArrayLiteralExp *ae = (ArrayLiteralExp *)e2; | |
2159 if (ae->elements->dim != (upperbound - lowerbound)) | |
2160 { | |
2161 error("Array length mismatch assigning [0..%d] to [%d..%d]", ae->elements->dim, lowerbound, upperbound); | |
2162 return e; | |
2163 } | |
2164 if (upperbound - lowerbound == dim) | |
2165 v->value = ae; | |
2166 else | |
2167 { | |
2168 // value[] = value[0..lower] ~ ae ~ value[upper..$] | |
2169 existing->elements = spliceElements(existing->elements, ae->elements, lowerbound); | |
2170 v->value = existing; | |
2171 } | |
2172 return e2; | |
2173 } | |
2174 else if (t->nextOf()->ty == e2->type->ty) | |
2175 { | |
2176 // Static array block assignment | |
2177 if (upperbound-lowerbound ==dim) | |
2178 v->value = createBlockDuplicatedArrayLiteral(v->type, e2, dim); | |
2179 else | |
2180 { | |
2181 // value[] = value[0..lower] ~ ae ~ value[upper..$] | |
2182 existing->elements = spliceElements(existing->elements, createBlockDuplicatedArrayLiteral(v->type, e2, upperbound-lowerbound)->elements, lowerbound); | |
2183 v->value = existing; | |
2184 } | |
2185 return e2; | |
2186 } | |
2187 else if (e2->op == TOKstring) | |
2188 { | |
2189 StringExp *se = (StringExp *)e2; | |
2190 // This is problematic. char[8] should be storing | |
2191 // values as a string literal, not | |
2192 // as an array literal. Then, for static arrays, we | |
2193 // could do modifications | |
2194 // in-place, with a dramatic memory and speed improvement. | |
2195 error("String slice assignment is not yet supported in CTFE"); | |
2196 return e2; | |
2197 } | |
2198 else | |
2199 { | |
2200 error("Slice operation %s cannot be evaluated at compile time", toChars()); | |
2201 return e; | |
2202 } | |
2203 } | |
1811 else | 2204 else |
1812 { | 2205 { |
2206 error("%s cannot be evaluated at compile time", toChars()); | |
1813 #ifdef DEBUG | 2207 #ifdef DEBUG |
1814 dump(0); | 2208 dump(0); |
1815 #endif | 2209 #endif |
1816 } | 2210 } |
1817 return e; | 2211 return e; |
1921 { Expression *e = EXP_CANT_INTERPRET; | 2315 { Expression *e = EXP_CANT_INTERPRET; |
1922 | 2316 |
1923 #if LOG | 2317 #if LOG |
1924 printf("CallExp::interpret() %s\n", toChars()); | 2318 printf("CallExp::interpret() %s\n", toChars()); |
1925 #endif | 2319 #endif |
2320 if (e1->op == TOKdotvar) | |
2321 { | |
2322 Expression * pthis = ((DotVarExp*)e1)->e1; | |
2323 FuncDeclaration *fd = ((DotVarExp*)e1)->var->isFuncDeclaration(); | |
2324 TypeFunction *tf = fd ? (TypeFunction *)(fd->type) : NULL; | |
2325 if (tf) | |
2326 { // Member function call | |
2327 if(pthis->op == TOKthis) | |
2328 pthis = istate->localThis; | |
2329 Expression *eresult = fd->interpret(istate, arguments, pthis); | |
2330 if (eresult) | |
2331 e = eresult; | |
2332 else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors) | |
2333 e = EXP_VOID_INTERPRET; | |
2334 else | |
2335 error("cannot evaluate %s at compile time", toChars()); | |
2336 return e; | |
2337 } | |
2338 error("cannot evaluate %s at compile time", toChars()); | |
2339 return EXP_CANT_INTERPRET; | |
2340 } | |
1926 if (e1->op == TOKvar) | 2341 if (e1->op == TOKvar) |
1927 { | 2342 { |
1928 FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration(); | 2343 FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration(); |
1929 if (fd) | 2344 if (fd) |
1930 { | 2345 { |
2153 Expression *e1; | 2568 Expression *e1; |
2154 | 2569 |
2155 #if LOG | 2570 #if LOG |
2156 printf("AssertExp::interpret() %s\n", toChars()); | 2571 printf("AssertExp::interpret() %s\n", toChars()); |
2157 #endif | 2572 #endif |
2573 if( this->e1->op == TOKaddress) | |
2574 { // Special case: deal with compiler-inserted assert(&this, "null this") | |
2575 AddrExp *ade = (AddrExp *)this->e1; | |
2576 if(ade->e1->op == TOKthis && istate->localThis) | |
2577 return istate->localThis->interpret(istate); | |
2578 } | |
2579 if (this->e1->op == TOKthis) | |
2580 { | |
2581 if(istate->localThis) | |
2582 return istate->localThis->interpret(istate); | |
2583 } | |
2158 e1 = this->e1->interpret(istate); | 2584 e1 = this->e1->interpret(istate); |
2159 if (e1 == EXP_CANT_INTERPRET) | 2585 if (e1 == EXP_CANT_INTERPRET) |
2160 goto Lcant; | 2586 goto Lcant; |
2161 if (e1->isBool(TRUE)) | 2587 if (e1->isBool(TRUE)) |
2162 { | 2588 { |
2221 if (!e) | 2647 if (!e) |
2222 e = EXP_CANT_INTERPRET; | 2648 e = EXP_CANT_INTERPRET; |
2223 } | 2649 } |
2224 } | 2650 } |
2225 } | 2651 } |
2652 #if DMDV2 | |
2653 #else // this is required for D1, where structs return *this instead of 'this'. | |
2654 else if (e1->op == TOKthis) | |
2655 { | |
2656 if(istate->localThis) | |
2657 return istate->localThis->interpret(istate); | |
2658 } | |
2659 #endif | |
2226 #if LOG | 2660 #if LOG |
2227 if (e == EXP_CANT_INTERPRET) | 2661 if (e == EXP_CANT_INTERPRET) |
2228 printf("PtrExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars()); | 2662 printf("PtrExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars()); |
2229 #endif | 2663 #endif |
2230 return e; | 2664 return e; |
2247 { e = se->getField(type, v->offset); | 2681 { e = se->getField(type, v->offset); |
2248 if (!e) | 2682 if (!e) |
2249 e = EXP_CANT_INTERPRET; | 2683 e = EXP_CANT_INTERPRET; |
2250 return e; | 2684 return e; |
2251 } | 2685 } |
2252 } | 2686 } else error("%s.%s is not yet implemented at compile time", ex->toChars(), var->toChars()); |
2253 } | 2687 } |
2254 | 2688 |
2255 #if LOG | 2689 #if LOG |
2256 if (e == EXP_CANT_INTERPRET) | 2690 if (e == EXP_CANT_INTERPRET) |
2257 printf("DotVarExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars()); | 2691 printf("DotVarExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars()); |
2276 return e; | 2710 return e; |
2277 } | 2711 } |
2278 | 2712 |
2279 Expression *interpret_aaKeys(InterState *istate, Expressions *arguments) | 2713 Expression *interpret_aaKeys(InterState *istate, Expressions *arguments) |
2280 { | 2714 { |
2281 //printf("interpret_aaKeys()\n"); | 2715 #if LOG |
2716 printf("interpret_aaKeys()\n"); | |
2717 #endif | |
2282 if (!arguments || arguments->dim != 2) | 2718 if (!arguments || arguments->dim != 2) |
2283 return NULL; | 2719 return NULL; |
2284 Expression *earg = (Expression *)arguments->data[0]; | 2720 Expression *earg = (Expression *)arguments->data[0]; |
2285 earg = earg->interpret(istate); | 2721 earg = earg->interpret(istate); |
2286 if (earg == EXP_CANT_INTERPRET) | 2722 if (earg == EXP_CANT_INTERPRET) |
2287 return NULL; | 2723 return NULL; |
2288 if (earg->op != TOKassocarrayliteral) | 2724 if (earg->op != TOKassocarrayliteral) |
2289 return NULL; | 2725 return NULL; |
2290 AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; | 2726 AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; |
2291 Expression *e = new ArrayLiteralExp(aae->loc, aae->keys); | 2727 Expression *e = new ArrayLiteralExp(aae->loc, aae->keys); |
2728 Type *elemType = ((TypeAArray *)aae->type)->index; | |
2729 e->type = new TypeSArray(elemType, new IntegerExp(arguments ? arguments->dim : 0)); | |
2292 return e; | 2730 return e; |
2293 } | 2731 } |
2294 | 2732 |
2295 Expression *interpret_aaValues(InterState *istate, Expressions *arguments) | 2733 Expression *interpret_aaValues(InterState *istate, Expressions *arguments) |
2296 { | 2734 { |
2303 return NULL; | 2741 return NULL; |
2304 if (earg->op != TOKassocarrayliteral) | 2742 if (earg->op != TOKassocarrayliteral) |
2305 return NULL; | 2743 return NULL; |
2306 AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; | 2744 AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; |
2307 Expression *e = new ArrayLiteralExp(aae->loc, aae->values); | 2745 Expression *e = new ArrayLiteralExp(aae->loc, aae->values); |
2746 Type *elemType = ((TypeAArray *)aae->type)->next; | |
2747 e->type = new TypeSArray(elemType, new IntegerExp(arguments ? arguments->dim : 0)); | |
2308 //printf("result is %s\n", e->toChars()); | 2748 //printf("result is %s\n", e->toChars()); |
2309 return e; | 2749 return e; |
2310 } | 2750 } |
2311 | 2751 |