Mercurial > projects > ldc
comparison dmd2/interpret.c @ 1577:e4f7b5d9c68a
DMD 2.032 Merge.
author | Robert Clipsham <robert@octarineparrot.com> |
---|---|
date | Tue, 08 Sep 2009 10:07:56 +0100 |
parents | 54b3c1394d62 |
children |
comparison
equal
deleted
inserted
replaced
1576:4551475bc6b6 | 1577:e4f7b5d9c68a |
---|---|
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 if (((VarExp *)v2->value)->var->isStaticStructInitDeclaration()) | |
200 { // This can happen if v is a struct initialized to | |
201 // 0 using an __initZ StaticStructInitDeclaration from | |
202 // TypeStruct::defaultInit() | |
203 break; // eg default-initialized variable | |
204 } | |
177 earg = v2->value; | 205 earg = v2->value; |
178 } | 206 } |
179 | 207 |
180 v->value = new VarExp(earg->loc, v2); | 208 v->value = new VarExp(earg->loc, v2); |
181 | 209 |
189 break; | 217 break; |
190 } | 218 } |
191 } | 219 } |
192 } | 220 } |
193 else | 221 else |
194 { /* Value parameters | 222 { // Value parameters and non-trivial references |
195 */ | |
196 v->value = earg; | 223 v->value = earg; |
197 } | 224 } |
198 #if LOG | 225 #if LOG |
199 printf("interpreted arg[%d] = %s\n", i, earg->toChars()); | 226 printf("interpreted arg[%d] = %s\n", i, earg->toChars()); |
200 #endif | 227 #endif |
228 } | |
229 } | |
230 // Don't restore the value of 'this' upon function return | |
231 if (needThis() && thisarg->op==TOKvar) { | |
232 VarDeclaration *thisvar = ((VarExp *)(thisarg))->var->isVarDeclaration(); | |
233 for (size_t i = 0; i < istate->vars.dim; i++) | |
234 { VarDeclaration *v = (VarDeclaration *)istate->vars.data[i]; | |
235 if (v == thisvar) | |
236 { istate->vars.data[i] = NULL; | |
237 break; | |
238 } | |
201 } | 239 } |
202 } | 240 } |
203 | 241 |
204 /* Save the values of the local variables used | 242 /* Save the values of the local variables used |
205 */ | 243 */ |
206 Expressions valueSaves; | 244 Expressions valueSaves; |
207 if (istate) | 245 if (istate && !isNested()) |
208 { | 246 { |
209 //printf("saving local variables...\n"); | 247 //printf("saving local variables...\n"); |
210 valueSaves.setDim(istate->vars.dim); | 248 valueSaves.setDim(istate->vars.dim); |
211 for (size_t i = 0; i < istate->vars.dim; i++) | 249 for (size_t i = 0; i < istate->vars.dim; i++) |
212 { VarDeclaration *v = (VarDeclaration *)istate->vars.data[i]; | 250 { VarDeclaration *v = (VarDeclaration *)istate->vars.data[i]; |
218 } | 256 } |
219 } | 257 } |
220 } | 258 } |
221 | 259 |
222 Expression *e = NULL; | 260 Expression *e = NULL; |
223 | |
224 while (1) | 261 while (1) |
225 { | 262 { |
226 e = fbody->interpret(&istatex); | 263 e = fbody->interpret(&istatex); |
227 if (e == EXP_CANT_INTERPRET) | 264 if (e == EXP_CANT_INTERPRET) |
228 { | 265 { |
244 istatex.gotoTarget = NULL; | 281 istatex.gotoTarget = NULL; |
245 } | 282 } |
246 else | 283 else |
247 break; | 284 break; |
248 } | 285 } |
249 | |
250 /* Restore the parameter values | 286 /* Restore the parameter values |
251 */ | 287 */ |
252 for (size_t i = 0; i < dim; i++) | 288 for (size_t i = 0; i < dim; i++) |
253 { | 289 { |
254 VarDeclaration *v = (VarDeclaration *)parameters->data[i]; | 290 VarDeclaration *v = (VarDeclaration *)parameters->data[i]; |
255 v->value = (Expression *)vsave.data[i]; | 291 v->value = (Expression *)vsave.data[i]; |
256 } | 292 } |
257 | 293 |
258 if (istate) | 294 if (istate && !isNested()) |
259 { | 295 { |
260 /* Restore the variable values | 296 /* Restore the variable values |
261 */ | 297 */ |
262 //printf("restoring local variables...\n"); | 298 //printf("restoring local variables...\n"); |
263 for (size_t i = 0; i < istate->vars.dim; i++) | 299 for (size_t i = 0; i < istate->vars.dim; i++) |
266 { v->value = (Expression *)valueSaves.data[i]; | 302 { v->value = (Expression *)valueSaves.data[i]; |
267 //printf("\trestoring [%d] %s = %s\n", i, v->toChars(), v->value ? v->value->toChars() : ""); | 303 //printf("\trestoring [%d] %s = %s\n", i, v->toChars(), v->value ? v->value->toChars() : ""); |
268 } | 304 } |
269 } | 305 } |
270 } | 306 } |
271 | |
272 return e; | 307 return e; |
273 } | 308 } |
274 | 309 |
275 /******************************** Statement ***************************/ | 310 /******************************** Statement ***************************/ |
276 | 311 |
476 return NULL; | 511 return NULL; |
477 if (e == EXP_CANT_INTERPRET) | 512 if (e == EXP_CANT_INTERPRET) |
478 return e; | 513 return e; |
479 if (e == EXP_BREAK_INTERPRET) | 514 if (e == EXP_BREAK_INTERPRET) |
480 return NULL; | 515 return NULL; |
481 if (e != EXP_CONTINUE_INTERPRET) | 516 if (e && e != EXP_CONTINUE_INTERPRET) |
482 return e; | 517 return e; |
483 } | 518 } |
484 | 519 |
485 while (1) | 520 while (1) |
486 { | 521 { |
756 { | 791 { |
757 key->value = elwr; | 792 key->value = elwr; |
758 | 793 |
759 while (1) | 794 while (1) |
760 { | 795 { |
761 e = Cmp(TOKlt, key->value->type, key->value, upr); | 796 e = Cmp(TOKlt, key->value->type, key->value, eupr); |
762 if (e == EXP_CANT_INTERPRET) | 797 if (e == EXP_CANT_INTERPRET) |
763 break; | 798 break; |
764 if (e->isBool(TRUE) == FALSE) | 799 if (e->isBool(TRUE) == FALSE) |
765 { e = NULL; | 800 { e = NULL; |
766 break; | 801 break; |
771 break; | 806 break; |
772 if (e == EXP_BREAK_INTERPRET) | 807 if (e == EXP_BREAK_INTERPRET) |
773 { e = NULL; | 808 { e = NULL; |
774 break; | 809 break; |
775 } | 810 } |
776 e = Add(key->value->type, key->value, new IntegerExp(loc, 1, key->value->type)); | 811 if (e == NULL || e == EXP_CONTINUE_INTERPRET) |
777 if (e == EXP_CANT_INTERPRET) | 812 { e = Add(key->value->type, key->value, new IntegerExp(loc, 1, key->value->type)); |
778 break; | 813 if (e == EXP_CANT_INTERPRET) |
779 key->value = e; | 814 break; |
815 key->value = e; | |
816 } | |
817 else | |
818 break; | |
780 } | 819 } |
781 } | 820 } |
782 else // TOKforeach_reverse | 821 else // TOKforeach_reverse |
783 { | 822 { |
784 key->value = eupr; | 823 key->value = eupr; |
785 | 824 |
786 while (1) | 825 do |
787 { | 826 { |
788 e = Cmp(TOKgt, key->value->type, key->value, lwr); | 827 e = Cmp(TOKgt, key->value->type, key->value, elwr); |
789 if (e == EXP_CANT_INTERPRET) | 828 if (e == EXP_CANT_INTERPRET) |
790 break; | 829 break; |
791 if (e->isBool(TRUE) == FALSE) | 830 if (e->isBool(TRUE) == FALSE) |
792 { e = NULL; | 831 { e = NULL; |
793 break; | 832 break; |
803 break; | 842 break; |
804 if (e == EXP_BREAK_INTERPRET) | 843 if (e == EXP_BREAK_INTERPRET) |
805 { e = NULL; | 844 { e = NULL; |
806 break; | 845 break; |
807 } | 846 } |
808 } | 847 } while (e == NULL || e == EXP_CONTINUE_INTERPRET); |
809 } | 848 } |
810 key->value = keysave; | 849 key->value = keysave; |
811 return e; | 850 return e; |
812 } | 851 } |
813 #endif | 852 #endif |
944 #if LOG | 983 #if LOG |
945 printf("Expression::interpret() %s\n", toChars()); | 984 printf("Expression::interpret() %s\n", toChars()); |
946 printf("type = %s\n", type->toChars()); | 985 printf("type = %s\n", type->toChars()); |
947 dump(0); | 986 dump(0); |
948 #endif | 987 #endif |
988 error("Cannot interpret %s at compile time", toChars()); | |
989 return EXP_CANT_INTERPRET; | |
990 } | |
991 | |
992 Expression *ThisExp::interpret(InterState *istate) | |
993 { | |
994 if (istate->localThis) | |
995 return istate->localThis->interpret(istate); | |
949 return EXP_CANT_INTERPRET; | 996 return EXP_CANT_INTERPRET; |
950 } | 997 } |
951 | 998 |
952 Expression *NullExp::interpret(InterState *istate) | 999 Expression *NullExp::interpret(InterState *istate) |
953 { | 1000 { |
993 SymbolDeclaration *s = d->isSymbolDeclaration(); | 1040 SymbolDeclaration *s = d->isSymbolDeclaration(); |
994 #endif | 1041 #endif |
995 if (v) | 1042 if (v) |
996 { | 1043 { |
997 #if DMDV2 | 1044 #if DMDV2 |
998 if ((v->isConst() || v->isInvariant()) && v->init && !v->value) | 1045 if ((v->isConst() || v->isInvariant() || v->storage_class & STCmanifest) && v->init && !v->value) |
999 #else | 1046 #else |
1000 if (v->isConst() && v->init) | 1047 if (v->isConst() && v->init) |
1001 #endif | 1048 #endif |
1002 { e = v->init->toExpression(); | 1049 { e = v->init->toExpression(); |
1003 if (e && !e->type) | 1050 if (e && !e->type) |
1004 e->type = v->type; | 1051 e->type = v->type; |
1005 } | 1052 } |
1006 else | 1053 else |
1007 { e = v->value; | 1054 { e = v->value; |
1008 if (!e) | 1055 if (v->isDataseg()) |
1056 { error(loc, "static variable %s cannot be read at compile time", v->toChars()); | |
1057 e = EXP_CANT_INTERPRET; | |
1058 } | |
1059 else if (!e) | |
1009 error(loc, "variable %s is used before initialization", v->toChars()); | 1060 error(loc, "variable %s is used before initialization", v->toChars()); |
1010 else if (e != EXP_CANT_INTERPRET) | 1061 else if (e != EXP_CANT_INTERPRET) |
1011 e = e->interpret(istate); | 1062 e = e->interpret(istate); |
1012 } | 1063 } |
1013 if (!e) | 1064 if (!e) |
1062 } | 1113 } |
1063 else if (declaration->isAttribDeclaration() || | 1114 else if (declaration->isAttribDeclaration() || |
1064 declaration->isTemplateMixin() || | 1115 declaration->isTemplateMixin() || |
1065 declaration->isTupleDeclaration()) | 1116 declaration->isTupleDeclaration()) |
1066 { // These can be made to work, too lazy now | 1117 { // These can be made to work, too lazy now |
1118 error("Declaration %s is not yet implemented in CTFE", toChars()); | |
1119 | |
1067 e = EXP_CANT_INTERPRET; | 1120 e = EXP_CANT_INTERPRET; |
1068 } | 1121 } |
1069 else | 1122 else |
1070 { // Others should not contain executable code, so are trivial to evaluate | 1123 { // Others should not contain executable code, so are trivial to evaluate |
1071 e = NULL; | 1124 e = NULL; |
1072 } | 1125 } |
1073 #if LOG | 1126 #if LOG |
1074 printf("-DeclarationExp::interpret(): %p\n", e); | 1127 printf("-DeclarationExp::interpret(%s): %p\n", toChars(), e); |
1075 #endif | 1128 #endif |
1076 return e; | 1129 return e; |
1077 } | 1130 } |
1078 | 1131 |
1079 Expression *TupleExp::interpret(InterState *istate) | 1132 Expression *TupleExp::interpret(InterState *istate) |
1259 printf("StructLiteralExp::interpret() %s\n", toChars()); | 1312 printf("StructLiteralExp::interpret() %s\n", toChars()); |
1260 #endif | 1313 #endif |
1261 /* We don't know how to deal with overlapping fields | 1314 /* We don't know how to deal with overlapping fields |
1262 */ | 1315 */ |
1263 if (sd->hasUnions) | 1316 if (sd->hasUnions) |
1264 return EXP_CANT_INTERPRET; | 1317 { error("Unions with overlapping fields are not yet supported in CTFE"); |
1318 return EXP_CANT_INTERPRET; | |
1319 } | |
1265 | 1320 |
1266 if (elements) | 1321 if (elements) |
1267 { | 1322 { |
1268 for (size_t i = 0; i < elements->dim; i++) | 1323 for (size_t i = 0; i < elements->dim; i++) |
1269 { Expression *e = (Expression *)elements->data[i]; | 1324 { Expression *e = (Expression *)elements->data[i]; |
1431 | 1486 |
1432 BIN_INTERPRET2(Equal) | 1487 BIN_INTERPRET2(Equal) |
1433 BIN_INTERPRET2(Identity) | 1488 BIN_INTERPRET2(Identity) |
1434 BIN_INTERPRET2(Cmp) | 1489 BIN_INTERPRET2(Cmp) |
1435 | 1490 |
1491 /* Helper functions for BinExp::interpretAssignCommon | |
1492 */ | |
1493 | |
1494 /*************************************** | |
1495 * Duplicate the elements array, then set field 'indexToChange' = newelem. | |
1496 */ | |
1497 Expressions *changeOneElement(Expressions *oldelems, size_t indexToChange, void *newelem) | |
1498 { | |
1499 Expressions *expsx = new Expressions(); | |
1500 expsx->setDim(oldelems->dim); | |
1501 for (size_t j = 0; j < expsx->dim; j++) | |
1502 { | |
1503 if (j == indexToChange) | |
1504 expsx->data[j] = newelem; | |
1505 else | |
1506 expsx->data[j] = oldelems->data[j]; | |
1507 } | |
1508 return expsx; | |
1509 } | |
1510 | |
1511 /*************************************** | |
1512 * Returns oldelems[0..insertpoint] ~ newelems ~ oldelems[insertpoint..$] | |
1513 */ | |
1514 Expressions *spliceElements(Expressions *oldelems, | |
1515 Expressions *newelems, size_t insertpoint) | |
1516 { | |
1517 Expressions *expsx = new Expressions(); | |
1518 expsx->setDim(oldelems->dim); | |
1519 for (size_t j = 0; j < expsx->dim; j++) | |
1520 { | |
1521 if (j >= insertpoint && j < insertpoint + newelems->dim) | |
1522 expsx->data[j] = newelems->data[j - insertpoint]; | |
1523 else | |
1524 expsx->data[j] = oldelems->data[j]; | |
1525 } | |
1526 return expsx; | |
1527 } | |
1528 | |
1529 /****************************** | |
1530 * Create an array literal consisting of 'elem' duplicated 'dim' times. | |
1531 */ | |
1532 ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Type *type, | |
1533 Expression *elem, size_t dim) | |
1534 { | |
1535 Expressions *elements = new Expressions(); | |
1536 elements->setDim(dim); | |
1537 for (size_t i = 0; i < dim; i++) | |
1538 elements->data[i] = elem; | |
1539 ArrayLiteralExp *ae = new ArrayLiteralExp(0, elements); | |
1540 ae->type = type; | |
1541 return ae; | |
1542 } | |
1543 | |
1544 | |
1545 /******************************** | |
1546 * Necessary because defaultInit() for a struct is a VarExp, not a StructLiteralExp. | |
1547 */ | |
1548 StructLiteralExp *createDefaultInitStructLiteral(Loc loc, StructDeclaration *sym) | |
1549 { | |
1550 Expressions *structelems = new Expressions(); | |
1551 structelems->setDim(sym->fields.dim); | |
1552 for (size_t j = 0; j < structelems->dim; j++) | |
1553 { | |
1554 structelems->data[j] = ((VarDeclaration *)(sym->fields.data[j]))->type->defaultInit(); | |
1555 } | |
1556 StructLiteralExp *structinit = new StructLiteralExp(loc, sym, structelems); | |
1557 // Why doesn't the StructLiteralExp constructor do this, when | |
1558 // sym->type != NULL ? | |
1559 structinit->type = sym->type; | |
1560 return structinit; | |
1561 } | |
1562 | |
1563 /******************************** | |
1564 * Add v to the istate list, unless it already exists there. | |
1565 */ | |
1566 void addVarToInterstate(InterState *istate, VarDeclaration *v) | |
1567 { | |
1568 if (!v->isParameter()) | |
1569 { | |
1570 for (size_t i = 0; 1; i++) | |
1571 { | |
1572 if (i == istate->vars.dim) | |
1573 { istate->vars.push(v); | |
1574 //printf("\tadding %s to istate\n", v->toChars()); | |
1575 break; | |
1576 } | |
1577 if (v == (VarDeclaration *)istate->vars.data[i]) | |
1578 break; | |
1579 } | |
1580 } | |
1581 } | |
1582 | |
1436 Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post) | 1583 Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post) |
1437 { | 1584 { |
1438 #if LOG | 1585 #if LOG |
1439 printf("BinExp::interpretAssignCommon() %s\n", toChars()); | 1586 printf("BinExp::interpretAssignCommon() %s\n", toChars()); |
1440 #endif | 1587 #endif |
1451 if (e1 == EXP_CANT_INTERPRET) | 1598 if (e1 == EXP_CANT_INTERPRET) |
1452 return e1; | 1599 return e1; |
1453 Expression *e2 = this->e2->interpret(istate); | 1600 Expression *e2 = this->e2->interpret(istate); |
1454 if (e2 == EXP_CANT_INTERPRET) | 1601 if (e2 == EXP_CANT_INTERPRET) |
1455 return e2; | 1602 return e2; |
1456 | 1603 |
1604 // Chase down rebinding of out and ref. | |
1605 if (e1->op == TOKvar) | |
1606 { | |
1607 VarExp *ve = (VarExp *)e1; | |
1608 VarDeclaration *v = ve->var->isVarDeclaration(); | |
1609 if (v && v->value && v->value->op == TOKvar) | |
1610 { | |
1611 VarExp *ve2 = (VarExp *)v->value; | |
1612 if (ve2->var->isStaticStructInitDeclaration()) | |
1613 { // This can happen if v is a struct initialized to | |
1614 // 0 using an __initZ StaticStructInitDeclaration from | |
1615 // TypeStruct::defaultInit() | |
1616 } | |
1617 else | |
1618 e1 = v->value; | |
1619 } | |
1620 else if (v && v->value && (v->value->op==TOKindex || v->value->op == TOKdotvar)) | |
1621 { | |
1622 // It is no longer be a TOKvar, eg when a[4] is passed by ref. | |
1623 e1 = v->value; | |
1624 } | |
1625 } | |
1626 | |
1627 // To reduce code complexity of handling dotvar expressions, | |
1628 // extract the aggregate now. | |
1629 Expression *aggregate; | |
1630 if (e1->op == TOKdotvar) { | |
1631 aggregate = ((DotVarExp *)e1)->e1; | |
1632 // Get rid of 'this'. | |
1633 if (aggregate->op == TOKthis && istate->localThis) | |
1634 aggregate = istate->localThis; | |
1635 } | |
1636 | |
1457 /* Assignment to variable of the form: | 1637 /* Assignment to variable of the form: |
1458 * v = e2 | 1638 * v = e2 |
1459 */ | 1639 */ |
1460 if (e1->op == TOKvar) | 1640 if (e1->op == TOKvar) |
1461 { | 1641 { |
1462 VarExp *ve = (VarExp *)e1; | 1642 VarExp *ve = (VarExp *)e1; |
1463 VarDeclaration *v = ve->var->isVarDeclaration(); | 1643 VarDeclaration *v = ve->var->isVarDeclaration(); |
1644 assert(v); | |
1645 if (v && v->isDataseg()) | |
1646 { // Can't modify global or static data | |
1647 error("%s cannot be modified at compile time", v->toChars()); | |
1648 return EXP_CANT_INTERPRET; | |
1649 } | |
1464 if (v && !v->isDataseg()) | 1650 if (v && !v->isDataseg()) |
1465 { | 1651 { |
1466 /* Chase down rebinding of out and ref | |
1467 */ | |
1468 if (v->value && v->value->op == TOKvar) | |
1469 { | |
1470 VarExp *ve2 = (VarExp *)v->value; | |
1471 if (ve2->var->isStaticStructInitDeclaration()) | |
1472 { | |
1473 /* This can happen if v is a struct initialized to | |
1474 * 0 using an StaticStructInitDeclaration from | |
1475 * TypeStruct::defaultInit() | |
1476 */ | |
1477 } | |
1478 else | |
1479 v = ve2->var->isVarDeclaration(); | |
1480 assert(v); | |
1481 } | |
1482 | |
1483 Expression *ev = v->value; | 1652 Expression *ev = v->value; |
1484 if (fp && !ev) | 1653 if (fp && !ev) |
1485 { error("variable %s is used before initialization", v->toChars()); | 1654 { error("variable %s is used before initialization", v->toChars()); |
1486 return e; | 1655 return e; |
1487 } | 1656 } |
1494 { | 1663 { |
1495 e2 = v->type->defaultInit(); | 1664 e2 = v->type->defaultInit(); |
1496 } | 1665 } |
1497 e2 = Cast(v->type, v->type, e2); | 1666 e2 = Cast(v->type, v->type, e2); |
1498 } | 1667 } |
1499 if (e2 != EXP_CANT_INTERPRET) | 1668 if (e2 == EXP_CANT_INTERPRET) |
1500 { | 1669 return e2; |
1501 if (!v->isParameter()) | 1670 |
1502 { | 1671 addVarToInterstate(istate, v); |
1503 for (size_t i = 0; 1; i++) | 1672 v->value = e2; |
1504 { | 1673 e = Cast(type, type, post ? ev : e2); |
1505 if (i == istate->vars.dim) | 1674 } |
1506 { istate->vars.push(v); | 1675 } |
1507 //printf("\tadding %s to istate\n", v->toChars()); | 1676 else if (e1->op == TOKdotvar && aggregate->op == TOKdotvar) |
1508 break; | 1677 { // eg v.u.var = e2, v[3].u.var = e2, etc. |
1509 } | 1678 error("Nested struct assignment %s is not yet supported in CTFE", toChars()); |
1510 if (v == (VarDeclaration *)istate->vars.data[i]) | |
1511 break; | |
1512 } | |
1513 } | |
1514 v->value = e2; | |
1515 e = Cast(type, type, post ? ev : e2); | |
1516 } | |
1517 } | |
1518 } | 1679 } |
1519 /* Assignment to struct member of the form: | 1680 /* Assignment to struct member of the form: |
1520 * v.var = e2 | 1681 * v.var = e2 |
1521 */ | 1682 */ |
1522 else if (e1->op == TOKdotvar && ((DotVarExp *)e1)->e1->op == TOKvar) | 1683 else if (e1->op == TOKdotvar && aggregate->op == TOKvar) |
1523 { VarExp *ve = (VarExp *)((DotVarExp *)e1)->e1; | 1684 { VarDeclaration *v = ((VarExp *)aggregate)->var->isVarDeclaration(); |
1524 VarDeclaration *v = ve->var->isVarDeclaration(); | |
1525 | 1685 |
1526 if (v->isDataseg()) | 1686 if (v->isDataseg()) |
1687 { // Can't modify global or static data | |
1688 error("%s cannot be modified at compile time", v->toChars()); | |
1527 return EXP_CANT_INTERPRET; | 1689 return EXP_CANT_INTERPRET; |
1690 } else { | |
1691 // Chase down rebinding of out and ref | |
1692 if (v->value && v->value->op == TOKvar) | |
1693 { | |
1694 VarExp *ve2 = (VarExp *)v->value; | |
1695 if (ve2->var->isStaticStructInitDeclaration()) | |
1696 { // This can happen if v is a struct initialized to | |
1697 // 0 using an __initZ StaticStructInitDeclaration from | |
1698 // TypeStruct::defaultInit() | |
1699 } | |
1700 else | |
1701 v = ve2->var->isVarDeclaration(); | |
1702 assert(v); | |
1703 } | |
1704 } | |
1528 if (fp && !v->value) | 1705 if (fp && !v->value) |
1529 { error("variable %s is used before initialization", v->toChars()); | 1706 { error("variable %s is used before initialization", v->toChars()); |
1530 return e; | 1707 return e; |
1531 } | 1708 } |
1532 if (v->value == NULL && v->init->isVoidInitializer()) | 1709 if (v->value == NULL && v->init->isVoidInitializer()) |
1559 else | 1736 else |
1560 e2 = Cast(type, type, e2); | 1737 e2 = Cast(type, type, e2); |
1561 if (e2 == EXP_CANT_INTERPRET) | 1738 if (e2 == EXP_CANT_INTERPRET) |
1562 return e2; | 1739 return e2; |
1563 | 1740 |
1564 if (!v->isParameter()) | 1741 addVarToInterstate(istate, v); |
1565 { | |
1566 for (size_t i = 0; 1; i++) | |
1567 { | |
1568 if (i == istate->vars.dim) | |
1569 { istate->vars.push(v); | |
1570 break; | |
1571 } | |
1572 if (v == (VarDeclaration *)istate->vars.data[i]) | |
1573 break; | |
1574 } | |
1575 } | |
1576 | 1742 |
1577 /* Create new struct literal reflecting updated fieldi | 1743 /* Create new struct literal reflecting updated fieldi |
1578 */ | 1744 */ |
1579 Expressions *expsx = new Expressions(); | 1745 Expressions *expsx = changeOneElement(se->elements, fieldi, e2); |
1580 expsx->setDim(se->elements->dim); | |
1581 for (size_t j = 0; j < expsx->dim; j++) | |
1582 { | |
1583 if (j == fieldi) | |
1584 expsx->data[j] = (void *)e2; | |
1585 else | |
1586 expsx->data[j] = se->elements->data[j]; | |
1587 } | |
1588 v->value = new StructLiteralExp(se->loc, se->sd, expsx); | 1746 v->value = new StructLiteralExp(se->loc, se->sd, expsx); |
1589 v->value->type = se->type; | 1747 v->value->type = se->type; |
1590 | 1748 |
1591 e = Cast(type, type, post ? ev : e2); | 1749 e = Cast(type, type, post ? ev : e2); |
1592 } | 1750 } |
1596 else if (e1->op == TOKstar && ((PtrExp *)e1)->e1->op == TOKsymoff) | 1754 else if (e1->op == TOKstar && ((PtrExp *)e1)->e1->op == TOKsymoff) |
1597 { SymOffExp *soe = (SymOffExp *)((PtrExp *)e1)->e1; | 1755 { SymOffExp *soe = (SymOffExp *)((PtrExp *)e1)->e1; |
1598 VarDeclaration *v = soe->var->isVarDeclaration(); | 1756 VarDeclaration *v = soe->var->isVarDeclaration(); |
1599 | 1757 |
1600 if (v->isDataseg()) | 1758 if (v->isDataseg()) |
1759 { | |
1760 error("%s cannot be modified at compile time", v->toChars()); | |
1601 return EXP_CANT_INTERPRET; | 1761 return EXP_CANT_INTERPRET; |
1762 } | |
1602 if (fp && !v->value) | 1763 if (fp && !v->value) |
1603 { error("variable %s is used before initialization", v->toChars()); | 1764 { error("variable %s is used before initialization", v->toChars()); |
1604 return e; | 1765 return e; |
1605 } | 1766 } |
1606 Expression *vie = v->value; | 1767 Expression *vie = v->value; |
1621 else | 1782 else |
1622 e2 = Cast(type, type, e2); | 1783 e2 = Cast(type, type, e2); |
1623 if (e2 == EXP_CANT_INTERPRET) | 1784 if (e2 == EXP_CANT_INTERPRET) |
1624 return e2; | 1785 return e2; |
1625 | 1786 |
1626 if (!v->isParameter()) | 1787 addVarToInterstate(istate, v); |
1627 { | |
1628 for (size_t i = 0; 1; i++) | |
1629 { | |
1630 if (i == istate->vars.dim) | |
1631 { istate->vars.push(v); | |
1632 break; | |
1633 } | |
1634 if (v == (VarDeclaration *)istate->vars.data[i]) | |
1635 break; | |
1636 } | |
1637 } | |
1638 | 1788 |
1639 /* Create new struct literal reflecting updated fieldi | 1789 /* Create new struct literal reflecting updated fieldi |
1640 */ | 1790 */ |
1641 Expressions *expsx = new Expressions(); | 1791 Expressions *expsx = changeOneElement(se->elements, fieldi, e2); |
1642 expsx->setDim(se->elements->dim); | |
1643 for (size_t j = 0; j < expsx->dim; j++) | |
1644 { | |
1645 if (j == fieldi) | |
1646 expsx->data[j] = (void *)e2; | |
1647 else | |
1648 expsx->data[j] = se->elements->data[j]; | |
1649 } | |
1650 v->value = new StructLiteralExp(se->loc, se->sd, expsx); | 1792 v->value = new StructLiteralExp(se->loc, se->sd, expsx); |
1651 v->value->type = se->type; | 1793 v->value->type = se->type; |
1652 | 1794 |
1653 e = Cast(type, type, post ? ev : e2); | 1795 e = Cast(type, type, post ? ev : e2); |
1654 } | 1796 } |
1657 */ | 1799 */ |
1658 else if (e1->op == TOKindex && ((IndexExp *)e1)->e1->op == TOKvar) | 1800 else if (e1->op == TOKindex && ((IndexExp *)e1)->e1->op == TOKvar) |
1659 { IndexExp *ie = (IndexExp *)e1; | 1801 { IndexExp *ie = (IndexExp *)e1; |
1660 VarExp *ve = (VarExp *)ie->e1; | 1802 VarExp *ve = (VarExp *)ie->e1; |
1661 VarDeclaration *v = ve->var->isVarDeclaration(); | 1803 VarDeclaration *v = ve->var->isVarDeclaration(); |
1662 | |
1663 if (!v || v->isDataseg()) | 1804 if (!v || v->isDataseg()) |
1805 { | |
1806 error("%s cannot be modified at compile time", v ? v->toChars(): "void"); | |
1664 return EXP_CANT_INTERPRET; | 1807 return EXP_CANT_INTERPRET; |
1808 } | |
1809 if (v->value && v->value->op == TOKvar) | |
1810 { | |
1811 VarExp *ve2 = (VarExp *)v->value; | |
1812 if (ve2->var->isStaticStructInitDeclaration()) | |
1813 { // This can happen if v is a struct initialized to | |
1814 // 0 using an __initZ StaticStructInitDeclaration from | |
1815 // TypeStruct::defaultInit() | |
1816 } | |
1817 else | |
1818 v = ve2->var->isVarDeclaration(); | |
1819 assert(v); | |
1820 } | |
1665 if (!v->value) | 1821 if (!v->value) |
1666 { | 1822 { |
1667 if (fp) | 1823 if (fp) |
1668 { error("variable %s is used before initialization", v->toChars()); | 1824 { error("variable %s is used before initialization", v->toChars()); |
1669 return e; | 1825 return e; |
1677 * What we should do is fill the array literal with | 1833 * What we should do is fill the array literal with |
1678 * NULL data, so use-before-initialized can be detected. | 1834 * NULL data, so use-before-initialized can be detected. |
1679 * But we're too lazy at the moment to do it, as that | 1835 * But we're too lazy at the moment to do it, as that |
1680 * involves redoing Index() and whoever calls it. | 1836 * involves redoing Index() and whoever calls it. |
1681 */ | 1837 */ |
1682 Expression *ev = v->type->defaultInit(); | 1838 |
1683 size_t dim = ((TypeSArray *)t)->dim->toInteger(); | 1839 size_t dim = ((TypeSArray *)t)->dim->toInteger(); |
1684 Expressions *elements = new Expressions(); | 1840 v->value = createBlockDuplicatedArrayLiteral(v->type, |
1685 elements->setDim(dim); | 1841 v->type->defaultInit(), dim); |
1686 for (size_t i = 0; i < dim; i++) | |
1687 elements->data[i] = (void *)ev; | |
1688 ArrayLiteralExp *ae = new ArrayLiteralExp(0, elements); | |
1689 ae->type = v->type; | |
1690 v->value = ae; | |
1691 } | 1842 } |
1692 else | 1843 else |
1693 return EXP_CANT_INTERPRET; | 1844 return EXP_CANT_INTERPRET; |
1694 } | 1845 } |
1695 | 1846 |
1700 ae = (ArrayLiteralExp *)v->value; | 1851 ae = (ArrayLiteralExp *)v->value; |
1701 else if (v->value->op == TOKassocarrayliteral) | 1852 else if (v->value->op == TOKassocarrayliteral) |
1702 aae = (AssocArrayLiteralExp *)v->value; | 1853 aae = (AssocArrayLiteralExp *)v->value; |
1703 else if (v->value->op == TOKstring) | 1854 else if (v->value->op == TOKstring) |
1704 se = (StringExp *)v->value; | 1855 se = (StringExp *)v->value; |
1856 else if (v->value->op == TOKnull) | |
1857 { | |
1858 // This would be a runtime segfault | |
1859 error("Cannot index null array %s", v->toChars()); | |
1860 return EXP_CANT_INTERPRET; | |
1861 } | |
1705 else | 1862 else |
1706 return EXP_CANT_INTERPRET; | 1863 return EXP_CANT_INTERPRET; |
1707 | 1864 |
1865 /* Set the $ variable | |
1866 */ | |
1867 Expression *ee = ArrayLength(Type::tsize_t, v->value); | |
1868 if (ee != EXP_CANT_INTERPRET && ie->lengthVar) | |
1869 ie->lengthVar->value = ee; | |
1708 Expression *index = ie->e2->interpret(istate); | 1870 Expression *index = ie->e2->interpret(istate); |
1709 if (index == EXP_CANT_INTERPRET) | 1871 if (index == EXP_CANT_INTERPRET) |
1710 return EXP_CANT_INTERPRET; | 1872 return EXP_CANT_INTERPRET; |
1711 Expression *ev; | 1873 Expression *ev; |
1712 if (fp || ae || se) // not for aae, because key might not be there | 1874 if (fp || ae || se) // not for aae, because key might not be there |
1720 e2 = (*fp)(type, ev, e2); | 1882 e2 = (*fp)(type, ev, e2); |
1721 else | 1883 else |
1722 e2 = Cast(type, type, e2); | 1884 e2 = Cast(type, type, e2); |
1723 if (e2 == EXP_CANT_INTERPRET) | 1885 if (e2 == EXP_CANT_INTERPRET) |
1724 return e2; | 1886 return e2; |
1725 | 1887 |
1726 if (!v->isParameter()) | 1888 addVarToInterstate(istate, v); |
1727 { | |
1728 for (size_t i = 0; 1; i++) | |
1729 { | |
1730 if (i == istate->vars.dim) | |
1731 { istate->vars.push(v); | |
1732 break; | |
1733 } | |
1734 if (v == (VarDeclaration *)istate->vars.data[i]) | |
1735 break; | |
1736 } | |
1737 } | |
1738 | |
1739 if (ae) | 1889 if (ae) |
1740 { | 1890 { |
1741 /* Create new array literal reflecting updated elem | 1891 /* Create new array literal reflecting updated elem |
1742 */ | 1892 */ |
1743 int elemi = index->toInteger(); | 1893 int elemi = index->toInteger(); |
1744 Expressions *expsx = new Expressions(); | 1894 Expressions *expsx = changeOneElement(ae->elements, elemi, e2); |
1745 expsx->setDim(ae->elements->dim); | |
1746 for (size_t j = 0; j < expsx->dim; j++) | |
1747 { | |
1748 if (j == elemi) | |
1749 expsx->data[j] = (void *)e2; | |
1750 else | |
1751 expsx->data[j] = ae->elements->data[j]; | |
1752 } | |
1753 v->value = new ArrayLiteralExp(ae->loc, expsx); | 1895 v->value = new ArrayLiteralExp(ae->loc, expsx); |
1754 v->value->type = ae->type; | 1896 v->value->type = ae->type; |
1755 } | 1897 } |
1756 else if (aae) | 1898 else if (aae) |
1757 { | 1899 { |
1810 else | 1952 else |
1811 assert(0); | 1953 assert(0); |
1812 | 1954 |
1813 e = Cast(type, type, post ? ev : e2); | 1955 e = Cast(type, type, post ? ev : e2); |
1814 } | 1956 } |
1957 | |
1958 /* Assignment to struct element in array, of the form: | |
1959 * a[i].var = e2 | |
1960 */ | |
1961 else if (e1->op == TOKdotvar && aggregate->op == TOKindex && | |
1962 ((IndexExp *)aggregate)->e1->op == TOKvar) | |
1963 { | |
1964 IndexExp * ie = (IndexExp *)aggregate; | |
1965 VarExp *ve = (VarExp *)(ie->e1); | |
1966 VarDeclaration *v = ve->var->isVarDeclaration(); | |
1967 if (!v || v->isDataseg()) | |
1968 { | |
1969 error("%s cannot be modified at compile time", v ? v->toChars(): "void"); | |
1970 return EXP_CANT_INTERPRET; | |
1971 } | |
1972 Type *t = ve->type->toBasetype(); | |
1973 ArrayLiteralExp *ae = (ArrayLiteralExp *)v->value; | |
1974 if (!ae) | |
1975 { | |
1976 // assignment to one element in an uninitialized (static) array. | |
1977 // This is quite difficult, because defaultInit() for a struct is a VarExp, | |
1978 // not a StructLiteralExp. | |
1979 Type *t = v->type->toBasetype(); | |
1980 if (t->ty != Tsarray) | |
1981 { | |
1982 error("Cannot index an uninitialized variable"); | |
1983 return EXP_CANT_INTERPRET; | |
1984 } | |
1985 | |
1986 Type *telem = ((TypeSArray *)t)->nextOf()->toBasetype(); | |
1987 if (telem->ty != Tstruct) { return EXP_CANT_INTERPRET; } | |
1988 | |
1989 // Create a default struct literal... | |
1990 StructDeclaration *sym = ((TypeStruct *)telem)->sym; | |
1991 StructLiteralExp *structinit = createDefaultInitStructLiteral(v->loc, sym); | |
1992 | |
1993 // ... and use to create a blank array literal | |
1994 size_t dim = ((TypeSArray *)t)->dim->toInteger(); | |
1995 ae = createBlockDuplicatedArrayLiteral(v->type, structinit, dim); | |
1996 v->value = ae; | |
1997 } | |
1998 if ((Expression *)(ae->elements) == EXP_CANT_INTERPRET) | |
1999 { | |
2000 // Note that this would be a runtime segfault | |
2001 error("Cannot index null array %s", v->toChars()); | |
2002 return EXP_CANT_INTERPRET; | |
2003 } | |
2004 // Set the $ variable | |
2005 Expression *ee = ArrayLength(Type::tsize_t, v->value); | |
2006 if (ee != EXP_CANT_INTERPRET && ie->lengthVar) | |
2007 ie->lengthVar->value = ee; | |
2008 // Determine the index, and check that it's OK. | |
2009 Expression *index = ie->e2->interpret(istate); | |
2010 if (index == EXP_CANT_INTERPRET) | |
2011 return EXP_CANT_INTERPRET; | |
2012 | |
2013 int elemi = index->toInteger(); | |
2014 if (elemi >= ae->elements->dim) | |
2015 { | |
2016 error("array index %d is out of bounds %s[0..%d]", elemi, | |
2017 v->toChars(), ae->elements->dim); | |
2018 return EXP_CANT_INTERPRET; | |
2019 } | |
2020 // Get old element | |
2021 Expression *vie = (Expression *)(ae->elements->data[elemi]); | |
2022 if (vie->op != TOKstructliteral) | |
2023 return EXP_CANT_INTERPRET; | |
2024 | |
2025 // Work out which field needs to be changed | |
2026 StructLiteralExp *se = (StructLiteralExp *)vie; | |
2027 VarDeclaration *vf = ((DotVarExp *)e1)->var->isVarDeclaration(); | |
2028 if (!vf) | |
2029 return EXP_CANT_INTERPRET; | |
2030 | |
2031 int fieldi = se->getFieldIndex(type, vf->offset); | |
2032 if (fieldi == -1) | |
2033 return EXP_CANT_INTERPRET; | |
2034 | |
2035 Expression *ev = se->getField(type, vf->offset); | |
2036 if (fp) | |
2037 e2 = (*fp)(type, ev, e2); | |
2038 else | |
2039 e2 = Cast(type, type, e2); | |
2040 if (e2 == EXP_CANT_INTERPRET) | |
2041 return e2; | |
2042 | |
2043 // Create new struct literal reflecting updated field | |
2044 Expressions *expsx = changeOneElement(se->elements, fieldi, e2); | |
2045 Expression * newstruct = new StructLiteralExp(se->loc, se->sd, expsx); | |
2046 | |
2047 // Create new array literal reflecting updated struct elem | |
2048 ae->elements = changeOneElement(ae->elements, elemi, newstruct); | |
2049 return ae; | |
2050 } | |
2051 /* Slice assignment, initialization of static arrays | |
2052 * a[] = e | |
2053 */ | |
2054 else if (e1->op == TOKslice && ((SliceExp *)e1)->e1->op==TOKvar) | |
2055 { | |
2056 SliceExp * sexp = (SliceExp *)e1; | |
2057 VarExp *ve = (VarExp *)(sexp->e1); | |
2058 VarDeclaration *v = ve->var->isVarDeclaration(); | |
2059 if (!v || v->isDataseg()) | |
2060 { | |
2061 error("%s cannot be modified at compile time", v->toChars()); | |
2062 return EXP_CANT_INTERPRET; | |
2063 } | |
2064 // Chase down rebinding of out and ref | |
2065 if (v->value && v->value->op == TOKvar) | |
2066 { | |
2067 VarExp *ve2 = (VarExp *)v->value; | |
2068 if (ve2->var->isStaticStructInitDeclaration()) | |
2069 { // This can happen if v is a struct initialized to | |
2070 // 0 using an __initZ StaticStructInitDeclaration from | |
2071 // TypeStruct::defaultInit() | |
2072 } | |
2073 else | |
2074 v = ve2->var->isVarDeclaration(); | |
2075 assert(v); | |
2076 } | |
2077 /* Set the $ variable | |
2078 */ | |
2079 Expression *ee = v->value ? ArrayLength(Type::tsize_t, v->value) | |
2080 : EXP_CANT_INTERPRET; | |
2081 if (ee != EXP_CANT_INTERPRET && sexp->lengthVar) | |
2082 sexp->lengthVar->value = ee; | |
2083 Expression *upper = NULL; | |
2084 Expression *lower = NULL; | |
2085 if (sexp->upr) | |
2086 { | |
2087 upper = sexp->upr->interpret(istate); | |
2088 if (upper == EXP_CANT_INTERPRET) | |
2089 return EXP_CANT_INTERPRET; | |
2090 } | |
2091 if (sexp->lwr) | |
2092 { | |
2093 lower = sexp->lwr->interpret(istate); | |
2094 if (lower == EXP_CANT_INTERPRET) | |
2095 return EXP_CANT_INTERPRET; | |
2096 } | |
2097 Type *t = v->type->toBasetype(); | |
2098 size_t dim; | |
2099 if (t->ty == Tsarray) | |
2100 dim = ((TypeSArray *)t)->dim->toInteger(); | |
2101 else if (t->ty == Tarray) | |
2102 { | |
2103 if (!v->value || v->value->op == TOKnull) | |
2104 { | |
2105 error("cannot assign to null array %s", v->toChars()); | |
2106 return EXP_CANT_INTERPRET; | |
2107 } | |
2108 if (v->value->op == TOKarrayliteral) | |
2109 dim = ((ArrayLiteralExp *)v->value)->elements->dim; | |
2110 else if (v->value->op ==TOKstring) | |
2111 { | |
2112 error("String slice assignment is not yet supported in CTFE"); | |
2113 return EXP_CANT_INTERPRET; | |
2114 } | |
2115 } | |
2116 else | |
2117 { | |
2118 error("%s cannot be evaluated at compile time", toChars()); | |
2119 return EXP_CANT_INTERPRET; | |
2120 } | |
2121 int upperbound = upper ? upper->toInteger() : dim; | |
2122 int lowerbound = lower ? lower->toInteger() : 0; | |
2123 | |
2124 ArrayLiteralExp *existing; | |
2125 if (((int)lowerbound < 0) || (upperbound > dim)) | |
2126 { | |
2127 error("Array bounds [0..%d] exceeded in slice [%d..%d]", dim, lowerbound, upperbound); | |
2128 return EXP_CANT_INTERPRET; | |
2129 } | |
2130 if (upperbound-lowerbound != dim) | |
2131 { | |
2132 // Only modifying part of the array. Must create a new array literal. | |
2133 // If the existing array is uninitialized (this can only happen | |
2134 // with static arrays), create it. | |
2135 if (v->value && v->value->op == TOKarrayliteral) | |
2136 existing = (ArrayLiteralExp *)v->value; | |
2137 else | |
2138 { | |
2139 // this can only happen with static arrays | |
2140 existing = createBlockDuplicatedArrayLiteral(v->type, v->type->defaultInit(), dim); | |
2141 } | |
2142 } | |
2143 | |
2144 if (e2->op == TOKarrayliteral) | |
2145 { | |
2146 // Static array assignment from literal | |
2147 ArrayLiteralExp *ae = (ArrayLiteralExp *)e2; | |
2148 if (ae->elements->dim != (upperbound - lowerbound)) | |
2149 { | |
2150 error("Array length mismatch assigning [0..%d] to [%d..%d]", ae->elements->dim, lowerbound, upperbound); | |
2151 return e; | |
2152 } | |
2153 if (upperbound - lowerbound == dim) | |
2154 v->value = ae; | |
2155 else | |
2156 { | |
2157 // value[] = value[0..lower] ~ ae ~ value[upper..$] | |
2158 existing->elements = spliceElements(existing->elements, ae->elements, lowerbound); | |
2159 v->value = existing; | |
2160 } | |
2161 return e2; | |
2162 } | |
2163 else if (t->nextOf()->ty == e2->type->ty) | |
2164 { | |
2165 // Static array block assignment | |
2166 if (upperbound-lowerbound ==dim) | |
2167 v->value = createBlockDuplicatedArrayLiteral(v->type, e2, dim); | |
2168 else | |
2169 { | |
2170 // value[] = value[0..lower] ~ ae ~ value[upper..$] | |
2171 existing->elements = spliceElements(existing->elements, createBlockDuplicatedArrayLiteral(v->type, e2, upperbound-lowerbound)->elements, lowerbound); | |
2172 v->value = existing; | |
2173 } | |
2174 return e2; | |
2175 } | |
2176 else if (e2->op == TOKstring) | |
2177 { | |
2178 StringExp *se = (StringExp *)e2; | |
2179 // This is problematic. char[8] should be storing | |
2180 // values as a string literal, not | |
2181 // as an array literal. Then, for static arrays, we | |
2182 // could do modifications | |
2183 // in-place, with a dramatic memory and speed improvement. | |
2184 error("String slice assignment is not yet supported in CTFE"); | |
2185 return e2; | |
2186 } | |
2187 else | |
2188 { | |
2189 error("Slice operation %s cannot be evaluated at compile time", toChars()); | |
2190 return e; | |
2191 } | |
2192 } | |
1815 else | 2193 else |
1816 { | 2194 { |
2195 error("%s cannot be evaluated at compile time", toChars()); | |
1817 #ifdef DEBUG | 2196 #ifdef DEBUG |
1818 dump(0); | 2197 dump(0); |
1819 #endif | 2198 #endif |
1820 } | 2199 } |
1821 return e; | 2200 return e; |
1925 { Expression *e = EXP_CANT_INTERPRET; | 2304 { Expression *e = EXP_CANT_INTERPRET; |
1926 | 2305 |
1927 #if LOG | 2306 #if LOG |
1928 printf("CallExp::interpret() %s\n", toChars()); | 2307 printf("CallExp::interpret() %s\n", toChars()); |
1929 #endif | 2308 #endif |
2309 if (e1->op == TOKdotvar) | |
2310 { | |
2311 Expression * pthis = ((DotVarExp*)e1)->e1; | |
2312 FuncDeclaration *fd = ((DotVarExp*)e1)->var->isFuncDeclaration(); | |
2313 TypeFunction *tf = fd ? (TypeFunction *)(fd->type) : NULL; | |
2314 if (tf) | |
2315 { // Member function call | |
2316 if(pthis->op == TOKthis) | |
2317 pthis = istate->localThis; | |
2318 Expression *eresult = fd->interpret(istate, arguments, pthis); | |
2319 if (eresult) | |
2320 e = eresult; | |
2321 else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors) | |
2322 e = EXP_VOID_INTERPRET; | |
2323 else | |
2324 error("cannot evaluate %s at compile time", toChars()); | |
2325 return e; | |
2326 } | |
2327 error("cannot evaluate %s at compile time", toChars()); | |
2328 return EXP_CANT_INTERPRET; | |
2329 } | |
1930 if (e1->op == TOKvar) | 2330 if (e1->op == TOKvar) |
1931 { | 2331 { |
1932 FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration(); | 2332 FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration(); |
1933 if (fd) | 2333 if (fd) |
1934 { | 2334 { |
2157 Expression *e1; | 2557 Expression *e1; |
2158 | 2558 |
2159 #if LOG | 2559 #if LOG |
2160 printf("AssertExp::interpret() %s\n", toChars()); | 2560 printf("AssertExp::interpret() %s\n", toChars()); |
2161 #endif | 2561 #endif |
2562 if( this->e1->op == TOKaddress) | |
2563 { // Special case: deal with compiler-inserted assert(&this, "null this") | |
2564 AddrExp *ade = (AddrExp *)this->e1; | |
2565 if(ade->e1->op == TOKthis && istate->localThis) | |
2566 return istate->localThis->interpret(istate); | |
2567 } | |
2568 if (this->e1->op == TOKthis) | |
2569 { | |
2570 if(istate->localThis) | |
2571 return istate->localThis->interpret(istate); | |
2572 } | |
2162 e1 = this->e1->interpret(istate); | 2573 e1 = this->e1->interpret(istate); |
2163 if (e1 == EXP_CANT_INTERPRET) | 2574 if (e1 == EXP_CANT_INTERPRET) |
2164 goto Lcant; | 2575 goto Lcant; |
2165 if (e1->isBool(TRUE)) | 2576 if (e1->isBool(TRUE)) |
2166 { | 2577 { |
2225 if (!e) | 2636 if (!e) |
2226 e = EXP_CANT_INTERPRET; | 2637 e = EXP_CANT_INTERPRET; |
2227 } | 2638 } |
2228 } | 2639 } |
2229 } | 2640 } |
2641 #if DMDV2 | |
2642 #else // this is required for D1, where structs return *this instead of 'this'. | |
2643 else if (e1->op == TOKthis) | |
2644 { | |
2645 if(istate->localThis) | |
2646 return istate->localThis->interpret(istate); | |
2647 } | |
2648 #endif | |
2230 #if LOG | 2649 #if LOG |
2231 if (e == EXP_CANT_INTERPRET) | 2650 if (e == EXP_CANT_INTERPRET) |
2232 printf("PtrExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars()); | 2651 printf("PtrExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars()); |
2233 #endif | 2652 #endif |
2234 return e; | 2653 return e; |
2251 { e = se->getField(type, v->offset); | 2670 { e = se->getField(type, v->offset); |
2252 if (!e) | 2671 if (!e) |
2253 e = EXP_CANT_INTERPRET; | 2672 e = EXP_CANT_INTERPRET; |
2254 return e; | 2673 return e; |
2255 } | 2674 } |
2256 } | 2675 } else error("%s.%s is not yet implemented at compile time", ex->toChars(), var->toChars()); |
2257 } | 2676 } |
2258 | 2677 |
2259 #if LOG | 2678 #if LOG |
2260 if (e == EXP_CANT_INTERPRET) | 2679 if (e == EXP_CANT_INTERPRET) |
2261 printf("DotVarExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars()); | 2680 printf("DotVarExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars()); |
2280 return e; | 2699 return e; |
2281 } | 2700 } |
2282 | 2701 |
2283 Expression *interpret_aaKeys(InterState *istate, Expressions *arguments) | 2702 Expression *interpret_aaKeys(InterState *istate, Expressions *arguments) |
2284 { | 2703 { |
2285 //printf("interpret_aaKeys()\n"); | 2704 #if LOG |
2705 printf("interpret_aaKeys()\n"); | |
2706 #endif | |
2286 if (!arguments || arguments->dim != 2) | 2707 if (!arguments || arguments->dim != 2) |
2287 return NULL; | 2708 return NULL; |
2288 Expression *earg = (Expression *)arguments->data[0]; | 2709 Expression *earg = (Expression *)arguments->data[0]; |
2289 earg = earg->interpret(istate); | 2710 earg = earg->interpret(istate); |
2290 if (earg == EXP_CANT_INTERPRET) | 2711 if (earg == EXP_CANT_INTERPRET) |