Vector type
This commit is contained in:
@@ -12,11 +12,61 @@ type
|
||||
function AsTValue: TValue;
|
||||
end;
|
||||
|
||||
function RttiTypeToDataType(rttiType: TRttiType): TDataType;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
System.TypInfo,
|
||||
System.Math;
|
||||
|
||||
// Recursively converts a TRttiType to an IDataType.
|
||||
function RttiTypeToDataType(rttiType: TRttiType): TDataType;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
// Convert an RTTI type representation to its corresponding IDataType.
|
||||
case rttiType.TypeKind of
|
||||
tkInteger, tkInt64, tkChar, tkWChar: Result := TDataType.Ordinal;
|
||||
tkFloat:
|
||||
if (rttiType.Handle = TypeInfo(TDateTime)) then
|
||||
Result := TDataType.Timestamp
|
||||
else
|
||||
Result := TDataType.Float;
|
||||
tkString, tkWideString, tkUString: Result := TDataType.Text;
|
||||
tkEnumeration:
|
||||
begin
|
||||
var enumType := rttiType as TRttiEnumerationType;
|
||||
var names := enumType.GetNames;
|
||||
var identifiers: TArray<string>;
|
||||
SetLength(identifiers, Length(names));
|
||||
for i := 0 to High(names) do
|
||||
identifiers[i] := names[i];
|
||||
Result := TDataType.EnumOf(enumType.Name, identifiers);
|
||||
end;
|
||||
tkDynArray:
|
||||
begin
|
||||
var arrayType := rttiType as TRttiDynamicArrayType;
|
||||
Result := TDataType.ArrayOf(RttiTypeToDataType(arrayType.ElementType));
|
||||
end;
|
||||
tkRecord:
|
||||
begin
|
||||
var recordType := rttiType as TRttiRecordType;
|
||||
var fields := recordType.GetFields;
|
||||
var recordFields: TArray<TDataRecordField>;
|
||||
SetLength(recordFields, Length(fields));
|
||||
for i := 0 to High(fields) do
|
||||
recordFields[i] := TDataRecordField.Create(fields[i].Name, RttiTypeToDataType(fields[i].FieldType));
|
||||
Result := TDataType.RecordOf(recordFields);
|
||||
end;
|
||||
else
|
||||
// Raise an exception for unsupported types.
|
||||
raise ENotSupportedException.CreateFmt(
|
||||
'Type "%s" (Kind: %s) is not supported for RTTI-based record creation.',
|
||||
[rttiType.Name, GetEnumName(TypeInfo(TTypeKind), Ord(rttiType.TypeKind))]);
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TValueHelper }
|
||||
|
||||
function TValueHelper.AsTValue: TValue;
|
||||
|
||||
@@ -38,17 +38,23 @@ type
|
||||
|
||||
class constructor CreateClass;
|
||||
class destructor DestroyClass;
|
||||
|
||||
// Factory method to get a cached or new record type instance.
|
||||
class function GetInstance(const AFields: TArray<TDataRecordField>): IDataRecordType; overload; static;
|
||||
class function GetInstance(const AFields: array of TDataRecordField): IDataRecordType; overload; static;
|
||||
|
||||
// TODO Create a record ba analyzing the RTTI of T
|
||||
class function GetInstance<T>: IDataRecordType; overload; static;
|
||||
|
||||
function CreateValue(const AItems: array of IDataValue): IDataRecordValue;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
System.SyncObjs;
|
||||
System.SyncObjs,
|
||||
System.Rtti,
|
||||
Myc.Data.Types.RTTI;
|
||||
|
||||
type
|
||||
// Implements the record data value.
|
||||
@@ -324,6 +330,23 @@ begin
|
||||
Result := GetInstance(tFields);
|
||||
end;
|
||||
|
||||
class function TImplDataRecordType.GetInstance<T>: IDataRecordType;
|
||||
var
|
||||
ctx: TRttiContext;
|
||||
rttiType: TRttiType;
|
||||
begin
|
||||
// Create an RTTI context to introspect the type T.
|
||||
ctx := TRttiContext.Create;
|
||||
rttiType := ctx.GetType(TypeInfo(T));
|
||||
|
||||
// The generic parameter T must be a record.
|
||||
if not (rttiType is TRttiRecordType) then
|
||||
raise EArgumentException.Create('Generic parameter T must be a record type.');
|
||||
|
||||
// Delegate the conversion from RTTI type to IDataType to the helper function.
|
||||
Result := RttiTypeToDataType(rttiType).AsRecord;
|
||||
end;
|
||||
|
||||
constructor TImplDataRecordType.Create(const AFields: array of TDataRecordField);
|
||||
var
|
||||
i: Integer;
|
||||
|
||||
@@ -0,0 +1,403 @@
|
||||
unit Myc.Data.Types.Vector;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
System.Generics.Collections,
|
||||
Myc.Data.Types;
|
||||
|
||||
type
|
||||
// Implements the IDataVectorType interface.
|
||||
TImplDataVectorType = class(TInterfacedObject, IDataType, IDataVectorType)
|
||||
private
|
||||
// Registry for singleton type instances.
|
||||
class var
|
||||
FVectorTypeRegistry: TDictionary<String, IDataVectorType>;
|
||||
|
||||
FElementType: IDataType;
|
||||
FElementCount: Integer;
|
||||
FName: string;
|
||||
function GetName: String;
|
||||
function GetKind: TDataKind;
|
||||
function GetElementType: IDataType;
|
||||
function GetElementCount: Integer;
|
||||
function CreateValue(const AItems: array of IDataValue): IDataVectorValue;
|
||||
|
||||
class constructor Create;
|
||||
class destructor Destroy;
|
||||
public
|
||||
constructor Create(const AElementType: IDataType; const AElementCount: Integer);
|
||||
|
||||
// Gets a cached or new instance for the given element type and count.
|
||||
class function GetInstance(const AElementType: IDataType; const AElementCount: Integer): IDataVectorType; static;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
System.SysUtils;
|
||||
|
||||
type
|
||||
// Implements a generic vector value for N > 4 elements.
|
||||
TImplDataVectorValue = class(TInterfacedObject, IDataVectorValue)
|
||||
private
|
||||
FDataType: IDataVectorType;
|
||||
FItems: TArray<IDataValue>;
|
||||
function GetDataType: IDataType;
|
||||
function GetAsString: string;
|
||||
function GetElementCount: Integer;
|
||||
function GetItem(Idx: Integer): IDataValue;
|
||||
public
|
||||
constructor Create(const ADataType: IDataVectorType; const AItems: array of IDataValue);
|
||||
end;
|
||||
|
||||
// Optimized implementation for a vector with 1 element.
|
||||
TImplDataVectorValue1 = class(TInterfacedObject, IDataValue, IDataVectorValue)
|
||||
private
|
||||
FDataType: IDataVectorType;
|
||||
FItem0: IDataValue;
|
||||
function GetDataType: IDataType;
|
||||
function GetAsString: string;
|
||||
function GetElementCount: Integer;
|
||||
function GetItem(Idx: Integer): IDataValue;
|
||||
public
|
||||
constructor Create(const ADataType: IDataVectorType; const AItems: array of IDataValue);
|
||||
end;
|
||||
|
||||
// Optimized implementation for a vector with 2 elements.
|
||||
TImplDataVectorValue2 = class(TInterfacedObject, IDataValue, IDataVectorValue)
|
||||
private
|
||||
FDataType: IDataVectorType;
|
||||
FItem0, FItem1: IDataValue;
|
||||
function GetDataType: IDataType;
|
||||
function GetAsString: string;
|
||||
function GetElementCount: Integer;
|
||||
function GetItem(Idx: Integer): IDataValue;
|
||||
public
|
||||
constructor Create(const ADataType: IDataVectorType; const AItems: array of IDataValue);
|
||||
end;
|
||||
|
||||
// Optimized implementation for a vector with 3 elements.
|
||||
TImplDataVectorValue3 = class(TInterfacedObject, IDataValue, IDataVectorValue)
|
||||
private
|
||||
FDataType: IDataVectorType;
|
||||
FItem0, FItem1, FItem2: IDataValue;
|
||||
function GetDataType: IDataType;
|
||||
function GetAsString: string;
|
||||
function GetElementCount: Integer;
|
||||
function GetItem(Idx: Integer): IDataValue;
|
||||
public
|
||||
constructor Create(const ADataType: IDataVectorType; const AItems: array of IDataValue);
|
||||
end;
|
||||
|
||||
// Optimized implementation for a vector with 4 elements.
|
||||
TImplDataVectorValue4 = class(TInterfacedObject, IDataValue, IDataVectorValue)
|
||||
private
|
||||
FDataType: IDataVectorType;
|
||||
FItem0, FItem1, FItem2, FItem3: IDataValue;
|
||||
function GetDataType: IDataType;
|
||||
function GetAsString: string;
|
||||
function GetElementCount: Integer;
|
||||
function GetItem(Idx: Integer): IDataValue;
|
||||
public
|
||||
constructor Create(const ADataType: IDataVectorType; const AItems: array of IDataValue);
|
||||
end;
|
||||
|
||||
{ TImplDataVectorValue }
|
||||
|
||||
constructor TImplDataVectorValue.Create(const ADataType: IDataVectorType; const AItems: array of IDataValue);
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
inherited Create;
|
||||
FDataType := ADataType;
|
||||
SetLength(FItems, Length(AItems));
|
||||
for i := 0 to High(FItems) do
|
||||
FItems[i] := AItems[i];
|
||||
end;
|
||||
|
||||
function TImplDataVectorValue.GetAsString: string;
|
||||
var
|
||||
i: Integer;
|
||||
sb: TStringBuilder;
|
||||
begin
|
||||
sb := TStringBuilder.Create;
|
||||
try
|
||||
sb.Append('(');
|
||||
for i := 0 to High(FItems) do
|
||||
begin
|
||||
if (i > 0) then
|
||||
sb.Append(', ');
|
||||
sb.Append(FItems[i].AsString);
|
||||
end;
|
||||
sb.Append(')');
|
||||
Result := sb.ToString;
|
||||
finally
|
||||
sb.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TImplDataVectorValue.GetDataType: IDataType;
|
||||
begin
|
||||
Result := FDataType;
|
||||
end;
|
||||
|
||||
function TImplDataVectorValue.GetElementCount: Integer;
|
||||
begin
|
||||
Result := Length(FItems);
|
||||
end;
|
||||
|
||||
function TImplDataVectorValue.GetItem(Idx: Integer): IDataValue;
|
||||
begin
|
||||
Result := FItems[Idx];
|
||||
end;
|
||||
|
||||
{ TImplDataVectorValue1 }
|
||||
|
||||
constructor TImplDataVectorValue1.Create(const ADataType: IDataVectorType; const AItems: array of IDataValue);
|
||||
begin
|
||||
inherited Create;
|
||||
FDataType := ADataType;
|
||||
FItem0 := AItems[0];
|
||||
end;
|
||||
|
||||
function TImplDataVectorValue1.GetAsString: string;
|
||||
begin
|
||||
Result := '(' + FItem0.AsString + ')';
|
||||
end;
|
||||
|
||||
function TImplDataVectorValue1.GetDataType: IDataType;
|
||||
begin
|
||||
Result := FDataType;
|
||||
end;
|
||||
|
||||
function TImplDataVectorValue1.GetElementCount: Integer;
|
||||
begin
|
||||
Result := 1;
|
||||
end;
|
||||
|
||||
function TImplDataVectorValue1.GetItem(Idx: Integer): IDataValue;
|
||||
begin
|
||||
case Idx of
|
||||
0: Result := FItem0;
|
||||
else
|
||||
raise EArgumentException.Create('Index out of bounds');
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TImplDataVectorValue2 }
|
||||
|
||||
constructor TImplDataVectorValue2.Create(const ADataType: IDataVectorType; const AItems: array of IDataValue);
|
||||
begin
|
||||
inherited Create;
|
||||
FDataType := ADataType;
|
||||
FItem0 := AItems[0];
|
||||
FItem1 := AItems[1];
|
||||
end;
|
||||
|
||||
function TImplDataVectorValue2.GetAsString: string;
|
||||
begin
|
||||
Result := '(' + FItem0.AsString + ', ' + FItem1.AsString + ')';
|
||||
end;
|
||||
|
||||
function TImplDataVectorValue2.GetDataType: IDataType;
|
||||
begin
|
||||
Result := FDataType;
|
||||
end;
|
||||
|
||||
function TImplDataVectorValue2.GetElementCount: Integer;
|
||||
begin
|
||||
Result := 2;
|
||||
end;
|
||||
|
||||
function TImplDataVectorValue2.GetItem(Idx: Integer): IDataValue;
|
||||
begin
|
||||
case Idx of
|
||||
0: Result := FItem0;
|
||||
1: Result := FItem1;
|
||||
else
|
||||
raise EArgumentException.Create('Index out of bounds');
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TImplDataVectorValue3 }
|
||||
|
||||
constructor TImplDataVectorValue3.Create(const ADataType: IDataVectorType; const AItems: array of IDataValue);
|
||||
begin
|
||||
inherited Create;
|
||||
FDataType := ADataType;
|
||||
FItem0 := AItems[0];
|
||||
FItem1 := AItems[1];
|
||||
FItem2 := AItems[2];
|
||||
end;
|
||||
|
||||
function TImplDataVectorValue3.GetAsString: string;
|
||||
begin
|
||||
Result := '(' + FItem0.AsString + ', ' + FItem1.AsString + ', ' + FItem2.AsString + ')';
|
||||
end;
|
||||
|
||||
function TImplDataVectorValue3.GetDataType: IDataType;
|
||||
begin
|
||||
Result := FDataType;
|
||||
end;
|
||||
|
||||
function TImplDataVectorValue3.GetElementCount: Integer;
|
||||
begin
|
||||
Result := 3;
|
||||
end;
|
||||
|
||||
function TImplDataVectorValue3.GetItem(Idx: Integer): IDataValue;
|
||||
begin
|
||||
case Idx of
|
||||
0: Result := FItem0;
|
||||
1: Result := FItem1;
|
||||
2: Result := FItem2;
|
||||
else
|
||||
raise EArgumentException.Create('Index out of bounds');
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TImplDataVectorValue4 }
|
||||
|
||||
constructor TImplDataVectorValue4.Create(const ADataType: IDataVectorType; const AItems: array of IDataValue);
|
||||
begin
|
||||
inherited Create;
|
||||
FDataType := ADataType;
|
||||
FItem0 := AItems[0];
|
||||
FItem1 := AItems[1];
|
||||
FItem2 := AItems[2];
|
||||
FItem3 := AItems[3];
|
||||
end;
|
||||
|
||||
function TImplDataVectorValue4.GetAsString: string;
|
||||
begin
|
||||
Result := '(' + FItem0.AsString + ', ' + FItem1.AsString + ', ' + FItem2.AsString + ', ' + FItem3.AsString + ')';
|
||||
end;
|
||||
|
||||
function TImplDataVectorValue4.GetDataType: IDataType;
|
||||
begin
|
||||
Result := FDataType;
|
||||
end;
|
||||
|
||||
function TImplDataVectorValue4.GetElementCount: Integer;
|
||||
begin
|
||||
Result := 4;
|
||||
end;
|
||||
|
||||
function TImplDataVectorValue4.GetItem(Idx: Integer): IDataValue;
|
||||
begin
|
||||
case Idx of
|
||||
0: Result := FItem0;
|
||||
1: Result := FItem1;
|
||||
2: Result := FItem2;
|
||||
3: Result := FItem3;
|
||||
else
|
||||
raise EArgumentException.Create('Index out of bounds');
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TImplDataVectorType }
|
||||
|
||||
class constructor TImplDataVectorType.Create;
|
||||
begin
|
||||
// Initialize the class-level type registry.
|
||||
FVectorTypeRegistry := TDictionary<String, IDataVectorType>.Create;
|
||||
end;
|
||||
|
||||
class destructor TImplDataVectorType.Destroy;
|
||||
begin
|
||||
// Free the class-level type registry.
|
||||
FVectorTypeRegistry.Free;
|
||||
FVectorTypeRegistry := nil;
|
||||
end;
|
||||
|
||||
constructor TImplDataVectorType.Create(const AElementType: IDataType; const AElementCount: Integer);
|
||||
begin
|
||||
inherited Create;
|
||||
if (AElementCount <= 0) then
|
||||
raise EArgumentException.Create('Element count must be greater than zero.');
|
||||
|
||||
FElementType := AElementType;
|
||||
FElementCount := AElementCount;
|
||||
FName := Format('Vector<%s>[%d]', [FElementType.Name, FElementCount]);
|
||||
end;
|
||||
|
||||
function TImplDataVectorType.CreateValue(const AItems: array of IDataValue): IDataVectorValue;
|
||||
var
|
||||
item: IDataValue;
|
||||
i: Integer;
|
||||
begin
|
||||
// Validate that the number of items matches the vector's element count.
|
||||
if (Length(AItems) <> FElementCount) then
|
||||
raise EArgumentException
|
||||
.CreateFmt('Invalid number of elements for vector. Expected %d, but got %d.', [FElementCount, Length(AItems)]);
|
||||
|
||||
// Validate that all items match the element type of this vector type.
|
||||
i := 0;
|
||||
for item in AItems do
|
||||
begin
|
||||
if (item.DataType <> FElementType) then
|
||||
raise EArgumentException.CreateFmt(
|
||||
'Invalid data type for item at index %d. Expected ''%s'', but got ''%s''.',
|
||||
[i, FElementType.Name, item.DataType.Name]);
|
||||
inc(i);
|
||||
end;
|
||||
|
||||
// Use optimized implementations for vectors with 1-4 elements.
|
||||
case FElementCount of
|
||||
1: Result := TImplDataVectorValue1.Create(Self, AItems);
|
||||
2: Result := TImplDataVectorValue2.Create(Self, AItems);
|
||||
3: Result := TImplDataVectorValue3.Create(Self, AItems);
|
||||
4: Result := TImplDataVectorValue4.Create(Self, AItems);
|
||||
else
|
||||
// Use the generic implementation for vectors with more than 4 elements.
|
||||
Result := TImplDataVectorValue.Create(Self, AItems);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TImplDataVectorType.GetElementCount: Integer;
|
||||
begin
|
||||
Result := FElementCount;
|
||||
end;
|
||||
|
||||
function TImplDataVectorType.GetElementType: IDataType;
|
||||
begin
|
||||
Result := FElementType;
|
||||
end;
|
||||
|
||||
function TImplDataVectorType.GetKind: TDataKind;
|
||||
begin
|
||||
Result := dkVector;
|
||||
end;
|
||||
|
||||
function TImplDataVectorType.GetName: String;
|
||||
begin
|
||||
Result := FName;
|
||||
end;
|
||||
|
||||
class function TImplDataVectorType.GetInstance(const AElementType: IDataType; const AElementCount: Integer): IDataVectorType;
|
||||
var
|
||||
key: string;
|
||||
begin
|
||||
if (AElementCount <= 0) then
|
||||
raise EArgumentException.Create('Element count must be greater than zero.');
|
||||
|
||||
if not Assigned(AElementType) then
|
||||
raise EArgumentException.Create('Cannot create a vector type with a nil element type.');
|
||||
|
||||
// Generate a unique key for the dictionary. Using a separator that is unlikely in a type name.
|
||||
key := AElementType.Name + '|' + AElementCount.ToString;
|
||||
|
||||
TMonitor.Enter(FVectorTypeRegistry);
|
||||
try
|
||||
if not FVectorTypeRegistry.TryGetValue(key, Result) then
|
||||
begin
|
||||
Result := TImplDataVectorType.Create(AElementType, AElementCount);
|
||||
FVectorTypeRegistry.Add(key, Result);
|
||||
end;
|
||||
finally
|
||||
TMonitor.Exit(FVectorTypeRegistry);
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
+157
-3
@@ -6,7 +6,7 @@ uses
|
||||
System.SysUtils;
|
||||
|
||||
type
|
||||
TDataKind = (dkVoid, dkOrdinal, dkFloat, dkText, dkTimestamp, dkDecimal, dkRecord, dkTuple, dkArray, dkEnum, dkMethod);
|
||||
TDataKind = (dkVoid, dkOrdinal, dkFloat, dkText, dkTimestamp, dkDecimal, dkRecord, dkTuple, dkArray, dkVector, dkEnum, dkMethod);
|
||||
|
||||
IDataType = interface
|
||||
{$region 'private'}
|
||||
@@ -189,6 +189,27 @@ type
|
||||
property ElementType: IDataType read GetElementType;
|
||||
end;
|
||||
|
||||
// Represents a fixed-size vector of data values.
|
||||
IDataVectorValue = interface(IDataValue)
|
||||
{$region 'private'}
|
||||
function GetElementCount: Integer;
|
||||
function GetItem(Idx: Integer): IDataValue;
|
||||
{$endregion}
|
||||
property ElementCount: Integer read GetElementCount;
|
||||
property Items[Idx: Integer]: IDataValue read GetItem; default;
|
||||
end;
|
||||
|
||||
// Represents the type of a fixed-size vector.
|
||||
IDataVectorType = interface(IDataType)
|
||||
{$region 'private'}
|
||||
function GetElementType: IDataType;
|
||||
function GetElementCount: Integer;
|
||||
{$endregion}
|
||||
function CreateValue(const AItems: array of IDataValue): IDataVectorValue;
|
||||
property ElementType: IDataType read GetElementType;
|
||||
property ElementCount: Integer read GetElementCount;
|
||||
end;
|
||||
|
||||
TDataType = record
|
||||
type
|
||||
TValue = record
|
||||
@@ -207,6 +228,7 @@ type
|
||||
function AsRecord: IDataRecordValue; inline;
|
||||
function AsTuple: IDataTupleValue; inline;
|
||||
function AsArray: IDataArrayValue; inline;
|
||||
function AsVector: IDataVectorValue; inline;
|
||||
function AsEnum: IDataEnumValue; inline;
|
||||
function AsMethod: IDataMethodValue; inline;
|
||||
function AsVoid: IDataVoidValue; inline;
|
||||
@@ -479,6 +501,36 @@ type
|
||||
property ElementType: IDataType read GetElementType;
|
||||
end;
|
||||
|
||||
TVector = record
|
||||
type
|
||||
TValue = record
|
||||
private
|
||||
FVectorValue: IDataVectorValue;
|
||||
function GetDataType: TDataType.TVector;
|
||||
function GetItems(Idx: Integer): TDataType.TValue; inline;
|
||||
function GetElementCount: Integer; inline;
|
||||
public
|
||||
constructor Create(const AVectorValue: IDataVectorValue);
|
||||
class operator Implicit(const A: IDataVectorValue): TDataType.TVector.TValue; overload; inline;
|
||||
class operator Implicit(const A: TDataType.TVector.TValue): IDataVectorValue; overload; inline;
|
||||
class operator Implicit(const A: TDataType.TVector.TValue): TDataType.TValue; overload; inline;
|
||||
property ElementCount: Integer read GetElementCount;
|
||||
property Items[Idx: Integer]: TDataType.TValue read GetItems; default;
|
||||
property DataType: TDataType.TVector read GetDataType;
|
||||
end;
|
||||
private
|
||||
FVectorType: IDataVectorType;
|
||||
function GetElementType: IDataType; inline;
|
||||
function GetElementCount: Integer; inline;
|
||||
public
|
||||
constructor Create(const AVectorType: IDataVectorType);
|
||||
class operator Implicit(const A: IDataVectorType): TDataType.TVector; overload; inline;
|
||||
class operator Implicit(const A: TDataType.TVector): IDataVectorType; overload; inline;
|
||||
function CreateValue(const AItems: array of IDataValue): TDataType.TVector.TValue;
|
||||
property ElementType: IDataType read GetElementType;
|
||||
property ElementCount: Integer read GetElementCount;
|
||||
end;
|
||||
|
||||
TMethod = record
|
||||
type
|
||||
TProc = reference to function(const AValue: TDataType.TValue): TDataType.TValue;
|
||||
@@ -530,6 +582,7 @@ type
|
||||
class operator Implicit(const A: TDataType.TRecord): TDataType; overload; inline;
|
||||
class operator Implicit(const A: TDataType.TTuple): TDataType; overload; inline;
|
||||
class operator Implicit(const A: TDataType.TArray): TDataType; overload; inline;
|
||||
class operator Implicit(const A: TDataType.TVector): TDataType; overload; inline;
|
||||
|
||||
// Type factories
|
||||
class function Void: TDataType.TVoid; static; inline;
|
||||
@@ -541,8 +594,10 @@ type
|
||||
class function Tuple: TDataType.TTuple; static; inline;
|
||||
class function MethodOf(const AArgType, AResultType: IDataType): TDataType.TMethod; static;
|
||||
class function ArrayOf(const AElementType: IDataType): TDataType.TArray; static;
|
||||
class function VectorOf(const AElementType: IDataType; const AElementCount: Integer): TDataType.TVector; static;
|
||||
class function RecordOf(const Fields: TArray<TDataRecordField>): TDataType.TRecord; overload; static;
|
||||
class function RecordOf(const Fields: array of TDataRecordField): TDataType.TRecord; overload; static;
|
||||
class function RecordOf<T>: TDataType.TRecord; overload; static;
|
||||
class function EnumOf(const AName: string; const AIdentifiers: array of string): TDataType.TEnum; static;
|
||||
|
||||
function AsOrdinal: TDataType.TOrdinal; inline;
|
||||
@@ -553,6 +608,7 @@ type
|
||||
function AsRecord: TDataType.TRecord; inline;
|
||||
function AsTuple: TDataType.TTuple; inline;
|
||||
function AsArray: TDataType.TArray; inline;
|
||||
function AsVector: TDataType.TVector; inline;
|
||||
function AsEnum: TDataType.TEnum; inline;
|
||||
function AsMethod: TDataType.TMethod; inline;
|
||||
|
||||
@@ -572,6 +628,7 @@ uses
|
||||
Myc.Data.Types.Timestamp,
|
||||
Myc.Data.Types.Decimal,
|
||||
Myc.Data.Types.Arrays,
|
||||
Myc.Data.Types.Vector,
|
||||
Myc.Data.Types.Records,
|
||||
Myc.Data.Types.Tuple,
|
||||
Myc.Data.Types.Enum,
|
||||
@@ -1264,6 +1321,75 @@ begin
|
||||
Result := A.FArrayType;
|
||||
end;
|
||||
|
||||
{ TDataType.TVector.TValue }
|
||||
|
||||
constructor TDataType.TVector.TValue.Create(const AVectorValue: IDataVectorValue);
|
||||
begin
|
||||
FVectorValue := AVectorValue;
|
||||
end;
|
||||
|
||||
function TDataType.TVector.TValue.GetDataType: TDataType.TVector;
|
||||
begin
|
||||
Result := IDataVectorType(FVectorValue.DataType);
|
||||
end;
|
||||
|
||||
function TDataType.TVector.TValue.GetElementCount: Integer;
|
||||
begin
|
||||
Result := FVectorValue.ElementCount;
|
||||
end;
|
||||
|
||||
function TDataType.TVector.TValue.GetItems(Idx: Integer): TDataType.TValue;
|
||||
begin
|
||||
Result.Create(FVectorValue.Items[Idx]);
|
||||
end;
|
||||
|
||||
class operator TDataType.TVector.TValue.Implicit(const A: IDataVectorValue): TDataType.TVector.TValue;
|
||||
begin
|
||||
Result.FVectorValue := A;
|
||||
end;
|
||||
|
||||
class operator TDataType.TVector.TValue.Implicit(const A: TDataType.TVector.TValue): IDataVectorValue;
|
||||
begin
|
||||
Result := A.FVectorValue;
|
||||
end;
|
||||
|
||||
class operator TDataType.TVector.TValue.Implicit(const A: TDataType.TVector.TValue): TDataType.TValue;
|
||||
begin
|
||||
Result.Create(A.FVectorValue);
|
||||
end;
|
||||
|
||||
{ TDataType.TVector }
|
||||
|
||||
constructor TDataType.TVector.Create(const AVectorType: IDataVectorType);
|
||||
begin
|
||||
FVectorType := AVectorType;
|
||||
end;
|
||||
|
||||
function TDataType.TVector.CreateValue(const AItems: array of IDataValue): TDataType.TVector.TValue;
|
||||
begin
|
||||
Result.Create(FVectorType.CreateValue(AItems));
|
||||
end;
|
||||
|
||||
function TDataType.TVector.GetElementCount: Integer;
|
||||
begin
|
||||
Result := FVectorType.ElementCount;
|
||||
end;
|
||||
|
||||
function TDataType.TVector.GetElementType: IDataType;
|
||||
begin
|
||||
Result := FVectorType.ElementType;
|
||||
end;
|
||||
|
||||
class operator TDataType.TVector.Implicit(const A: IDataVectorType): TDataType.TVector;
|
||||
begin
|
||||
Result.FVectorType := A;
|
||||
end;
|
||||
|
||||
class operator TDataType.TVector.Implicit(const A: TDataType.TVector): IDataVectorType;
|
||||
begin
|
||||
Result := A.FVectorType;
|
||||
end;
|
||||
|
||||
{ TDataType }
|
||||
|
||||
constructor TDataType.Create(const ADataType: IDataType);
|
||||
@@ -1330,16 +1456,19 @@ end;
|
||||
|
||||
class function TDataType.RecordOf(const Fields: TArray<TDataRecordField>): TDataType.TRecord;
|
||||
begin
|
||||
// The TImplDataRecordType now manages its own instances.
|
||||
Result.Create(TImplDataRecordType.GetInstance(Fields));
|
||||
end;
|
||||
|
||||
class function TDataType.RecordOf(const Fields: array of TDataRecordField): TDataType.TRecord;
|
||||
begin
|
||||
// The TImplDataRecordType now manages its own instances.
|
||||
Result.Create(TImplDataRecordType.GetInstance(Fields));
|
||||
end;
|
||||
|
||||
class function TDataType.RecordOf<T>: TDataType.TRecord;
|
||||
begin
|
||||
Result.Create(TImplDataRecordType.GetInstance<T>);
|
||||
end;
|
||||
|
||||
class function TDataType.Text: TDataType.TText;
|
||||
begin
|
||||
Result.Create(TImplDataTextType.Singleton);
|
||||
@@ -1355,6 +1484,12 @@ begin
|
||||
Result.Create(TImplDataTupleType.Singleton);
|
||||
end;
|
||||
|
||||
class function TDataType.VectorOf(const AElementType: IDataType; const AElementCount: Integer): TDataType.TVector;
|
||||
begin
|
||||
// The TImplDataVectorType now manages its own instances.
|
||||
Result.Create(TImplDataVectorType.GetInstance(AElementType, AElementCount));
|
||||
end;
|
||||
|
||||
class function TDataType.Void: TDataType.TVoid;
|
||||
begin
|
||||
Result.Create(TImplDataVoidType.Singleton);
|
||||
@@ -1375,6 +1510,11 @@ begin
|
||||
Result.FDataType := A.FArrayType;
|
||||
end;
|
||||
|
||||
class operator TDataType.Implicit(const A: TDataType.TVector): TDataType;
|
||||
begin
|
||||
Result.FDataType := A.FVectorType;
|
||||
end;
|
||||
|
||||
class operator TDataType.Implicit(const A: TDataType.TDecimal): TDataType;
|
||||
begin
|
||||
Result.FDataType := A.FDecimalType;
|
||||
@@ -1503,6 +1643,13 @@ begin
|
||||
Result := IDataTupleValue(FDataValue);
|
||||
end;
|
||||
|
||||
function TDataType.TValue.AsVector: IDataVectorValue;
|
||||
begin
|
||||
if (FDataValue.DataType.Kind <> dkVector) then
|
||||
raise EInvalidCast.Create('Vector expected');
|
||||
Result := IDataVectorValue(FDataValue);
|
||||
end;
|
||||
|
||||
function TDataType.TValue.AsVoid: IDataVoidValue;
|
||||
begin
|
||||
if (FDataValue.DataType.Kind <> dkVoid) then
|
||||
@@ -1598,4 +1745,11 @@ begin
|
||||
Result.Create(IDataTupleType(FDataType));
|
||||
end;
|
||||
|
||||
function TDataType.AsVector: TDataType.TVector;
|
||||
begin
|
||||
if (FDataType.Kind <> dkVector) then
|
||||
raise EInvalidCast.Create('Vector expected');
|
||||
Result.Create(IDataVectorType(FDataType));
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
Reference in New Issue
Block a user