unit Myc.Data.Types; interface uses System.Generics.Collections, System.SysUtils, System.RTTI; type TDataKind = (dkOrdinal, dkFloat, dkText, dkTimestamp, dkRecord, dkTuple, dkArray, dkEnum, dkMethod); IDataType = interface function GetName: String; function GetKind: TDataKind; property Name: String read GetName; property Kind: TDataKind read GetKind; end; IDataValue = interface function GetDataType: IDataType; function GetAsString: string; function AsTValue: TValue; property DataType: IDataType read GetDataType; property AsString: string read GetAsString; end; IDataOrdinalValue = interface(IDataValue) function GetValue: Int64; property Value: Int64 read GetValue; end; // Helper for IDataOrdinalValue TDataOrdinalValue = record private FOrdinalValue: IDataOrdinalValue; function GetValue: Int64; inline; public constructor Create(const AOrdinalValue: IDataOrdinalValue); class operator Implicit(const A: IDataOrdinalValue): TDataOrdinalValue; overload; class operator Implicit(const A: TDataOrdinalValue): IDataOrdinalValue; overload; property Value: Int64 read GetValue; end; IDataOrdinalType = interface(IDataType) function CreateValue(Init: Int64): IDataOrdinalValue; end; // Helper for IDataOrdinalType TDataOrdinalType = record private FOrdinalType: IDataOrdinalType; public constructor Create(const AOrdinalType: IDataOrdinalType); class operator Implicit(const A: IDataOrdinalType): TDataOrdinalType; overload; class operator Implicit(const A: TDataOrdinalType): IDataOrdinalType; overload; function CreateValue(Init: Int64): TDataOrdinalValue; inline; end; IDataFloatValue = interface(IDataValue) function GetValue: Double; property Value: Double read GetValue; end; // Helper for IDataFloatValue TDataFloatValue = record private FFloatValue: IDataFloatValue; function GetValue: Double; inline; public constructor Create(const AFloatValue: IDataFloatValue); class operator Implicit(const A: IDataFloatValue): TDataFloatValue; overload; class operator Implicit(const A: TDataFloatValue): IDataFloatValue; overload; property Value: Double read GetValue; end; IDataFloatType = interface(IDataType) function CreateValue(Init: Double): IDataFloatValue; end; // Helper for IDataFloatType TDataFloatType = record private FFloatType: IDataFloatType; public constructor Create(const AFloatType: IDataFloatType); class operator Implicit(const A: IDataFloatType): TDataFloatType; overload; class operator Implicit(const A: TDataFloatType): IDataFloatType; overload; function CreateValue(Init: Double): TDataFloatValue; inline; end; IDataTextValue = interface(IDataValue) function GetValue: string; property Value: string read GetValue; end; // Helper for IDataTextValue TDataTextValue = record private FTextValue: IDataTextValue; function GetValue: string; inline; public constructor Create(const ATextValue: IDataTextValue); class operator Implicit(const A: IDataTextValue): TDataTextValue; overload; class operator Implicit(const A: TDataTextValue): IDataTextValue; overload; property Value: string read GetValue; end; IDataTextType = interface(IDataType) function CreateValue(const AValue: string): IDataTextValue; end; // Helper for IDataTextType TDataTextType = record private FTextType: IDataTextType; public constructor Create(const ATextType: IDataTextType); class operator Implicit(const A: IDataTextType): TDataTextType; overload; class operator Implicit(const A: TDataTextType): IDataTextType; overload; function CreateValue(const AValue: string): TDataTextValue; inline; end; IDataTimestampValue = interface(IDataValue) function GetValue: TDateTime; property Value: TDateTime read GetValue; end; // Helper for IDataTimestampValue TDataTimestampValue = record private FTimestampValue: IDataTimestampValue; function GetValue: TDateTime; inline; public constructor Create(const ATimestampValue: IDataTimestampValue); class operator Implicit(const A: IDataTimestampValue): TDataTimestampValue; overload; class operator Implicit(const A: TDataTimestampValue): IDataTimestampValue; overload; property Value: TDateTime read GetValue; end; IDataTimestampType = interface(IDataType) function CreateValue(const AValue: TDateTime): IDataTimestampValue; end; // Helper for IDataTimestampType TDataTimestampType = record private FTimestampType: IDataTimestampType; public constructor Create(const ATimestampType: IDataTimestampType); class operator Implicit(const A: IDataTimestampType): TDataTimestampType; overload; class operator Implicit(const A: TDataTimestampType): IDataTimestampType; overload; function CreateValue(const AValue: TDateTime): TDataTimestampValue; inline; end; IDataEnumValue = interface(IDataValue) function GetValue: Integer; property Value: Integer read GetValue; end; // Helper for IDataEnumValue TDataEnumValue = record private FEnumValue: IDataEnumValue; function GetValue: Integer; inline; public constructor Create(const AEnumValue: IDataEnumValue); class operator Implicit(const A: IDataEnumValue): TDataEnumValue; overload; class operator Implicit(const A: TDataEnumValue): IDataEnumValue; overload; property Value: Integer read GetValue; end; IDataEnumType = interface(IDataType) function GetIdentifier(Idx: Integer): string; function GetIdentifierCount: Integer; function IndexOf(const AIdentifier: string): Integer; function CreateValue(const AValue: Integer): IDataEnumValue; overload; function CreateValue(const AIdentifier: string): IDataEnumValue; overload; property IdentifierCount: Integer read GetIdentifierCount; property Identifiers[Idx: Integer]: string read GetIdentifier; default; end; // Helper for IDataEnumType TDataEnumType = record private FEnumType: IDataEnumType; function GetIdentifier(Idx: Integer): string; inline; function GetIdentifierCount: Integer; inline; public constructor Create(const AEnumType: IDataEnumType); class operator Implicit(const A: IDataEnumType): TDataEnumType; overload; class operator Implicit(const A: TDataEnumType): IDataEnumType; overload; function IndexOf(const AIdentifier: string): Integer; inline; function CreateValue(const AValue: Integer): TDataEnumValue; overload; inline; function CreateValue(const AIdentifier: string): TDataEnumValue; overload; inline; property IdentifierCount: Integer read GetIdentifierCount; property Identifiers[Idx: Integer]: string read GetIdentifier; default; end; // A method that transforms one data value into another. TDataMethodProc = reference to function(const AValue: IDataValue): IDataValue; // Represents an executable method data value. IDataMethodValue = interface(IDataValue) {$region 'private'} function GetValue: TDataMethodProc; {$endregion} property Value: TDataMethodProc read GetValue; end; // Helper for IDataMethodValue TDataMethodValue = record private FMethodValue: IDataMethodValue; function GetValue: TDataMethodProc; inline; public constructor Create(const AMethodValue: IDataMethodValue); class operator Implicit(const A: IDataMethodValue): TDataMethodValue; overload; class operator Implicit(const A: TDataMethodValue): IDataMethodValue; overload; property Value: TDataMethodProc read GetValue; end; // Represents the type of a method data value, including its signature. IDataMethodType = interface(IDataType) {$region 'private'} function GetArgType: IDataType; function GetResultType: IDataType; {$endregion} property ArgType: IDataType read GetArgType; property ResultType: IDataType read GetResultType; function CreateValue(const AValue: TDataMethodProc): IDataMethodValue; end; // Helper for IDataMethodType TDataMethodType = record private FMethodType: IDataMethodType; function GetArgType: IDataType; inline; function GetResultType: IDataType; inline; public constructor Create(const AMethodType: IDataMethodType); class operator Implicit(const A: IDataMethodType): TDataMethodType; overload; class operator Implicit(const A: TDataMethodType): IDataMethodType; overload; property ArgType: IDataType read GetArgType; property ResultType: IDataType read GetResultType; function CreateValue(const AValue: TDataMethodProc): TDataMethodValue; inline; end; IDataRecordValue = interface(IDataValue) function GetItem(Idx: Integer): IDataValue; property Items[Idx: Integer]: IDataValue read GetItem; default; end; // Helper for IDataRecordValue TDataRecordValue = record private FRecordValue: IDataRecordValue; function GetItem(Idx: Integer): IDataValue; inline; public constructor Create(const ARecordValue: IDataRecordValue); class operator Implicit(const A: IDataRecordValue): TDataRecordValue; overload; class operator Implicit(const A: TDataRecordValue): IDataRecordValue; overload; property Items[Idx: Integer]: IDataValue read GetItem; default; end; TRecordField = record Name: string; DataType: IDataType; constructor Create(const AName: string; const ADataType: IDataType); end; IDataRecordType = interface(IDataType) function GetFieldCount: Integer; function GetField(Idx: Integer): TRecordField; function IndexOf(const AName: string): Integer; function CreateValue(const AItems: array of IDataValue): IDataRecordValue; property FieldCount: Integer read GetFieldCount; property Fields[Idx: Integer]: TRecordField read GetField; default; end; // Helper for IDataRecordType TDataRecordType = record private FRecordType: IDataRecordType; function GetFieldCount: Integer; inline; function GetField(Idx: Integer): TRecordField; inline; public constructor Create(const ARecordType: IDataRecordType); class operator Implicit(const A: IDataRecordType): TDataRecordType; overload; class operator Implicit(const A: TDataRecordType): IDataRecordType; overload; function IndexOf(const AName: string): Integer; inline; function CreateValue(const AItems: array of IDataValue): TDataRecordValue; property FieldCount: Integer read GetFieldCount; property Fields[Idx: Integer]: TRecordField read GetField; default; end; IDataTupleValue = interface(IDataValue) function GetItemCount: Integer; function GetItem(Idx: Integer): IDataValue; property ItemCount: Integer read GetItemCount; property Items[Idx: Integer]: IDataValue read GetItem; default; end; // Helper for IDataTupleValue TDataTupleValue = record private FTupleValue: IDataTupleValue; function GetItemCount: Integer; inline; function GetItem(Idx: Integer): IDataValue; inline; public constructor Create(const ATupleValue: IDataTupleValue); class operator Implicit(const A: IDataTupleValue): TDataTupleValue; overload; class operator Implicit(const A: TDataTupleValue): IDataTupleValue; overload; property ItemCount: Integer read GetItemCount; property Items[Idx: Integer]: IDataValue read GetItem; default; end; IDataTupleType = interface(IDataType) function CreateValue(const AItems: array of IDataValue): IDataTupleValue; end; // Helper for IDataTupleType TDataTupleType = record private FTupleType: IDataTupleType; public constructor Create(const ATupleType: IDataTupleType); class operator Implicit(const A: IDataTupleType): TDataTupleType; overload; class operator Implicit(const A: TDataTupleType): IDataTupleType; overload; function CreateValue(const AItems: array of IDataValue): TDataTupleValue; end; IDataArrayValue = interface(IDataValue) function GetElementCount: Integer; function GetItem(Idx: Integer): IDataValue; property ElementCount: Integer read GetElementCount; property Items[Idx: Integer]: IDataValue read GetItem; default; end; // Helper for IDataArrayValue TDataArrayValue = record private FArrayValue: IDataArrayValue; function GetElementCount: Integer; inline; function GetItem(Idx: Integer): IDataValue; inline; public constructor Create(const AArrayValue: IDataArrayValue); class operator Implicit(const A: IDataArrayValue): TDataArrayValue; overload; class operator Implicit(const A: TDataArrayValue): IDataArrayValue; overload; property ElementCount: Integer read GetElementCount; property Items[Idx: Integer]: IDataValue read GetItem; default; end; IDataArrayType = interface(IDataType) function GetElementType: IDataType; function CreateValue(const AItems: array of IDataValue): IDataArrayValue; property ElementType: IDataType read GetElementType; end; // Helper for IDataArrayType TDataArrayType = record private FArrayType: IDataArrayType; function GetElementType: IDataType; inline; public constructor Create(const AArrayType: IDataArrayType); class operator Implicit(const A: IDataArrayType): TDataArrayType; overload; class operator Implicit(const A: TDataArrayType): IDataArrayType; overload; function CreateValue(const AItems: array of IDataValue): TDataArrayValue; property ElementType: IDataType read GetElementType; end; TDataType = record strict private FDataType: IDataType; function GetName: String; inline; function GetKind: TDataKind; inline; class var FArrayTypeRegistry: TDictionary; FRecordTypeRegistry: TDictionary, IDataRecordType>; FMethodTypeRegistry: TDictionary, IDataMethodType>; class constructor CreateClass; class destructor DestroyClass; public constructor Create(const ADataType: IDataType); class operator Implicit(const A: IDataType): TDataType; overload; class operator Implicit(const A: TDataType): IDataType; overload; class operator Implicit(const A: TDataOrdinalType): TDataType; overload; class operator Implicit(const A: TDataFloatType): TDataType; overload; class operator Implicit(const A: TDataTextType): TDataType; overload; class operator Implicit(const A: TDataTimestampType): TDataType; overload; class operator Implicit(const A: TDataEnumType): TDataType; overload; class operator Implicit(const A: TDataMethodType): TDataType; overload; class operator Implicit(const A: TDataRecordType): TDataType; overload; class operator Implicit(const A: TDataTupleType): TDataType; overload; class operator Implicit(const A: TDataArrayType): TDataType; overload; // Type factories class function Ordinal: TDataOrdinalType; static; class function Float: TDataFloatType; static; class function Text: TDataTextType; static; class function Timestamp: TDataTimestampType; static; class function Tuple: TDataTupleType; static; class function MethodOf(const AArgType, AResultType: IDataType): TDataMethodType; static; class function ArrayOf(const AElementType: IDataType): TDataArrayType; static; class function RecordOf(const Fields: TArray): TDataRecordType; overload; static; class function RecordOf(const Fields: array of TRecordField): TDataRecordType; overload; static; class function EnumOf(const AName: string; const AIdentifiers: array of string): TDataEnumType; static; // Casting function AsOrdinal: TDataOrdinalType; function AsFloat: TDataFloatType; function AsText: TDataTextType; function AsTimestamp: TDataTimestampType; function AsRecord: TDataRecordType; function AsTuple: TDataTupleType; function AsArray: TDataArrayType; function AsEnum: TDataEnumType; function AsMethod: TDataMethodType; property DataType: IDataType read FDataType; property Name: String read GetName; property Kind: TDataKind read GetKind; end; TDataValue = record private FDataValue: IDataValue; function GetDataType: IDataType; inline; public constructor Create(const ADataValue: IDataValue); // Casting function AsOrdinal: TDataOrdinalValue; function AsFloat: TDataFloatValue; function AsText: TDataTextValue; function AsTimestamp: TDataTimestampValue; function AsRecord: TDataRecordValue; function AsTuple: TDataTupleValue; function AsArray: TDataArrayValue; function AsEnum: TDataEnumValue; function AsMethod: TDataMethodValue; class operator Implicit(const A: IDataValue): TDataValue; overload; class operator Implicit(const A: TDataValue): IDataValue; overload; class operator Implicit(const A: TDataOrdinalValue): TDataValue; overload; class operator Implicit(const A: TDataFloatValue): TDataValue; overload; class operator Implicit(const A: TDataTextValue): TDataValue; overload; class operator Implicit(const A: TDataTimestampValue): TDataValue; overload; class operator Implicit(const A: TDataEnumValue): TDataValue; overload; class operator Implicit(const A: TDataMethodValue): TDataValue; overload; class operator Implicit(const A: TDataRecordValue): TDataValue; overload; class operator Implicit(const A: TDataTupleValue): TDataValue; overload; class operator Implicit(const A: TDataArrayValue): TDataValue; overload; // Value factories class function FromOrdinal(const AValue: Int64): TDataOrdinalValue; static; class function FromFloat(const AValue: Double): TDataFloatValue; static; class function FromText(const AValue: string): TDataTextValue; static; class function FromTimestamp(const AValue: TDateTime): TDataTimestampValue; static; class function FromTuple(const AItems: array of IDataValue): TDataTupleValue; static; class function FromMethod(const AMethodType: TDataMethodType; const AValue: TDataMethodProc): TDataMethodValue; static; property DataValue: IDataValue read FDataValue; property DataType: IDataType read GetDataType; end; implementation uses System.SyncObjs, System.Generics.Defaults, Myc.Data.Types.Ordinal, Myc.Data.Types.Float, Myc.Data.Types.Text, Myc.Data.Types.Timestamp, Myc.Data.Types.Arrays, Myc.Data.Types.Records, Myc.Data.Types.Tuple, Myc.Data.Types.Enum, Myc.Data.Types.Method; { TRecordField } constructor TRecordField.Create(const AName: string; const ADataType: IDataType); begin Name := AName; DataType := ADataType; end; { TDataOrdinalValue } constructor TDataOrdinalValue.Create(const AOrdinalValue: IDataOrdinalValue); begin FOrdinalValue := AOrdinalValue; end; function TDataOrdinalValue.GetValue: Int64; begin Result := FOrdinalValue.Value; end; class operator TDataOrdinalValue.Implicit(const A: TDataOrdinalValue): IDataOrdinalValue; begin Result := A.FOrdinalValue; end; class operator TDataOrdinalValue.Implicit(const A: IDataOrdinalValue): TDataOrdinalValue; begin Result.FOrdinalValue := A; end; { TDataOrdinalType } constructor TDataOrdinalType.Create(const AOrdinalType: IDataOrdinalType); begin FOrdinalType := AOrdinalType; end; function TDataOrdinalType.CreateValue(Init: Int64): TDataOrdinalValue; begin Result := FOrdinalType.CreateValue(Init); end; class operator TDataOrdinalType.Implicit(const A: TDataOrdinalType): IDataOrdinalType; begin Result := A.FOrdinalType; end; class operator TDataOrdinalType.Implicit(const A: IDataOrdinalType): TDataOrdinalType; begin Result.FOrdinalType := A; end; { TDataFloatValue } constructor TDataFloatValue.Create(const AFloatValue: IDataFloatValue); begin FFloatValue := AFloatValue; end; function TDataFloatValue.GetValue: Double; begin Result := FFloatValue.Value; end; class operator TDataFloatValue.Implicit(const A: IDataFloatValue): TDataFloatValue; begin Result.FFloatValue := A; end; class operator TDataFloatValue.Implicit(const A: TDataFloatValue): IDataFloatValue; begin Result := A.FFloatValue; end; { TDataFloatType } constructor TDataFloatType.Create(const AFloatType: IDataFloatType); begin FFloatType := AFloatType; end; function TDataFloatType.CreateValue(Init: Double): TDataFloatValue; begin Result := FFloatType.CreateValue(Init); end; class operator TDataFloatType.Implicit(const A: IDataFloatType): TDataFloatType; begin Result.FFloatType := A; end; class operator TDataFloatType.Implicit(const A: TDataFloatType): IDataFloatType; begin Result := A.FFloatType; end; { TDataTextValue } constructor TDataTextValue.Create(const ATextValue: IDataTextValue); begin FTextValue := ATextValue; end; function TDataTextValue.GetValue: string; begin Result := FTextValue.Value; end; class operator TDataTextValue.Implicit(const A: IDataTextValue): TDataTextValue; begin Result.FTextValue := A; end; class operator TDataTextValue.Implicit(const A: TDataTextValue): IDataTextValue; begin Result := A.FTextValue; end; { TDataTextType } constructor TDataTextType.Create(const ATextType: IDataTextType); begin FTextType := ATextType; end; function TDataTextType.CreateValue(const AValue: string): TDataTextValue; begin Result := FTextType.CreateValue(AValue); end; class operator TDataTextType.Implicit(const A: IDataTextType): TDataTextType; begin Result.FTextType := A; end; class operator TDataTextType.Implicit(const A: TDataTextType): IDataTextType; begin Result := A.FTextType; end; { TDataTimestampValue } constructor TDataTimestampValue.Create(const ATimestampValue: IDataTimestampValue); begin FTimestampValue := ATimestampValue; end; function TDataTimestampValue.GetValue: TDateTime; begin Result := FTimestampValue.Value; end; class operator TDataTimestampValue.Implicit(const A: IDataTimestampValue): TDataTimestampValue; begin Result.FTimestampValue := A; end; class operator TDataTimestampValue.Implicit(const A: TDataTimestampValue): IDataTimestampValue; begin Result := A.FTimestampValue; end; { TDataTimestampType } constructor TDataTimestampType.Create(const ATimestampType: IDataTimestampType); begin FTimestampType := ATimestampType; end; function TDataTimestampType.CreateValue(const AValue: TDateTime): TDataTimestampValue; begin Result := FTimestampType.CreateValue(AValue); end; class operator TDataTimestampType.Implicit(const A: IDataTimestampType): TDataTimestampType; begin Result.FTimestampType := A; end; class operator TDataTimestampType.Implicit(const A: TDataTimestampType): IDataTimestampType; begin Result := A.FTimestampType; end; { TDataEnumValue } constructor TDataEnumValue.Create(const AEnumValue: IDataEnumValue); begin FEnumValue := AEnumValue; end; function TDataEnumValue.GetValue: Integer; begin Result := FEnumValue.Value; end; class operator TDataEnumValue.Implicit(const A: IDataEnumValue): TDataEnumValue; begin Result.FEnumValue := A; end; class operator TDataEnumValue.Implicit(const A: TDataEnumValue): IDataEnumValue; begin Result := A.FEnumValue; end; { TDataEnumType } constructor TDataEnumType.Create(const AEnumType: IDataEnumType); begin FEnumType := AEnumType; end; function TDataEnumType.CreateValue(const AValue: Integer): TDataEnumValue; begin Result := FEnumType.CreateValue(AValue); end; function TDataEnumType.CreateValue(const AIdentifier: string): TDataEnumValue; begin Result := FEnumType.CreateValue(AIdentifier); end; function TDataEnumType.GetIdentifier(Idx: Integer): string; begin Result := FEnumType.GetIdentifier(Idx); end; function TDataEnumType.GetIdentifierCount: Integer; begin Result := FEnumType.IdentifierCount; end; function TDataEnumType.IndexOf(const AIdentifier: string): Integer; begin Result := FEnumType.IndexOf(AIdentifier); end; class operator TDataEnumType.Implicit(const A: IDataEnumType): TDataEnumType; begin Result.FEnumType := A; end; class operator TDataEnumType.Implicit(const A: TDataEnumType): IDataEnumType; begin Result := A.FEnumType; end; { TDataMethodValue } constructor TDataMethodValue.Create(const AMethodValue: IDataMethodValue); begin FMethodValue := AMethodValue; end; function TDataMethodValue.GetValue: TDataMethodProc; begin Result := FMethodValue.Value; end; class operator TDataMethodValue.Implicit(const A: IDataMethodValue): TDataMethodValue; begin Result.FMethodValue := A; end; class operator TDataMethodValue.Implicit(const A: TDataMethodValue): IDataMethodValue; begin Result := A.FMethodValue; end; { TDataMethodType } constructor TDataMethodType.Create(const AMethodType: IDataMethodType); begin FMethodType := AMethodType; end; function TDataMethodType.CreateValue(const AValue: TDataMethodProc): TDataMethodValue; begin Result := FMethodType.CreateValue(AValue); end; function TDataMethodType.GetArgType: IDataType; begin Result := FMethodType.ArgType; end; function TDataMethodType.GetResultType: IDataType; begin Result := FMethodType.ResultType; end; class operator TDataMethodType.Implicit(const A: IDataMethodType): TDataMethodType; begin Result.FMethodType := A; end; class operator TDataMethodType.Implicit(const A: TDataMethodType): IDataMethodType; begin Result := A.FMethodType; end; { TDataRecordValue } constructor TDataRecordValue.Create(const ARecordValue: IDataRecordValue); begin FRecordValue := ARecordValue; end; function TDataRecordValue.GetItem(Idx: Integer): IDataValue; begin Result := FRecordValue.GetItem(Idx); end; class operator TDataRecordValue.Implicit(const A: IDataRecordValue): TDataRecordValue; begin Result.FRecordValue := A; end; class operator TDataRecordValue.Implicit(const A: TDataRecordValue): IDataRecordValue; begin Result := A.FRecordValue; end; { TDataRecordType } constructor TDataRecordType.Create(const ARecordType: IDataRecordType); begin FRecordType := ARecordType; end; function TDataRecordType.CreateValue(const AItems: array of IDataValue): TDataRecordValue; begin Result := FRecordType.CreateValue(AItems); end; function TDataRecordType.GetField(Idx: Integer): TRecordField; begin Result := FRecordType.GetField(Idx); end; function TDataRecordType.GetFieldCount: Integer; begin Result := FRecordType.FieldCount; end; function TDataRecordType.IndexOf(const AName: string): Integer; begin Result := FRecordType.IndexOf(AName); end; class operator TDataRecordType.Implicit(const A: IDataRecordType): TDataRecordType; begin Result.FRecordType := A; end; class operator TDataRecordType.Implicit(const A: TDataRecordType): IDataRecordType; begin Result := A.FRecordType; end; { TDataTupleValue } constructor TDataTupleValue.Create(const ATupleValue: IDataTupleValue); begin FTupleValue := ATupleValue; end; function TDataTupleValue.GetItem(Idx: Integer): IDataValue; begin Result := FTupleValue.GetItem(Idx); end; function TDataTupleValue.GetItemCount: Integer; begin Result := FTupleValue.ItemCount; end; class operator TDataTupleValue.Implicit(const A: IDataTupleValue): TDataTupleValue; begin Result.FTupleValue := A; end; class operator TDataTupleValue.Implicit(const A: TDataTupleValue): IDataTupleValue; begin Result := A.FTupleValue; end; { TDataTupleType } constructor TDataTupleType.Create(const ATupleType: IDataTupleType); begin FTupleType := ATupleType; end; function TDataTupleType.CreateValue(const AItems: array of IDataValue): TDataTupleValue; begin Result := FTupleType.CreateValue(AItems); end; class operator TDataTupleType.Implicit(const A: IDataTupleType): TDataTupleType; begin Result.FTupleType := A; end; class operator TDataTupleType.Implicit(const A: TDataTupleType): IDataTupleType; begin Result := A.FTupleType; end; { TDataArrayValue } constructor TDataArrayValue.Create(const AArrayValue: IDataArrayValue); begin FArrayValue := AArrayValue; end; function TDataArrayValue.GetElementCount: Integer; begin Result := FArrayValue.ElementCount; end; function TDataArrayValue.GetItem(Idx: Integer): IDataValue; begin Result := FArrayValue.GetItem(Idx); end; class operator TDataArrayValue.Implicit(const A: IDataArrayValue): TDataArrayValue; begin Result.FArrayValue := A; end; class operator TDataArrayValue.Implicit(const A: TDataArrayValue): IDataArrayValue; begin Result := A.FArrayValue; end; { TDataArrayType } constructor TDataArrayType.Create(const AArrayType: IDataArrayType); begin FArrayType := AArrayType; end; function TDataArrayType.CreateValue(const AItems: array of IDataValue): TDataArrayValue; begin Result := FArrayType.CreateValue(AItems); end; function TDataArrayType.GetElementType: IDataType; begin Result := FArrayType.ElementType; end; class operator TDataArrayType.Implicit(const A: IDataArrayType): TDataArrayType; begin Result.FArrayType := A; end; class operator TDataArrayType.Implicit(const A: TDataArrayType): IDataArrayType; begin Result := A.FArrayType; end; { TDataType } constructor TDataType.Create(const ADataType: IDataType); begin Assert(Assigned(ADataType)); FDataType := ADataType; end; class constructor TDataType.CreateClass; begin FArrayTypeRegistry := TDictionary.Create; FRecordTypeRegistry := TDictionary, IDataRecordType>.Create(TRecordFieldComparer.Create); FMethodTypeRegistry := TDictionary, IDataMethodType>.Create( TEqualityComparer>.Construct( function(const Left, Right: TPair): Boolean begin Result := (Left.Key = Right.Key) and (Left.Value = Right.Value); end, function(const Value: TPair): Integer var hash1, hash2: NativeInt; begin hash1 := NativeInt(Value.Key); hash2 := NativeInt(Value.Value); // Simple XOR combination for pointer hashes Result := Integer(hash1 xor hash2); end ) ); end; class destructor TDataType.DestroyClass; begin FArrayTypeRegistry.Free; FRecordTypeRegistry.Free; FMethodTypeRegistry.Free; end; class function TDataType.ArrayOf(const AElementType: IDataType): TDataArrayType; var res: IDataArrayType; begin if not Assigned(AElementType) then raise EArgumentException.Create('Cannot create an array type with a nil element type.'); TMonitor.Enter(FArrayTypeRegistry); try if not FArrayTypeRegistry.TryGetValue(AElementType, res) then begin res := TImplDataArrayType.Create(AElementType); FArrayTypeRegistry.Add(AElementType, res); end; finally TMonitor.Exit(FArrayTypeRegistry); end; Result.Create(res); end; function TDataType.AsArray: TDataArrayType; begin if (FDataType.Kind <> dkArray) then raise EInvalidCast.Create('Array expected'); Result.Create(IDataArrayType(FDataType)); end; function TDataType.AsEnum: TDataEnumType; begin if (FDataType.Kind <> dkEnum) then raise EInvalidCast.Create('Enum expected'); Result.Create(IDataEnumType(FDataType)); end; function TDataType.AsFloat: TDataFloatType; begin if (FDataType.Kind <> dkFloat) then raise EInvalidCast.Create('Float expected'); Result.Create(IDataFloatType(FDataType)); end; function TDataType.AsMethod: TDataMethodType; begin if (FDataType.Kind <> dkMethod) then raise EInvalidCast.Create('Method expected'); Result.Create(IDataMethodType(FDataType)); end; function TDataType.AsOrdinal: TDataOrdinalType; begin if (FDataType.Kind <> dkOrdinal) then raise EInvalidCast.Create('Ordinal expected'); Result.Create(IDataOrdinalType(FDataType)); end; function TDataType.AsRecord: TDataRecordType; begin if (FDataType.Kind <> dkRecord) then raise EInvalidCast.Create('Record expected'); Result.Create(IDataRecordType(FDataType)); end; function TDataType.AsText: TDataTextType; begin if (FDataType.Kind <> dkText) then raise EInvalidCast.Create('Text expected'); Result.Create(IDataTextType(FDataType)); end; function TDataType.AsTimestamp: TDataTimestampType; begin if (FDataType.Kind <> dkTimestamp) then raise EInvalidCast.Create('Timestamp expected'); Result.Create(IDataTimestampType(FDataType)); end; function TDataType.AsTuple: TDataTupleType; begin if (FDataType.Kind <> dkTuple) then raise EInvalidCast.Create('Tuple expected'); Result.Create(IDataTupleType(FDataType)); end; class function TDataType.Float: TDataFloatType; begin Result.Create(TImplDataFloatType.Singleton); end; function TDataType.GetName: String; begin if Assigned(FDataType) then Result := FDataType.Name else Result := ''; end; class function TDataType.MethodOf(const AArgType, AResultType: IDataType): TDataMethodType; var key: TPair; res: IDataMethodType; begin key := TPair.Create(AArgType, AResultType); TMonitor.Enter(FMethodTypeRegistry); try if not FMethodTypeRegistry.TryGetValue(key, res) then begin res := TImplDataMethodType.Create(AArgType, AResultType); FMethodTypeRegistry.Add(key, res); end; finally TMonitor.Exit(FMethodTypeRegistry); end; Result.Create(res); end; class function TDataType.Ordinal: TDataOrdinalType; begin Result.Create(TImplDataOrdinalType.Singleton); end; class function TDataType.RecordOf(const Fields: TArray): TDataRecordType; var res: IDataRecordType; begin TMonitor.Enter(FRecordTypeRegistry); try if not FRecordTypeRegistry.TryGetValue(Fields, res) then begin res := TImplDataRecordType.Create(Fields); FRecordTypeRegistry.Add(Fields, res); end; finally TMonitor.Exit(FRecordTypeRegistry); end; Result.Create(res); end; class function TDataType.RecordOf(const Fields: array of TRecordField): TDataRecordType; var tFields: TArray; i: Integer; begin SetLength(tFields, Length(Fields)); for i := 0 to High(Fields) do tFields[i] := Fields[i]; Result := RecordOf(tFields); end; class function TDataType.EnumOf(const AName: string; const AIdentifiers: array of string): TDataEnumType; begin Result.Create(TImplDataEnumType.Create(AName, AIdentifiers)); end; function TDataType.GetKind: TDataKind; begin Result := FDataType.Kind; end; class function TDataType.Text: TDataTextType; begin Result.Create(TImplDataTextType.Singleton); end; class function TDataType.Timestamp: TDataTimestampType; begin Result.Create(TImplDataTimestampType.Singleton); end; class function TDataType.Tuple: TDataTupleType; begin Result.Create(TImplDataTupleType.Singleton); end; class operator TDataType.Implicit(const A: TDataType): IDataType; begin Result := A.FDataType; end; class operator TDataType.Implicit(const A: IDataType): TDataType; begin Result.FDataType := A; end; class operator TDataType.Implicit(const A: TDataOrdinalType): TDataType; begin Result.FDataType := A.FOrdinalType; end; class operator TDataType.Implicit(const A: TDataFloatType): TDataType; begin Result.FDataType := A.FFloatType; end; class operator TDataType.Implicit(const A: TDataTextType): TDataType; begin Result.FDataType := A.FTextType; end; class operator TDataType.Implicit(const A: TDataTimestampType): TDataType; begin Result.FDataType := A.FTimestampType; end; class operator TDataType.Implicit(const A: TDataEnumType): TDataType; begin Result.FDataType := A.FEnumType; end; class operator TDataType.Implicit(const A: TDataMethodType): TDataType; begin Result.FDataType := A.FMethodType; end; class operator TDataType.Implicit(const A: TDataRecordType): TDataType; begin Result.FDataType := A.FRecordType; end; class operator TDataType.Implicit(const A: TDataTupleType): TDataType; begin Result.FDataType := A.FTupleType; end; class operator TDataType.Implicit(const A: TDataArrayType): TDataType; begin Result.FDataType := A.FArrayType; end; { TDataValue } constructor TDataValue.Create(const ADataValue: IDataValue); begin Assert(Assigned(ADataValue)); FDataValue := ADataValue; end; function TDataValue.AsArray: TDataArrayValue; begin if (FDataValue.DataType.Kind <> dkArray) then raise EInvalidCast.Create('Array expected'); Result.Create(IDataArrayValue(FDataValue)); end; function TDataValue.AsFloat: TDataFloatValue; begin if (FDataValue.DataType.Kind <> dkFloat) then raise EInvalidCast.Create('Float expected'); Result.Create(IDataFloatValue(FDataValue)); end; function TDataValue.AsMethod: TDataMethodValue; begin if (FDataValue.DataType.Kind <> dkMethod) then raise EInvalidCast.Create('Method expected'); Result.Create(IDataMethodValue(FDataValue)); end; function TDataValue.AsText: TDataTextValue; begin if (FDataValue.DataType.Kind <> dkText) then raise EInvalidCast.Create('Text expected'); Result.Create(IDataTextValue(FDataValue)); end; function TDataValue.AsTimestamp: TDataTimestampValue; begin if (FDataValue.DataType.Kind <> dkTimestamp) then raise EInvalidCast.Create('Timestamp expected'); Result.Create(IDataTimestampValue(FDataValue)); end; function TDataValue.AsOrdinal: TDataOrdinalValue; begin if (FDataValue.DataType.Kind <> dkOrdinal) then raise EInvalidCast.Create('Ordinal expected'); Result.Create(IDataOrdinalValue(FDataValue)); end; function TDataValue.AsRecord: TDataRecordValue; begin if (FDataValue.DataType.Kind <> dkRecord) then raise EInvalidCast.Create('Record expected'); Result.Create(IDataRecordValue(FDataValue)); end; function TDataValue.AsTuple: TDataTupleValue; begin if (FDataValue.DataType.Kind <> dkTuple) then raise EInvalidCast.Create('Tuple expected'); Result.Create(IDataTupleValue(FDataValue)); end; function TDataValue.AsEnum: TDataEnumValue; begin if (FDataValue.DataType.Kind <> dkEnum) then raise EInvalidCast.Create('Enum expected'); Result.Create(IDataEnumValue(FDataValue)); end; class function TDataValue.FromOrdinal(const AValue: Int64): TDataOrdinalValue; begin Result := TDataType.Ordinal.CreateValue(AValue); end; class function TDataValue.FromFloat(const AValue: Double): TDataFloatValue; begin Result := TDataType.Float.CreateValue(AValue); end; class function TDataValue.FromMethod(const AMethodType: TDataMethodType; const AValue: TDataMethodProc): TDataMethodValue; begin if not Assigned(AMethodType.FMethodType) then // Check underlying interface raise EArgumentException.Create('AMethodType'); Result := AMethodType.CreateValue(AValue); end; class function TDataValue.FromText(const AValue: string): TDataTextValue; begin Result := TDataType.Text.CreateValue(AValue); end; class function TDataValue.FromTimestamp(const AValue: TDateTime): TDataTimestampValue; begin Result := TDataType.Timestamp.CreateValue(AValue); end; class function TDataValue.FromTuple(const AItems: array of IDataValue): TDataTupleValue; begin Result := TDataType.Tuple.CreateValue(AItems); end; function TDataValue.GetDataType: IDataType; begin if Assigned(FDataValue) then Result := FDataValue.DataType else Result := nil; end; class operator TDataValue.Implicit(const A: TDataValue): IDataValue; begin Result := A.FDataValue; end; class operator TDataValue.Implicit(const A: IDataValue): TDataValue; begin Result.FDataValue := A; end; class operator TDataValue.Implicit(const A: TDataOrdinalValue): TDataValue; begin Result.FDataValue := A.FOrdinalValue; end; class operator TDataValue.Implicit(const A: TDataFloatValue): TDataValue; begin Result.FDataValue := A.FFloatValue; end; class operator TDataValue.Implicit(const A: TDataTextValue): TDataValue; begin Result.FDataValue := A.FTextValue; end; class operator TDataValue.Implicit(const A: TDataTimestampValue): TDataValue; begin Result.FDataValue := A.FTimestampValue; end; class operator TDataValue.Implicit(const A: TDataEnumValue): TDataValue; begin Result.FDataValue := A.FEnumValue; end; class operator TDataValue.Implicit(const A: TDataMethodValue): TDataValue; begin Result.FDataValue := A.FMethodValue; end; class operator TDataValue.Implicit(const A: TDataRecordValue): TDataValue; begin Result.FDataValue := A.FRecordValue; end; class operator TDataValue.Implicit(const A: TDataTupleValue): TDataValue; begin Result.FDataValue := A.FTupleValue; end; class operator TDataValue.Implicit(const A: TDataArrayValue): TDataValue; begin Result.FDataValue := A.FArrayValue; end; end.