|
@@ -0,0 +1,148 @@
|
|
|
|
+program tmoperator8;
|
|
|
|
+
|
|
|
|
+{$MODE DELPHI}
|
|
|
|
+
|
|
|
|
+type
|
|
|
|
+ TCopyState = (csNone, csSource, csDest);
|
|
|
|
+ PFoo = ^TFoo;
|
|
|
|
+ TFoo = record
|
|
|
|
+ private
|
|
|
|
+ class operator Initialize(var aFoo: TFoo);
|
|
|
|
+ class operator Finalize(var aFoo: TFoo);
|
|
|
|
+ class operator AddRef(var aFoo: TFoo);
|
|
|
|
+ class operator Copy(constref aSrc: TFoo; var aDst: TFoo);
|
|
|
|
+ public
|
|
|
|
+ CopyState: TCopyState;
|
|
|
|
+ Ref: Boolean;
|
|
|
|
+ F, Test: Integer;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ TFooArray = array of TFoo;
|
|
|
|
+
|
|
|
|
+procedure TestFoo(const AValue: TFoo; AF, ATest: Integer; ARef: Boolean; ACopyState: TCopyState);
|
|
|
|
+begin
|
|
|
|
+ WriteLn(' AValue.F = ', AValue.F);
|
|
|
|
+ if AValue.F <> AF then
|
|
|
|
+ Halt(1);
|
|
|
|
+ WriteLn(' AValue.Test = ', AValue.Test);
|
|
|
|
+ if AValue.Test <> ATest then
|
|
|
|
+ Halt(2);
|
|
|
|
+ WriteLn(' AValue.Ref = ', AValue.Ref);
|
|
|
|
+ if AValue.Ref <> ARef then
|
|
|
|
+ Halt(4);
|
|
|
|
+ WriteLn(' AValue.CopyState = ', Ord(AValue.CopyState));
|
|
|
|
+ if AValue.CopyState <> ACopyState then
|
|
|
|
+ Halt(3);
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+class operator TFoo.Initialize(var aFoo: TFoo);
|
|
|
|
+begin
|
|
|
|
+ WriteLn('TFoo.Initialize');
|
|
|
|
+ aFoo.F := 1;
|
|
|
|
+ aFoo.Ref := False;
|
|
|
|
+ aFoo.Test := 0;
|
|
|
|
+ aFoo.CopyState := csNone;
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+class operator TFoo.Finalize(var aFoo: TFoo);
|
|
|
|
+begin
|
|
|
|
+ WriteLn('TFoo.Finalize');
|
|
|
|
+ if (aFoo.F <> 2) and not ((aFoo.F = 3) and aFoo.Ref) then
|
|
|
|
+ Halt(5);
|
|
|
|
+ aFoo.F := 4;
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+class operator TFoo.AddRef(var aFoo: TFoo);
|
|
|
|
+begin
|
|
|
|
+ WriteLn('TFoo.AddRef');
|
|
|
|
+ aFoo.F := 3;
|
|
|
|
+ aFoo.Test := aFoo.Test + 1;
|
|
|
|
+ aFoo.Ref := True;
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+class operator TFoo.Copy(constref aSrc: TFoo; var aDst: TFoo);
|
|
|
|
+var
|
|
|
|
+ LSrc: PFoo;
|
|
|
|
+begin
|
|
|
|
+ WriteLn('TFoo.Copy');
|
|
|
|
+ LSrc := @aSrc;
|
|
|
|
+ LSrc.CopyState := csSource;
|
|
|
|
+ aDst.CopyState := csDest;
|
|
|
|
+ aDst.Test := aSrc.Test + 1;
|
|
|
|
+ aDst.F := aSrc.F;
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+procedure TestValue(Value: TFoo);
|
|
|
|
+begin
|
|
|
|
+ writeln(' *Test without modifier:');
|
|
|
|
+ TestFoo(Value, 3, 1, True, csNone);
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+procedure TestOut(out Value: TFoo);
|
|
|
|
+begin
|
|
|
|
+ WriteLn(' *Test out modifier:');
|
|
|
|
+ TestFoo(Value, 1, 0, False, csNone);
|
|
|
|
+ Value.F := 2;
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+procedure TestVar(var Value: TFoo);
|
|
|
|
+begin
|
|
|
|
+ writeln(' *Test var modifier:');
|
|
|
|
+ TestFoo(Value, 2, 0, False, csNone);
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+procedure TestConst(const Value: TFoo);
|
|
|
|
+begin
|
|
|
|
+ writeln(' *Test const modifier:');
|
|
|
|
+ TestFoo(Value, 2, 0, False, csNone);
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+procedure TestConstref(constref Value: TFoo);
|
|
|
|
+begin
|
|
|
|
+ WriteLn(' *Test constref modifier:');
|
|
|
|
+ TestFoo(Value, 2, 0, False, csNone);
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+procedure Test;
|
|
|
|
+var
|
|
|
|
+ Foos: TFooArray;
|
|
|
|
+ Foos2: TFooArray;
|
|
|
|
+ A, B, C: TFoo;
|
|
|
|
+ i: Integer;
|
|
|
|
+begin
|
|
|
|
+ WriteLn('*** Test for variable copy');
|
|
|
|
+ TestFoo(B, 1, 0, False, csNone);
|
|
|
|
+ B.F := 2;
|
|
|
|
+ A := B;
|
|
|
|
+ TestFoo(B, 2, 0, False, csSource);
|
|
|
|
+ TestFoo(A, 2, 1, False, csDest);
|
|
|
|
+
|
|
|
|
+ WriteLn('*** Test for Copy(dyn array)');
|
|
|
|
+ SetLength(Foos, 5);
|
|
|
|
+ for i := 0 to 4 do
|
|
|
|
+ begin
|
|
|
|
+ Foos[i].F := 2;
|
|
|
|
+ Foos[i].Test := i;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ Foos2 := Copy(Foos);
|
|
|
|
+
|
|
|
|
+ for i := 0 to 4 do
|
|
|
|
+ begin
|
|
|
|
+ TestFoo(Foos[i], 2, i, False, csNone);
|
|
|
|
+ TestFoo(Foos2[i], 3, i + 1, True, csNone);
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ WriteLn('*** Test for parameters modifiers');
|
|
|
|
+ TestValue(C);
|
|
|
|
+ C.F := 2; // reset F to pass finalize before out parameter
|
|
|
|
+ TestOut(C);
|
|
|
|
+ TestVar(C);
|
|
|
|
+ TestConst(C);
|
|
|
|
+ TestConstref(C);
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+begin
|
|
|
|
+ Test;
|
|
|
|
+ WriteLn('end');
|
|
|
|
+end.
|