unit Myc.Data.Types; interface uses System.Generics.Collections, System.SysUtils, System.RTTI; type TDataKind = (dkVoid, dkOrdinal, dkFloat, dkText, dkTimestamp, dkDecimal, dkRecord, dkTuple, dkArray, dkEnum, dkMethod); IDataType = interface {$region 'private'} function GetName: String; function GetKind: TDataKind; {$endregion} property Name: String read GetName; property Kind: TDataKind read GetKind; end; IDataValue = interface {$region 'private'} function GetDataType: IDataType; function GetAsString: string; {$endregion} function AsTValue: TValue; property DataType: IDataType read GetDataType; property AsString: string read GetAsString; end; IDataVoidValue = interface(IDataValue) end; IDataVoidType = interface(IDataType) function GetValue: IDataVoidValue; property Value: IDataVoidValue read GetValue; end; IDataOrdinalValue = interface(IDataValue) {$region 'private'} function GetValue: Int64; {$endregion} property Value: Int64 read GetValue; end; IDataOrdinalType = interface(IDataType) function CreateValue(Init: Int64): IDataOrdinalValue; end; IDataFloatValue = interface(IDataValue) {$region 'private'} function GetValue: Double; {$endregion} property Value: Double read GetValue; end; IDataFloatType = interface(IDataType) function CreateValue(Init: Double): IDataFloatValue; end; IDataTextValue = interface(IDataValue) {$region 'private'} function GetValue: string; {$endregion} property Value: string read GetValue; end; IDataTextType = interface(IDataType) function CreateValue(const AValue: string): IDataTextValue; end; IDataTimestampValue = interface(IDataValue) {$region 'private'} function GetValue: TDateTime; {$endregion} property Value: TDateTime read GetValue; end; IDataTimestampType = interface(IDataType) function CreateValue(const AValue: TDateTime): IDataTimestampValue; end; // Represents a fixed-point decimal data value. IDataDecimalValue = interface(IDataValue) {$region 'private'} function GetValue: Int64; {$endregion} property Value: Int64 read GetValue; end; // Represents the type of a fixed-point decimal data value. IDataDecimalType = interface(IDataType) {$region 'private'} function GetScale: Integer; {$endregion} function CreateValue(const AValue: Int64): IDataDecimalValue; property Scale: Integer read GetScale; end; IDataEnumValue = interface(IDataValue) {$region 'private'} function GetValue: Integer; {$endregion} property Value: Integer read GetValue; end; IDataEnumType = interface(IDataType) {$region 'private'} function GetIdentifier(Idx: Integer): string; function GetIdentifierCount: Integer; {$endregion} function IndexOf(const AIdentifier: string): Integer; function CreateValue(const AValue: Integer): IDataEnumValue; 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; // 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; IDataRecordValue = interface(IDataValue) {$region 'private'} function GetItem(Idx: Integer): IDataValue; {$endregion} property Items[Idx: Integer]: IDataValue read GetItem; default; end; TDataRecordField = record DataType: IDataType; Name: string; constructor Create(const AName: string; const ADataType: IDataType); end; IDataRecordType = interface(IDataType) {$region 'private'} function GetFieldCount: Integer; function GetField(Idx: Integer): TDataRecordField; {$endregion} function IndexOf(const AName: string): Integer; function CreateValue(const AItems: array of IDataValue): IDataRecordValue; property FieldCount: Integer read GetFieldCount; property Fields[Idx: Integer]: TDataRecordField read GetField; default; end; IDataTupleValue = interface(IDataValue) {$region 'private'} function GetItemCount: Integer; function GetItem(Idx: Integer): IDataValue; {$endregion} 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; IDataArrayValue = 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; IDataArrayType = interface(IDataType) {$region 'private'} function GetElementType: IDataType; {$endregion} function CreateValue(const AItems: array of IDataValue): IDataArrayValue; property ElementType: IDataType read GetElementType; end; TDataType = record type TValue = record private FDataValue: IDataValue; function GetDataType: IDataType; inline; public constructor Create(const ADataValue: IDataValue); // Casting function AsOrdinal: IDataOrdinalValue; inline; function AsFloat: IDataFloatValue; inline; function AsText: IDataTextValue; inline; function AsTimestamp: IDataTimestampValue; inline; function AsDecimal: IDataDecimalValue; inline; function AsRecord: IDataRecordValue; inline; function AsTuple: IDataTupleValue; inline; function AsArray: IDataArrayValue; inline; function AsEnum: IDataEnumValue; inline; function AsMethod: IDataMethodValue; inline; function AsVoid: IDataVoidValue; inline; class operator Implicit(const A: IDataValue): TDataType.TValue; overload; inline; class operator Implicit(const A: TDataType.TValue): IDataValue; overload; inline; property DataValue: IDataValue read FDataValue; property DataType: IDataType read GetDataType; end; TVoid = record type TValue = record private FVoidValue: IDataVoidValue; function GetDataType: TDataType.TVoid; public constructor Create(const AVoidValue: IDataVoidValue); class operator Implicit(const A: IDataVoidValue): TDataType.TVoid.TValue; overload; inline; class operator Implicit(const A: TDataType.TVoid.TValue): IDataVoidValue; overload; inline; class operator Implicit(const A: TDataType.TVoid.TValue): TDataType.TValue; overload; inline; property DataType: TDataType.TVoid read GetDataType; end; private FVoidType: IDataVoidType; function GetValue: TDataType.TVoid.TValue; inline; public constructor Create(const AVoidType: IDataVoidType); class operator Implicit(const A: IDataVoidType): TDataType.TVoid; overload; inline; class operator Implicit(const A: TDataType.TVoid): IDataVoidType; overload; inline; property Value: TDataType.TVoid.TValue read GetValue; end; TOrdinal = record type TValue = record private FOrdinalValue: IDataOrdinalValue; function GetDataType: TDataType.TOrdinal; function GetValue: Int64; inline; public constructor Create(const AOrdinalValue: IDataOrdinalValue); class operator Implicit(const A: IDataOrdinalValue): TDataType.TOrdinal.TValue; overload; inline; class operator Implicit(const A: TDataType.TOrdinal.TValue): IDataOrdinalValue; overload; inline; class operator Implicit(const A: TDataType.TOrdinal.TValue): TDataType.TValue; overload; inline; property Value: Int64 read GetValue; property DataType: TDataType.TOrdinal read GetDataType; end; private FOrdinalType: IDataOrdinalType; public constructor Create(const AOrdinalType: IDataOrdinalType); class operator Implicit(const A: IDataOrdinalType): TDataType.TOrdinal; overload; inline; class operator Implicit(const A: TDataType.TOrdinal): IDataOrdinalType; overload; inline; function CreateValue(Init: Int64): TDataType.TOrdinal.TValue; inline; end; TFloat = record type TValue = record private FFloatValue: IDataFloatValue; function GetDataType: TDataType.TFloat; function GetValue: Double; inline; public constructor Create(const AFloatValue: IDataFloatValue); class operator Implicit(const A: IDataFloatValue): TDataType.TFloat.TValue; overload; inline; class operator Implicit(const A: TDataType.TFloat.TValue): IDataFloatValue; overload; inline; class operator Implicit(const A: TDataType.TFloat.TValue): TDataType.TValue; overload; inline; property Value: Double read GetValue; property DataType: TDataType.TFloat read GetDataType; end; private FFloatType: IDataFloatType; public constructor Create(const AFloatType: IDataFloatType); class operator Implicit(const A: IDataFloatType): TDataType.TFloat; overload; inline; class operator Implicit(const A: TDataType.TFloat): IDataFloatType; overload; inline; function CreateValue(Init: Double): TDataType.TFloat.TValue; inline; end; TText = record type TValue = record private FTextValue: IDataTextValue; function GetDataType: TDataType.TText; function GetValue: string; inline; public constructor Create(const ATextValue: IDataTextValue); class operator Implicit(const A: IDataTextValue): TDataType.TText.TValue; overload; inline; class operator Implicit(const A: TDataType.TText.TValue): IDataTextValue; overload; inline; class operator Implicit(const A: TDataType.TText.TValue): TDataType.TValue; overload; inline; property Value: string read GetValue; property DataType: TDataType.TText read GetDataType; end; private FTextType: IDataTextType; public constructor Create(const ATextType: IDataTextType); class operator Implicit(const A: IDataTextType): TDataType.TText; overload; inline; class operator Implicit(const A: TDataType.TText): IDataTextType; overload; inline; function CreateValue(const AValue: string): TDataType.TText.TValue; inline; end; TTimestamp = record type TValue = record private FTimestampValue: IDataTimestampValue; function GetDataType: TDataType.TTimestamp; function GetValue: TDateTime; inline; public constructor Create(const ATimestampValue: IDataTimestampValue); class operator Implicit(const A: IDataTimestampValue): TDataType.TTimestamp.TValue; overload; inline; class operator Implicit(const A: TDataType.TTimestamp.TValue): IDataTimestampValue; overload; inline; class operator Implicit(const A: TDataType.TTimestamp.TValue): TDataType.TValue; overload; inline; property Value: TDateTime read GetValue; property DataType: TDataType.TTimestamp read GetDataType; end; private FTimestampType: IDataTimestampType; public constructor Create(const ATimestampType: IDataTimestampType); class operator Implicit(const A: IDataTimestampType): TDataType.TTimestamp; overload; inline; class operator Implicit(const A: TDataType.TTimestamp): IDataTimestampType; overload; inline; function CreateValue(const AValue: TDateTime): TDataType.TTimestamp.TValue; inline; end; TDecimal = record type TValue = record private FDecimalValue: IDataDecimalValue; function GetDataType: TDataType.TDecimal; function GetScale: Integer; inline; function GetValue: Int64; inline; public constructor Create(const ADecimalValue: IDataDecimalValue); class operator Implicit(const A: IDataDecimalValue): TDataType.TDecimal.TValue; overload; inline; class operator Implicit(const A: TDataType.TDecimal.TValue): IDataDecimalValue; overload; inline; class operator Implicit(const A: TDataType.TDecimal.TValue): TDataType.TValue; overload; inline; function ToDouble: Double; property Value: Int64 read GetValue; property Scale: Integer read GetScale; property DataType: TDataType.TDecimal read GetDataType; end; private FDecimalType: IDataDecimalType; function GetScale: Integer; inline; public constructor Create(const ADecimalType: IDataDecimalType); class operator Implicit(const A: IDataDecimalType): TDataType.TDecimal; overload; inline; class operator Implicit(const A: TDataType.TDecimal): IDataDecimalType; overload; inline; function CreateValue(const AValue: Int64): TDataType.TDecimal.TValue; inline; property Scale: Integer read GetScale; end; TEnum = record type TValue = record private FEnumValue: IDataEnumValue; function GetDataType: TDataType.TEnum; function GetValue: Integer; inline; public constructor Create(const AEnumValue: IDataEnumValue); class operator Implicit(const A: IDataEnumValue): TDataType.TEnum.TValue; overload; inline; class operator Implicit(const A: TDataType.TEnum.TValue): IDataEnumValue; overload; inline; class operator Implicit(const A: TDataType.TEnum.TValue): TDataType.TValue; overload; inline; property Value: Integer read GetValue; property DataType: TDataType.TEnum read GetDataType; end; 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): TDataType.TEnum; overload; inline; class operator Implicit(const A: TDataType.TEnum): IDataEnumType; overload; inline; function IndexOf(const AIdentifier: string): Integer; inline; function CreateValue(const AValue: Integer): TDataType.TEnum.TValue; overload; inline; function CreateValue(const AIdentifier: string): TDataType.TEnum.TValue; overload; inline; property IdentifierCount: Integer read GetIdentifierCount; property Identifiers[Idx: Integer]: string read GetIdentifier; default; end; TRecord = record type TValue = record private FRecordValue: IDataRecordValue; function GetDataType: TDataType.TRecord; function GetItems(Idx: Integer): TDataType.TValue; inline; public constructor Create(const ARecordValue: IDataRecordValue); class operator Implicit(const A: IDataRecordValue): TDataType.TRecord.TValue; overload; inline; class operator Implicit(const A: TDataType.TRecord.TValue): IDataRecordValue; overload; inline; class operator Implicit(const A: TDataType.TRecord.TValue): TDataType.TValue; overload; inline; property Items[Idx: Integer]: TDataType.TValue read GetItems; default; property DataType: TDataType.TRecord read GetDataType; end; private FRecordType: IDataRecordType; function GetFieldCount: Integer; inline; function GetField(Idx: Integer): TDataRecordField; inline; public constructor Create(const ARecordType: IDataRecordType); class operator Implicit(const A: IDataRecordType): TDataType.TRecord; overload; inline; class operator Implicit(const A: TDataType.TRecord): IDataRecordType; overload; inline; function IndexOf(const AName: string): Integer; inline; function CreateValue(const AItems: array of IDataValue): TDataType.TRecord.TValue; property FieldCount: Integer read GetFieldCount; property Fields[Idx: Integer]: TDataRecordField read GetField; default; end; TTuple = record type TValue = record private FTupleValue: IDataTupleValue; function GetDataType: TDataType.TTuple; function GetItems(Idx: Integer): TDataType.TValue; inline; function GetItemCount: Integer; inline; public constructor Create(const ATupleValue: IDataTupleValue); class operator Implicit(const A: IDataTupleValue): TDataType.TTuple.TValue; overload; inline; class operator Implicit(const A: TDataType.TTuple.TValue): IDataTupleValue; overload; inline; class operator Implicit(const A: TDataType.TTuple.TValue): TDataType.TValue; overload; inline; property ItemCount: Integer read GetItemCount; property Items[Idx: Integer]: TDataType.TValue read GetItems; default; property DataType: TDataType.TTuple read GetDataType; end; private FTupleType: IDataTupleType; public constructor Create(const ATupleType: IDataTupleType); class operator Implicit(const A: IDataTupleType): TDataType.TTuple; overload; inline; class operator Implicit(const A: TDataType.TTuple): IDataTupleType; overload; inline; function CreateValue(const AItems: array of IDataValue): TDataType.TTuple.TValue; end; TArray = record type TValue = record private FArrayValue: IDataArrayValue; function GetDataType: TDataType.TArray; function GetItems(Idx: Integer): TDataType.TValue; inline; function GetElementCount: Integer; inline; public constructor Create(const AArrayValue: IDataArrayValue); class operator Implicit(const A: IDataArrayValue): TDataType.TArray.TValue; overload; inline; class operator Implicit(const A: TDataType.TArray.TValue): IDataArrayValue; overload; inline; class operator Implicit(const A: TDataType.TArray.TValue): TDataType.TValue; overload; inline; property ElementCount: Integer read GetElementCount; property Items[Idx: Integer]: TDataType.TValue read GetItems; default; property DataType: TDataType.TArray read GetDataType; end; private FArrayType: IDataArrayType; function GetElementType: IDataType; inline; public constructor Create(const AArrayType: IDataArrayType); class operator Implicit(const A: IDataArrayType): TDataType.TArray; overload; inline; class operator Implicit(const A: TDataType.TArray): IDataArrayType; overload; inline; function CreateValue(const AItems: array of IDataValue): TDataType.TArray.TValue; property ElementType: IDataType read GetElementType; end; TMethod = record type TProc = reference to function(const AValue: TDataType.TValue): TDataType.TValue; TValue = record private FMethodValue: IDataMethodValue; function GetDataType: TDataType.TMethod; function GetValue: TDataMethodProc; inline; public constructor Create(const AMethodValue: IDataMethodValue); class operator Implicit(const A: IDataMethodValue): TDataType.TMethod.TValue; overload; inline; class operator Implicit(const A: TDataType.TMethod.TValue): IDataMethodValue; overload; inline; class operator Implicit(const A: TDataType.TMethod.TValue): TDataType.TValue; overload; inline; property Value: TDataMethodProc read GetValue; property DataType: TDataType.TMethod read GetDataType; end; private FMethodType: IDataMethodType; function GetArgType: IDataType; inline; function GetResultType: IDataType; inline; public constructor Create(const AMethodType: IDataMethodType); class operator Implicit(const A: IDataMethodType): TDataType.TMethod; overload; inline; class operator Implicit(const A: TDataType.TMethod): IDataMethodType; overload; inline; property ArgType: IDataType read GetArgType; property ResultType: IDataType read GetResultType; function CreateValue(const Proc: TProc): TDataType.TMethod.TValue; inline; end; strict private FDataType: IDataType; function GetName: String; inline; function GetKind: TDataKind; inline; class var FArrayTypeRegistry: TDictionary; FRecordTypeRegistry: TDictionary, IDataRecordType>; FMethodTypeRegistry: TDictionary, IDataMethodType>; FDecimalTypes: TArray; class constructor CreateClass; class destructor DestroyClass; public constructor Create(const ADataType: IDataType); class operator Implicit(const A: IDataType): TDataType; overload; inline; class operator Implicit(const A: TDataType): IDataType; overload; inline; class operator Implicit(const A: TDataType.TVoid): TDataType; overload; inline; class operator Implicit(const A: TDataType.TOrdinal): TDataType; overload; inline; class operator Implicit(const A: TDataType.TFloat): TDataType; overload; inline; class operator Implicit(const A: TDataType.TText): TDataType; overload; inline; class operator Implicit(const A: TDataType.TTimestamp): TDataType; overload; inline; class operator Implicit(const A: TDataType.TDecimal): TDataType; overload; inline; class operator Implicit(const A: TDataType.TEnum): TDataType; overload; inline; class operator Implicit(const A: TDataType.TMethod): TDataType; overload; inline; 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; // Type factories class function Void: TDataType.TVoid; static; inline; class function Ordinal: TDataType.TOrdinal; static; inline; class function Float: TDataType.TFloat; static; inline; class function Text: TDataType.TText; static; inline; class function Timestamp: TDataType.TTimestamp; static; inline; class function DecimalOf(const AScale: Integer): TDataType.TDecimal; static; 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 RecordOf(const Fields: TArray): TDataType.TRecord; overload; static; class function RecordOf(const Fields: array of TDataRecordField): TDataType.TRecord; overload; static; class function EnumOf(const AName: string; const AIdentifiers: array of string): TDataType.TEnum; static; function AsOrdinal: TDataType.TOrdinal; inline; function AsFloat: TDataType.TFloat; inline; function AsText: TDataType.TText; inline; function AsTimestamp: TDataType.TTimestamp; inline; function AsDecimal: TDataType.TDecimal; inline; function AsRecord: TDataType.TRecord; inline; function AsTuple: TDataType.TTuple; inline; function AsArray: TDataType.TArray; inline; function AsEnum: TDataType.TEnum; inline; function AsMethod: TDataType.TMethod; inline; property DataType: IDataType read FDataType; property Name: String read GetName; property Kind: TDataKind read GetKind; end; implementation uses System.Math, // Added for Power function System.SyncObjs, System.Generics.Defaults, Myc.Data.Types.Void, Myc.Data.Types.Ordinal, Myc.Data.Types.Float, Myc.Data.Types.Text, Myc.Data.Types.Timestamp, Myc.Data.Types.Decimal, Myc.Data.Types.Arrays, Myc.Data.Types.Records, Myc.Data.Types.Tuple, Myc.Data.Types.Enum, Myc.Data.Types.Method; type TDataRecordFieldComparer = class(TEqualityComparer>) public function Equals(const Left, Right: TArray): Boolean; override; function GetHashCode(const Value: TArray): Integer; override; end; { TDataRecordFieldComparer } function TDataRecordFieldComparer.Equals(const Left, Right: TArray): Boolean; var i: Integer; begin if Length(Left) <> Length(Right) then Exit(False); for i := 0 to High(Left) do begin // Compare field names (case-insensitive) and data types (pointer comparison) if (not SameText(Left[i].Name, Right[i].Name)) or (Left[i].DataType <> Right[i].DataType) then Exit(False); end; Result := True; end; function TDataRecordFieldComparer.GetHashCode(const Value: TArray): Integer; var field: TDataRecordField; begin Result := 0; for field in Value do begin // Combine hash codes of field name (case-insensitive) and data type pointer Result := Result xor TEqualityComparer.Default.GetHashCode(field.Name.ToUpper) xor Integer(NativeInt(field.DataType)); end; end; { TDataRecordField } constructor TDataRecordField.Create(const AName: string; const ADataType: IDataType); begin Name := AName; DataType := ADataType; end; { TDataType.TDecimal.TValue } constructor TDataType.TDecimal.TValue.Create(const ADecimalValue: IDataDecimalValue); begin FDecimalValue := ADecimalValue; end; function TDataType.TDecimal.TValue.GetDataType: TDataType.TDecimal; begin Result := IDataDecimalType(FDecimalValue.DataType); end; function TDataType.TDecimal.TValue.GetScale: Integer; begin Result := GetDataType.Scale; end; function TDataType.TDecimal.TValue.GetValue: Int64; begin Result := FDecimalValue.Value; end; function TDataType.TDecimal.TValue.ToDouble: Double; var scaleValue: Integer; begin scaleValue := GetDataType.Scale; if scaleValue > 0 then Result := FDecimalValue.Value / Power(10, scaleValue) else Result := FDecimalValue.Value; end; class operator TDataType.TDecimal.TValue.Implicit(const A: IDataDecimalValue): TDataType.TDecimal.TValue; begin Result.FDecimalValue := A; end; class operator TDataType.TDecimal.TValue.Implicit(const A: TDataType.TDecimal.TValue): IDataDecimalValue; begin Result := A.FDecimalValue; end; class operator TDataType.TDecimal.TValue.Implicit(const A: TDataType.TDecimal.TValue): TDataType.TValue; begin Result.Create(A.FDecimalValue); end; { TDataType.TDecimal } constructor TDataType.TDecimal.Create(const ADecimalType: IDataDecimalType); begin FDecimalType := ADecimalType; end; function TDataType.TDecimal.CreateValue(const AValue: Int64): TDataType.TDecimal.TValue; begin Result.Create(FDecimalType.CreateValue(AValue)); end; function TDataType.TDecimal.GetScale: Integer; begin Result := FDecimalType.Scale; end; class operator TDataType.TDecimal.Implicit(const A: IDataDecimalType): TDataType.TDecimal; begin Result.FDecimalType := A; end; class operator TDataType.TDecimal.Implicit(const A: TDataType.TDecimal): IDataDecimalType; begin Result := A.FDecimalType; end; { TDataType.TVoid.TValue } constructor TDataType.TVoid.TValue.Create(const AVoidValue: IDataVoidValue); begin FVoidValue := AVoidValue; end; function TDataType.TVoid.TValue.GetDataType: TDataType.TVoid; begin Result := IDataVoidType(FVoidValue.DataType); end; class operator TDataType.TVoid.TValue.Implicit(const A: IDataVoidValue): TDataType.TVoid.TValue; begin Result.FVoidValue := A; end; class operator TDataType.TVoid.TValue.Implicit(const A: TDataType.TVoid.TValue): IDataVoidValue; begin Result := A.FVoidValue; end; class operator TDataType.TVoid.TValue.Implicit(const A: TDataType.TVoid.TValue): TDataType.TValue; begin Result.Create(A.FVoidValue); end; { TDataType.TVoid } constructor TDataType.TVoid.Create(const AVoidType: IDataVoidType); begin FVoidType := AVoidType; end; function TDataType.TVoid.GetValue: TDataType.TVoid.TValue; begin Result.Create(FVoidType.Value); end; class operator TDataType.TVoid.Implicit(const A: IDataVoidType): TDataType.TVoid; begin Result.FVoidType := A; end; class operator TDataType.TVoid.Implicit(const A: TDataType.TVoid): IDataVoidType; begin Result := A.FVoidType; end; { TDataType.TOrdinal.TValue } constructor TDataType.TOrdinal.TValue.Create(const AOrdinalValue: IDataOrdinalValue); begin FOrdinalValue := AOrdinalValue; end; function TDataType.TOrdinal.TValue.GetDataType: TDataType.TOrdinal; begin Result := IDataOrdinalType(FOrdinalValue.DataType); end; function TDataType.TOrdinal.TValue.GetValue: Int64; begin Result := FOrdinalValue.Value; end; class operator TDataType.TOrdinal.TValue.Implicit(const A: IDataOrdinalValue): TDataType.TOrdinal.TValue; begin Result.FOrdinalValue := A; end; class operator TDataType.TOrdinal.TValue.Implicit(const A: TDataType.TOrdinal.TValue): IDataOrdinalValue; begin Result := A.FOrdinalValue; end; class operator TDataType.TOrdinal.TValue.Implicit(const A: TDataType.TOrdinal.TValue): TDataType.TValue; begin Result.Create(A.FOrdinalValue); end; { TDataType.TOrdinal } constructor TDataType.TOrdinal.Create(const AOrdinalType: IDataOrdinalType); begin FOrdinalType := AOrdinalType; end; function TDataType.TOrdinal.CreateValue(Init: Int64): TDataType.TOrdinal.TValue; begin Result.Create(FOrdinalType.CreateValue(Init)); end; class operator TDataType.TOrdinal.Implicit(const A: TDataType.TOrdinal): IDataOrdinalType; begin Result := A.FOrdinalType; end; class operator TDataType.TOrdinal.Implicit(const A: IDataOrdinalType): TDataType.TOrdinal; begin Result.FOrdinalType := A; end; { TDataType.TFloat.TValue } constructor TDataType.TFloat.TValue.Create(const AFloatValue: IDataFloatValue); begin FFloatValue := AFloatValue; end; function TDataType.TFloat.TValue.GetDataType: TDataType.TFloat; begin Result := IDataFloatType(FFloatValue.DataType); end; function TDataType.TFloat.TValue.GetValue: Double; begin Result := FFloatValue.Value; end; class operator TDataType.TFloat.TValue.Implicit(const A: IDataFloatValue): TDataType.TFloat.TValue; begin Result.FFloatValue := A; end; class operator TDataType.TFloat.TValue.Implicit(const A: TDataType.TFloat.TValue): IDataFloatValue; begin Result := A.FFloatValue; end; class operator TDataType.TFloat.TValue.Implicit(const A: TDataType.TFloat.TValue): TDataType.TValue; begin Result.Create(A.FFloatValue); end; { TDataType.TFloat } constructor TDataType.TFloat.Create(const AFloatType: IDataFloatType); begin FFloatType := AFloatType; end; function TDataType.TFloat.CreateValue(Init: Double): TDataType.TFloat.TValue; begin Result.Create(FFloatType.CreateValue(Init)); end; class operator TDataType.TFloat.Implicit(const A: IDataFloatType): TDataType.TFloat; begin Result.FFloatType := A; end; class operator TDataType.TFloat.Implicit(const A: TDataType.TFloat): IDataFloatType; begin Result := A.FFloatType; end; { TDataType.TText.TValue } constructor TDataType.TText.TValue.Create(const ATextValue: IDataTextValue); begin FTextValue := ATextValue; end; function TDataType.TText.TValue.GetDataType: TDataType.TText; begin Result := IDataTextType(FTextValue.DataType); end; function TDataType.TText.TValue.GetValue: string; begin Result := FTextValue.Value; end; class operator TDataType.TText.TValue.Implicit(const A: IDataTextValue): TDataType.TText.TValue; begin Result.FTextValue := A; end; class operator TDataType.TText.TValue.Implicit(const A: TDataType.TText.TValue): IDataTextValue; begin Result := A.FTextValue; end; class operator TDataType.TText.TValue.Implicit(const A: TDataType.TText.TValue): TDataType.TValue; begin Result.Create(A.FTextValue); end; { TDataType.TText } constructor TDataType.TText.Create(const ATextType: IDataTextType); begin FTextType := ATextType; end; function TDataType.TText.CreateValue(const AValue: string): TDataType.TText.TValue; begin Result.Create(FTextType.CreateValue(AValue)); end; class operator TDataType.TText.Implicit(const A: IDataTextType): TDataType.TText; begin Result.FTextType := A; end; class operator TDataType.TText.Implicit(const A: TDataType.TText): IDataTextType; begin Result := A.FTextType; end; { TDataType.TTimestamp.TValue } constructor TDataType.TTimestamp.TValue.Create(const ATimestampValue: IDataTimestampValue); begin FTimestampValue := ATimestampValue; end; function TDataType.TTimestamp.TValue.GetDataType: TDataType.TTimestamp; begin Result := IDataTimestampType(FTimestampValue.DataType); end; function TDataType.TTimestamp.TValue.GetValue: TDateTime; begin Result := FTimestampValue.Value; end; class operator TDataType.TTimestamp.TValue.Implicit(const A: IDataTimestampValue): TDataType.TTimestamp.TValue; begin Result.FTimestampValue := A; end; class operator TDataType.TTimestamp.TValue.Implicit(const A: TDataType.TTimestamp.TValue): IDataTimestampValue; begin Result := A.FTimestampValue; end; class operator TDataType.TTimestamp.TValue.Implicit(const A: TDataType.TTimestamp.TValue): TDataType.TValue; begin Result.Create(A.FTimestampValue); end; { TDataType.TTimestamp } constructor TDataType.TTimestamp.Create(const ATimestampType: IDataTimestampType); begin FTimestampType := ATimestampType; end; function TDataType.TTimestamp.CreateValue(const AValue: TDateTime): TDataType.TTimestamp.TValue; begin Result.Create(FTimestampType.CreateValue(AValue)); end; class operator TDataType.TTimestamp.Implicit(const A: IDataTimestampType): TDataType.TTimestamp; begin Result.FTimestampType := A; end; class operator TDataType.TTimestamp.Implicit(const A: TDataType.TTimestamp): IDataTimestampType; begin Result := A.FTimestampType; end; { TDataType.TEnum.TValue } constructor TDataType.TEnum.TValue.Create(const AEnumValue: IDataEnumValue); begin FEnumValue := AEnumValue; end; function TDataType.TEnum.TValue.GetDataType: TDataType.TEnum; begin Result := IDataEnumType(FEnumValue.DataType); end; function TDataType.TEnum.TValue.GetValue: Integer; begin Result := FEnumValue.Value; end; class operator TDataType.TEnum.TValue.Implicit(const A: IDataEnumValue): TDataType.TEnum.TValue; begin Result.FEnumValue := A; end; class operator TDataType.TEnum.TValue.Implicit(const A: TDataType.TEnum.TValue): IDataEnumValue; begin Result := A.FEnumValue; end; class operator TDataType.TEnum.TValue.Implicit(const A: TDataType.TEnum.TValue): TDataType.TValue; begin Result.Create(A.FEnumValue); end; { TDataType.TEnum } constructor TDataType.TEnum.Create(const AEnumType: IDataEnumType); begin FEnumType := AEnumType; end; function TDataType.TEnum.CreateValue(const AValue: Integer): TDataType.TEnum.TValue; begin Result.Create(FEnumType.CreateValue(AValue)); end; function TDataType.TEnum.CreateValue(const AIdentifier: string): TDataType.TEnum.TValue; var idx: Integer; begin idx := IndexOf(AIdentifier); if idx < 0 then raise EArgumentException.CreateFmt('Unknown identifier: %s', [AIdentifier]); Result := CreateValue(idx); end; function TDataType.TEnum.GetIdentifier(Idx: Integer): string; begin Result := FEnumType.GetIdentifier(Idx); end; function TDataType.TEnum.GetIdentifierCount: Integer; begin Result := FEnumType.IdentifierCount; end; function TDataType.TEnum.IndexOf(const AIdentifier: string): Integer; begin Result := FEnumType.IndexOf(AIdentifier); end; class operator TDataType.TEnum.Implicit(const A: IDataEnumType): TDataType.TEnum; begin Result.FEnumType := A; end; class operator TDataType.TEnum.Implicit(const A: TDataType.TEnum): IDataEnumType; begin Result := A.FEnumType; end; { TDataType.TMethod.TValue } constructor TDataType.TMethod.TValue.Create(const AMethodValue: IDataMethodValue); begin FMethodValue := AMethodValue; end; function TDataType.TMethod.TValue.GetDataType: TDataType.TMethod; begin Result := IDataMethodType(FMethodValue.DataType); end; function TDataType.TMethod.TValue.GetValue: TDataMethodProc; begin Result := FMethodValue.Value; end; class operator TDataType.TMethod.TValue.Implicit(const A: IDataMethodValue): TDataType.TMethod.TValue; begin Result.FMethodValue := A; end; class operator TDataType.TMethod.TValue.Implicit(const A: TDataType.TMethod.TValue): IDataMethodValue; begin Result := A.FMethodValue; end; class operator TDataType.TMethod.TValue.Implicit(const A: TDataType.TMethod.TValue): TDataType.TValue; begin Result.Create(A.FMethodValue); end; { TDataType.TMethod } constructor TDataType.TMethod.Create(const AMethodType: IDataMethodType); begin FMethodType := AMethodType; end; function TDataType.TMethod.CreateValue(const Proc: TProc): TDataType.TMethod.TValue; begin if not Assigned(Proc) then raise EArgumentException.Create('Proc'); var cProc: TProc := Proc; Result.Create(FMethodType.CreateValue(function(const Value: IDataValue): IDataValue begin Result := cProc(Value); end)); end; function TDataType.TMethod.GetArgType: IDataType; begin Result := FMethodType.ArgType; end; function TDataType.TMethod.GetResultType: IDataType; begin Result := FMethodType.ResultType; end; class operator TDataType.TMethod.Implicit(const A: IDataMethodType): TDataType.TMethod; begin Result.FMethodType := A; end; class operator TDataType.TMethod.Implicit(const A: TDataType.TMethod): IDataMethodType; begin Result := A.FMethodType; end; { TDataType.TRecord.TValue } constructor TDataType.TRecord.TValue.Create(const ARecordValue: IDataRecordValue); begin FRecordValue := ARecordValue; end; function TDataType.TRecord.TValue.GetDataType: TDataType.TRecord; begin Result := IDataRecordType(FRecordValue.DataType); end; function TDataType.TRecord.TValue.GetItems(Idx: Integer): TDataType.TValue; begin Result.Create(FRecordValue.Items[Idx]); end; class operator TDataType.TRecord.TValue.Implicit(const A: IDataRecordValue): TDataType.TRecord.TValue; begin Result.FRecordValue := A; end; class operator TDataType.TRecord.TValue.Implicit(const A: TDataType.TRecord.TValue): IDataRecordValue; begin Result := A.FRecordValue; end; class operator TDataType.TRecord.TValue.Implicit(const A: TDataType.TRecord.TValue): TDataType.TValue; begin Result.Create(A.FRecordValue); end; { TDataType.TRecord } constructor TDataType.TRecord.Create(const ARecordType: IDataRecordType); begin FRecordType := ARecordType; end; function TDataType.TRecord.CreateValue(const AItems: array of IDataValue): TDataType.TRecord.TValue; begin Result.Create(FRecordType.CreateValue(AItems)); end; function TDataType.TRecord.GetField(Idx: Integer): TDataRecordField; begin Result := FRecordType.GetField(Idx); end; function TDataType.TRecord.GetFieldCount: Integer; begin Result := FRecordType.FieldCount; end; function TDataType.TRecord.IndexOf(const AName: string): Integer; begin Result := FRecordType.IndexOf(AName); end; class operator TDataType.TRecord.Implicit(const A: IDataRecordType): TDataType.TRecord; begin Result.FRecordType := A; end; class operator TDataType.TRecord.Implicit(const A: TDataType.TRecord): IDataRecordType; begin Result := A.FRecordType; end; { TDataType.TTuple.TValue } constructor TDataType.TTuple.TValue.Create(const ATupleValue: IDataTupleValue); begin FTupleValue := ATupleValue; end; function TDataType.TTuple.TValue.GetDataType: TDataType.TTuple; begin Result := IDataTupleType(FTupleValue.DataType); end; function TDataType.TTuple.TValue.GetItems(Idx: Integer): TDataType.TValue; begin Result.Create(FTupleValue.Items[Idx]); end; function TDataType.TTuple.TValue.GetItemCount: Integer; begin Result := FTupleValue.ItemCount; end; class operator TDataType.TTuple.TValue.Implicit(const A: IDataTupleValue): TDataType.TTuple.TValue; begin Result.FTupleValue := A; end; class operator TDataType.TTuple.TValue.Implicit(const A: TDataType.TTuple.TValue): IDataTupleValue; begin Result := A.FTupleValue; end; class operator TDataType.TTuple.TValue.Implicit(const A: TDataType.TTuple.TValue): TDataType.TValue; begin Result.Create(A.FTupleValue); end; { TDataType.TTuple } constructor TDataType.TTuple.Create(const ATupleType: IDataTupleType); begin FTupleType := ATupleType; end; function TDataType.TTuple.CreateValue(const AItems: array of IDataValue): TDataType.TTuple.TValue; begin Result.Create(FTupleType.CreateValue(AItems)); end; class operator TDataType.TTuple.Implicit(const A: IDataTupleType): TDataType.TTuple; begin Result.FTupleType := A; end; class operator TDataType.TTuple.Implicit(const A: TDataType.TTuple): IDataTupleType; begin Result := A.FTupleType; end; { TDataType.TArray.TValue } constructor TDataType.TArray.TValue.Create(const AArrayValue: IDataArrayValue); begin FArrayValue := AArrayValue; end; function TDataType.TArray.TValue.GetDataType: TDataType.TArray; begin Result := IDataArrayType(FArrayValue.DataType); end; function TDataType.TArray.TValue.GetElementCount: Integer; begin Result := FArrayValue.ElementCount; end; function TDataType.TArray.TValue.GetItems(Idx: Integer): TDataType.TValue; begin Result.Create(FArrayValue.Items[Idx]); end; class operator TDataType.TArray.TValue.Implicit(const A: IDataArrayValue): TDataType.TArray.TValue; begin Result.FArrayValue := A; end; class operator TDataType.TArray.TValue.Implicit(const A: TDataType.TArray.TValue): IDataArrayValue; begin Result := A.FArrayValue; end; class operator TDataType.TArray.TValue.Implicit(const A: TDataType.TArray.TValue): TDataType.TValue; begin Result.Create(A.FArrayValue); end; { TDataType.TArray } constructor TDataType.TArray.Create(const AArrayType: IDataArrayType); begin FArrayType := AArrayType; end; function TDataType.TArray.CreateValue(const AItems: array of IDataValue): TDataType.TArray.TValue; begin Result.Create(FArrayType.CreateValue(AItems)); end; function TDataType.TArray.GetElementType: IDataType; begin Result := FArrayType.ElementType; end; class operator TDataType.TArray.Implicit(const A: IDataArrayType): TDataType.TArray; begin Result.FArrayType := A; end; class operator TDataType.TArray.Implicit(const A: TDataType.TArray): IDataArrayType; begin Result := A.FArrayType; end; { TDataType } constructor TDataType.Create(const ADataType: IDataType); begin Assert(Assigned(ADataType)); FDataType := ADataType; end; class constructor TDataType.CreateClass; var i: Integer; begin FArrayTypeRegistry := TDictionary.Create; FRecordTypeRegistry := TDictionary, IDataRecordType>.Create(TDataRecordFieldComparer.Create); SetLength(FDecimalTypes, 19); for i := 0 to 18 do FDecimalTypes[i] := TImplDataDecimalType.Create(i); 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; FDecimalTypes := nil; FMethodTypeRegistry.Free; end; class function TDataType.ArrayOf(const AElementType: IDataType): TDataType.TArray; 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; class function TDataType.DecimalOf(const AScale: Integer): TDataType.TDecimal; begin if (AScale < 0) or (AScale > 18) then raise EArgumentException.Create('Scale for decimal must be between 0 and 18.'); Result.Create(FDecimalTypes[AScale]); end; class function TDataType.EnumOf(const AName: string; const AIdentifiers: array of string): TDataType.TEnum; begin Result.Create(TImplDataEnumType.Create(AName, AIdentifiers)); end; class function TDataType.Float: TDataType.TFloat; begin Result.Create(TImplDataFloatType.Singleton); end; function TDataType.GetKind: TDataKind; begin Result := FDataType.Kind; end; function TDataType.GetName: String; begin if Assigned(FDataType) then Result := FDataType.Name else Result := ''; end; class function TDataType.MethodOf(const AArgType, AResultType: IDataType): TDataType.TMethod; 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: TDataType.TOrdinal; begin Result.Create(TImplDataOrdinalType.Singleton); end; class function TDataType.RecordOf(const Fields: TArray): TDataType.TRecord; 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 TDataRecordField): TDataType.TRecord; 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.Text: TDataType.TText; begin Result.Create(TImplDataTextType.Singleton); end; class function TDataType.Timestamp: TDataType.TTimestamp; begin Result.Create(TImplDataTimestampType.Singleton); end; class function TDataType.Tuple: TDataType.TTuple; begin Result.Create(TImplDataTupleType.Singleton); end; class function TDataType.Void: TDataType.TVoid; begin Result.Create(TImplDataVoidType.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: TDataType.TArray): TDataType; begin Result.FDataType := A.FArrayType; end; class operator TDataType.Implicit(const A: TDataType.TDecimal): TDataType; begin Result.FDataType := A.FDecimalType; end; class operator TDataType.Implicit(const A: TDataType.TEnum): TDataType; begin Result.FDataType := A.FEnumType; end; class operator TDataType.Implicit(const A: TDataType.TFloat): TDataType; begin Result.FDataType := A.FFloatType; end; class operator TDataType.Implicit(const A: TDataType.TMethod): TDataType; begin Result.FDataType := A.FMethodType; end; class operator TDataType.Implicit(const A: TDataType.TOrdinal): TDataType; begin Result.FDataType := A.FOrdinalType; end; class operator TDataType.Implicit(const A: TDataType.TRecord): TDataType; begin Result.FDataType := A.FRecordType; end; class operator TDataType.Implicit(const A: TDataType.TText): TDataType; begin Result.FDataType := A.FTextType; end; class operator TDataType.Implicit(const A: TDataType.TTimestamp): TDataType; begin Result.FDataType := A.FTimestampType; end; class operator TDataType.Implicit(const A: TDataType.TTuple): TDataType; begin Result.FDataType := A.FTupleType; end; class operator TDataType.Implicit(const A: TDataType.TVoid): TDataType; begin Result.FDataType := A.FVoidType; end; { TDataType.TValue } constructor TDataType.TValue.Create(const ADataValue: IDataValue); begin Assert(Assigned(ADataValue)); FDataValue := ADataValue; end; function TDataType.TValue.AsArray: IDataArrayValue; begin if (FDataValue.DataType.Kind <> dkArray) then raise EInvalidCast.Create('Array expected'); Result := IDataArrayValue(FDataValue); end; function TDataType.TValue.AsDecimal: IDataDecimalValue; begin if (FDataValue.DataType.Kind <> dkDecimal) then raise EInvalidCast.Create('Decimal expected'); Result := IDataDecimalValue(FDataValue); end; function TDataType.TValue.AsEnum: IDataEnumValue; begin if (FDataValue.DataType.Kind <> dkEnum) then raise EInvalidCast.Create('Enum expected'); Result := IDataEnumValue(FDataValue); end; function TDataType.TValue.AsFloat: IDataFloatValue; begin if (FDataValue.DataType.Kind <> dkFloat) then raise EInvalidCast.Create('Float expected'); Result := IDataFloatValue(FDataValue); end; function TDataType.TValue.AsMethod: IDataMethodValue; begin if (FDataValue.DataType.Kind <> dkMethod) then raise EInvalidCast.Create('Method expected'); Result := IDataMethodValue(FDataValue); end; function TDataType.TValue.AsOrdinal: IDataOrdinalValue; begin if (FDataValue.DataType.Kind <> dkOrdinal) then raise EInvalidCast.Create('Ordinal expected'); Result := IDataOrdinalValue(FDataValue); end; function TDataType.TValue.AsRecord: IDataRecordValue; begin if (FDataValue.DataType.Kind <> dkRecord) then raise EInvalidCast.Create('Record expected'); Result := IDataRecordValue(FDataValue); end; function TDataType.TValue.AsText: IDataTextValue; begin if (FDataValue.DataType.Kind <> dkText) then raise EInvalidCast.Create('Text expected'); Result := IDataTextValue(FDataValue); end; function TDataType.TValue.AsTimestamp: IDataTimestampValue; begin if (FDataValue.DataType.Kind <> dkTimestamp) then raise EInvalidCast.Create('Timestamp expected'); Result := IDataTimestampValue(FDataValue); end; function TDataType.TValue.AsTuple: IDataTupleValue; begin if (FDataValue.DataType.Kind <> dkTuple) then raise EInvalidCast.Create('Tuple expected'); Result := IDataTupleValue(FDataValue); end; function TDataType.TValue.AsVoid: IDataVoidValue; begin if (FDataValue.DataType.Kind <> dkVoid) then raise EInvalidCast.Create('Void expected'); Result := IDataVoidValue(FDataValue); end; function TDataType.TValue.GetDataType: IDataType; begin if Assigned(FDataValue) then Result := FDataValue.DataType else Result := nil; end; class operator TDataType.TValue.Implicit(const A: TDataType.TValue): IDataValue; begin Result := A.FDataValue; end; class operator TDataType.TValue.Implicit(const A: IDataValue): TDataType.TValue; begin Result.FDataValue := A; end; function TDataType.AsArray: TDataType.TArray; begin if (FDataType.Kind <> dkArray) then raise EInvalidCast.Create('Array expected'); Result.Create(IDataArrayType(FDataType)); end; function TDataType.AsDecimal: TDataType.TDecimal; begin if (FDataType.Kind <> dkDecimal) then raise EInvalidCast.Create('Decimal expected'); Result.Create(IDataDecimalType(FDataType)); end; function TDataType.AsEnum: TDataType.TEnum; begin if (FDataType.Kind <> dkEnum) then raise EInvalidCast.Create('Enum expected'); Result.Create(IDataEnumType(FDataType)); end; function TDataType.AsFloat: TDataType.TFloat; begin if (FDataType.Kind <> dkFloat) then raise EInvalidCast.Create('Float expected'); Result.Create(IDataFloatType(FDataType)); end; function TDataType.AsMethod: TDataType.TMethod; begin if (FDataType.Kind <> dkMethod) then raise EInvalidCast.Create('Method expected'); Result.Create(IDataMethodType(FDataType)); end; function TDataType.AsOrdinal: TDataType.TOrdinal; begin if (FDataType.Kind <> dkOrdinal) then raise EInvalidCast.Create('Ordinal expected'); Result.Create(IDataOrdinalType(FDataType)); end; function TDataType.AsRecord: TDataType.TRecord; begin if (FDataType.Kind <> dkRecord) then raise EInvalidCast.Create('Record expected'); Result.Create(IDataRecordType(FDataType)); end; function TDataType.AsText: TDataType.TText; begin if (FDataType.Kind <> dkText) then raise EInvalidCast.Create('Text expected'); Result.Create(IDataTextType(FDataType)); end; function TDataType.AsTimestamp: TDataType.TTimestamp; begin if (FDataType.Kind <> dkTimestamp) then raise EInvalidCast.Create('Timestamp expected'); Result.Create(IDataTimestampType(FDataType)); end; function TDataType.AsTuple: TDataType.TTuple; begin if (FDataType.Kind <> dkTuple) then raise EInvalidCast.Create('Tuple expected'); Result.Create(IDataTupleType(FDataType)); end; end.