@@ -601,6 +601,13 @@ function SameData(x: TInstructionData; y: TXprVar): Boolean;
601601 (x.IsTemporary = y.IsTemporary);
602602end ;
603603
604+ function TransferableData (x: TInstructionData; y: TXprVar): Boolean;
605+ begin
606+ Result := (x.Pos = y.MemPos) and (BaseIntType(x.BaseType) = BaseIntType(y.VarType.BaseType)) and
607+ (x.NestingLevel = y.NestingLevel) and (x.Reference = y.Reference) and
608+ (x.IsTemporary = y.IsTemporary);
609+ end ;
610+
604611function NodeArray (Arr: array of XTree_Node): XNodeArray;
605612begin
606613 SetLength(Result, Length(Arr));
@@ -1601,7 +1608,7 @@ function XTree_TypeCast.CompileLValue(Dest: TXprVar): TXprVar;
16011608 end ;
16021609
16031610 // Compile the underlying pointer expression.
1604- SourceVar := Expression.Compile(NullResVar, [] );
1611+ SourceVar := Expression.CompileLValue(Dest );
16051612
16061613 Result := SourceVar;
16071614 Result.VarType := Self.TargetType;
@@ -1612,7 +1619,6 @@ function XTree_TypeCast.CompileLValue(Dest: TXprVar): TXprVar;
16121619// Class Declaration
16131620//
16141621constructor XTree_ClassDecl.Create(AName, AParentName: string; AFields, AMethods: XNodeArray; ACTX: TCompilerContext; DocPos: TDocPos);
1615- var i: Int32;
16161622begin
16171623 inherited Create(ACTX, DocPos);
16181624
@@ -3447,14 +3453,11 @@ function XTree_Invoke.CompileLValue(Dest: TXprVar): TXprVar;
34473453 if (Length(args) <> 1 ) then
34483454 ctx.RaiseExceptionFmt(' Typecast expects exactly one argument, but got %d.' , [Length(Args)], FDocPos);
34493455
3450- if (not (args[0 ] is XTree_Identifier)) or (not (Method is XTree_Identifier)) then
3451- ctx.RaiseException(' Functions can not be written to' , FDocPos);
3452-
3453- vType := ctx.GetType(XTree_Identifier(Self.Method).Name );
3454- if vType <> nil then
3456+ if (Length(Args) = 1 ) and (SelfExpr = nil ) and (Method is XTree_Identifier) then
34553457 begin
3456- if Length(Args) <> 1 then
3457- ctx.RaiseExceptionFmt(' Typecast expects exactly one argument, but got %d.' , [Length(Args)], FDocPos);
3458+ vType := ctx.GetType(XTree_Identifier(Self.Method).Name );
3459+ if vType = nil then
3460+ ctx.RaiseException(' Functions can not be written to' , FDocPos);
34583461
34593462 with XTree_TypeCast.Create(vType, Self.Args[0 ], FContext, FDocPos) do
34603463 try
@@ -3463,7 +3466,7 @@ function XTree_Invoke.CompileLValue(Dest: TXprVar): TXprVar;
34633466 Free;
34643467 end ;
34653468 end else
3466- ctx.RaiseException(eUnexpected , FDocPos);
3469+ ctx.RaiseException(' Functions can not be written to ' , FDocPos);
34673470end ;
34683471
34693472
@@ -4969,7 +4972,7 @@ function XTree_Assign.Compile(Dest: TXprVar; Flags: TCompilerFlags): TXprVar;
49694972 case last_instr_ptr^.Code of
49704973 icADD..icSAR:
49714974 begin
4972- if SameData (last_instr_ptr^.Args[2 ], RightVar) then
4975+ if TransferableData (last_instr_ptr^.Args[2 ], RightVar) then
49734976 begin
49744977 last_instr_ptr^.Args[2 ].Addr := LeftVar.Addr;
49754978 Exit(True);
@@ -4978,7 +4981,7 @@ function XTree_Assign.Compile(Dest: TXprVar; Flags: TCompilerFlags): TXprVar;
49784981
49794982 icDREF:
49804983 begin
4981- if SameData (last_instr_ptr^.Args[0 ], RightVar) then
4984+ if TransferableData (last_instr_ptr^.Args[0 ], RightVar) then
49824985 begin
49834986 last_instr_ptr^.Args[0 ].Addr := LeftVar.Addr;
49844987 Exit(True);
@@ -5036,25 +5039,45 @@ function XTree_Assign.Compile(Dest: TXprVar; Flags: TCompilerFlags): TXprVar;
50365039 TargetNode: XTree_Node;
50375040 SourceFieldNode: XTree_Field;
50385041 AssignNode: XTree_Assign;
5039- TempFieldNames: XStringList ;
5040- TempTypeList: XTypeList ;
5042+ RightHandSideValues: array of TXprVar ;
5043+ InitializerList: XTree_InitializerList ;
50415044 begin
50425045 // Compile RHS expression once to a temp!
50435046
50445047 // special case of (a,b) := [b,a]
50455048 if RHS_Node is XTree_InitializerList then
50465049 begin
5047- TempFieldNames.Init([]);
5048- TempTypeList.Init([]);
5049- for i:=0 to High(PatternNode.Targets) do
5050+ InitializerList := RHS_Node as XTree_InitializerList;
5051+
5052+ // Sanity check: the number of items must match.
5053+ if Length(PatternNode.Targets) <> Length(InitializerList.Items) then
5054+ ctx.RaiseExceptionFmt(' The number of variables in the pattern (%d) does not match the number of values in the initializer list (%d).' ,
5055+ [Length(PatternNode.Targets), Length(InitializerList.Items)], PatternNode.FDocPos);
5056+
5057+ // Evaluate all expressions on the right-hand side and store their
5058+ // results in **tempvars** before any assignment happens.
5059+ RightHandSideValues := [];
5060+ SetLength(RightHandSideValues, Length(InitializerList.Items));
5061+ for i := 0 to High(InitializerList.Items) do
5062+ RightHandSideValues[i] := InitializerList.Items[i].Compile(NullResVar, Flags);
5063+
5064+ // Now we can assign them to the LHS targets!
5065+ for i := 0 to High(PatternNode.Targets) do
50505066 begin
5051- TempFieldNames.Add(' !' +i.ToString());
5052- TempTypeList.Add(PatternNode.Targets[i].ResType());
5067+ AssignNode := XTree_Assign.Create(
5068+ op_Asgn,
5069+ PatternNode.Targets[i],
5070+ XTree_VarStub.Create(RightHandSideValues[i], ctx, RHS_Node.FDocPos),
5071+ ctx,
5072+ FDocPos
5073+ );
5074+ try
5075+ AssignNode.Compile(NullResVar, Flags);
5076+ finally
5077+ AssignNode.Free;
5078+ end ;
50535079 end ;
5054-
5055- RecType := XType_Record.Create(TempFieldNames, TempTypeList);
5056- ctx.AddManagedType(RecType);
5057- RHS_Node.FResType := RecType;
5080+ Exit; // We are done with this path.
50585081 end ;
50595082
50605083
0 commit comments