Mercurial > projects > ddmd
comparison dmd/BinExp.d @ 179:cd48cb899aee
Updated to dmd2.040
author | korDen |
---|---|
date | Sun, 17 Oct 2010 20:56:07 +0400 |
parents | e3afd1303184 |
children | b0d41ff5e0df |
comparison
equal
deleted
inserted
replaced
178:e3afd1303184 | 179:cd48cb899aee |
---|---|
785 Expression e2 = this.e2.interpret(istate); | 785 Expression e2 = this.e2.interpret(istate); |
786 if (e2 is EXP_CANT_INTERPRET) | 786 if (e2 is EXP_CANT_INTERPRET) |
787 return e2; | 787 return e2; |
788 | 788 |
789 // Chase down rebinding of out and ref. | 789 // Chase down rebinding of out and ref. |
790 if (e1.op == TOKvar) | 790 if (e1.op == TOKvar) |
791 { | 791 { |
792 VarExp ve = cast(VarExp)e1; | 792 VarExp ve = cast(VarExp)e1; |
793 VarDeclaration v = ve.var.isVarDeclaration(); | 793 VarDeclaration v = ve.var.isVarDeclaration(); |
794 if (v && v.value && v.value.op == TOKvar) | 794 if (v && v.value && v.value.op == TOKvar) |
795 { | 795 { |
811 } | 811 } |
812 | 812 |
813 // To reduce code complexity of handling dotvar expressions, | 813 // To reduce code complexity of handling dotvar expressions, |
814 // extract the aggregate now. | 814 // extract the aggregate now. |
815 Expression aggregate; | 815 Expression aggregate; |
816 if (e1.op == TOKdotvar) { | 816 if (e1.op == TOKdotvar) |
817 { | |
817 aggregate = (cast(DotVarExp)e1).e1; | 818 aggregate = (cast(DotVarExp)e1).e1; |
818 // Get rid of 'this'. | 819 // Get rid of 'this'. |
819 if (aggregate.op == TOKthis && istate.localThis) | 820 if (aggregate.op == TOKthis && istate.localThis) |
820 aggregate = istate.localThis; | 821 aggregate = istate.localThis; |
821 } | 822 } |
823 if (e1.op == TOKthis && istate.localThis) | |
824 e1 = istate.localThis; | |
822 | 825 |
823 /* Assignment to variable of the form: | 826 /* Assignment to variable of the form: |
824 * v = e2 | 827 * v = e2 |
825 */ | 828 */ |
826 if (e1.op == TOKvar) | 829 if (e1.op == TOKvar) |
855 e2 = Cast(v.type, v.type, e2); | 858 e2 = Cast(v.type, v.type, e2); |
856 } | 859 } |
857 if (e2 is EXP_CANT_INTERPRET) | 860 if (e2 is EXP_CANT_INTERPRET) |
858 return e2; | 861 return e2; |
859 | 862 |
860 addVarToInterstate(istate, v); | 863 if (istate) |
864 addVarToInterstate(istate, v); | |
861 v.value = e2; | 865 v.value = e2; |
862 e = Cast(type, type, post ? ev : e2); | 866 e = Cast(type, type, post ? ev : e2); |
863 } | 867 } |
864 } | 868 } |
865 else if (e1.op == TOKdotvar && aggregate.op == TOKdotvar) | 869 else if (e1.op == TOKdotvar && aggregate.op == TOKdotvar) |
906 * values, it is valid here to use the default initializer. | 910 * values, it is valid here to use the default initializer. |
907 * No attempt is made to determine if someone actually relies | 911 * No attempt is made to determine if someone actually relies |
908 * on the void value - to do that we'd need a VoidExp. | 912 * on the void value - to do that we'd need a VoidExp. |
909 * That's probably a good enhancement idea. | 913 * That's probably a good enhancement idea. |
910 */ | 914 */ |
911 v.value = v.type.defaultInit(Loc(0)); | 915 v.value = v.type.defaultInitLiteral(Loc(0)); |
912 } | 916 } |
913 Expression vie = v.value; | 917 Expression vie = v.value; |
918 assert(vie !is EXP_CANT_INTERPRET); | |
914 if (vie.op == TOKvar) | 919 if (vie.op == TOKvar) |
915 { | 920 { |
916 Declaration d = (cast(VarExp)vie).var; | 921 Declaration d = (cast(VarExp)vie).var; |
917 vie = getVarExp(e1.loc, istate, d); | 922 vie = getVarExp(e1.loc, istate, d); |
918 } | 923 } |
919 if (vie.op != TOKstructliteral) | 924 if (vie.op != TOKstructliteral) |
920 return EXP_CANT_INTERPRET; | 925 { |
926 error("Cannot assign %s=%s in CTFE", v.toChars(), vie.toChars()); | |
927 return EXP_CANT_INTERPRET; | |
928 } | |
921 StructLiteralExp se = cast(StructLiteralExp)vie; | 929 StructLiteralExp se = cast(StructLiteralExp)vie; |
922 VarDeclaration vf = (cast(DotVarExp)e1).var.isVarDeclaration(); | 930 VarDeclaration vf = (cast(DotVarExp)e1).var.isVarDeclaration(); |
923 if (!vf) | 931 if (!vf) |
924 return EXP_CANT_INTERPRET; | 932 return EXP_CANT_INTERPRET; |
925 int fieldi = se.getFieldIndex(type, vf.offset); | 933 int fieldi = se.getFieldIndex(type, vf.offset); |
1309 return EXP_CANT_INTERPRET; | 1317 return EXP_CANT_INTERPRET; |
1310 } | 1318 } |
1311 if (v.value.op == TOKarrayliteral) | 1319 if (v.value.op == TOKarrayliteral) |
1312 dim = (cast(ArrayLiteralExp)v.value).elements.dim; | 1320 dim = (cast(ArrayLiteralExp)v.value).elements.dim; |
1313 else if (v.value.op ==TOKstring) | 1321 else if (v.value.op ==TOKstring) |
1314 { | 1322 dim = (cast(StringExp)v.value).len; |
1315 error("String slice assignment is not yet supported in CTFE"); | |
1316 return EXP_CANT_INTERPRET; | |
1317 } | |
1318 } | 1323 } |
1319 else | 1324 else |
1320 { | 1325 { |
1321 error("%s cannot be evaluated at compile time", toChars()); | 1326 error("%s cannot be evaluated at compile time", toChars()); |
1322 return EXP_CANT_INTERPRET; | 1327 return EXP_CANT_INTERPRET; |
1323 } | 1328 } |
1324 int upperbound = upper ? cast(int)upper.toInteger() : dim; | 1329 int upperbound = upper ? cast(int)upper.toInteger() : dim; |
1325 int lowerbound = lower ? cast(int)lower.toInteger() : 0; | 1330 int lowerbound = lower ? cast(int)lower.toInteger() : 0; |
1326 | 1331 |
1327 ArrayLiteralExp existing; | |
1328 if ((cast(int)lowerbound < 0) || (upperbound > dim)) | 1332 if ((cast(int)lowerbound < 0) || (upperbound > dim)) |
1329 { | 1333 { |
1330 error("Array bounds [0..%d] exceeded in slice [%d..%d]", dim, lowerbound, upperbound); | 1334 error("Array bounds [0..%d] exceeded in slice [%d..%d]", dim, lowerbound, upperbound); |
1331 return EXP_CANT_INTERPRET; | 1335 return EXP_CANT_INTERPRET; |
1332 } | 1336 } |
1333 if (upperbound-lowerbound != dim) | 1337 // Could either be slice assignment (v[] = e[]), |
1334 { | 1338 // or block assignment (v[] = val). |
1335 // Only modifying part of the array. Must create a new array literal. | 1339 // For the former, we check that the lengths match. |
1336 // If the existing array is uninitialized (this can only happen | 1340 bool isSliceAssignment = (e2.op == TOKarrayliteral) |
1337 // with static arrays), create it. | 1341 || (e2.op == TOKstring); |
1338 if (v.value && v.value.op == TOKarrayliteral) | 1342 size_t srclen = 0; |
1339 existing = cast(ArrayLiteralExp)v.value; | 1343 if (e2.op == TOKarrayliteral) |
1340 else | 1344 srclen = (cast(ArrayLiteralExp)e2).elements.dim; |
1341 { | 1345 else if (e2.op == TOKstring) |
1342 // this can only happen with static arrays | 1346 srclen = (cast(StringExp)e2).len; |
1343 existing = createBlockDuplicatedArrayLiteral(v.type, v.type.defaultInit(Loc(0)), dim); | 1347 if (isSliceAssignment && srclen != (upperbound - lowerbound)) |
1344 } | 1348 { |
1345 } | 1349 error("Array length mismatch assigning [0..%d] to [%d..%d]", srclen, lowerbound, upperbound); |
1346 | 1350 return e; |
1351 } | |
1347 if (e2.op == TOKarrayliteral) | 1352 if (e2.op == TOKarrayliteral) |
1348 { | 1353 { |
1349 // Static array assignment from literal | 1354 // Static array assignment from literal |
1350 ArrayLiteralExp ae = cast(ArrayLiteralExp)e2; | 1355 ArrayLiteralExp ae = cast(ArrayLiteralExp)e2; |
1351 if (ae.elements.dim != (upperbound - lowerbound)) | |
1352 { | |
1353 error("Array length mismatch assigning [0..%d] to [%d..%d]", ae.elements.dim, lowerbound, upperbound); | |
1354 return e; | |
1355 } | |
1356 if (upperbound - lowerbound == dim) | 1356 if (upperbound - lowerbound == dim) |
1357 v.value = ae; | 1357 v.value = ae; |
1358 else | 1358 else |
1359 { | 1359 { |
1360 ArrayLiteralExp existing; | |
1361 // Only modifying part of the array. Must create a new array literal. | |
1362 // If the existing array is uninitialized (this can only happen | |
1363 // with static arrays), create it. | |
1364 if (v.value && v.value.op == TOKarrayliteral) | |
1365 existing = cast(ArrayLiteralExp)v.value; | |
1366 else // this can only happen with static arrays | |
1367 existing = createBlockDuplicatedArrayLiteral(v.type, v.type.defaultInit(Loc(0)), dim); | |
1368 | |
1360 // value[] = value[0..lower] ~ ae ~ value[upper..$] | 1369 // value[] = value[0..lower] ~ ae ~ value[upper..$] |
1361 existing.elements = spliceElements(existing.elements, ae.elements, lowerbound); | 1370 existing.elements = spliceElements(existing.elements, ae.elements, lowerbound); |
1362 v.value = existing; | 1371 v.value = existing; |
1363 } | 1372 } |
1364 return e2; | 1373 return e2; |
1365 } | 1374 } |
1375 else if (e2.op == TOKstring) | |
1376 { | |
1377 StringExp se = cast(StringExp)e2; | |
1378 if (upperbound-lowerbound == dim) | |
1379 v.value = e2; | |
1380 else | |
1381 { | |
1382 if (!v.value) | |
1383 v.value = createBlockDuplicatedStringLiteral(se.type, cast(dchar)se.type.defaultInit(Loc(0)).toInteger(), dim, se.sz); | |
1384 if (v.value.op==TOKstring) | |
1385 v.value = spliceStringExp(cast(StringExp)v.value, se, lowerbound); | |
1386 else | |
1387 error("String slice assignment is not yet supported in CTFE"); | |
1388 } | |
1389 return e2; | |
1390 } | |
1366 else if (t.nextOf().ty == e2.type.ty) | 1391 else if (t.nextOf().ty == e2.type.ty) |
1367 { | 1392 { |
1368 // Static array block assignment | 1393 // Static array block assignment |
1369 if (upperbound-lowerbound ==dim) | 1394 if (upperbound - lowerbound == dim) |
1370 v.value = createBlockDuplicatedArrayLiteral(v.type, e2, dim); | 1395 v.value = createBlockDuplicatedArrayLiteral(v.type, e2, dim); |
1371 else | 1396 else |
1372 { | 1397 { |
1398 ArrayLiteralExp existing; | |
1399 // Only modifying part of the array. Must create a new array literal. | |
1400 // If the existing array is uninitialized (this can only happen | |
1401 // with static arrays), create it. | |
1402 if (v.value && v.value.op == TOKarrayliteral) | |
1403 existing = cast(ArrayLiteralExp)v.value; | |
1404 else // this can only happen with static arrays | |
1405 existing = createBlockDuplicatedArrayLiteral(v.type, v.type.defaultInit(Loc(0)), dim); | |
1373 // value[] = value[0..lower] ~ ae ~ value[upper..$] | 1406 // value[] = value[0..lower] ~ ae ~ value[upper..$] |
1374 existing.elements = spliceElements(existing.elements, createBlockDuplicatedArrayLiteral(v.type, e2, upperbound-lowerbound).elements, lowerbound); | 1407 existing.elements = spliceElements(existing.elements, |
1408 createBlockDuplicatedArrayLiteral(v.type, e2, upperbound-lowerbound).elements, | |
1409 lowerbound); | |
1375 v.value = existing; | 1410 v.value = existing; |
1376 } | 1411 } |
1377 return e2; | 1412 |
1378 } | |
1379 else if (e2.op == TOKstring) | |
1380 { | |
1381 StringExp se = cast(StringExp)e2; | |
1382 // This is problematic. char[8] should be storing | |
1383 // values as a string literal, not | |
1384 // as an array literal. Then, for static arrays, we | |
1385 // could do modifications | |
1386 // in-place, with a dramatic memory and speed improvement. | |
1387 error("String slice assignment is not yet supported in CTFE"); | |
1388 return e2; | 1413 return e2; |
1389 } | 1414 } |
1390 else | 1415 else |
1391 { | 1416 { |
1392 error("Slice operation %s cannot be evaluated at compile time", toChars()); | 1417 error("Slice operation %s cannot be evaluated at compile time", toChars()); |