New type system

This commit is contained in:
Michael Schimmel
2025-08-26 15:49:28 +02:00
parent e9608a746a
commit 54d470b2f8
15 changed files with 58 additions and 364 deletions
+2 -40
View File
@@ -34,8 +34,7 @@ type
implementation
uses
System.SyncObjs,
System.Rtti;
System.SyncObjs;
type
// Implements the array data value.
@@ -45,7 +44,6 @@ type
FItems: TArray<IDataValue>;
function GetDataType: IDataType;
function GetAsString: string;
function AsTValue: TValue;
function GetElementCount: Integer;
function GetItem(Idx: Integer): IDataValue;
public
@@ -54,15 +52,10 @@ type
// Optimized implementation for an array with 0 elements.
TImplDataArrayValue0 = class(TInterfacedObject, IDataValue, IDataArrayValue)
strict private
class var
FEmptyTValue: TValue; // Singleton TValue for an empty array
class constructor CreateClass;
private
FArrayType: IDataArrayType;
function GetDataType: IDataType;
function GetAsString: string;
function AsTValue: TValue;
function GetElementCount: Integer;
function GetItem(Idx: Integer): IDataValue;
public
@@ -71,12 +64,12 @@ type
// Optimized implementation for an array with 1 element.
TImplDataArrayValue1 = class(TInterfacedObject, IDataValue, IDataArrayValue)
private
private
FArrayType: IDataArrayType;
FItem0: IDataValue;
function GetDataType: IDataType;
function GetAsString: string;
function AsTValue: TValue;
function GetElementCount: Integer;
function GetItem(Idx: Integer): IDataValue;
public
@@ -122,17 +115,6 @@ begin
end;
end;
function TImplDataArrayValue.AsTValue: TValue;
var
tvalueArray: TArray<TValue>;
i: Integer;
begin
SetLength(tvalueArray, Length(FItems));
for i := 0 to High(FItems) do
tvalueArray[i] := FItems[i].AsTValue;
Result := TValue.From<TArray<TValue>>(tvalueArray);
end;
function TImplDataArrayValue.GetElementCount: Integer;
begin
Result := Length(FItems);
@@ -145,12 +127,6 @@ end;
{ TImplDataArrayValue0 }
class constructor TImplDataArrayValue0.CreateClass;
begin
// Create a singleton TValue representing an empty dynamic array.
FEmptyTValue := TValue.From<TArray<TValue>>([]);
end;
constructor TImplDataArrayValue0.Create(const AArrayType: IDataArrayType);
begin
inherited Create;
@@ -162,11 +138,6 @@ begin
Result := '[]';
end;
function TImplDataArrayValue0.AsTValue: TValue;
begin
Result := FEmptyTValue;
end;
function TImplDataArrayValue0.GetDataType: IDataType;
begin
Result := FArrayType;
@@ -196,15 +167,6 @@ begin
Result := '[' + FItem0.AsString + ']';
end;
function TImplDataArrayValue1.AsTValue: TValue;
var
tvalueArray: TArray<TValue>;
begin
SetLength(tvalueArray, 1);
tvalueArray[0] := FItem0.AsTValue;
Result := TValue.From<TArray<TValue>>(tvalueArray);
end;
function TImplDataArrayValue1.GetDataType: IDataType;
begin
Result := FArrayType;
-7
View File
@@ -36,7 +36,6 @@ implementation
uses
System.SysUtils,
System.Rtti,
System.Math;
type
@@ -50,7 +49,6 @@ type
// IDataValue
function GetDataType: IDataType;
function GetAsString: string;
function AsTValue: TValue;
// IDataDecimalValue
function GetValue: Int64;
@@ -115,11 +113,6 @@ begin
FDataType := ADataType;
end;
function TDataDecimalValue.AsTValue: TValue;
begin
Result := TValue.From<Int64>(FValue);
end;
function TDataDecimalValue.GetAsString: string;
var
s: string;
-9
View File
@@ -26,9 +26,6 @@ type
implementation
uses
System.Rtti;
type
TImplDataEnumValue = class(TInterfacedObject, IDataEnumValue)
private
@@ -37,7 +34,6 @@ type
function GetDataType: IDataType;
function GetAsString: string;
function GetValue: Integer;
function AsTValue: TValue;
public
constructor Create(const ADataType: IDataEnumType; const AValue: Integer);
end;
@@ -123,9 +119,4 @@ begin
Result := FValue;
end;
function TImplDataEnumValue.AsTValue: TValue;
begin
Result := TValue.From<Integer>(FValue);
end;
end.
+1 -42
View File
@@ -25,8 +25,7 @@ type
implementation
uses
System.Math,
System.Rtti;
System.Math;
type
// Implements the float data value.
@@ -39,7 +38,6 @@ type
// IDataValue
function GetDataType: IDataType;
function GetAsString: string;
function AsTValue: TValue;
// IDataFloatValue
function GetValue: Double;
@@ -47,28 +45,18 @@ type
// Special implementation for the value 0.0 (Singleton)
TImplDataFloatValueZero = class(TInterfacedObject, IDataValue, IDataFloatValue)
strict private
class var
FValue: TValue;
class constructor CreateClass;
public
function GetDataType: IDataType;
function GetAsString: string;
function GetValue: Double;
function AsTValue: TValue;
end;
// Special implementation for NaN (Not a Number) (Singleton)
TImplDataFloatValueNaN = class(TInterfacedObject, IDataValue, IDataFloatValue)
strict private
class var
FValue: TValue;
class constructor CreateClass;
public
function GetDataType: IDataType;
function GetAsString: string;
function GetValue: Double;
function AsTValue: TValue;
end;
{ TImplDataFloatValue }
@@ -89,23 +77,11 @@ begin
Result := FloatToStr(FValue);
end;
function TImplDataFloatValue.AsTValue: TValue;
begin
Result := TValue.From<Double>(FValue);
end;
function TImplDataFloatValue.GetValue: Double;
begin
Result := FValue;
end;
{ TImplDataFloatValueZero }
class constructor TImplDataFloatValueZero.CreateClass;
begin
FValue := TValue.From<Double>(0.0);
end;
function TImplDataFloatValueZero.GetAsString: string;
begin
Result := '0';
@@ -121,18 +97,6 @@ begin
Result := 0.0;
end;
function TImplDataFloatValueZero.AsTValue: TValue;
begin
Result := FValue;
end;
{ TImplDataFloatValueNaN }
class constructor TImplDataFloatValueNaN.CreateClass;
begin
FValue := TValue.From<Double>(NaN);
end;
function TImplDataFloatValueNaN.GetAsString: string;
begin
Result := 'NaN';
@@ -148,11 +112,6 @@ begin
Result := NaN;
end;
function TImplDataFloatValueNaN.AsTValue: TValue;
begin
Result := FValue;
end;
{ TImplDataFloatType }
class constructor TImplDataFloatType.CreateClass;
-7
View File
@@ -4,7 +4,6 @@ interface
uses
System.SysUtils,
System.Rtti,
System.Generics.Collections,
Myc.Data.Types;
@@ -47,7 +46,6 @@ type
FValue: TDataMethodProc;
function GetDataType: IDataType;
function GetAsString: string;
function AsTValue: TValue;
function GetValue: TDataMethodProc;
public
constructor Create(const ADataType: IDataMethodType; const AValue: TDataMethodProc);
@@ -180,11 +178,6 @@ begin
Result := '<METHOD>';
end;
function TImplDataMethodValue.AsTValue: TValue;
begin
Result := TValue.From<TDataMethodProc>(FValue);
end;
function TImplDataMethodValue.GetValue: TDataMethodProc;
begin
Result := FValue;
-28
View File
@@ -37,7 +37,6 @@ type
// IDataValue
function GetDataType: IDataType;
function GetAsString: string;
function AsTValue: TValue;
// IDataOrdinalValue
function GetValue: Int64;
@@ -53,7 +52,6 @@ type
function GetDataType: IDataType;
function GetAsString: string;
function GetValue: Int64;
function AsTValue: TValue;
end;
// Specialized implementation for the value 0.
@@ -66,7 +64,6 @@ type
function GetDataType: IDataType;
function GetAsString: string;
function GetValue: Int64;
function AsTValue: TValue;
end;
// Specialized implementation for the value 1.
@@ -79,7 +76,6 @@ type
function GetDataType: IDataType;
function GetAsString: string;
function GetValue: Int64;
function AsTValue: TValue;
end;
{ TImplDataOrdinalValue }
@@ -100,12 +96,6 @@ begin
Result := FValue.ToString;
end;
function TImplDataOrdinalValue.AsTValue: TValue;
begin
// Convert Int64 to TValue
Result := TValue.From<Int64>(FValue);
end;
function TImplDataOrdinalValue.GetValue: Int64;
begin
Result := FValue;
@@ -128,12 +118,6 @@ begin
Result := '-1';
end;
function TDataOrdinalValueMinusOne.AsTValue: TValue;
begin
// Return the singleton TValue instance.
Result := FValue;
end;
function TDataOrdinalValueMinusOne.GetValue: Int64;
begin
Result := -1;
@@ -156,12 +140,6 @@ begin
Result := '0';
end;
function TDataOrdinalValueZero.AsTValue: TValue;
begin
// Return the singleton TValue instance.
Result := FValue;
end;
function TDataOrdinalValueZero.GetValue: Int64;
begin
Result := 0;
@@ -184,12 +162,6 @@ begin
Result := '1';
end;
function TDataOrdinalValueOne.AsTValue: TValue;
begin
// Return the singleton TValue instance.
Result := FValue;
end;
function TDataOrdinalValueOne.GetValue: Int64;
begin
Result := 1;
+37
View File
@@ -0,0 +1,37 @@
unit Myc.Data.Types.RTTI;
interface
uses
System.SysUtils,
System.RTTI,
Myc.Data.Types;
type
TValueHelper = record helper for TDataType.TValue
function AsTValue: TValue;
end;
implementation
uses
System.Math;
{ TValueHelper }
function TValueHelper.AsTValue: TValue;
begin
case DataType.Kind of
dkVoid: Result := TValue.Empty;
dkOrdinal: Result := TValue.From<Int64>(AsOrdinal.Value);
dkFloat: Result := TValue.From<Double>(AsFloat.Value);
dkText: Result := TValue.From<string>(AsText.Value);
dkTimestamp: Result := TValue.From<TDateTime>(AsTimestamp.Value);
dkEnum: Result := TValue.From<Integer>(AsEnum.Value);
dkMethod: Result := TValue.From<TDataMethodProc>(AsMethod.Value);
else
raise EInvalidOpException.Create('Unsupported data type');
end;
end;
end.
+3 -49
View File
@@ -48,8 +48,7 @@ type
implementation
uses
System.SyncObjs,
System.Rtti;
System.SyncObjs;
type
// Implements the record data value.
@@ -59,7 +58,6 @@ type
FItems: TArray<IDataValue>;
function GetDataType: IDataType;
function GetAsString: string;
function AsTValue: TValue;
function GetItem(Idx: Integer): IDataValue;
public
constructor Create(const ADataType: IDataRecordType; const AItems: array of IDataValue);
@@ -68,14 +66,11 @@ type
// Optimized implementation for a record with 0 fields.
TImplDataRecordValue0 = class(TInterfacedObject, IDataValue, IDataRecordValue)
strict private
class var
FEmptyTValue: TValue; // Singleton TValue for an empty record
class constructor CreateClass;
private
FDataType: IDataRecordType;
function GetDataType: IDataType;
function GetAsString: string;
function AsTValue: TValue;
function GetItem(Idx: Integer): IDataValue;
public
constructor Create(const ADataType: IDataRecordType);
@@ -88,7 +83,6 @@ type
FItem0: IDataValue;
function GetDataType: IDataType;
function GetAsString: string;
function AsTValue: TValue;
function GetItem(Idx: Integer): IDataValue;
public
constructor Create(const ADataType: IDataRecordType; const AItems: array of IDataValue);
@@ -101,7 +95,6 @@ type
FItem0, FItem1: IDataValue;
function GetDataType: IDataType;
function GetAsString: string;
function AsTValue: TValue;
function GetItem(Idx: Integer): IDataValue;
public
constructor Create(const ADataType: IDataRecordType; const AItems: array of IDataValue);
@@ -178,17 +171,6 @@ begin
end;
end;
function TImplDataRecordValue.AsTValue: TValue;
var
tvalueArray: TArray<TValue>;
i: Integer;
begin
SetLength(tvalueArray, Length(FItems));
for i := 0 to High(FItems) do
tvalueArray[i] := FItems[i].AsTValue;
Result := TValue.From<TArray<TValue>>(tvalueArray);
end;
function TImplDataRecordValue.GetItem(Idx: Integer): IDataValue;
begin
Result := FItems[Idx];
@@ -197,11 +179,7 @@ end;
{ TImplDataRecordValue0 }
class constructor TImplDataRecordValue0.CreateClass;
var
emptyArray: TArray<TValue>;
begin
SetLength(emptyArray, 0);
FEmptyTValue := TValue.From<TArray<TValue>>(emptyArray);
end;
constructor TImplDataRecordValue0.Create(const ADataType: IDataRecordType);
@@ -215,11 +193,6 @@ begin
Result := '<>';
end;
function TImplDataRecordValue0.AsTValue: TValue;
begin
Result := FEmptyTValue;
end;
function TImplDataRecordValue0.GetDataType: IDataType;
begin
Result := FDataType;
@@ -247,15 +220,6 @@ begin
Result := Format('<%s: %s>', [recordType.Fields[0].Name, FItem0.AsString]);
end;
function TImplDataRecordValue1.AsTValue: TValue;
var
tvalueArray: TArray<TValue>;
begin
SetLength(tvalueArray, 1);
tvalueArray[0] := FItem0.AsTValue;
Result := TValue.From<TArray<TValue>>(tvalueArray);
end;
function TImplDataRecordValue1.GetDataType: IDataType;
begin
Result := FDataType;
@@ -303,16 +267,6 @@ begin
end;
end;
function TImplDataRecordValue2.AsTValue: TValue;
var
tvalueArray: TArray<TValue>;
begin
SetLength(tvalueArray, 2);
tvalueArray[0] := FItem0.AsTValue;
tvalueArray[1] := FItem1.AsTValue;
Result := TValue.From<TArray<TValue>>(tvalueArray);
end;
function TImplDataRecordValue2.GetDataType: IDataType;
begin
Result := FDataType;
@@ -382,7 +336,7 @@ begin
begin
field := AFields[i];
if FFieldMap.ContainsKey(field.Name) then
raise EArgumentException.CreateFmt('Duplicate field name: ''%s''', [field.Name]);
raise EArgumentException.CreateFmt('Duplicate field name: %s', [field.Name]);
FFields[i] := field;
FFieldMap.Add(field.Name, i);
end;
@@ -409,7 +363,7 @@ begin
for i := 0 to High(AItems) do
if (AItems[i].DataType <> FFields[i].DataType) then
raise EArgumentException.CreateFmt(
'Invalid data type for field ''%s'' at index %d. Expected ''%s'', but got ''%s''.',
'Invalid data type for field %s at index %d. Expected %s',
[FFields[i].Name, i, FFields[i].DataType.Name, AItems[i].DataType.Name]);
// Use optimized implementations for records with 0, 1, or 2 fields.
-17
View File
@@ -21,9 +21,6 @@ type
implementation
uses
System.Rtti;
type
TImplDataTextValue = class(TInterfacedObject, IDataValue, IDataTextValue)
private
@@ -31,7 +28,6 @@ type
function GetDataType: IDataType;
function GetAsString: string;
function GetValue: string;
function AsTValue: TValue;
public
constructor Create(const AValue: string);
end;
@@ -41,13 +37,11 @@ type
strict private
class var
FSingleton: IDataTextValue;
FEmptyTValue: TValue;
class constructor CreateClass;
private
function GetDataType: IDataType;
function GetAsString: string;
function GetValue: string;
function AsTValue: TValue;
public
class property Singleton: IDataTextValue read FSingleton;
end;
@@ -101,17 +95,11 @@ begin
Result := FValue;
end;
function TImplDataTextValue.AsTValue: TValue;
begin
Result := TValue.From<string>(FValue);
end;
{ TImplDataTextValueEmpty }
class constructor TImplDataTextValueEmpty.CreateClass;
begin
FSingleton := TImplDataTextValueEmpty.Create;
FEmptyTValue := TValue.From<string>('');
end;
function TImplDataTextValueEmpty.GetAsString: string;
@@ -129,9 +117,4 @@ begin
Result := '';
end;
function TImplDataTextValueEmpty.AsTValue: TValue;
begin
Result := FEmptyTValue;
end;
end.
-9
View File
@@ -21,9 +21,6 @@ type
implementation
uses
System.Rtti;
type
TImplDataTimestampValue = class(TInterfacedObject, IDataValue, IDataTimestampValue)
private
@@ -31,7 +28,6 @@ type
function GetDataType: IDataType;
function GetAsString: string;
function GetValue: TDateTime;
function AsTValue: TValue;
public
constructor Create(const AValue: TDateTime);
end;
@@ -81,9 +77,4 @@ begin
Result := FValue;
end;
function TImplDataTimestampValue.AsTValue: TValue;
begin
Result := TValue.From<TDateTime>(FValue);
end;
end.
-86
View File
@@ -23,9 +23,6 @@ type
implementation
uses
System.Rtti;
type
// Implements the simple tuple data value.
TImplDataTupleValue = class(TInterfacedObject, IDataValue, IDataTupleValue)
@@ -33,7 +30,6 @@ type
FItems: TArray<IDataValue>;
function GetDataType: IDataType;
function GetAsString: string;
function AsTValue: TValue;
function GetItemCount: Integer;
function GetItem(Idx: Integer): IDataValue;
public
@@ -45,12 +41,10 @@ type
strict private
class var
FSingleton: IDataTupleValue;
FEmptyTValue: TValue;
class constructor CreateClass;
private
function GetDataType: IDataType;
function GetAsString: string;
function AsTValue: TValue;
function GetItemCount: Integer;
function GetItem(Idx: Integer): IDataValue;
public
@@ -63,7 +57,6 @@ type
FItem0: IDataValue;
function GetDataType: IDataType;
function GetAsString: string;
function AsTValue: TValue;
function GetItemCount: Integer;
function GetItem(Idx: Integer): IDataValue;
public
@@ -76,7 +69,6 @@ type
FItem0, FItem1: IDataValue;
function GetDataType: IDataType;
function GetAsString: string;
function AsTValue: TValue;
function GetItemCount: Integer;
function GetItem(Idx: Integer): IDataValue;
public
@@ -89,7 +81,6 @@ type
FItem0, FItem1, FItem2: IDataValue;
function GetDataType: IDataType;
function GetAsString: string;
function AsTValue: TValue;
function GetItemCount: Integer;
function GetItem(Idx: Integer): IDataValue;
public
@@ -102,7 +93,6 @@ type
FItem0, FItem1, FItem2, FItem3: IDataValue;
function GetDataType: IDataType;
function GetAsString: string;
function AsTValue: TValue;
function GetItemCount: Integer;
function GetItem(Idx: Integer): IDataValue;
public
@@ -115,7 +105,6 @@ type
FItem0, FItem1, FItem2, FItem3, FItem4: IDataValue;
function GetDataType: IDataType;
function GetAsString: string;
function AsTValue: TValue;
function GetItemCount: Integer;
function GetItem(Idx: Integer): IDataValue;
public
@@ -160,17 +149,6 @@ begin
end;
end;
function TImplDataTupleValue.AsTValue: TValue;
var
tvalueArray: TArray<TValue>;
i: Integer;
begin
SetLength(tvalueArray, Length(FItems));
for i := 0 to High(FItems) do
tvalueArray[i] := FItems[i].AsTValue;
Result := TValue.From<TArray<TValue>>(tvalueArray);
end;
function TImplDataTupleValue.GetItem(Idx: Integer): IDataValue;
begin
Result := FItems[Idx];
@@ -184,12 +162,8 @@ end;
{ TImplDataTupleValue0 }
class constructor TImplDataTupleValue0.CreateClass;
var
emptyArray: TArray<TValue>;
begin
FSingleton := TImplDataTupleValue0.Create;
SetLength(emptyArray, 0);
FEmptyTValue := TValue.From<TArray<TValue>>(emptyArray);
end;
function TImplDataTupleValue0.GetAsString: string;
@@ -197,11 +171,6 @@ begin
Result := '()';
end;
function TImplDataTupleValue0.AsTValue: TValue;
begin
Result := FEmptyTValue;
end;
function TImplDataTupleValue0.GetDataType: IDataType;
begin
Result := TImplDataTupleType.Singleton;
@@ -230,15 +199,6 @@ begin
Result := '(' + FItem0.AsString + ')';
end;
function TImplDataTupleValue1.AsTValue: TValue;
var
tvalueArray: TArray<TValue>;
begin
SetLength(tvalueArray, 1);
tvalueArray[0] := FItem0.AsTValue;
Result := TValue.From<TArray<TValue>>(tvalueArray);
end;
function TImplDataTupleValue1.GetDataType: IDataType;
begin
Result := TImplDataTupleType.Singleton;
@@ -272,16 +232,6 @@ begin
Result := '(' + FItem0.AsString + ', ' + FItem1.AsString + ')';
end;
function TImplDataTupleValue2.AsTValue: TValue;
var
tvalueArray: TArray<TValue>;
begin
SetLength(tvalueArray, 2);
tvalueArray[0] := FItem0.AsTValue;
tvalueArray[1] := FItem1.AsTValue;
Result := TValue.From<TArray<TValue>>(tvalueArray);
end;
function TImplDataTupleValue2.GetDataType: IDataType;
begin
Result := TImplDataTupleType.Singleton;
@@ -331,17 +281,6 @@ begin
end;
end;
function TImplDataTupleValue3.AsTValue: TValue;
var
tvalueArray: TArray<TValue>;
begin
SetLength(tvalueArray, 3);
tvalueArray[0] := FItem0.AsTValue;
tvalueArray[1] := FItem1.AsTValue;
tvalueArray[2] := FItem2.AsTValue;
Result := TValue.From<TArray<TValue>>(tvalueArray);
end;
function TImplDataTupleValue3.GetDataType: IDataType;
begin
Result := TImplDataTupleType.Singleton;
@@ -395,18 +334,6 @@ begin
end;
end;
function TImplDataTupleValue4.AsTValue: TValue;
var
tvalueArray: TArray<TValue>;
begin
SetLength(tvalueArray, 4);
tvalueArray[0] := FItem0.AsTValue;
tvalueArray[1] := FItem1.AsTValue;
tvalueArray[2] := FItem2.AsTValue;
tvalueArray[3] := FItem3.AsTValue;
Result := TValue.From<TArray<TValue>>(tvalueArray);
end;
function TImplDataTupleValue4.GetDataType: IDataType;
begin
Result := TImplDataTupleType.Singleton;
@@ -464,19 +391,6 @@ begin
end;
end;
function TImplDataTupleValue5.AsTValue: TValue;
var
tvalueArray: TArray<TValue>;
begin
SetLength(tvalueArray, 5);
tvalueArray[0] := FItem0.AsTValue;
tvalueArray[1] := FItem1.AsTValue;
tvalueArray[2] := FItem2.AsTValue;
tvalueArray[3] := FItem3.AsTValue;
tvalueArray[4] := FItem4.AsTValue;
Result := TValue.From<TArray<TValue>>(tvalueArray);
end;
function TImplDataTupleValue5.GetDataType: IDataType;
begin
Result := TImplDataTupleType.Singleton;
-9
View File
@@ -4,7 +4,6 @@ interface
uses
System.SysUtils,
System.RTTI,
Myc.Data.Types;
type
@@ -18,7 +17,6 @@ type
// IDataValue
function GetDataType: IDataType;
function GetAsString: string;
function AsTValue: TValue;
class property Singleton: IDataVoidValue read FSingleton;
end;
@@ -42,13 +40,6 @@ type
implementation
{ TImplDataVoidValue }
function TImplDataVoidValue.AsTValue: TValue;
begin
Result := TValue.Empty;
end;
class constructor TImplDataVoidValue.CreateSingleton;
begin
// Singleton instance created for the void value
-1
View File
@@ -23,7 +23,6 @@ type
function GetDataType: IDataType;
function GetAsString: string;
{$endregion}
function AsTValue: TValue;
property DataType: IDataType read GetDataType;
property AsString: string read GetAsString;
end;
+5 -51
View File
@@ -47,7 +47,8 @@ uses
System.Math,
System.Rtti,
System.TypInfo,
Myc.Data.Types;
Myc.Data.Types,
Myc.Data.Types.RTTI;
procedure TMyTestObject.TestRecords;
var
@@ -547,17 +548,14 @@ end;
procedure TMyTestObject.TestAsTValue;
var
dataValue: IDataValue; // Keep as generic interface to test AsTValue
tv, element: TValue;
dataValue: TDataType.TValue; // Keep as generic interface to test AsTValue
now: TDateTime;
colorType: TDataType.TEnum;
intArrayType: TDataType.TArray;
personType: TDataType.TRecord;
begin
// This test is specifically for the IDataValue.AsTValue method. No changes needed.
// --- Ordinal ---
dataValue := TDataType.Ordinal.CreateValue(123);
tv := dataValue.AsTValue;
var tv := dataValue.AsTValue;
Assert.IsFalse(tv.IsEmpty, 'Ordinal TValue should not be empty');
Assert.AreEqual(tkInt64, tv.Kind, 'Ordinal TValue kind should be tkInt64');
Assert.AreEqual(Int64(123), tv.AsInt64, 'Ordinal TValue content is incorrect');
@@ -591,50 +589,6 @@ begin
Assert.IsFalse(tv.IsEmpty, 'Enum TValue should not be empty');
Assert.AreEqual(tkInteger, tv.Kind, 'Enum TValue kind should be tkInteger');
Assert.AreEqual(1, tv.AsInteger, 'Enum TValue content is incorrect');
// --- Array ---
intArrayType := TDataType.ArrayOf(TDataType.Ordinal);
dataValue := intArrayType.CreateValue([TDataType.Ordinal.CreateValue(10), TDataType.Ordinal.CreateValue(20)]);
tv := dataValue.AsTValue;
Assert.IsFalse(tv.IsEmpty, 'Array TValue should not be empty');
Assert.IsTrue(tv.IsArray, 'Array TValue should be an array');
Assert.AreEqual(tkDynArray, tv.Kind, 'Array TValue kind should be tkDynArray');
Assert.AreEqual(NativeInt(2), tv.GetArrayLength, 'Array TValue length is incorrect');
// Correctly unwrap the nested TValue before asserting kind and value
element := tv.GetArrayElement(0).AsType<TValue>;
Assert.AreEqual(tkInt64, element.Kind, 'Unwrapped array element 0 kind is incorrect');
Assert.AreEqual(Int64(10), element.AsInt64, 'Array TValue element 0 is incorrect');
element := tv.GetArrayElement(1).AsType<TValue>;
Assert.AreEqual(Int64(20), element.AsInt64, 'Array TValue element 1 is incorrect');
// Check empty array
dataValue := intArrayType.CreateValue([]);
tv := dataValue.AsTValue;
Assert.IsTrue(tv.IsArray, 'Empty Array TValue should be an array');
Assert.AreEqual(NativeInt(0), tv.GetArrayLength, 'Empty Array TValue length is incorrect');
// --- Record ---
personType := TDataType.RecordOf([TDataRecordField.Create('ID', TDataType.Ordinal), TDataRecordField.Create('Name', TDataType.Text)]);
dataValue := personType.CreateValue([TDataType.Ordinal.CreateValue(1), TDataType.Text.CreateValue('Bob')]);
tv := dataValue.AsTValue;
Assert.IsFalse(tv.IsEmpty, 'Record TValue should not be empty');
Assert.IsTrue(tv.IsArray, 'Record TValue should be represented as an array');
Assert.AreEqual(tkDynArray, tv.Kind, 'Record TValue kind should be tkDynArray');
Assert.AreEqual(NativeInt(2), tv.GetArrayLength, 'Record TValue length is incorrect');
Assert.AreEqual(Int64(1), tv.GetArrayElement(0).AsType<TValue>.AsInt64, 'Record TValue element 0 is incorrect');
Assert.AreEqual('Bob', tv.GetArrayElement(1).AsType<TValue>.AsString, 'Record TValue element 1 is incorrect');
// --- Tuple ---
dataValue := TDataType.Tuple.CreateValue([TDataType.Ordinal.CreateValue(99), TDataType.Text.CreateValue('Red')]);
tv := dataValue.AsTValue;
Assert.IsFalse(tv.IsEmpty, 'Tuple TValue should not be empty');
Assert.IsTrue(tv.IsArray, 'Tuple TValue should be represented as an array');
Assert.AreEqual(tkDynArray, tv.Kind, 'Tuple TValue kind should be tkDynArray');
Assert.AreEqual(NativeInt(2), tv.GetArrayLength, 'Tuple TValue length is incorrect');
Assert.AreEqual(Int64(99), tv.GetArrayElement(0).AsType<TValue>.AsInt64, 'Tuple TValue element 0 is incorrect');
Assert.AreEqual('Red', tv.GetArrayElement(1).AsType<TValue>.AsString, 'Tuple TValue element 1 is incorrect');
end;
procedure TMyTestObject.TestMethods;
@@ -708,7 +662,7 @@ begin
// --- 5. Test AsString and AsTValue ---
Assert.AreEqual('<METHOD>', IDataValue(methodValue).AsString, 'Method AsString is incorrect');
tv := IDataValue(methodValue).AsTValue;
tv := TDataType.TValue(methodValue).AsTValue;
Assert.IsFalse(tv.IsEmpty, 'Method TValue should not be empty');
Assert.AreEqual(tkInterface, tv.Kind, 'TValue kind for a TMethodProc should be tkInterface, as it is a reference-to-function');
Assert.IsTrue(TypeInfo(TDataMethodProc) = tv.TypeInfo, 'TValue should hold TMethodProc type info');
+10 -9
View File
@@ -9,6 +9,7 @@ uses
System.Rtti,
Myc.Data.Pipeline,
Myc.Data.Types,
Myc.Data.Types.RTTI,
System.Classes;
type
@@ -89,7 +90,7 @@ type
TGenericIndicatorFactory = class(TInterfacedObject, IIndicatorFactory)
private
FFactoryProc: TIndicatorFactoryProc<IDataValue, IDataValue, IDataValue>;
FFactoryProc: TIndicatorFactoryProc<TDataType.TValue, TDataType.TValue, TDataType.TValue>;
FName: String;
FShortName: String;
FHint: String;
@@ -99,7 +100,7 @@ type
public
constructor Create(
const AFactoryProc: TIndicatorFactoryProc<IDataValue, IDataValue, IDataValue>;
const AFactoryProc: TIndicatorFactoryProc<TDataType.TValue, TDataType.TValue, TDataType.TValue>;
const AShortName, AName, AHint: String;
const AParamType, AArgType, AResultType: TDataType
);
@@ -259,7 +260,7 @@ end;
{ TGenericIndicatorFactory }
constructor TGenericIndicatorFactory.Create(
const AFactoryProc: TIndicatorFactoryProc<IDataValue, IDataValue, IDataValue>;
const AFactoryProc: TIndicatorFactoryProc<TDataType.TValue, TDataType.TValue, TDataType.TValue>;
const AShortName, AName, AHint: String;
const AParamType, AArgType, AResultType: TDataType
);
@@ -280,7 +281,7 @@ var
rttiType: TRttiType;
paramsDataType, argsDataType, resultDataType: TDataType;
templateFactoryMethod: TRttiMethod;
factoryProc: TIndicatorFactoryProc<IDataValue, IDataValue, IDataValue>;
factoryProc: TIndicatorFactoryProc<TDataType.TValue, TDataType.TValue, TDataType.TValue>;
shortName, name, hint: string;
begin
// This function creates a generic factory from a template class.
@@ -380,7 +381,7 @@ begin
// Create the main factory procedure. This is a double-nested anonymous method
// that wraps the template's specific factory and worker functions.
factoryProc :=
function(const Params: IDataValue): TConvertFunc<IDataValue, IDataValue>
function(const Params: TDataType.TValue): TConvertFunc<TDataType.TValue, TDataType.TValue>
begin
// Outer anonymous method: This is the factory proc.
// It gets called with an IDataValue wrapping the parameters record.
@@ -405,7 +406,7 @@ begin
var currentIndicatorInvoke := rttiWorkerProc.GetMethod('Invoke');
Result :=
function(const Args: IDataValue): IDataValue
function(const Args: TDataType.TValue): TDataType.TValue
begin
// Inner anonymous method: This is the actual indicator proc wrapper.
// Convert input from IDataValue to TValue.
@@ -440,7 +441,7 @@ end;
function TGenericIndicatorFactory.CreateIndicator(const Params: TDataType.TValue): TConvertFunc<TDataType.TValue, TDataType.TValue>;
var
internalProc: TConvertFunc<IDataValue, IDataValue>;
internalProc: TConvertFunc<TDataType.TValue, TDataType.TValue>;
begin
internalProc := FFactoryProc(Params);
Result := function(const Args: TDataType.TValue): TDataType.TValue begin Result := internalProc(Args); end;
@@ -458,7 +459,7 @@ begin
var argsAsTValue := TValue.From<TArgs>(Args);
var argsAsDataValue := DataValueFromTValue(argsAsTValue);
var resultAsDataValue := cIndicator(argsAsDataValue);
var resultAsTValue := IDataValue(resultAsDataValue).AsTValue;
var resultAsTValue := resultAsDataValue.AsTValue;
Result := resultAsTValue.AsType<TResult>;
end;
end;
@@ -488,7 +489,7 @@ begin
var argsAsTValue := TValue.From<TArgs>(Args);
var argsAsDataValue := DataValueFromTValue(argsAsTValue);
var resultAsDataValue := cIndicator(argsAsDataValue);
var resultAsTValue := IDataValue(resultAsDataValue).AsTValue;
var resultAsTValue := resultAsDataValue.AsTValue;
Result := resultAsTValue.AsType<TResult>;
end;
end;