comparison dmd/BinExp.d @ 174:af724d3510d7

lot os toCBuffer methods implemented moved shared Type.* stuff into Global
author korDen
date Sun, 10 Oct 2010 03:47:23 +0400
parents 14feb7ae01a6
children 94b6033c07f3
comparison
equal deleted inserted replaced
173:d237b38b5858 174:af724d3510d7
275 else if (i1) 275 else if (i1)
276 { 276 {
277 goto Lt1; 277 goto Lt1;
278 } 278 }
279 else if (t1.ty == TY.Tclass && t2.ty == TY.Tclass) 279 else if (t1.ty == TY.Tclass && t2.ty == TY.Tclass)
280 { 280 {
281 TypeClass tc1 = cast(TypeClass)t1; 281 TypeClass tc1 = cast(TypeClass)t1;
282 TypeClass tc2 = cast(TypeClass)t2; 282 TypeClass tc2 = cast(TypeClass)t2;
283 283
284 /* Pick 'tightest' type 284 /* Pick 'tightest' type
285 */ 285 */
397 { 397 {
398 super(loc, op, size); 398 super(loc, op, size);
399 this.e1 = e1; 399 this.e1 = e1;
400 this.e2 = e2; 400 this.e2 = e2;
401 } 401 }
402 402
403 override Expression syntaxCopy() 403 override Expression syntaxCopy()
404 { 404 {
405 BinExp e = cast(BinExp)copy(); 405 BinExp e = cast(BinExp)copy();
406 e.type = null; 406 e.type = null;
407 e.e1 = e.e1.syntaxCopy(); 407 e.e1 = e.e1.syntaxCopy();
427 error("%s has no value", e2.toChars()); 427 error("%s has no value", e2.toChars());
428 e2.type = Type.terror; 428 e2.type = Type.terror;
429 } 429 }
430 return this; 430 return this;
431 } 431 }
432 432
433 Expression semanticp(Scope sc) 433 Expression semanticp(Scope sc)
434 { 434 {
435 BinExp.semantic(sc); 435 BinExp.semantic(sc);
436 436
437 e1 = resolveProperties(sc, e1); 437 e1 = resolveProperties(sc, e1);
438 e2 = resolveProperties(sc, e2); 438 e2 = resolveProperties(sc, e2);
439 return this; 439 return this;
440 } 440 }
441 441
442 /*************************** 442 /***************************
443 * Common semantic routine for some xxxAssignExp's. 443 * Common semantic routine for some xxxAssignExp's.
444 */ 444 */
445 Expression commonSemanticAssign(Scope sc) 445 Expression commonSemanticAssign(Scope sc)
446 { 446 {
459 { 459 {
460 e = ArrayLengthExp.rewriteOpAssign(this); 460 e = ArrayLengthExp.rewriteOpAssign(this);
461 e = e.semantic(sc); 461 e = e.semantic(sc);
462 return e; 462 return e;
463 } 463 }
464 464
465 if (e1.op == TOKslice) 465 if (e1.op == TOKslice)
466 { 466 {
467 // T[] op= ... 467 // T[] op= ...
468 typeCombine(sc); 468 typeCombine(sc);
469 type = e1.type; 469 type = e1.type;
470 return arrayOp(sc); 470 return arrayOp(sc);
471 } 471 }
506 { 506 {
507 e = ArrayLengthExp.rewriteOpAssign(this); 507 e = ArrayLengthExp.rewriteOpAssign(this);
508 e = e.semantic(sc); 508 e = e.semantic(sc);
509 return e; 509 return e;
510 } 510 }
511 511
512 if (e1.op == TOK.TOKslice) 512 if (e1.op == TOK.TOKslice)
513 { // T[] op= ... 513 { // T[] op= ...
514 typeCombine(sc); 514 typeCombine(sc);
515 type = e1.type; 515 type = e1.type;
516 return arrayOp(sc); 516 return arrayOp(sc);
529 e2.checkIntegral(); 529 e2.checkIntegral();
530 } 530 }
531 531
532 return this; 532 return this;
533 } 533 }
534 534
535 override bool checkSideEffect(int flag) 535 override bool checkSideEffect(int flag)
536 { 536 {
537 switch (op) { 537 switch (op) {
538 case TOK.TOKplusplus: 538 case TOK.TOKplusplus:
539 case TOK.TOKminusminus: 539 case TOK.TOKminusminus:
559 559
560 default: 560 default:
561 return Expression.checkSideEffect(flag); 561 return Expression.checkSideEffect(flag);
562 } 562 }
563 } 563 }
564 564
565 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) 565 override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
566 { 566 {
567 expToCBuffer(buf, hgs, e1, precedence[op]); 567 expToCBuffer(buf, hgs, e1, precedence[op]);
568 buf.writeByte(' '); 568 buf.writeByte(' ');
569 buf.writestring(Token.toChars(op)); 569 buf.writestring(Token.toChars(op));
579 ulong stride; 579 ulong stride;
580 Type t1b = e1.type.toBasetype(); 580 Type t1b = e1.type.toBasetype();
581 Type t2b = e2.type.toBasetype(); 581 Type t2b = e2.type.toBasetype();
582 582
583 if (t1b.ty == Tpointer && t2b.isintegral()) 583 if (t1b.ty == Tpointer && t2b.isintegral())
584 { 584 {
585 // Need to adjust operator by the stride 585 // Need to adjust operator by the stride
586 // Replace (ptr + int) with (ptr + (int * stride)) 586 // Replace (ptr + int) with (ptr + (int * stride))
587 Type t = Type.tptrdiff_t; 587 Type t = Type.tptrdiff_t;
588 588
589 stride = t1b.nextOf().size(loc); 589 stride = t1b.nextOf().size(loc);
592 e2 = new MulExp(loc, e2, new IntegerExp(Loc(0), stride, t)); 592 e2 = new MulExp(loc, e2, new IntegerExp(Loc(0), stride, t));
593 e2.type = t; 593 e2.type = t;
594 type = e1.type; 594 type = e1.type;
595 } 595 }
596 else if (t2b.ty == Tpointer && t1b.isintegral()) 596 else if (t2b.ty == Tpointer && t1b.isintegral())
597 { 597 {
598 // Need to adjust operator by the stride 598 // Need to adjust operator by the stride
599 // Replace (int + ptr) with (ptr + (int * stride)) 599 // Replace (int + ptr) with (ptr + (int * stride))
600 Type t = Type.tptrdiff_t; 600 Type t = Type.tptrdiff_t;
601 Expression e; 601 Expression e;
602 602
611 e1 = e2; 611 e1 = e2;
612 e2 = e; 612 e2 = e;
613 } 613 }
614 return this; 614 return this;
615 } 615 }
616 616
617 /************************************ 617 /************************************
618 * Bring leaves to common type. 618 * Bring leaves to common type.
619 */ 619 */
620 Expression typeCombine(Scope sc) 620 Expression typeCombine(Scope sc)
621 { 621 {
661 { 661 {
662 long i2 = e2.toInteger(); 662 long i2 = e2.toInteger();
663 ulong sz = e1.type.size() * 8; 663 ulong sz = e1.type.size() * 8;
664 664
665 if (i2 < 0 || i2 > sz) 665 if (i2 < 0 || i2 > sz)
666 { 666 {
667 error("shift assign by %jd is outside the range 0..%zu", i2, sz); 667 error("shift assign by %jd is outside the range 0..%zu", i2, sz);
668 e2 = new IntegerExp(0); 668 e2 = new IntegerExp(0);
669 } 669 }
670 } 670 }
671 } 671 }
675 675
676 bool isunsigned() 676 bool isunsigned()
677 { 677 {
678 return e1.type.isunsigned() || e2.type.isunsigned(); 678 return e1.type.isunsigned() || e2.type.isunsigned();
679 } 679 }
680 680
681 void incompatibleTypes() 681 void incompatibleTypes()
682 { 682 {
683 error("incompatible types for ((%s) %s (%s)): '%s' and '%s'", 683 error("incompatible types for ((%s) %s (%s)): '%s' and '%s'",
684 e1.toChars(), Token.toChars(op), e2.toChars(), 684 e1.toChars(), Token.toChars(op), e2.toChars(),
685 e1.type.toChars(), e2.type.toChars()); 685 e1.type.toChars(), e2.type.toChars());
759 return e; 759 return e;
760 760
761 Lcant: 761 Lcant:
762 return EXP_CANT_INTERPRET; 762 return EXP_CANT_INTERPRET;
763 } 763 }
764 764
765 Expression interpretAssignCommon(InterState istate, Expression function(Type, Expression, Expression) fp, int post = 0) 765 Expression interpretAssignCommon(InterState istate, Expression function(Type, Expression, Expression) fp, int post = 0)
766 { 766 {
767 version (LOG) 767 version (LOG)
768 { 768 {
769 writef("BinExp.interpretAssignCommon() %.*s\n", toChars()); 769 writef("BinExp.interpretAssignCommon() %.*s\n", toChars());
772 Expression e1 = this.e1; 772 Expression e1 = this.e1;
773 773
774 if (fp) 774 if (fp)
775 { 775 {
776 if (e1.op == TOKcast) 776 if (e1.op == TOKcast)
777 { 777 {
778 CastExp ce = cast(CastExp)e1; 778 CastExp ce = cast(CastExp)e1;
779 e1 = ce.e1; 779 e1 = ce.e1;
780 } 780 }
781 } 781 }
782 if (e1 is EXP_CANT_INTERPRET) 782 if (e1 is EXP_CANT_INTERPRET)
783 return e1; 783 return e1;
784 Expression e2 = this.e2.interpret(istate); 784 Expression e2 = this.e2.interpret(istate);
785 if (e2 is EXP_CANT_INTERPRET) 785 if (e2 is EXP_CANT_INTERPRET)
786 return e2; 786 return e2;
787 787
788 // Chase down rebinding of out and ref. 788 // Chase down rebinding of out and ref.
789 if (e1.op == TOKvar) 789 if (e1.op == TOKvar)
790 { 790 {
791 VarExp ve = cast(VarExp)e1; 791 VarExp ve = cast(VarExp)e1;
792 VarDeclaration v = ve.var.isVarDeclaration(); 792 VarDeclaration v = ve.var.isVarDeclaration();
793 if (v && v.value && v.value.op == TOKvar) 793 if (v && v.value && v.value.op == TOKvar)
794 { 794 {
795 VarExp ve2 = cast(VarExp)v.value; 795 VarExp ve2 = cast(VarExp)v.value;
796 if (ve2.var.isSymbolDeclaration()) 796 if (ve2.var.isSymbolDeclaration())
797 { 797 {
798 // This can happen if v is a struct initialized to 798 // This can happen if v is a struct initialized to
799 // 0 using an __initZ SymbolDeclaration from 799 // 0 using an __initZ SymbolDeclaration from
800 // TypeStruct.defaultInit() 800 // TypeStruct.defaultInit()
801 } 801 }
802 else 802 else
803 e1 = v.value; 803 e1 = v.value;
804 } 804 }
805 else if (v && v.value && (v.value.op==TOKindex || v.value.op == TOKdotvar)) 805 else if (v && v.value && (v.value.op==TOKindex || v.value.op == TOKdotvar))
806 { 806 {
807 // It is no longer a TOKvar, eg when a[4] is passed by ref. 807 // It is no longer a TOKvar, eg when a[4] is passed by ref.
808 e1 = v.value; 808 e1 = v.value;
809 } 809 }
810 } 810 }
811 811
812 // To reduce code complexity of handling dotvar expressions, 812 // To reduce code complexity of handling dotvar expressions,
813 // extract the aggregate now. 813 // extract the aggregate now.
814 Expression aggregate; 814 Expression aggregate;
815 if (e1.op == TOKdotvar) { 815 if (e1.op == TOKdotvar) {
816 aggregate = (cast(DotVarExp)e1).e1; 816 aggregate = (cast(DotVarExp)e1).e1;
817 // Get rid of 'this'. 817 // Get rid of 'this'.
818 if (aggregate.op == TOKthis && istate.localThis) 818 if (aggregate.op == TOKthis && istate.localThis)
819 aggregate = istate.localThis; 819 aggregate = istate.localThis;
820 } 820 }
821 821
822 /* Assignment to variable of the form: 822 /* Assignment to variable of the form:
823 * v = e2 823 * v = e2
824 */ 824 */
825 if (e1.op == TOKvar) 825 if (e1.op == TOKvar)
826 { 826 {
827 VarExp ve = cast(VarExp)e1; 827 VarExp ve = cast(VarExp)e1;
828 VarDeclaration v = ve.var.isVarDeclaration(); 828 VarDeclaration v = ve.var.isVarDeclaration();
829 assert(v); 829 assert(v);
830 if (v && !v.isCTFE()) 830 if (v && !v.isCTFE())
831 { 831 {
832 // Can't modify global or static data 832 // Can't modify global or static data
833 error("%s cannot be modified at compile time", v.toChars()); 833 error("%s cannot be modified at compile time", v.toChars());
834 return EXP_CANT_INTERPRET; 834 return EXP_CANT_INTERPRET;
835 } 835 }
836 if (v && v.isCTFE()) 836 if (v && v.isCTFE())
837 { 837 {
838 Expression ev = v.value; 838 Expression ev = v.value;
839 if (fp && !ev) 839 if (fp && !ev)
840 { 840 {
841 error("variable %s is used before initialization", v.toChars()); 841 error("variable %s is used before initialization", v.toChars());
842 return e; 842 return e;
843 } 843 }
844 if (fp) 844 if (fp)
845 e2 = (*fp)(v.type, ev, e2); 845 e2 = (*fp)(v.type, ev, e2);
846 else 846 else
847 { 847 {
848 /* Look for special case of struct being initialized with 0. 848 /* Look for special case of struct being initialized with 0.
849 */ 849 */
850 if (v.type.toBasetype().ty == Tstruct && e2.op == TOKint64) 850 if (v.type.toBasetype().ty == Tstruct && e2.op == TOKint64)
851 { 851 {
852 e2 = v.type.defaultInitLiteral(Loc(0)); 852 e2 = v.type.defaultInitLiteral(Loc(0));
860 v.value = e2; 860 v.value = e2;
861 e = Cast(type, type, post ? ev : e2); 861 e = Cast(type, type, post ? ev : e2);
862 } 862 }
863 } 863 }
864 else if (e1.op == TOKdotvar && aggregate.op == TOKdotvar) 864 else if (e1.op == TOKdotvar && aggregate.op == TOKdotvar)
865 { 865 {
866 // eg v.u.var = e2, v[3].u.var = e2, etc. 866 // eg v.u.var = e2, v[3].u.var = e2, etc.
867 error("Nested struct assignment %s is not yet supported in CTFE", toChars()); 867 error("Nested struct assignment %s is not yet supported in CTFE", toChars());
868 } 868 }
869 /* Assignment to struct member of the form: 869 /* Assignment to struct member of the form:
870 * v.var = e2 870 * v.var = e2
871 */ 871 */
872 else if (e1.op == TOKdotvar && aggregate.op == TOKvar) 872 else if (e1.op == TOKdotvar && aggregate.op == TOKvar)
873 { 873 {
874 VarDeclaration v = (cast(VarExp)aggregate).var.isVarDeclaration(); 874 VarDeclaration v = (cast(VarExp)aggregate).var.isVarDeclaration();
875 875
876 if (!v.isCTFE()) 876 if (!v.isCTFE())
877 { 877 {
878 // Can't modify global or static data 878 // Can't modify global or static data
879 error("%s cannot be modified at compile time", v.toChars()); 879 error("%s cannot be modified at compile time", v.toChars());
880 return EXP_CANT_INTERPRET; 880 return EXP_CANT_INTERPRET;
881 } else { 881 } else {
882 // Chase down rebinding of out and ref 882 // Chase down rebinding of out and ref
883 if (v.value && v.value.op == TOKvar) 883 if (v.value && v.value.op == TOKvar)
884 { 884 {
885 VarExp ve2 = cast(VarExp)v.value; 885 VarExp ve2 = cast(VarExp)v.value;
886 if (ve2.var.isSymbolDeclaration()) 886 if (ve2.var.isSymbolDeclaration())
887 { 887 {
888 // This can happen if v is a struct initialized to 888 // This can happen if v is a struct initialized to
889 // 0 using an __initZ SymbolDeclaration from 889 // 0 using an __initZ SymbolDeclaration from
890 // TypeStruct.defaultInit() 890 // TypeStruct.defaultInit()
891 } 891 }
892 else 892 else
893 v = ve2.var.isVarDeclaration(); 893 v = ve2.var.isVarDeclaration();
894 assert(v); 894 assert(v);
895 } 895 }
896 } 896 }
897 if (fp && !v.value) 897 if (fp && !v.value)
898 { 898 {
899 error("variable %s is used before initialization", v.toChars()); 899 error("variable %s is used before initialization", v.toChars());
900 return e; 900 return e;
901 } 901 }
902 if (v.value is null && v.init.isVoidInitializer()) 902 if (v.value is null && v.init.isVoidInitializer())
903 { 903 {
904 /* Since a void initializer initializes to undefined 904 /* Since a void initializer initializes to undefined
905 * values, it is valid here to use the default initializer. 905 * values, it is valid here to use the default initializer.
906 * No attempt is made to determine if someone actually relies 906 * No attempt is made to determine if someone actually relies
907 * on the void value - to do that we'd need a VoidExp. 907 * on the void value - to do that we'd need a VoidExp.
908 * That's probably a good enhancement idea. 908 * That's probably a good enhancement idea.
944 } 944 }
945 /* Assignment to struct member of the form: 945 /* Assignment to struct member of the form:
946 * *(symoffexp) = e2 946 * *(symoffexp) = e2
947 */ 947 */
948 else if (e1.op == TOKstar && (cast(PtrExp)e1).e1.op == TOKsymoff) 948 else if (e1.op == TOKstar && (cast(PtrExp)e1).e1.op == TOKsymoff)
949 { 949 {
950 SymOffExp soe = cast(SymOffExp)(cast(PtrExp)e1).e1; 950 SymOffExp soe = cast(SymOffExp)(cast(PtrExp)e1).e1;
951 VarDeclaration v = soe.var.isVarDeclaration(); 951 VarDeclaration v = soe.var.isVarDeclaration();
952 952
953 if (!v.isCTFE()) 953 if (!v.isCTFE())
954 { 954 {
955 error("%s cannot be modified at compile time", v.toChars()); 955 error("%s cannot be modified at compile time", v.toChars());
956 return EXP_CANT_INTERPRET; 956 return EXP_CANT_INTERPRET;
957 } 957 }
958 if (fp && !v.value) 958 if (fp && !v.value)
959 { 959 {
960 error("variable %s is used before initialization", v.toChars()); 960 error("variable %s is used before initialization", v.toChars());
961 return e; 961 return e;
962 } 962 }
963 Expression vie = v.value; 963 Expression vie = v.value;
964 if (vie.op == TOKvar) 964 if (vie.op == TOKvar)
992 } 992 }
993 /* Assignment to array element of the form: 993 /* Assignment to array element of the form:
994 * a[i] = e2 994 * a[i] = e2
995 */ 995 */
996 else if (e1.op == TOKindex && (cast(IndexExp)e1).e1.op == TOKvar) 996 else if (e1.op == TOKindex && (cast(IndexExp)e1).e1.op == TOKvar)
997 { 997 {
998 IndexExp ie = cast(IndexExp)e1; 998 IndexExp ie = cast(IndexExp)e1;
999 VarExp ve = cast(VarExp)ie.e1; 999 VarExp ve = cast(VarExp)ie.e1;
1000 VarDeclaration v = ve.var.isVarDeclaration(); 1000 VarDeclaration v = ve.var.isVarDeclaration();
1001 if (!v || !v.isCTFE()) 1001 if (!v || !v.isCTFE())
1002 { 1002 {
1005 } 1005 }
1006 if (v.value && v.value.op == TOKvar) 1006 if (v.value && v.value.op == TOKvar)
1007 { 1007 {
1008 VarExp ve2 = cast(VarExp)v.value; 1008 VarExp ve2 = cast(VarExp)v.value;
1009 if (ve2.var.isSymbolDeclaration()) 1009 if (ve2.var.isSymbolDeclaration())
1010 { 1010 {
1011 // This can happen if v is a struct initialized to 1011 // This can happen if v is a struct initialized to
1012 // 0 using an __initZ SymbolDeclaration from 1012 // 0 using an __initZ SymbolDeclaration from
1013 // TypeStruct.defaultInit() 1013 // TypeStruct.defaultInit()
1014 } 1014 }
1015 else 1015 else
1017 assert(v); 1017 assert(v);
1018 } 1018 }
1019 if (!v.value) 1019 if (!v.value)
1020 { 1020 {
1021 if (fp) 1021 if (fp)
1022 { 1022 {
1023 error("variable %s is used before initialization", v.toChars()); 1023 error("variable %s is used before initialization", v.toChars());
1024 return e; 1024 return e;
1025 } 1025 }
1026 1026
1027 Type t = v.type.toBasetype(); 1027 Type t = v.type.toBasetype();
1081 e2 = (*fp)(type, ev, e2); 1081 e2 = (*fp)(type, ev, e2);
1082 else 1082 else
1083 e2 = Cast(type, type, e2); 1083 e2 = Cast(type, type, e2);
1084 if (e2 is EXP_CANT_INTERPRET) 1084 if (e2 is EXP_CANT_INTERPRET)
1085 return e2; 1085 return e2;
1086 1086
1087 addVarToInterstate(istate, v); 1087 addVarToInterstate(istate, v);
1088 if (ae) 1088 if (ae)
1089 { 1089 {
1090 /* Create new array literal reflecting updated elem 1090 /* Create new array literal reflecting updated elem
1091 */ 1091 */
1101 Expressions keysx = aae.keys; 1101 Expressions keysx = aae.keys;
1102 Expressions valuesx = new Expressions(); 1102 Expressions valuesx = new Expressions();
1103 valuesx.setDim(aae.values.dim); 1103 valuesx.setDim(aae.values.dim);
1104 int updated = 0; 1104 int updated = 0;
1105 for (size_t j = valuesx.dim; j; ) 1105 for (size_t j = valuesx.dim; j; )
1106 { 1106 {
1107 j--; 1107 j--;
1108 Expression ekey = aae.keys[j]; 1108 Expression ekey = aae.keys[j];
1109 Expression ex = Equal(TOKequal, Type.tbool, ekey, index); 1109 Expression ex = Equal(TOKequal, Type.tbool, ekey, index);
1110 if (ex is EXP_CANT_INTERPRET) 1110 if (ex is EXP_CANT_INTERPRET)
1111 return EXP_CANT_INTERPRET; 1111 return EXP_CANT_INTERPRET;
1112 if (ex.isBool(true)) 1112 if (ex.isBool(true))
1113 { 1113 {
1114 valuesx[j] = e2; 1114 valuesx[j] = e2;
1115 updated = 1; 1115 updated = 1;
1116 } 1116 }
1117 else 1117 else
1118 valuesx[j] = aae.values[j]; 1118 valuesx[j] = aae.values[j];
1119 } 1119 }
1120 if (!updated) 1120 if (!updated)
1121 { 1121 {
1122 // Append index/e2 to keysx[]/valuesx[] 1122 // Append index/e2 to keysx[]/valuesx[]
1123 valuesx.push(e2); 1123 valuesx.push(e2);
1124 keysx = keysx.copy(); 1124 keysx = keysx.copy();
1125 keysx.push(index); 1125 keysx.push(index);
1126 } 1126 }
1154 else 1154 else
1155 assert(0); 1155 assert(0);
1156 1156
1157 e = Cast(type, type, post ? ev : e2); 1157 e = Cast(type, type, post ? ev : e2);
1158 } 1158 }
1159 1159
1160 /* Assignment to struct element in array, of the form: 1160 /* Assignment to struct element in array, of the form:
1161 * a[i].var = e2 1161 * a[i].var = e2
1162 */ 1162 */
1163 else if (e1.op == TOKdotvar && aggregate.op == TOKindex && 1163 else if (e1.op == TOKdotvar && aggregate.op == TOKindex &&
1164 (cast(IndexExp)aggregate).e1.op == TOKvar) 1164 (cast(IndexExp)aggregate).e1.op == TOKvar)
1212 return EXP_CANT_INTERPRET; 1212 return EXP_CANT_INTERPRET;
1213 1213
1214 int elemi = cast(int)index.toInteger(); 1214 int elemi = cast(int)index.toInteger();
1215 if (elemi >= ae.elements.dim) 1215 if (elemi >= ae.elements.dim)
1216 { 1216 {
1217 error("array index %d is out of bounds %s[0..%d]", elemi, 1217 error("array index %d is out of bounds %s[0..%d]", elemi,
1218 v.toChars(), ae.elements.dim); 1218 v.toChars(), ae.elements.dim);
1219 return EXP_CANT_INTERPRET; 1219 return EXP_CANT_INTERPRET;
1220 } 1220 }
1221 // Get old element 1221 // Get old element
1222 auto vie = ae.elements[elemi]; 1222 auto vie = ae.elements[elemi];
1230 return EXP_CANT_INTERPRET; 1230 return EXP_CANT_INTERPRET;
1231 1231
1232 int fieldi = se.getFieldIndex(type, vf.offset); 1232 int fieldi = se.getFieldIndex(type, vf.offset);
1233 if (fieldi == -1) 1233 if (fieldi == -1)
1234 return EXP_CANT_INTERPRET; 1234 return EXP_CANT_INTERPRET;
1235 1235
1236 Expression ev = se.getField(type, vf.offset); 1236 Expression ev = se.getField(type, vf.offset);
1237 if (fp) 1237 if (fp)
1238 e2 = (*fp)(type, ev, e2); 1238 e2 = (*fp)(type, ev, e2);
1239 else 1239 else
1240 e2 = Cast(type, type, e2); 1240 e2 = Cast(type, type, e2);
1265 // Chase down rebinding of out and ref 1265 // Chase down rebinding of out and ref
1266 if (v.value && v.value.op == TOKvar) 1266 if (v.value && v.value.op == TOKvar)
1267 { 1267 {
1268 VarExp ve2 = cast(VarExp)v.value; 1268 VarExp ve2 = cast(VarExp)v.value;
1269 if (ve2.var.isSymbolDeclaration()) 1269 if (ve2.var.isSymbolDeclaration())
1270 { 1270 {
1271 // This can happen if v is a struct initialized to 1271 // This can happen if v is a struct initialized to
1272 // 0 using an __initZ SymbolDeclaration from 1272 // 0 using an __initZ SymbolDeclaration from
1273 // TypeStruct.defaultInit() 1273 // TypeStruct.defaultInit()
1274 } 1274 }
1275 else 1275 else
1296 if (lower is EXP_CANT_INTERPRET) 1296 if (lower is EXP_CANT_INTERPRET)
1297 return EXP_CANT_INTERPRET; 1297 return EXP_CANT_INTERPRET;
1298 } 1298 }
1299 Type t = v.type.toBasetype(); 1299 Type t = v.type.toBasetype();
1300 size_t dim; 1300 size_t dim;
1301 if (t.ty == Tsarray) 1301 if (t.ty == Tsarray)
1302 dim = cast(size_t)(cast(TypeSArray)t).dim.toInteger(); 1302 dim = cast(size_t)(cast(TypeSArray)t).dim.toInteger();
1303 else if (t.ty == Tarray) 1303 else if (t.ty == Tarray)
1304 { 1304 {
1305 if (!v.value || v.value.op == TOKnull) 1305 if (!v.value || v.value.op == TOKnull)
1306 { 1306 {
1344 } 1344 }
1345 1345
1346 if (e2.op == TOKarrayliteral) 1346 if (e2.op == TOKarrayliteral)
1347 { 1347 {
1348 // Static array assignment from literal 1348 // Static array assignment from literal
1349 ArrayLiteralExp ae = cast(ArrayLiteralExp)e2; 1349 ArrayLiteralExp ae = cast(ArrayLiteralExp)e2;
1350 if (ae.elements.dim != (upperbound - lowerbound)) 1350 if (ae.elements.dim != (upperbound - lowerbound))
1351 { 1351 {
1352 error("Array length mismatch assigning [0..%d] to [%d..%d]", ae.elements.dim, lowerbound, upperbound); 1352 error("Array length mismatch assigning [0..%d] to [%d..%d]", ae.elements.dim, lowerbound, upperbound);
1353 return e; 1353 return e;
1354 } 1354 }
1370 else 1370 else
1371 { 1371 {
1372 // value[] = value[0..lower] ~ ae ~ value[upper..$] 1372 // value[] = value[0..lower] ~ ae ~ value[upper..$]
1373 existing.elements = spliceElements(existing.elements, createBlockDuplicatedArrayLiteral(v.type, e2, upperbound-lowerbound).elements, lowerbound); 1373 existing.elements = spliceElements(existing.elements, createBlockDuplicatedArrayLiteral(v.type, e2, upperbound-lowerbound).elements, lowerbound);
1374 v.value = existing; 1374 v.value = existing;
1375 } 1375 }
1376 return e2; 1376 return e2;
1377 } 1377 }
1378 else if (e2.op == TOKstring) 1378 else if (e2.op == TOKstring)
1379 { 1379 {
1380 StringExp se = cast(StringExp)e2; 1380 StringExp se = cast(StringExp)e2;
1405 version(DMDV2) 1405 version(DMDV2)
1406 override bool canThrow() 1406 override bool canThrow()
1407 { 1407 {
1408 return e1.canThrow() || e2.canThrow(); 1408 return e1.canThrow() || e2.canThrow();
1409 } 1409 }
1410 1410
1411 // generate an error if this is a nonsensical *=,/=, or %=, eg real *= imaginary 1411 // generate an error if this is a nonsensical *=,/=, or %=, eg real *= imaginary
1412 void checkComplexMulAssign() 1412 void checkComplexMulAssign()
1413 { 1413 {
1414 // Any multiplication by an imaginary or complex number yields a complex result. 1414 // Any multiplication by an imaginary or complex number yields a complex result.
1415 // r *= c, i*=c, r*=i, i*=i are all forbidden operations. 1415 // r *= c, i*=c, r*=i, i*=i are all forbidden operations.
1416 string opstr = Token.toChars(op); 1416 string opstr = Token.toChars(op);
1417 if ( e1.type.isreal() && e2.type.iscomplex()) 1417 if ( e1.type.isreal() && e2.type.iscomplex())
1418 { 1418 {
1419 error("%s %s %s is undefined. Did you mean %s %s %s.re ?", 1419 error("%s %s %s is undefined. Did you mean %s %s %s.re ?",
1420 e1.type.toChars(), opstr, e2.type.toChars(), 1420 e1.type.toChars(), opstr, e2.type.toChars(),
1421 e1.type.toChars(), opstr, e2.type.toChars()); 1421 e1.type.toChars(), opstr, e2.type.toChars());
1422 } 1422 }
1423 else if (e1.type.isimaginary() && e2.type.iscomplex()) 1423 else if (e1.type.isimaginary() && e2.type.iscomplex())
1424 { 1424 {
1425 error("%s %s %s is undefined. Did you mean %s %s %s.im ?", 1425 error("%s %s %s is undefined. Did you mean %s %s %s.im ?",
1437 void checkComplexAddAssign() 1437 void checkComplexAddAssign()
1438 { 1438 {
1439 // Addition or subtraction of a real and an imaginary is a complex result. 1439 // Addition or subtraction of a real and an imaginary is a complex result.
1440 // Thus, r+=i, r+=c, i+=r, i+=c are all forbidden operations. 1440 // Thus, r+=i, r+=c, i+=r, i+=c are all forbidden operations.
1441 if ( (e1.type.isreal() && (e2.type.isimaginary() || e2.type.iscomplex())) || 1441 if ( (e1.type.isreal() && (e2.type.isimaginary() || e2.type.iscomplex())) ||
1442 (e1.type.isimaginary() && (e2.type.isreal() || e2.type.iscomplex())) 1442 (e1.type.isimaginary() && (e2.type.isreal() || e2.type.iscomplex()))
1443 ) 1443 )
1444 { 1444 {
1445 error("%s %s %s is undefined (result is complex)", 1445 error("%s %s %s is undefined (result is complex)",
1446 e1.type.toChars(), Token.toChars(op), e2.type.toChars()); 1446 e1.type.toChars(), Token.toChars(op), e2.type.toChars());
1447 } 1447 }
1452 * Construct the array operation expression. 1452 * Construct the array operation expression.
1453 */ 1453 */
1454 Expression arrayOp(Scope sc) 1454 Expression arrayOp(Scope sc)
1455 { 1455 {
1456 //printf("BinExp.arrayOp() %s\n", toChars()); 1456 //printf("BinExp.arrayOp() %s\n", toChars());
1457 1457
1458 if (type.toBasetype().nextOf().toBasetype().ty == Tvoid) 1458 if (type.toBasetype().nextOf().toBasetype().ty == Tvoid)
1459 { 1459 {
1460 error("Cannot perform array operations on void[] arrays"); 1460 error("Cannot perform array operations on void[] arrays");
1461 return new ErrorExp(); 1461 return new ErrorExp();
1462 } 1462 }
1463 1463
1464 auto arguments = new Expressions(); 1464 auto arguments = new Expressions();
1465 1465
1466 /* The expression to generate an array operation for is mangled 1466 /* The expression to generate an array operation for is mangled
1467 * into a name to use as the array operation function name. 1467 * into a name to use as the array operation function name.
1468 * Mangle in the operands and operators in RPN order, and type. 1468 * Mangle in the operands and operators in RPN order, and type.
1738 1738
1739 override int inlineCost(InlineCostState* ics) 1739 override int inlineCost(InlineCostState* ics)
1740 { 1740 {
1741 return 1 + e1.inlineCost(ics) + e2.inlineCost(ics); 1741 return 1 + e1.inlineCost(ics) + e2.inlineCost(ics);
1742 } 1742 }
1743 1743
1744 override Expression doInline(InlineDoState ids) 1744 override Expression doInline(InlineDoState ids)
1745 { 1745 {
1746 BinExp be = cast(BinExp)copy(); 1746 BinExp be = cast(BinExp)copy();
1747 1747
1748 be.e1 = e1.doInline(ids); 1748 be.e1 = e1.doInline(ids);
1749 be.e2 = e2.doInline(ids); 1749 be.e2 = e2.doInline(ids);
1750 return be; 1750 return be;
1751 } 1751 }
1752 1752
1753 override Expression inlineScan(InlineScanState* iss) 1753 override Expression inlineScan(InlineScanState* iss)
1754 { 1754 {
1755 e1 = e1.inlineScan(iss); 1755 e1 = e1.inlineScan(iss);
1756 e2 = e2.inlineScan(iss); 1756 e2 = e2.inlineScan(iss);
1757 return this; 1757 return this;
1826 if (fd) 1826 if (fd)
1827 { 1827 {
1828 overloadResolveX(&m, fd, null, args2); 1828 overloadResolveX(&m, fd, null, args2);
1829 } 1829 }
1830 else 1830 else
1831 { 1831 {
1832 td = s.isTemplateDeclaration(); 1832 td = s.isTemplateDeclaration();
1833 templateResolve(&m, td, sc, loc, null, null, args2); 1833 templateResolve(&m, td, sc, loc, null, null, args2);
1834 } 1834 }
1835 } 1835 }
1836 1836
1837 lastf = m.lastf; 1837 lastf = m.lastf;
1838 1838
1839 if (s_r) 1839 if (s_r)
1840 { 1840 {
1841 fd = s_r.isFuncDeclaration(); 1841 fd = s_r.isFuncDeclaration();
1842 if (fd) 1842 if (fd)
1843 { 1843 {
1844 overloadResolveX(&m, fd, null, args1); 1844 overloadResolveX(&m, fd, null, args1);
1845 } 1845 }
1846 else 1846 else
1847 { 1847 {
1848 td = s_r.isTemplateDeclaration(); 1848 td = s_r.isTemplateDeclaration();
1849 templateResolve(&m, td, sc, loc, null, null, args1); 1849 templateResolve(&m, td, sc, loc, null, null, args1);
1850 } 1850 }
1851 } 1851 }
1852 1852
1898 * b.opfunc(a) 1898 * b.opfunc(a)
1899 * and see which is better. 1899 * and see which is better.
1900 */ 1900 */
1901 1901
1902 if (!argsset) 1902 if (!argsset)
1903 { 1903 {
1904 args1.setDim(1); 1904 args1.setDim(1);
1905 args1[0] = e1; 1905 args1[0] = e1;
1906 args2.setDim(1); 1906 args2.setDim(1);
1907 args2[0] = e2; 1907 args2[0] = e2;
1908 } 1908 }
2029 el_setLoc(e,loc); 2029 el_setLoc(e,loc);
2030 2030
2031 return e; 2031 return e;
2032 } 2032 }
2033 final void AssignExp_buildArrayIdent(OutBuffer buf, Expressions arguments, string Str) 2033 final void AssignExp_buildArrayIdent(OutBuffer buf, Expressions arguments, string Str)
2034 { 2034 {
2035 /* Evaluate assign expressions right to left 2035 /* Evaluate assign expressions right to left
2036 */ 2036 */
2037 e2.buildArrayIdent(buf, arguments); 2037 e2.buildArrayIdent(buf, arguments);
2038 e1.buildArrayIdent(buf, arguments); 2038 e1.buildArrayIdent(buf, arguments);
2039 buf.writestring(Str); 2039 buf.writestring(Str);
2040 buf.writestring("ass"); 2040 buf.writestring("ass");
2041 } 2041 }
2042 2042
2043 final void Exp_buildArrayIdent(OutBuffer buf, Expressions arguments, string Str) 2043 final void Exp_buildArrayIdent(OutBuffer buf, Expressions arguments, string Str)
2044 { 2044 {
2045 /* Evaluate assign expressions left to right 2045 /* Evaluate assign expressions left to right
2046 */ 2046 */
2047 e1.buildArrayIdent(buf, arguments); 2047 e1.buildArrayIdent(buf, arguments);
2048 e2.buildArrayIdent(buf, arguments); 2048 e2.buildArrayIdent(buf, arguments);
2049 buf.writestring(Str); 2049 buf.writestring(Str);
2050 } 2050 }
2051 2051
2052 final Expression AssignExp_buildArrayLoop(AssignExpType)(Parameters fparams)// if (is (AssignExpType : AssignExp)) 2052 final Expression AssignExp_buildArrayLoop(AssignExpType)(Parameters fparams)// if (is (AssignExpType : AssignExp))
2053 { 2053 {
2054 /* Evaluate assign expressions right to left 2054 /* Evaluate assign expressions right to left
2055 */ 2055 */
2056 Expression ex2 = e2.buildArrayLoop(fparams); 2056 Expression ex2 = e2.buildArrayLoop(fparams);
2058 auto param = fparams[0]; 2058 auto param = fparams[0];
2059 param.storageClass = STCundefined; 2059 param.storageClass = STCundefined;
2060 Expression e = new AssignExpType(Loc(0), ex1, ex2); 2060 Expression e = new AssignExpType(Loc(0), ex1, ex2);
2061 return e; 2061 return e;
2062 } 2062 }
2063 2063
2064 final Expression Exp_buildArrayLoop(ExpType)(Parameters fparams) if (is (ExpType : BinExp)) 2064 final Expression Exp_buildArrayLoop(ExpType)(Parameters fparams) if (is (ExpType : BinExp))
2065 { 2065 {
2066 /* Evaluate assign expressions left to right 2066 /* Evaluate assign expressions left to right
2067 */ 2067 */
2068 Expression ex1 = e1.buildArrayLoop(fparams); 2068 Expression ex1 = e1.buildArrayLoop(fparams);