New type system
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user