From d2f7b019110d88d97b1328c47582c805cb1c4048 Mon Sep 17 00:00:00 2001 From: Michael Schimmel Date: Tue, 26 Aug 2025 12:06:47 +0200 Subject: [PATCH] Type System --- Src/Data/Myc.Data.Types.Method.pas | 3 +- Src/Data/Myc.Data.Types.pas | 664 ++++++++++++++-------------- Src/Data/TestDataTypes.pas | 195 ++++---- Src/Myc.Trade.Indicators.Common.pas | 437 ++++++++---------- Src/Myc.Trade.Indicators_v2.pas | 22 +- 5 files changed, 634 insertions(+), 687 deletions(-) diff --git a/Src/Data/Myc.Data.Types.Method.pas b/Src/Data/Myc.Data.Types.Method.pas index cf9ddda..b67c086 100644 --- a/Src/Data/Myc.Data.Types.Method.pas +++ b/Src/Data/Myc.Data.Types.Method.pas @@ -52,8 +52,7 @@ end; function TImplDataMethodType.CreateValue(const AValue: TDataMethodProc): IDataMethodValue; begin - if not Assigned(AValue) then - raise EArgumentException.Create('AValue'); + Assert(Assigned(AValue)); Result := TImplDataMethodValue.Create(Self, AValue); end; diff --git a/Src/Data/Myc.Data.Types.pas b/Src/Data/Myc.Data.Types.pas index 9bc8840..67af8bb 100644 --- a/Src/Data/Myc.Data.Types.pas +++ b/Src/Data/Myc.Data.Types.pas @@ -46,17 +46,6 @@ type 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; @@ -78,17 +67,6 @@ type 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; @@ -110,17 +88,6 @@ type 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; @@ -142,17 +109,6 @@ type 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; @@ -180,23 +136,6 @@ type 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; @@ -231,21 +170,6 @@ type 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; @@ -278,22 +202,6 @@ type 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; @@ -319,17 +227,6 @@ type 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; @@ -357,20 +254,151 @@ type 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 + type + TValue = 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): TDataType.TValue; overload; + class operator Implicit(const A: TDataType.TValue): IDataValue; overload; + class operator Implicit(const A: TDataOrdinalValue): TDataType.TValue; overload; + class operator Implicit(const A: TDataFloatValue): TDataType.TValue; overload; + class operator Implicit(const A: TDataTextValue): TDataType.TValue; overload; + class operator Implicit(const A: TDataTimestampValue): TDataType.TValue; overload; + class operator Implicit(const A: TDataEnumValue): TDataType.TValue; overload; + class operator Implicit(const A: TDataMethodValue): TDataType.TValue; overload; + class operator Implicit(const A: TDataRecordValue): TDataType.TValue; overload; + class operator Implicit(const A: TDataTupleValue): TDataType.TValue; overload; + class operator Implicit(const A: TDataArrayValue): TDataType.TValue; overload; + + property DataValue: IDataValue read FDataValue; + property DataType: IDataType read GetDataType; + end; + + TOrdinal = record + private + FOrdinalType: IDataOrdinalType; + public + constructor Create(const AOrdinalType: IDataOrdinalType); + class operator Implicit(const A: IDataOrdinalType): TDataType.TOrdinal; overload; + class operator Implicit(const A: TDataType.TOrdinal): IDataOrdinalType; overload; + function CreateValue(Init: Int64): TDataOrdinalValue; inline; + end; + + TFloat = record + private + FFloatType: IDataFloatType; + public + constructor Create(const AFloatType: IDataFloatType); + class operator Implicit(const A: IDataFloatType): TDataType.TFloat; overload; + class operator Implicit(const A: TDataType.TFloat): IDataFloatType; overload; + function CreateValue(Init: Double): TDataFloatValue; inline; + end; + + TText = record + private + FTextType: IDataTextType; + public + constructor Create(const ATextType: IDataTextType); + class operator Implicit(const A: IDataTextType): TDataType.TText; overload; + class operator Implicit(const A: TDataType.TText): IDataTextType; overload; + function CreateValue(const AValue: string): TDataTextValue; inline; + end; + + TTimestamp = record + private + FTimestampType: IDataTimestampType; + public + constructor Create(const ATimestampType: IDataTimestampType); + class operator Implicit(const A: IDataTimestampType): TDataType.TTimestamp; overload; + class operator Implicit(const A: TDataType.TTimestamp): IDataTimestampType; overload; + function CreateValue(const AValue: TDateTime): TDataTimestampValue; inline; + end; + + TEnum = 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): TDataType.TEnum; overload; + class operator Implicit(const A: TDataType.TEnum): 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; + + TRecord = 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): TDataType.TRecord; overload; + class operator Implicit(const A: TDataType.TRecord): 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; + + TTuple = record + private + FTupleType: IDataTupleType; + public + constructor Create(const ATupleType: IDataTupleType); + class operator Implicit(const A: IDataTupleType): TDataType.TTuple; overload; + class operator Implicit(const A: TDataType.TTuple): IDataTupleType; overload; + function CreateValue(const AItems: array of IDataValue): TDataTupleValue; + end; + + TArray = record + private + FArrayType: IDataArrayType; + function GetElementType: IDataType; inline; + public + constructor Create(const AArrayType: IDataArrayType); + class operator Implicit(const A: IDataArrayType): TDataType.TArray; overload; + class operator Implicit(const A: TDataType.TArray): IDataArrayType; overload; + function CreateValue(const AItems: array of IDataValue): TDataArrayValue; + property ElementType: IDataType read GetElementType; + end; + + TMethod = record + type + TProc = reference to function(const AValue: TDataType.TValue): TDataType.TValue; + 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; + class operator Implicit(const A: TDataType.TMethod): IDataMethodType; overload; + property ArgType: IDataType read GetArgType; + property ResultType: IDataType read GetResultType; + function CreateValue(const Proc: TProc): TDataMethodValue; inline; + end; + strict private FDataType: IDataType; function GetName: String; inline; @@ -386,84 +414,50 @@ type 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; + class operator Implicit(const A: TDataType.TOrdinal): TDataType; overload; + class operator Implicit(const A: TDataType.TFloat): TDataType; overload; + class operator Implicit(const A: TDataType.TText): TDataType; overload; + class operator Implicit(const A: TDataType.TTimestamp): TDataType; overload; + class operator Implicit(const A: TDataType.TEnum): TDataType; overload; + class operator Implicit(const A: TDataType.TMethod): TDataType; overload; + class operator Implicit(const A: TDataType.TRecord): TDataType; overload; + class operator Implicit(const A: TDataType.TTuple): TDataType; overload; + class operator Implicit(const A: TDataType.TArray): 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; + class function Ordinal: TDataType.TOrdinal; static; + class function Float: TDataType.TFloat; static; + class function Text: TDataType.TText; static; + class function Timestamp: TDataType.TTimestamp; static; + class function Tuple: TDataType.TTuple; static; + 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 TRecordField): TDataType.TRecord; overload; static; + class function EnumOf(const AName: string; const AIdentifiers: array of string): TDataType.TEnum; 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 + // Value factories moved from TValue 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; + class function FromMethod(const AMethodType: TDataType.TMethod; const AValue: TMethod.TProc): TDataMethodValue; static; - property DataValue: IDataValue read FDataValue; - property DataType: IDataType read GetDataType; + // Casting + function AsOrdinal: TDataType.TOrdinal; + function AsFloat: TDataType.TFloat; + function AsText: TDataType.TText; + function AsTimestamp: TDataType.TTimestamp; + function AsRecord: TDataType.TRecord; + function AsTuple: TDataType.TTuple; + function AsArray: TDataType.TArray; + function AsEnum: TDataType.TEnum; + function AsMethod: TDataType.TMethod; + + property DataType: IDataType read FDataType; + property Name: String read GetName; + property Kind: TDataKind read GetKind; end; implementation @@ -511,24 +505,24 @@ begin Result.FOrdinalValue := A; end; -{ TDataOrdinalType } +{ TDataType.TOrdinal } -constructor TDataOrdinalType.Create(const AOrdinalType: IDataOrdinalType); +constructor TDataType.TOrdinal.Create(const AOrdinalType: IDataOrdinalType); begin FOrdinalType := AOrdinalType; end; -function TDataOrdinalType.CreateValue(Init: Int64): TDataOrdinalValue; +function TDataType.TOrdinal.CreateValue(Init: Int64): TDataOrdinalValue; begin Result := FOrdinalType.CreateValue(Init); end; -class operator TDataOrdinalType.Implicit(const A: TDataOrdinalType): IDataOrdinalType; +class operator TDataType.TOrdinal.Implicit(const A: TDataType.TOrdinal): IDataOrdinalType; begin Result := A.FOrdinalType; end; -class operator TDataOrdinalType.Implicit(const A: IDataOrdinalType): TDataOrdinalType; +class operator TDataType.TOrdinal.Implicit(const A: IDataOrdinalType): TDataType.TOrdinal; begin Result.FOrdinalType := A; end; @@ -555,24 +549,24 @@ begin Result := A.FFloatValue; end; -{ TDataFloatType } +{ TDataType.TFloat } -constructor TDataFloatType.Create(const AFloatType: IDataFloatType); +constructor TDataType.TFloat.Create(const AFloatType: IDataFloatType); begin FFloatType := AFloatType; end; -function TDataFloatType.CreateValue(Init: Double): TDataFloatValue; +function TDataType.TFloat.CreateValue(Init: Double): TDataFloatValue; begin Result := FFloatType.CreateValue(Init); end; -class operator TDataFloatType.Implicit(const A: IDataFloatType): TDataFloatType; +class operator TDataType.TFloat.Implicit(const A: IDataFloatType): TDataType.TFloat; begin Result.FFloatType := A; end; -class operator TDataFloatType.Implicit(const A: TDataFloatType): IDataFloatType; +class operator TDataType.TFloat.Implicit(const A: TDataType.TFloat): IDataFloatType; begin Result := A.FFloatType; end; @@ -599,24 +593,24 @@ begin Result := A.FTextValue; end; -{ TDataTextType } +{ TDataType.TText } -constructor TDataTextType.Create(const ATextType: IDataTextType); +constructor TDataType.TText.Create(const ATextType: IDataTextType); begin FTextType := ATextType; end; -function TDataTextType.CreateValue(const AValue: string): TDataTextValue; +function TDataType.TText.CreateValue(const AValue: string): TDataTextValue; begin Result := FTextType.CreateValue(AValue); end; -class operator TDataTextType.Implicit(const A: IDataTextType): TDataTextType; +class operator TDataType.TText.Implicit(const A: IDataTextType): TDataType.TText; begin Result.FTextType := A; end; -class operator TDataTextType.Implicit(const A: TDataTextType): IDataTextType; +class operator TDataType.TText.Implicit(const A: TDataType.TText): IDataTextType; begin Result := A.FTextType; end; @@ -643,24 +637,24 @@ begin Result := A.FTimestampValue; end; -{ TDataTimestampType } +{ TDataType.TTimestamp } -constructor TDataTimestampType.Create(const ATimestampType: IDataTimestampType); +constructor TDataType.TTimestamp.Create(const ATimestampType: IDataTimestampType); begin FTimestampType := ATimestampType; end; -function TDataTimestampType.CreateValue(const AValue: TDateTime): TDataTimestampValue; +function TDataType.TTimestamp.CreateValue(const AValue: TDateTime): TDataTimestampValue; begin Result := FTimestampType.CreateValue(AValue); end; -class operator TDataTimestampType.Implicit(const A: IDataTimestampType): TDataTimestampType; +class operator TDataType.TTimestamp.Implicit(const A: IDataTimestampType): TDataType.TTimestamp; begin Result.FTimestampType := A; end; -class operator TDataTimestampType.Implicit(const A: TDataTimestampType): IDataTimestampType; +class operator TDataType.TTimestamp.Implicit(const A: TDataType.TTimestamp): IDataTimestampType; begin Result := A.FTimestampType; end; @@ -687,44 +681,44 @@ begin Result := A.FEnumValue; end; -{ TDataEnumType } +{ TDataType.TEnum } -constructor TDataEnumType.Create(const AEnumType: IDataEnumType); +constructor TDataType.TEnum.Create(const AEnumType: IDataEnumType); begin FEnumType := AEnumType; end; -function TDataEnumType.CreateValue(const AValue: Integer): TDataEnumValue; +function TDataType.TEnum.CreateValue(const AValue: Integer): TDataEnumValue; begin Result := FEnumType.CreateValue(AValue); end; -function TDataEnumType.CreateValue(const AIdentifier: string): TDataEnumValue; +function TDataType.TEnum.CreateValue(const AIdentifier: string): TDataEnumValue; begin Result := FEnumType.CreateValue(AIdentifier); end; -function TDataEnumType.GetIdentifier(Idx: Integer): string; +function TDataType.TEnum.GetIdentifier(Idx: Integer): string; begin Result := FEnumType.GetIdentifier(Idx); end; -function TDataEnumType.GetIdentifierCount: Integer; +function TDataType.TEnum.GetIdentifierCount: Integer; begin Result := FEnumType.IdentifierCount; end; -function TDataEnumType.IndexOf(const AIdentifier: string): Integer; +function TDataType.TEnum.IndexOf(const AIdentifier: string): Integer; begin Result := FEnumType.IndexOf(AIdentifier); end; -class operator TDataEnumType.Implicit(const A: IDataEnumType): TDataEnumType; +class operator TDataType.TEnum.Implicit(const A: IDataEnumType): TDataType.TEnum; begin Result.FEnumType := A; end; -class operator TDataEnumType.Implicit(const A: TDataEnumType): IDataEnumType; +class operator TDataType.TEnum.Implicit(const A: TDataType.TEnum): IDataEnumType; begin Result := A.FEnumType; end; @@ -751,34 +745,38 @@ begin Result := A.FMethodValue; end; -{ TDataMethodType } +{ TDataType.TMethod } -constructor TDataMethodType.Create(const AMethodType: IDataMethodType); +constructor TDataType.TMethod.Create(const AMethodType: IDataMethodType); begin FMethodType := AMethodType; end; -function TDataMethodType.CreateValue(const AValue: TDataMethodProc): TDataMethodValue; +function TDataType.TMethod.CreateValue(const Proc: TProc): TDataMethodValue; begin - Result := FMethodType.CreateValue(AValue); + if not Assigned(Proc) then + raise EArgumentException.Create('Proc'); + + var cProc: TProc := Proc; + Result := FMethodType.CreateValue(function(const Value: IDataValue): IDataValue begin Result := cProc(Value); end); end; -function TDataMethodType.GetArgType: IDataType; +function TDataType.TMethod.GetArgType: IDataType; begin Result := FMethodType.ArgType; end; -function TDataMethodType.GetResultType: IDataType; +function TDataType.TMethod.GetResultType: IDataType; begin Result := FMethodType.ResultType; end; -class operator TDataMethodType.Implicit(const A: IDataMethodType): TDataMethodType; +class operator TDataType.TMethod.Implicit(const A: IDataMethodType): TDataType.TMethod; begin Result.FMethodType := A; end; -class operator TDataMethodType.Implicit(const A: TDataMethodType): IDataMethodType; +class operator TDataType.TMethod.Implicit(const A: TDataType.TMethod): IDataMethodType; begin Result := A.FMethodType; end; @@ -805,39 +803,39 @@ begin Result := A.FRecordValue; end; -{ TDataRecordType } +{ TDataType.TRecord } -constructor TDataRecordType.Create(const ARecordType: IDataRecordType); +constructor TDataType.TRecord.Create(const ARecordType: IDataRecordType); begin FRecordType := ARecordType; end; -function TDataRecordType.CreateValue(const AItems: array of IDataValue): TDataRecordValue; +function TDataType.TRecord.CreateValue(const AItems: array of IDataValue): TDataRecordValue; begin Result := FRecordType.CreateValue(AItems); end; -function TDataRecordType.GetField(Idx: Integer): TRecordField; +function TDataType.TRecord.GetField(Idx: Integer): TRecordField; begin Result := FRecordType.GetField(Idx); end; -function TDataRecordType.GetFieldCount: Integer; +function TDataType.TRecord.GetFieldCount: Integer; begin Result := FRecordType.FieldCount; end; -function TDataRecordType.IndexOf(const AName: string): Integer; +function TDataType.TRecord.IndexOf(const AName: string): Integer; begin Result := FRecordType.IndexOf(AName); end; -class operator TDataRecordType.Implicit(const A: IDataRecordType): TDataRecordType; +class operator TDataType.TRecord.Implicit(const A: IDataRecordType): TDataType.TRecord; begin Result.FRecordType := A; end; -class operator TDataRecordType.Implicit(const A: TDataRecordType): IDataRecordType; +class operator TDataType.TRecord.Implicit(const A: TDataType.TRecord): IDataRecordType; begin Result := A.FRecordType; end; @@ -869,24 +867,24 @@ begin Result := A.FTupleValue; end; -{ TDataTupleType } +{ TDataType.TTuple } -constructor TDataTupleType.Create(const ATupleType: IDataTupleType); +constructor TDataType.TTuple.Create(const ATupleType: IDataTupleType); begin FTupleType := ATupleType; end; -function TDataTupleType.CreateValue(const AItems: array of IDataValue): TDataTupleValue; +function TDataType.TTuple.CreateValue(const AItems: array of IDataValue): TDataTupleValue; begin Result := FTupleType.CreateValue(AItems); end; -class operator TDataTupleType.Implicit(const A: IDataTupleType): TDataTupleType; +class operator TDataType.TTuple.Implicit(const A: IDataTupleType): TDataType.TTuple; begin Result.FTupleType := A; end; -class operator TDataTupleType.Implicit(const A: TDataTupleType): IDataTupleType; +class operator TDataType.TTuple.Implicit(const A: TDataType.TTuple): IDataTupleType; begin Result := A.FTupleType; end; @@ -918,29 +916,29 @@ begin Result := A.FArrayValue; end; -{ TDataArrayType } +{ TDataType.TArray } -constructor TDataArrayType.Create(const AArrayType: IDataArrayType); +constructor TDataType.TArray.Create(const AArrayType: IDataArrayType); begin FArrayType := AArrayType; end; -function TDataArrayType.CreateValue(const AItems: array of IDataValue): TDataArrayValue; +function TDataType.TArray.CreateValue(const AItems: array of IDataValue): TDataArrayValue; begin Result := FArrayType.CreateValue(AItems); end; -function TDataArrayType.GetElementType: IDataType; +function TDataType.TArray.GetElementType: IDataType; begin Result := FArrayType.ElementType; end; -class operator TDataArrayType.Implicit(const A: IDataArrayType): TDataArrayType; +class operator TDataType.TArray.Implicit(const A: IDataArrayType): TDataType.TArray; begin Result.FArrayType := A; end; -class operator TDataArrayType.Implicit(const A: TDataArrayType): IDataArrayType; +class operator TDataType.TArray.Implicit(const A: TDataType.TArray): IDataArrayType; begin Result := A.FArrayType; end; @@ -984,7 +982,7 @@ begin FMethodTypeRegistry.Free; end; -class function TDataType.ArrayOf(const AElementType: IDataType): TDataArrayType; +class function TDataType.ArrayOf(const AElementType: IDataType): TDataType.TArray; var res: IDataArrayType; begin @@ -1004,74 +1002,116 @@ begin Result.Create(res); end; -function TDataType.AsArray: TDataArrayType; +function TDataType.AsArray: TDataType.TArray; begin if (FDataType.Kind <> dkArray) then raise EInvalidCast.Create('Array expected'); Result.Create(IDataArrayType(FDataType)); end; -function TDataType.AsEnum: TDataEnumType; +function TDataType.AsEnum: TDataType.TEnum; begin if (FDataType.Kind <> dkEnum) then raise EInvalidCast.Create('Enum expected'); Result.Create(IDataEnumType(FDataType)); end; -function TDataType.AsFloat: TDataFloatType; +function TDataType.AsFloat: TDataType.TFloat; begin if (FDataType.Kind <> dkFloat) then raise EInvalidCast.Create('Float expected'); Result.Create(IDataFloatType(FDataType)); end; -function TDataType.AsMethod: TDataMethodType; +function TDataType.AsMethod: TDataType.TMethod; begin if (FDataType.Kind <> dkMethod) then raise EInvalidCast.Create('Method expected'); Result.Create(IDataMethodType(FDataType)); end; -function TDataType.AsOrdinal: TDataOrdinalType; +function TDataType.AsOrdinal: TDataType.TOrdinal; begin if (FDataType.Kind <> dkOrdinal) then raise EInvalidCast.Create('Ordinal expected'); Result.Create(IDataOrdinalType(FDataType)); end; -function TDataType.AsRecord: TDataRecordType; +function TDataType.AsRecord: TDataType.TRecord; begin if (FDataType.Kind <> dkRecord) then raise EInvalidCast.Create('Record expected'); Result.Create(IDataRecordType(FDataType)); end; -function TDataType.AsText: TDataTextType; +function TDataType.AsText: TDataType.TText; begin if (FDataType.Kind <> dkText) then raise EInvalidCast.Create('Text expected'); Result.Create(IDataTextType(FDataType)); end; -function TDataType.AsTimestamp: TDataTimestampType; +function TDataType.AsTimestamp: TDataType.TTimestamp; begin if (FDataType.Kind <> dkTimestamp) then raise EInvalidCast.Create('Timestamp expected'); Result.Create(IDataTimestampType(FDataType)); end; -function TDataType.AsTuple: TDataTupleType; +function TDataType.AsTuple: TDataType.TTuple; begin if (FDataType.Kind <> dkTuple) then raise EInvalidCast.Create('Tuple expected'); Result.Create(IDataTupleType(FDataType)); end; -class function TDataType.Float: TDataFloatType; +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; +class function TDataType.FromFloat(const AValue: Double): TDataFloatValue; +begin + Result := TDataType.Float.CreateValue(AValue); +end; + +class function TDataType.FromMethod(const AMethodType: TDataType.TMethod; const AValue: TMethod.TProc): TDataMethodValue; +begin + if not Assigned(AMethodType.FMethodType) then // Check underlying interface + raise EArgumentException.Create('AMethodType'); + Result := AMethodType.CreateValue(AValue); +end; + +class function TDataType.FromOrdinal(const AValue: Int64): TDataOrdinalValue; +begin + Result := TDataType.Ordinal.CreateValue(AValue); +end; + +class function TDataType.FromText(const AValue: string): TDataTextValue; +begin + Result := TDataType.Text.CreateValue(AValue); +end; + +class function TDataType.FromTimestamp(const AValue: TDateTime): TDataTimestampValue; +begin + Result := TDataType.Timestamp.CreateValue(AValue); +end; + +class function TDataType.FromTuple(const AItems: array of IDataValue): TDataTupleValue; +begin + Result := TDataType.Tuple.CreateValue(AItems); +end; + +function TDataType.GetKind: TDataKind; +begin + Result := FDataType.Kind; +end; + function TDataType.GetName: String; begin if Assigned(FDataType) then @@ -1080,7 +1120,7 @@ begin Result := ''; end; -class function TDataType.MethodOf(const AArgType, AResultType: IDataType): TDataMethodType; +class function TDataType.MethodOf(const AArgType, AResultType: IDataType): TDataType.TMethod; var key: TPair; res: IDataMethodType; @@ -1099,12 +1139,12 @@ begin Result.Create(res); end; -class function TDataType.Ordinal: TDataOrdinalType; +class function TDataType.Ordinal: TDataType.TOrdinal; begin Result.Create(TImplDataOrdinalType.Singleton); end; -class function TDataType.RecordOf(const Fields: TArray): TDataRecordType; +class function TDataType.RecordOf(const Fields: TArray): TDataType.TRecord; var res: IDataRecordType; begin @@ -1121,7 +1161,7 @@ begin Result.Create(res); end; -class function TDataType.RecordOf(const Fields: array of TRecordField): TDataRecordType; +class function TDataType.RecordOf(const Fields: array of TRecordField): TDataType.TRecord; var tFields: TArray; i: Integer; @@ -1132,27 +1172,17 @@ begin 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; +class function TDataType.Text: TDataType.TText; begin Result.Create(TImplDataTextType.Singleton); end; -class function TDataType.Timestamp: TDataTimestampType; +class function TDataType.Timestamp: TDataType.TTimestamp; begin Result.Create(TImplDataTimestampType.Singleton); end; -class function TDataType.Tuple: TDataTupleType; +class function TDataType.Tuple: TDataType.TTuple; begin Result.Create(TImplDataTupleType.Singleton); end; @@ -1167,155 +1197,123 @@ begin Result.FDataType := A; end; -class operator TDataType.Implicit(const A: TDataOrdinalType): TDataType; +class operator TDataType.Implicit(const A: TDataType.TOrdinal): TDataType; begin Result.FDataType := A.FOrdinalType; end; -class operator TDataType.Implicit(const A: TDataFloatType): TDataType; +class operator TDataType.Implicit(const A: TDataType.TFloat): TDataType; begin Result.FDataType := A.FFloatType; end; -class operator TDataType.Implicit(const A: TDataTextType): TDataType; +class operator TDataType.Implicit(const A: TDataType.TText): TDataType; begin Result.FDataType := A.FTextType; end; -class operator TDataType.Implicit(const A: TDataTimestampType): TDataType; +class operator TDataType.Implicit(const A: TDataType.TTimestamp): TDataType; begin Result.FDataType := A.FTimestampType; end; -class operator TDataType.Implicit(const A: TDataEnumType): TDataType; +class operator TDataType.Implicit(const A: TDataType.TEnum): TDataType; begin Result.FDataType := A.FEnumType; end; -class operator TDataType.Implicit(const A: TDataMethodType): TDataType; +class operator TDataType.Implicit(const A: TDataType.TMethod): TDataType; begin Result.FDataType := A.FMethodType; end; -class operator TDataType.Implicit(const A: TDataRecordType): TDataType; +class operator TDataType.Implicit(const A: TDataType.TRecord): TDataType; begin Result.FDataType := A.FRecordType; end; -class operator TDataType.Implicit(const A: TDataTupleType): TDataType; +class operator TDataType.Implicit(const A: TDataType.TTuple): TDataType; begin Result.FDataType := A.FTupleType; end; -class operator TDataType.Implicit(const A: TDataArrayType): TDataType; +class operator TDataType.Implicit(const A: TDataType.TArray): TDataType; begin Result.FDataType := A.FArrayType; end; -{ TDataValue } +{ TDataType.TValue } -constructor TDataValue.Create(const ADataValue: IDataValue); +constructor TDataType.TValue.Create(const ADataValue: IDataValue); begin Assert(Assigned(ADataValue)); FDataValue := ADataValue; end; -function TDataValue.AsArray: TDataArrayValue; +function TDataType.TValue.AsArray: TDataArrayValue; begin if (FDataValue.DataType.Kind <> dkArray) then raise EInvalidCast.Create('Array expected'); Result.Create(IDataArrayValue(FDataValue)); end; -function TDataValue.AsFloat: TDataFloatValue; +function TDataType.TValue.AsFloat: TDataFloatValue; begin if (FDataValue.DataType.Kind <> dkFloat) then raise EInvalidCast.Create('Float expected'); Result.Create(IDataFloatValue(FDataValue)); end; -function TDataValue.AsMethod: TDataMethodValue; +function TDataType.TValue.AsMethod: TDataMethodValue; begin if (FDataValue.DataType.Kind <> dkMethod) then raise EInvalidCast.Create('Method expected'); Result.Create(IDataMethodValue(FDataValue)); end; -function TDataValue.AsText: TDataTextValue; +function TDataType.TValue.AsText: TDataTextValue; begin if (FDataValue.DataType.Kind <> dkText) then raise EInvalidCast.Create('Text expected'); Result.Create(IDataTextValue(FDataValue)); end; -function TDataValue.AsTimestamp: TDataTimestampValue; +function TDataType.TValue.AsTimestamp: TDataTimestampValue; begin if (FDataValue.DataType.Kind <> dkTimestamp) then raise EInvalidCast.Create('Timestamp expected'); Result.Create(IDataTimestampValue(FDataValue)); end; -function TDataValue.AsOrdinal: TDataOrdinalValue; +function TDataType.TValue.AsOrdinal: TDataOrdinalValue; begin if (FDataValue.DataType.Kind <> dkOrdinal) then raise EInvalidCast.Create('Ordinal expected'); Result.Create(IDataOrdinalValue(FDataValue)); end; -function TDataValue.AsRecord: TDataRecordValue; +function TDataType.TValue.AsRecord: TDataRecordValue; begin if (FDataValue.DataType.Kind <> dkRecord) then raise EInvalidCast.Create('Record expected'); Result.Create(IDataRecordValue(FDataValue)); end; -function TDataValue.AsTuple: TDataTupleValue; +function TDataType.TValue.AsTuple: TDataTupleValue; begin if (FDataValue.DataType.Kind <> dkTuple) then raise EInvalidCast.Create('Tuple expected'); Result.Create(IDataTupleValue(FDataValue)); end; -function TDataValue.AsEnum: TDataEnumValue; +function TDataType.TValue.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; +function TDataType.TValue.GetDataType: IDataType; begin if Assigned(FDataValue) then Result := FDataValue.DataType @@ -1323,57 +1321,57 @@ begin Result := nil; end; -class operator TDataValue.Implicit(const A: TDataValue): IDataValue; +class operator TDataType.TValue.Implicit(const A: TDataType.TValue): IDataValue; begin Result := A.FDataValue; end; -class operator TDataValue.Implicit(const A: IDataValue): TDataValue; +class operator TDataType.TValue.Implicit(const A: IDataValue): TDataType.TValue; begin Result.FDataValue := A; end; -class operator TDataValue.Implicit(const A: TDataOrdinalValue): TDataValue; +class operator TDataType.TValue.Implicit(const A: TDataOrdinalValue): TDataType.TValue; begin Result.FDataValue := A.FOrdinalValue; end; -class operator TDataValue.Implicit(const A: TDataFloatValue): TDataValue; +class operator TDataType.TValue.Implicit(const A: TDataFloatValue): TDataType.TValue; begin Result.FDataValue := A.FFloatValue; end; -class operator TDataValue.Implicit(const A: TDataTextValue): TDataValue; +class operator TDataType.TValue.Implicit(const A: TDataTextValue): TDataType.TValue; begin Result.FDataValue := A.FTextValue; end; -class operator TDataValue.Implicit(const A: TDataTimestampValue): TDataValue; +class operator TDataType.TValue.Implicit(const A: TDataTimestampValue): TDataType.TValue; begin Result.FDataValue := A.FTimestampValue; end; -class operator TDataValue.Implicit(const A: TDataEnumValue): TDataValue; +class operator TDataType.TValue.Implicit(const A: TDataEnumValue): TDataType.TValue; begin Result.FDataValue := A.FEnumValue; end; -class operator TDataValue.Implicit(const A: TDataMethodValue): TDataValue; +class operator TDataType.TValue.Implicit(const A: TDataMethodValue): TDataType.TValue; begin Result.FDataValue := A.FMethodValue; end; -class operator TDataValue.Implicit(const A: TDataRecordValue): TDataValue; +class operator TDataType.TValue.Implicit(const A: TDataRecordValue): TDataType.TValue; begin Result.FDataValue := A.FRecordValue; end; -class operator TDataValue.Implicit(const A: TDataTupleValue): TDataValue; +class operator TDataType.TValue.Implicit(const A: TDataTupleValue): TDataType.TValue; begin Result.FDataValue := A.FTupleValue; end; -class operator TDataValue.Implicit(const A: TDataArrayValue): TDataValue; +class operator TDataType.TValue.Implicit(const A: TDataArrayValue): TDataType.TValue; begin Result.FDataValue := A.FArrayValue; end; diff --git a/Src/Data/TestDataTypes.pas b/Src/Data/TestDataTypes.pas index 5c80d71..c32f888 100644 --- a/Src/Data/TestDataTypes.pas +++ b/Src/Data/TestDataTypes.pas @@ -51,9 +51,9 @@ uses procedure TMyTestObject.TestRecords; var - intType: TDataOrdinalType; - floatType: TDataFloatType; - personType1, personType2, otherType: TDataRecordType; + intType: TDataType.TOrdinal; + floatType: TDataType.TFloat; + personType1, personType2, otherType: TDataType.TRecord; personValue: TDataRecordValue; idValue: TDataOrdinalValue; floatValue: TDataFloatValue; @@ -86,19 +86,19 @@ begin Assert.AreNotSame(IDataRecordType(personType1), IDataRecordType(otherType), 'Different definitions should result in different types'); // --- 3. Test Value Creation and Access --- - personValue := personType1.CreateValue([TDataValue.FromOrdinal(123), TDataValue.FromFloat(45.67)]); + personValue := personType1.CreateValue([TDataType.FromOrdinal(123), TDataType.FromFloat(45.67)]); Assert.IsNotNull(IDataRecordValue(personValue), 'RecordValue should be created'); Assert.AreSame(IDataRecordType(personType1), IDataRecordValue(personValue).DataType, 'Value should have the correct data type'); // Access by index - idValue := TDataValue(personValue.Items[0]).AsOrdinal; + idValue := TDataType.TValue(personValue.Items[0]).AsOrdinal; Assert.AreEqual(Int64(123), idValue.Value, 'Value at index 0 is incorrect'); - floatValue := TDataValue(personValue.Items[1]).AsFloat; + floatValue := TDataType.TValue(personValue.Items[1]).AsFloat; Assert.AreEqual(45.67, floatValue.Value, 'Value at index 1 is incorrect'); // Access by name - floatValue := TDataValue(personValue.Items[personType1.IndexOf('Value')]).AsFloat; + floatValue := TDataType.TValue(personValue.Items[personType1.IndexOf('Value')]).AsFloat; Assert.AreEqual(45.67, floatValue.Value, 'Value accessed by name is incorrect'); // --- 4. Test Validation and Error Handling --- @@ -111,7 +111,7 @@ begin // Test for wrong number of items during value creation Assert.WillRaise( - procedure begin personType1.CreateValue([TDataValue.FromOrdinal(99)]); end, + procedure begin personType1.CreateValue([TDataType.FromOrdinal(99)]); end, EArgumentException, 'Wrong number of items should raise exception' ); @@ -121,7 +121,7 @@ begin procedure begin // Passing Float instead of Integer for the first item - personType1.CreateValue([TDataValue.FromFloat(1.0), TDataValue.FromFloat(2.0)]); + personType1.CreateValue([TDataType.FromFloat(1.0), TDataType.FromFloat(2.0)]); end, EArgumentException, 'Wrong item type should raise exception' @@ -130,7 +130,7 @@ end; procedure TMyTestObject.TestRecords_Generic; var - dataType: TDataRecordType; + dataType: TDataType.TRecord; dataValue: TDataRecordValue; begin // Test the generic implementation for records with > 2 fields. @@ -142,13 +142,13 @@ begin TRecordField.Create('C', TDataType.Float) ] ); - dataValue := dataType.CreateValue([TDataValue.FromOrdinal(1), TDataValue.FromText('two'), TDataValue.FromFloat(3.0)]); + dataValue := dataType.CreateValue([TDataType.FromOrdinal(1), TDataType.FromText('two'), TDataType.FromFloat(3.0)]); Assert.IsNotNull(IDataRecordValue(dataValue), 'Generic record value should be created'); Assert.AreEqual(3, dataType.FieldCount, 'Generic record should have 3 fields'); - Assert.AreEqual(Int64(1), TDataValue(dataValue.Items[0]).AsOrdinal.Value, 'Field A is incorrect'); - Assert.AreEqual('two', TDataValue(dataValue.Items[1]).AsText.Value, 'Field B is incorrect'); - Assert.AreEqual(3.0, TDataValue(dataValue.Items[2]).AsFloat.Value, 'Field C is incorrect'); + Assert.AreEqual(Int64(1), TDataType.TValue(dataValue.Items[0]).AsOrdinal.Value, 'Field A is incorrect'); + Assert.AreEqual('two', TDataType.TValue(dataValue.Items[1]).AsText.Value, 'Field B is incorrect'); + Assert.AreEqual(3.0, TDataType.TValue(dataValue.Items[2]).AsFloat.Value, 'Field C is incorrect'); Assert.AreEqual('', IDataRecordValue(dataValue).AsString, 'Generic record AsString is incorrect'); end; @@ -161,11 +161,11 @@ var begin // This test covers optimized implementations for 1 and 2 elements. // --- 1. Setup: Create some values --- - intValue := TDataValue.FromOrdinal(123); - floatValue := TDataValue.FromFloat(45.67); + intValue := TDataType.FromOrdinal(123); + floatValue := TDataType.FromFloat(45.67); // --- 2. Test Value Creation and basic properties --- - tuple1 := TDataValue.FromTuple([intValue, floatValue]); + tuple1 := TDataType.FromTuple([intValue, floatValue]); Assert.IsNotNull(IDataTupleValue(tuple1), 'Tuple value should be created'); Assert.AreEqual(2, tuple1.ItemCount, 'ItemCount should be on the value'); @@ -174,8 +174,8 @@ begin // --- 3. Test Singleton Type Behavior --- // Create more tuples with different structures - tuple2 := TDataValue.FromTuple([TDataValue.FromOrdinal(99), TDataValue.FromFloat(1.1)]); - tuple3 := TDataValue.FromTuple([intValue]); + tuple2 := TDataType.FromTuple([TDataType.FromOrdinal(99), TDataType.FromFloat(1.1)]); + tuple3 := TDataType.FromTuple([intValue]); // Access the DataType via the underlying interface type1 := IDataValue(tuple1).DataType; @@ -196,29 +196,29 @@ var begin // Test the generic implementation for tuples with > 5 elements. tupleValue := - TDataValue.FromTuple( + TDataType.FromTuple( [ - TDataValue.FromOrdinal(1), - TDataValue.FromOrdinal(2), - TDataValue.FromOrdinal(3), - TDataValue.FromOrdinal(4), - TDataValue.FromOrdinal(5), - TDataValue.FromOrdinal(6) + TDataType.FromOrdinal(1), + TDataType.FromOrdinal(2), + TDataType.FromOrdinal(3), + TDataType.FromOrdinal(4), + TDataType.FromOrdinal(5), + TDataType.FromOrdinal(6) ] ); Assert.IsNotNull(IDataTupleValue(tupleValue), 'Generic tuple value should be created'); Assert.AreEqual(6, tupleValue.ItemCount, 'Generic tuple should have 6 items'); - Assert.AreEqual(Int64(6), TDataValue(tupleValue.Items[5]).AsOrdinal.Value, 'Last item is incorrect'); + Assert.AreEqual(Int64(6), TDataType.TValue(tupleValue.Items[5]).AsOrdinal.Value, 'Last item is incorrect'); Assert.AreEqual('(1, 2, 3, 4, 5, 6)', IDataTupleValue(tupleValue).AsString, 'Generic tuple AsString is incorrect'); end; procedure TMyTestObject.TestArrays; var - intType: TDataOrdinalType; - floatType: TDataFloatType; - intArrayType1, intArrayType2: TDataArrayType; - floatArrayType: TDataArrayType; + intType: TDataType.TOrdinal; + floatType: TDataType.TFloat; + intArrayType1, intArrayType2: TDataType.TArray; + floatArrayType: TDataType.TArray; arrayValue: TDataArrayValue; v1, v2: TDataOrdinalValue; begin @@ -247,16 +247,16 @@ begin Assert.AreEqual('Array', TDataType(floatArrayType).Name, 'Type name should be Array'); // --- 3. Test Value Creation and Access --- - v1 := TDataValue.FromOrdinal(10); - v2 := TDataValue.FromOrdinal(20); + v1 := TDataType.FromOrdinal(10); + v2 := TDataType.FromOrdinal(20); arrayValue := intArrayType1.CreateValue([v1, v2]); Assert.IsNotNull(IDataArrayValue(arrayValue), 'ArrayValue should be created'); Assert.AreEqual(2, arrayValue.ElementCount, 'ElementCount should be 2'); // Access items and check values - Assert.AreEqual(Int64(10), TDataValue(arrayValue.Items[0]).AsOrdinal.Value, 'Item at index 0 is incorrect'); - Assert.AreEqual(Int64(20), TDataValue(arrayValue.Items[1]).AsOrdinal.Value, 'Item at index 1 is incorrect'); + Assert.AreEqual(Int64(10), TDataType.TValue(arrayValue.Items[0]).AsOrdinal.Value, 'Item at index 0 is incorrect'); + Assert.AreEqual(Int64(20), TDataType.TValue(arrayValue.Items[1]).AsOrdinal.Value, 'Item at index 1 is incorrect'); // --- 4. Test Validation and Error Handling --- // Test creating an array with a nil element type @@ -267,7 +267,7 @@ begin procedure begin // Try to add a float value to an Array - intArrayType1.CreateValue([v1, TDataValue.FromFloat(3.14)]); + intArrayType1.CreateValue([v1, TDataType.FromFloat(3.14)]); end, EArgumentException, 'Wrong element type should raise an exception' @@ -276,7 +276,7 @@ end; procedure TMyTestObject.TestArrays_OptimizedAndGeneric; var - arrayType: TDataArrayType; + arrayType: TDataType.TArray; empty1, empty2, single, generic: TDataArrayValue; begin arrayType := TDataType.ArrayOf(TDataType.Ordinal); @@ -290,14 +290,14 @@ begin Assert.AreEqual('[]', IDataArrayValue(empty1).AsString, 'Empty array AsString is incorrect'); // Test optimized path for 1 element - single := arrayType.CreateValue([TDataValue.FromOrdinal(42)]); + single := arrayType.CreateValue([TDataType.FromOrdinal(42)]); Assert.IsNotNull(IDataArrayValue(single), 'Single element array should be created'); Assert.AreEqual(1, single.ElementCount, 'Single element array should have 1 element'); - Assert.AreEqual(Int64(42), TDataValue(single.Items[0]).AsOrdinal.Value, 'Single element value is incorrect'); + Assert.AreEqual(Int64(42), TDataType.TValue(single.Items[0]).AsOrdinal.Value, 'Single element value is incorrect'); Assert.AreEqual('[42]', IDataArrayValue(single).AsString, 'Single element array AsString is incorrect'); // Test generic path for > 1 elements - generic := arrayType.CreateValue([TDataValue.FromOrdinal(1), TDataValue.FromOrdinal(2), TDataValue.FromOrdinal(3)]); + generic := arrayType.CreateValue([TDataType.FromOrdinal(1), TDataType.FromOrdinal(2), TDataType.FromOrdinal(3)]); Assert.IsNotNull(IDataArrayValue(generic), 'Generic array should be created'); Assert.AreEqual(3, generic.ElementCount, 'Generic array should have 3 elements'); Assert.AreEqual('[1, 2, 3]', IDataArrayValue(generic).AsString, 'Generic array AsString is incorrect'); @@ -305,7 +305,7 @@ end; procedure TMyTestObject.TestTexts; var - textType: TDataTextType; + textType: TDataType.TText; textValue1, textValue2: TDataTextValue; dataValue: IDataValue; begin @@ -317,24 +317,27 @@ begin Assert.AreEqual(dkText, TDataType(textType).Kind, 'Type kind should be dkText'); // --- 2. Test Value Creation and Access --- - textValue1 := TDataValue.FromText('Hello World'); + textValue1 := TDataType.FromText('Hello World'); Assert.IsNotNull(IDataTextValue(textValue1), 'TextValue should be created'); Assert.AreSame(IDataType(textType), IDataTextValue(textValue1).DataType, 'Value should have the correct data type'); Assert.AreEqual('Hello World', textValue1.Value, 'Value should be ''Hello World'''); // Test another text value - textValue2 := TDataValue.FromText('Delphi'); + textValue2 := TDataType.FromText('Delphi'); Assert.AreEqual('Delphi', textValue2.Value, 'Value should be ''Delphi'''); // --- 3. Test AsText casting --- - dataValue := TDataValue.FromText('Test Text'); - Assert.AreEqual('Test Text', TDataValue(dataValue).AsText.Value, 'AsText should return correct value'); + dataValue := TDataType.FromText('Test Text'); + Assert.AreEqual('Test Text', TDataType.TValue(dataValue).AsText.Value, 'AsText should return correct value'); // Test invalid cast - dataValue := TDataValue.FromOrdinal(123); - Assert - .WillRaise(procedure begin TDataValue(dataValue).AsText; end, EInvalidCast, 'Casting non-text to AsText should raise EInvalidCast'); + dataValue := TDataType.FromOrdinal(123); + Assert.WillRaise( + procedure begin TDataType.TValue(dataValue).AsText; end, + EInvalidCast, + 'Casting non-text to AsText should raise EInvalidCast' + ); end; procedure TMyTestObject.TestTexts_OptimizedEmpty; @@ -342,8 +345,8 @@ var empty1, empty2: TDataTextValue; begin // Test the singleton implementation for the empty string. - empty1 := TDataValue.FromText(''); - empty2 := TDataValue.FromText(''); + empty1 := TDataType.FromText(''); + empty2 := TDataType.FromText(''); Assert.IsNotNull(IDataTextValue(empty1), 'Empty text value should be created'); Assert.AreSame(IDataTextValue(empty1), IDataTextValue(empty2), 'Empty text value should be a singleton'); @@ -356,22 +359,22 @@ var zero1, zero2, nan1, nan2, generic: TDataFloatValue; begin // Test singleton for 0.0 - zero1 := TDataValue.FromFloat(0.0); - zero2 := TDataValue.FromFloat(0.0); + zero1 := TDataType.FromFloat(0.0); + zero2 := TDataType.FromFloat(0.0); Assert.IsNotNull(IDataFloatValue(zero1), 'Zero float should be created'); Assert.AreSame(IDataFloatValue(zero1), IDataFloatValue(zero2), 'Zero float should be a singleton'); Assert.AreEqual(0.0, zero1.Value, 'Value of zero float is incorrect'); // Test singleton for NaN - nan1 := TDataValue.FromFloat(NaN); - nan2 := TDataValue.FromFloat(NaN); + nan1 := TDataType.FromFloat(NaN); + nan2 := TDataType.FromFloat(NaN); Assert.IsNotNull(IDataFloatValue(nan1), 'NaN float should be created'); Assert.AreSame(IDataFloatValue(nan1), IDataFloatValue(nan2), 'NaN float should be a singleton'); Assert.IsTrue(IsNaN(nan1.Value), 'Value of NaN float should be NaN'); Assert.AreEqual('NaN', IDataFloatValue(nan1).AsString, 'NaN AsString is incorrect'); // Test generic path - generic := TDataValue.FromFloat(123.45); + generic := TDataType.FromFloat(123.45); Assert.IsNotNull(IDataFloatValue(generic), 'Generic float should be created'); Assert.AreNotSame(IDataFloatValue(zero1), IDataFloatValue(generic), 'Generic float should not be the zero singleton'); Assert.AreNotSame(IDataFloatValue(nan1), IDataFloatValue(generic), 'Generic float should not be the NaN singleton'); @@ -380,7 +383,7 @@ end; procedure TMyTestObject.TestTimestamps; var - tsType: TDataTimestampType; + tsType: TDataType.TTimestamp; tsValue1, tsValue2: TDataTimestampValue; dataValue: IDataValue; now: TDateTime; @@ -394,24 +397,24 @@ begin // --- 2. Test Value Creation and Access --- now := System.Sysutils.Now; - tsValue1 := TDataValue.FromTimestamp(now); + tsValue1 := TDataType.FromTimestamp(now); Assert.IsNotNull(IDataTimestampValue(tsValue1), 'TimestampValue should be created'); Assert.AreSame(IDataType(tsType), IDataTimestampValue(tsValue1).DataType, 'Value should have the correct data type'); Assert.AreEqual(now, tsValue1.Value, 'Value should be the same'); // Test another text value - tsValue2 := TDataValue.FromTimestamp(Date); + tsValue2 := TDataType.FromTimestamp(Date); Assert.AreEqual(Date, tsValue2.Value, 'Value should be the same'); // --- 3. Test AsTimestamp casting --- - dataValue := TDataValue.FromTimestamp(now); - Assert.AreEqual(now, TDataValue(dataValue).AsTimestamp.Value, 'AsTimestamp should return correct value'); + dataValue := TDataType.FromTimestamp(now); + Assert.AreEqual(now, TDataType.TValue(dataValue).AsTimestamp.Value, 'AsTimestamp should return correct value'); // Test invalid cast - dataValue := TDataValue.FromOrdinal(123); + dataValue := TDataType.FromOrdinal(123); Assert.WillRaise( - procedure begin TDataValue(dataValue).AsTimestamp; end, + procedure begin TDataType.TValue(dataValue).AsTimestamp; end, EInvalidCast, 'Casting non-timestamp to AsTimestamp should raise EInvalidCast' ); @@ -419,7 +422,7 @@ end; procedure TMyTestObject.TestEnums; var - colorType: TDataEnumType; + colorType: TDataType.TEnum; red, green, blue: TDataEnumValue; begin // --- 1. Test Type Creation --- @@ -482,26 +485,26 @@ var arrayValue: TDataArrayValue; recordValue: TDataRecordValue; tupleValue: TDataTupleValue; - colorType: TDataEnumType; - personType: TDataRecordType; - intArrayType: TDataArrayType; + colorType: TDataType.TEnum; + personType: TDataType.TRecord; + intArrayType: TDataType.TArray; now: TDateTime; begin // Ordinal - ordinalValue := TDataValue.FromOrdinal(123); + ordinalValue := TDataType.FromOrdinal(123); Assert.AreEqual('123', IDataOrdinalValue(ordinalValue).AsString, 'Ordinal AsString incorrect'); // Float - floatValue := TDataValue.FromFloat(45.67); + floatValue := TDataType.FromFloat(45.67); Assert.AreEqual(FloatToStr(45.67), IDataFloatValue(floatValue).AsString, 'Float AsString incorrect'); // Text - textValue := TDataValue.FromText('Hello'); + textValue := TDataType.FromText('Hello'); Assert.AreEqual('Hello', IDataTextValue(textValue).AsString, 'Text AsString incorrect'); // Timestamp now := System.Sysutils.Now; - tsValue := TDataValue.FromTimestamp(now); + tsValue := TDataType.FromTimestamp(now); Assert.AreEqual(DateTimeToStr(now), IDataTimestampValue(tsValue).AsString, 'Timestamp AsString incorrect'); // Enum @@ -511,16 +514,16 @@ begin // Array intArrayType := TDataType.ArrayOf(TDataType.Ordinal); - arrayValue := intArrayType.CreateValue([TDataValue.FromOrdinal(1), TDataValue.FromOrdinal(2)]); + arrayValue := intArrayType.CreateValue([TDataType.FromOrdinal(1), TDataType.FromOrdinal(2)]); Assert.AreEqual('[1, 2]', IDataArrayValue(arrayValue).AsString, 'Array AsString incorrect'); // Record personType := TDataType.RecordOf([TRecordField.Create('ID', TDataType.Ordinal), TRecordField.Create('Name', TDataType.Text)]); - recordValue := personType.CreateValue([TDataValue.FromOrdinal(1), TDataValue.FromText('Bob')]); + recordValue := personType.CreateValue([TDataType.FromOrdinal(1), TDataType.FromText('Bob')]); Assert.AreEqual('', IDataRecordValue(recordValue).AsString, 'Record AsString incorrect'); // Tuple - tupleValue := TDataValue.FromTuple([TDataValue.FromOrdinal(10), TDataValue.FromText('Tuple')]); + tupleValue := TDataType.FromTuple([TDataType.FromOrdinal(10), TDataType.FromText('Tuple')]); Assert.AreEqual('(10, Tuple)', IDataTupleValue(tupleValue).AsString, 'Tuple AsString incorrect'); end; @@ -529,26 +532,26 @@ var dataValue: IDataValue; // Keep as generic interface to test AsTValue tv, element: TValue; now: TDateTime; - colorType: TDataEnumType; - intArrayType: TDataArrayType; - personType: TDataRecordType; + colorType: TDataType.TEnum; + intArrayType: TDataType.TArray; + personType: TDataType.TRecord; begin // --- Ordinal --- - dataValue := TDataValue.FromOrdinal(123); + dataValue := TDataType.FromOrdinal(123); tv := dataValue.AsTValue; Assert.IsFalse(tv.IsEmpty, 'Ordinal TValue should not be empty'); Assert.AreEqual(tkInt64, tv.Kind, 'Ordinal TValue kind should be tkInt64'); Assert.AreEqual(Int64(123), tv.AsInt64, 'Ordinal TValue content is incorrect'); // --- Float --- - dataValue := TDataValue.FromFloat(45.67); + dataValue := TDataType.FromFloat(45.67); tv := dataValue.AsTValue; Assert.IsFalse(tv.IsEmpty, 'Float TValue should not be empty'); Assert.AreEqual(tkFloat, tv.Kind, 'Float TValue kind should be tkFloat'); Assert.AreEqual(45.67, tv.AsExtended, 'Float TValue content is incorrect'); // --- Text --- - dataValue := TDataValue.FromText('Hello'); + dataValue := TDataType.FromText('Hello'); tv := dataValue.AsTValue; Assert.IsFalse(tv.IsEmpty, 'Text TValue should not be empty'); Assert.AreEqual(tkUString, tv.Kind, 'Text TValue kind should be tkUString'); @@ -556,7 +559,7 @@ begin // --- Timestamp --- now := System.SysUtils.Now; - dataValue := TDataValue.FromTimestamp(now); + dataValue := TDataType.FromTimestamp(now); tv := dataValue.AsTValue; Assert.IsFalse(tv.IsEmpty, 'Timestamp TValue should not be empty'); Assert.AreEqual(tkFloat, tv.Kind, 'Timestamp TValue kind is incorrect'); @@ -572,7 +575,7 @@ begin // --- Array --- intArrayType := TDataType.ArrayOf(TDataType.Ordinal); - dataValue := intArrayType.CreateValue([TDataValue.FromOrdinal(10), TDataValue.FromOrdinal(20)]); + dataValue := intArrayType.CreateValue([TDataType.FromOrdinal(10), TDataType.FromOrdinal(20)]); tv := dataValue.AsTValue; Assert.IsFalse(tv.IsEmpty, 'Array TValue should not be empty'); Assert.IsTrue(tv.IsArray, 'Array TValue should be an array'); @@ -595,7 +598,7 @@ begin // --- Record --- personType := TDataType.RecordOf([TRecordField.Create('ID', TDataType.Ordinal), TRecordField.Create('Name', TDataType.Text)]); - dataValue := personType.CreateValue([TDataValue.FromOrdinal(1), TDataValue.FromText('Bob')]); + dataValue := personType.CreateValue([TDataType.FromOrdinal(1), TDataType.FromText('Bob')]); tv := dataValue.AsTValue; Assert.IsFalse(tv.IsEmpty, 'Record TValue should not be empty'); Assert.IsTrue(tv.IsArray, 'Record TValue should be represented as an array'); @@ -605,7 +608,7 @@ begin Assert.AreEqual('Bob', tv.GetArrayElement(1).AsType.AsString, 'Record TValue element 1 is incorrect'); // --- Tuple --- - dataValue := TDataValue.FromTuple([TDataValue.FromOrdinal(99), TDataValue.FromText('Red')]); + dataValue := TDataType.FromTuple([TDataType.FromOrdinal(99), TDataType.FromText('Red')]); tv := dataValue.AsTValue; Assert.IsFalse(tv.IsEmpty, 'Tuple TValue should not be empty'); Assert.IsTrue(tv.IsArray, 'Tuple TValue should be represented as an array'); @@ -617,10 +620,10 @@ end; procedure TMyTestObject.TestMethods; var - ordinalType: TDataOrdinalType; - textType: TDataTextType; - methodType1, methodType2, otherMethodType: TDataMethodType; - myFunc: TMethodProc; + ordinalType: TDataType.TOrdinal; + textType: TDataType.TText; + methodType1, methodType2, otherMethodType: TDataType.TMethod; + myFunc: TDataType.TMethod.TProc; methodValue: TDataMethodValue; inputValue: TDataOrdinalValue; resultValue: IDataValue; @@ -657,28 +660,28 @@ begin // --- 3. Test Value Creation --- // Define a function that matches the signature Ordinal -> Text myFunc := - function(const AValue: IDataValue): IDataValue + function(const AValue: TDataType.TValue): TDataType.TValue var ordinalValue: TDataOrdinalValue; val: Int64; begin - ordinalValue := TDataValue(AValue).AsOrdinal; + ordinalValue := AValue.AsOrdinal; val := ordinalValue.Value; - Result := TDataValue.FromText(val.ToString); + Result := TDataType.FromText(val.ToString); end; - methodValue := TDataValue.FromMethod(methodType1, myFunc); + methodValue := TDataType.FromMethod(methodType1, myFunc); Assert.IsNotNull(IDataMethodValue(methodValue), 'MethodValue should be created'); Assert.AreSame(IDataType(methodType1), IDataMethodValue(methodValue).DataType, 'Value should have the correct data type'); // --- 4. Test Execution (Simulated) --- - inputValue := TDataValue.FromOrdinal(42); + inputValue := TDataType.FromOrdinal(42); // Execute the function retrieved from the value resultValue := methodValue.Value(inputValue); Assert.IsNotNull(resultValue, 'Execution result should not be nil'); Assert.AreSame(IDataType(textType), resultValue.DataType, 'Result value should have Text type'); - Assert.AreEqual('42', TDataValue(resultValue).AsText.Value, 'Result value content is incorrect'); + Assert.AreEqual('42', TDataType.TValue(resultValue).AsText.Value, 'Result value content is incorrect'); // --- 5. Test AsString and AsTValue --- Assert.AreEqual('', IDataMethodValue(methodValue).AsString, 'Method AsString is incorrect'); @@ -686,19 +689,19 @@ begin tv := IDataMethodValue(methodValue).AsTValue; Assert.IsFalse(tv.IsEmpty, 'Method TValue should not be empty'); Assert.AreEqual(tkInterface, tv.Kind, 'TValue kind for a TMethodProc should be tkInterface, as it is a reference-to-function'); - Assert.IsTrue(TypeInfo(TMethodProc) = tv.TypeInfo, 'TValue should hold TMethodProc type info'); + Assert.IsTrue(TypeInfo(TDataMethodProc) = tv.TypeInfo, 'TValue should hold TMethodProc type info'); // --- 6. Test Validation and Error Handling --- // Test creating a value with a nil type Assert.WillRaise( - procedure begin TDataValue.FromMethod(nil, myFunc); end, + procedure begin TDataType.FromMethod(nil, myFunc); end, EArgumentException, 'FromMethod with nil type should raise an exception' ); // Test creating a value with a nil function Assert.WillRaise( - procedure begin TDataValue.FromMethod(methodType1, nil); end, + procedure begin TDataType.FromMethod(methodType1, nil); end, EArgumentException, 'FromMethod with nil function should raise an exception' ); diff --git a/Src/Myc.Trade.Indicators.Common.pas b/Src/Myc.Trade.Indicators.Common.pas index bd8e51a..b06eb2a 100644 --- a/Src/Myc.Trade.Indicators.Common.pas +++ b/Src/Myc.Trade.Indicators.Common.pas @@ -350,57 +350,24 @@ implementation class constructor TSMA.CreateClass; begin - { var params := TDataType.RecordOf( [TRecordField.Create( 'Period', TDataType.Ordinal )] ); - var args := TDataType.RecordOf( [TRecordField.Create( 'Value', TDataType.Float )] ); - var results := TDataType.RecordOf( [TRecordField.Create( 'SMA', TDataType.Float )] ); + var paramsType := TDataType.Ordinal; + var argsType := TDataType.Float; + var resultType := TDataType.Float; - var indicatorMethod := TDataType.MethodOf( args, results ); - var factoryMethod := TDataType.MethodOf( params, indicatorMethod ); - - FFactory := factoryMethod.CreateValue( - function( const Params: IDataValue ): IDataValue - begin - var period := TDataValue(TDataValue(Params).AsRecord.Items[0]).AsOrdinal.Value; - - var SMA := CreateSMA( period ); - - Result := indicatorMethod.CreateValue( - function( const Args: IDataValue ): IDataValue - begin - var value := TDataValue(TDataValue(Args).AsRecord.Items[0]).AsFloat.Value; - - var res := SMA( value ); - - Result := results.CreateValue( [TDataValue.FromFloat(res)] ); - end ); - end ); -} - - // ....or.... - var params := TDataType.Ordinal; - var args := TDataType.Float; - var results := TDataType.Float; - - var indicatorMethod := TDataType.MethodOf(args, results); - var factoryMethod := TDataType.MethodOf(params, indicatorMethod); + var indicatorMethodType := TDataType.MethodOf(argsType, resultType); + var factoryMethodType := TDataType.MethodOf(paramsType, indicatorMethodType); FFactory := - factoryMethod.CreateValue( - function(const Params: IDataValue): IDataValue + factoryMethodType.CreateValue( + function(const Params: TDataType.TValue): TDataType.TValue begin - var period := TDataValue(Params).AsOrdinal.Value; - - var SMA := CreateSMA(period); - + // Local variable is necessary here to capture the created function. + var SMA := CreateSMA(Params.AsOrdinal.Value); Result := - indicatorMethod.CreateValue( - function(const Args: IDataValue): IDataValue + indicatorMethodType.CreateValue( + function(const Args: TDataType.TValue): TDataType.TValue begin - var value := TDataValue(Args).AsFloat.Value; - - var res := SMA(value); - - Result := results.CreateValue(res); + Result := TDataType.FromFloat(SMA(Args.AsFloat.Value)); end ); end @@ -483,28 +450,23 @@ end; class constructor TEMA.CreateClass; begin - var params := TDataType.RecordOf([TRecordField.Create('Period', TDataType.Ordinal)]); - var args := TDataType.RecordOf([TRecordField.Create('Value', TDataType.Float)]); - var results := TDataType.RecordOf([TRecordField.Create('EMA', TDataType.Float)]); + var paramsType := TDataType.Ordinal; + var argsType := TDataType.Float; + var resultType := TDataType.Float; - var indicatorMethod := TDataType.MethodOf(args, results); - var factoryMethod := TDataType.MethodOf(params, indicatorMethod); + var indicatorMethodType := TDataType.MethodOf(argsType, resultType); + var factoryMethodType := TDataType.MethodOf(paramsType, indicatorMethodType); FFactory := - factoryMethod.CreateValue( - function(const Params: IDataValue): IDataValue + factoryMethodType.CreateValue( + function(const Params: TDataType.TValue): TDataType.TValue begin - var period := TDataValue(TDataValue(Params).AsRecord.Items[0]).AsOrdinal.Value; - - var EMA := CreateEMA(period); - + var EMA := CreateEMA(Params.AsOrdinal.Value); Result := - indicatorMethod.CreateValue( - function(const Args: IDataValue): IDataValue + indicatorMethodType.CreateValue( + function(const Args: TDataType.TValue): TDataType.TValue begin - var value := TDataValue(TDataValue(Args).AsRecord.Items[0]).AsFloat.Value; - var res := EMA(value); - Result := results.CreateValue([TDataValue.FromFloat(res)]); + Result := TDataType.FromFloat(EMA(Args.AsFloat.Value)); end ); end @@ -571,26 +533,23 @@ end; class constructor TWMA.CreateClass; begin - var params := TDataType.RecordOf([TRecordField.Create('Period', TDataType.Ordinal)]); - var args := TDataType.RecordOf([TRecordField.Create('Value', TDataType.Float)]); - var results := TDataType.RecordOf([TRecordField.Create('WMA', TDataType.Float)]); + var paramsType := TDataType.Ordinal; + var argsType := TDataType.Float; + var resultType := TDataType.Float; - var indicatorMethod := TDataType.MethodOf(args, results); - var factoryMethod := TDataType.MethodOf(params, indicatorMethod); + var indicatorMethodType := TDataType.MethodOf(argsType, resultType); + var factoryMethodType := TDataType.MethodOf(paramsType, indicatorMethodType); FFactory := - factoryMethod.CreateValue( - function(const Params: IDataValue): IDataValue + factoryMethodType.CreateValue( + function(const Params: TDataType.TValue): TDataType.TValue begin - var period := TDataValue(TDataValue(Params).AsRecord.Items[0]).AsOrdinal.Value; - var WMA := CreateWMA(period); + var WMA := CreateWMA(Params.AsOrdinal.Value); Result := - indicatorMethod.CreateValue( - function(const Args: IDataValue): IDataValue + indicatorMethodType.CreateValue( + function(const Args: TDataType.TValue): TDataType.TValue begin - var value := TDataValue(TDataValue(Args).AsRecord.Items[0]).AsFloat.Value; - var res := WMA(value); - Result := results.CreateValue([TDataValue.FromFloat(res)]); + Result := TDataType.FromFloat(WMA(Args.AsFloat.Value)); end ); end @@ -669,26 +628,23 @@ end; class constructor THMA.CreateClass; begin - var params := TDataType.RecordOf([TRecordField.Create('Period', TDataType.Ordinal)]); - var args := TDataType.RecordOf([TRecordField.Create('Value', TDataType.Float)]); - var results := TDataType.RecordOf([TRecordField.Create('HMA', TDataType.Float)]); + var paramsType := TDataType.Ordinal; + var argsType := TDataType.Float; + var resultType := TDataType.Float; - var indicatorMethod := TDataType.MethodOf(args, results); - var factoryMethod := TDataType.MethodOf(params, indicatorMethod); + var indicatorMethodType := TDataType.MethodOf(argsType, resultType); + var factoryMethodType := TDataType.MethodOf(paramsType, indicatorMethodType); FFactory := - factoryMethod.CreateValue( - function(const Params: IDataValue): IDataValue + factoryMethodType.CreateValue( + function(const Params: TDataType.TValue): TDataType.TValue begin - var period := TDataValue(TDataValue(Params).AsRecord.Items[0]).AsOrdinal.Value; - var HMA := CreateHMA(period); + var HMA := CreateHMA(Params.AsOrdinal.Value); Result := - indicatorMethod.CreateValue( - function(const Args: IDataValue): IDataValue + indicatorMethodType.CreateValue( + function(const Args: TDataType.TValue): TDataType.TValue begin - var value := TDataValue(TDataValue(Args).AsRecord.Items[0]).AsFloat.Value; - var res := HMA(value); - Result := results.CreateValue([TDataValue.FromFloat(res)]); + Result := TDataType.FromFloat(HMA(Args.AsFloat.Value)); end ); end @@ -740,26 +696,23 @@ end; class constructor TRSI.CreateClass; begin - var params := TDataType.RecordOf([TRecordField.Create('Period', TDataType.Ordinal)]); - var args := TDataType.RecordOf([TRecordField.Create('Value', TDataType.Float)]); - var results := TDataType.RecordOf([TRecordField.Create('RSI', TDataType.Float)]); + var paramsType := TDataType.Ordinal; + var argsType := TDataType.Float; + var resultType := TDataType.Float; - var indicatorMethod := TDataType.MethodOf(args, results); - var factoryMethod := TDataType.MethodOf(params, indicatorMethod); + var indicatorMethodType := TDataType.MethodOf(argsType, resultType); + var factoryMethodType := TDataType.MethodOf(paramsType, indicatorMethodType); FFactory := - factoryMethod.CreateValue( - function(const Params: IDataValue): IDataValue + factoryMethodType.CreateValue( + function(const Params: TDataType.TValue): TDataType.TValue begin - var period := TDataValue(TDataValue(Params).AsRecord.Items[0]).AsOrdinal.Value; - var RSI := CreateRSI(period); + var RSI := CreateRSI(Params.AsOrdinal.Value); Result := - indicatorMethod.CreateValue( - function(const Args: IDataValue): IDataValue + indicatorMethodType.CreateValue( + function(const Args: TDataType.TValue): TDataType.TValue begin - var value := TDataValue(TDataValue(Args).AsRecord.Items[0]).AsFloat.Value; - var res := RSI(value); - Result := results.CreateValue([TDataValue.FromFloat(res)]); + Result := TDataType.FromFloat(RSI(Args.AsFloat.Value)); end ); end @@ -841,7 +794,7 @@ end; class constructor TMACD.CreateClass; begin - var params := + var paramsType := TDataType.RecordOf( [ TRecordField.Create('FastPeriod', TDataType.Ordinal), @@ -849,8 +802,8 @@ begin TRecordField.Create('SignalPeriod', TDataType.Ordinal) ] ); - var args := TDataType.RecordOf([TRecordField.Create('Value', TDataType.Float)]); - var results := + var argsType := TDataType.Float; + var resultType := TDataType.RecordOf( [ TRecordField.Create('MacdLine', TDataType.Float), @@ -859,33 +812,34 @@ begin ] ); - var indicatorMethod := TDataType.MethodOf(args, results); - var factoryMethod := TDataType.MethodOf(params, indicatorMethod); + var indicatorMethodType := TDataType.MethodOf(argsType, resultType); + var factoryMethodType := TDataType.MethodOf(paramsType, indicatorMethodType); FFactory := - factoryMethod.CreateValue( - function(const Params: IDataValue): IDataValue + factoryMethodType.CreateValue( + function(const Params: TDataType.TValue): TDataType.TValue var - paramsRec: IDataRecordValue; + paramsRec: TDataRecordValue; begin - paramsRec := TDataValue(Params).AsRecord; - var fastPeriod := TDataValue(paramsRec.Items[0]).AsOrdinal.Value; - var slowPeriod := TDataValue(paramsRec.Items[1]).AsOrdinal.Value; - var signalPeriod := TDataValue(paramsRec.Items[2]).AsOrdinal.Value; - var MACD := CreateMACD(fastPeriod, slowPeriod, signalPeriod); + paramsRec := Params.AsRecord; + var MACD := + CreateMACD( + TDataType.TValue(paramsRec.Items[0]).AsOrdinal.Value, + TDataType.TValue(paramsRec.Items[1]).AsOrdinal.Value, + TDataType.TValue(paramsRec.Items[2]).AsOrdinal.Value + ); Result := - indicatorMethod.CreateValue( - function(const Args: IDataValue): IDataValue + indicatorMethodType.CreateValue( + function(const Args: TDataType.TValue): TDataType.TValue begin - var value := TDataValue(TDataValue(Args).AsRecord.Items[0]).AsFloat.Value; - var res := MACD(value); + var res := MACD(Args.AsFloat.Value); Result := - results.CreateValue( + resultType.CreateValue( [ - TDataValue.FromFloat(res.MacdLine), - TDataValue.FromFloat(res.SignalLine), - TDataValue.FromFloat(res.Histogram) + TDataType.FromFloat(res.MacdLine), + TDataType.FromFloat(res.SignalLine), + TDataType.FromFloat(res.Histogram) ] ); end @@ -1007,7 +961,7 @@ end; class constructor TStochastic.CreateClass; begin - var params := + var paramsType := TDataType.RecordOf([TRecordField.Create('KPeriod', TDataType.Ordinal), TRecordField.Create('DPeriod', TDataType.Ordinal)]); var ohlcType := @@ -1021,42 +975,43 @@ begin ] ); - var args := TDataType.RecordOf([TRecordField.Create('Value', ohlcType)]); - var results := TDataType.RecordOf([TRecordField.Create('K', TDataType.Float), TRecordField.Create('D', TDataType.Float)]); + var argsType := ohlcType; + var resultType := TDataType.RecordOf([TRecordField.Create('K', TDataType.Float), TRecordField.Create('D', TDataType.Float)]); - var indicatorMethod := TDataType.MethodOf(args, results); - var factoryMethod := TDataType.MethodOf(params, indicatorMethod); + var indicatorMethodType := TDataType.MethodOf(argsType, resultType); + var factoryMethodType := TDataType.MethodOf(paramsType, indicatorMethodType); FFactory := - factoryMethod.CreateValue( - function(const Params: IDataValue): IDataValue + factoryMethodType.CreateValue( + function(const Params: TDataType.TValue): TDataType.TValue var - paramsRec: IDataRecordValue; + paramsRec: TDataRecordValue; begin - paramsRec := TDataValue(Params).AsRecord; - var kPeriod := TDataValue(paramsRec.Items[0]).AsOrdinal.Value; - var dPeriod := TDataValue(paramsRec.Items[1]).AsOrdinal.Value; - var Stochastic := CreateStochastic(kPeriod, dPeriod); + paramsRec := Params.AsRecord; + var Stochastic := + CreateStochastic( + TDataType.TValue(paramsRec.Items[0]).AsOrdinal.Value, + TDataType.TValue(paramsRec.Items[1]).AsOrdinal.Value + ); Result := - indicatorMethod.CreateValue( - function(const Args: IDataValue): IDataValue + indicatorMethodType.CreateValue( + function(const Args: TDataType.TValue): TDataType.TValue var - argRec, ohlcRec: IDataRecordValue; + ohlcRec: TDataRecordValue; ohlcVal: TOhlcItem; begin - argRec := TDataValue(Args).AsRecord; - ohlcRec := TDataValue(argRec.Items[0]).AsRecord; + ohlcRec := Args.AsRecord; - ohlcVal.Open := TDataValue(ohlcRec.Items[0]).AsFloat.Value; - ohlcVal.High := TDataValue(ohlcRec.Items[1]).AsFloat.Value; - ohlcVal.Low := TDataValue(ohlcRec.Items[2]).AsFloat.Value; - ohlcVal.Close := TDataValue(ohlcRec.Items[3]).AsFloat.Value; - ohlcVal.Volume := TDataValue(ohlcRec.Items[4]).AsFloat.Value; + ohlcVal.Open := TDataType.TValue(ohlcRec.Items[0]).AsFloat.Value; + ohlcVal.High := TDataType.TValue(ohlcRec.Items[1]).AsFloat.Value; + ohlcVal.Low := TDataType.TValue(ohlcRec.Items[2]).AsFloat.Value; + ohlcVal.Close := TDataType.TValue(ohlcRec.Items[3]).AsFloat.Value; + ohlcVal.Volume := TDataType.TValue(ohlcRec.Items[4]).AsFloat.Value; var res := Stochastic(ohlcVal); - Result := results.CreateValue([TDataValue.FromFloat(res.K), TDataValue.FromFloat(res.D)]); + Result := resultType.CreateValue([TDataType.FromFloat(res.K), TDataType.FromFloat(res.D)]); end ); end @@ -1172,26 +1127,23 @@ end; class constructor TStdDev.CreateClass; begin - var params := TDataType.RecordOf([TRecordField.Create('Period', TDataType.Ordinal)]); - var args := TDataType.RecordOf([TRecordField.Create('Value', TDataType.Float)]); - var results := TDataType.RecordOf([TRecordField.Create('StdDev', TDataType.Float)]); + var paramsType := TDataType.Ordinal; + var argsType := TDataType.Float; + var resultType := TDataType.Float; - var indicatorMethod := TDataType.MethodOf(args, results); - var factoryMethod := TDataType.MethodOf(params, indicatorMethod); + var indicatorMethodType := TDataType.MethodOf(argsType, resultType); + var factoryMethodType := TDataType.MethodOf(paramsType, indicatorMethodType); FFactory := - factoryMethod.CreateValue( - function(const Params: IDataValue): IDataValue + factoryMethodType.CreateValue( + function(const Params: TDataType.TValue): TDataType.TValue begin - var period := TDataValue(TDataValue(Params).AsRecord.Items[0]).AsOrdinal.Value; - var StdDev := CreateStdDev(period); + var StdDev := CreateStdDev(Params.AsOrdinal.Value); Result := - indicatorMethod.CreateValue( - function(const Args: IDataValue): IDataValue + indicatorMethodType.CreateValue( + function(const Args: TDataType.TValue): TDataType.TValue begin - var value := TDataValue(TDataValue(Args).AsRecord.Items[0]).AsFloat.Value; - var res := StdDev(value); - Result := results.CreateValue([TDataValue.FromFloat(res)]); + Result := TDataType.FromFloat(StdDev(Args.AsFloat.Value)); end ); end @@ -1265,10 +1217,10 @@ end; class constructor TBollingerBands.CreateClass; begin - var params := + var paramsType := TDataType.RecordOf([TRecordField.Create('Period', TDataType.Ordinal), TRecordField.Create('Multiplier', TDataType.Float)]); - var args := TDataType.RecordOf([TRecordField.Create('Value', TDataType.Float)]); - var results := + var argsType := TDataType.Float; + var resultType := TDataType.RecordOf( [ TRecordField.Create('UpperBand', TDataType.Float), @@ -1277,32 +1229,33 @@ begin ] ); - var indicatorMethod := TDataType.MethodOf(args, results); - var factoryMethod := TDataType.MethodOf(params, indicatorMethod); + var indicatorMethodType := TDataType.MethodOf(argsType, resultType); + var factoryMethodType := TDataType.MethodOf(paramsType, indicatorMethodType); FFactory := - factoryMethod.CreateValue( - function(const Params: IDataValue): IDataValue + factoryMethodType.CreateValue( + function(const Params: TDataType.TValue): TDataType.TValue var - paramsRec: IDataRecordValue; + paramsRec: TDataRecordValue; begin - paramsRec := TDataValue(Params).AsRecord; - var period := TDataValue(paramsRec.Items[0]).AsOrdinal.Value; - var multiplier := TDataValue(paramsRec.Items[1]).AsFloat.Value; - var BollingerBands := CreateBollingerBands(period, multiplier); + paramsRec := Params.AsRecord; + var BollingerBands := + CreateBollingerBands( + TDataType.TValue(paramsRec.Items[0]).AsOrdinal.Value, + TDataType.TValue(paramsRec.Items[1]).AsFloat.Value + ); Result := - indicatorMethod.CreateValue( - function(const Args: IDataValue): IDataValue + indicatorMethodType.CreateValue( + function(const Args: TDataType.TValue): TDataType.TValue begin - var value := TDataValue(TDataValue(Args).AsRecord.Items[0]).AsFloat.Value; - var res := BollingerBands(value); + var res := BollingerBands(Args.AsFloat.Value); Result := - results.CreateValue( + resultType.CreateValue( [ - TDataValue.FromFloat(res.UpperBand), - TDataValue.FromFloat(res.MiddleBand), - TDataValue.FromFloat(res.LowerBand) + TDataType.FromFloat(res.UpperBand), + TDataType.FromFloat(res.MiddleBand), + TDataType.FromFloat(res.LowerBand) ] ); end @@ -1359,8 +1312,7 @@ end; class constructor TATR.CreateClass; begin - var params := TDataType.RecordOf([TRecordField.Create('Period', TDataType.Ordinal)]); - + var paramsType := TDataType.Ordinal; var ohlcType := TDataType.RecordOf( [ @@ -1371,35 +1323,32 @@ begin TRecordField.Create('Volume', TDataType.Float) ] ); - var args := TDataType.RecordOf([TRecordField.Create('Value', ohlcType)]); - var results := TDataType.RecordOf([TRecordField.Create('ATR', TDataType.Float)]); + var argsType := ohlcType; + var resultType := TDataType.Float; - var indicatorMethod := TDataType.MethodOf(args, results); - var factoryMethod := TDataType.MethodOf(params, indicatorMethod); + var indicatorMethodType := TDataType.MethodOf(argsType, resultType); + var factoryMethodType := TDataType.MethodOf(paramsType, indicatorMethodType); FFactory := - factoryMethod.CreateValue( - function(const Params: IDataValue): IDataValue + factoryMethodType.CreateValue( + function(const Params: TDataType.TValue): TDataType.TValue begin - var period := TDataValue(TDataValue(Params).AsRecord.Items[0]).AsOrdinal.Value; - var ATR := CreateATR(period); + var ATR := CreateATR(Params.AsOrdinal.Value); Result := - indicatorMethod.CreateValue( - function(const Args: IDataValue): IDataValue + indicatorMethodType.CreateValue( + function(const Args: TDataType.TValue): TDataType.TValue var - argRec, ohlcRec: IDataRecordValue; + ohlcRec: TDataRecordValue; ohlcVal: TOhlcItem; begin - argRec := TDataValue(Args).AsRecord; - ohlcRec := TDataValue(argRec.Items[0]).AsRecord; - ohlcVal.Open := TDataValue(ohlcRec.Items[0]).AsFloat.Value; - ohlcVal.High := TDataValue(ohlcRec.Items[1]).AsFloat.Value; - ohlcVal.Low := TDataValue(ohlcRec.Items[2]).AsFloat.Value; - ohlcVal.Close := TDataValue(ohlcRec.Items[3]).AsFloat.Value; - ohlcVal.Volume := TDataValue(ohlcRec.Items[4]).AsFloat.Value; - var res := ATR(ohlcVal); - Result := results.CreateValue([TDataValue.FromFloat(res)]); + ohlcRec := Args.AsRecord; + ohlcVal.Open := TDataType.TValue(ohlcRec.Items[0]).AsFloat.Value; + ohlcVal.High := TDataType.TValue(ohlcRec.Items[1]).AsFloat.Value; + ohlcVal.Low := TDataType.TValue(ohlcRec.Items[2]).AsFloat.Value; + ohlcVal.Close := TDataType.TValue(ohlcRec.Items[3]).AsFloat.Value; + ohlcVal.Volume := TDataType.TValue(ohlcRec.Items[4]).AsFloat.Value; + Result := TDataType.FromFloat(ATR(ohlcVal)); end ); end @@ -1455,7 +1404,7 @@ end; class constructor TKeltnerChannels.CreateClass; begin - var params := + var paramsType := TDataType.RecordOf([TRecordField.Create('Period', TDataType.Ordinal), TRecordField.Create('Multiplier', TDataType.Float)]); var ohlcType := TDataType.RecordOf( @@ -1467,8 +1416,8 @@ begin TRecordField.Create('Volume', TDataType.Float) ] ); - var args := TDataType.RecordOf([TRecordField.Create('Value', ohlcType)]); - var results := + var argsType := ohlcType; + var resultType := TDataType.RecordOf( [ TRecordField.Create('UpperBand', TDataType.Float), @@ -1477,42 +1426,43 @@ begin ] ); - var indicatorMethod := TDataType.MethodOf(args, results); - var factoryMethod := TDataType.MethodOf(params, indicatorMethod); + var indicatorMethodType := TDataType.MethodOf(argsType, resultType); + var factoryMethodType := TDataType.MethodOf(paramsType, indicatorMethodType); FFactory := - factoryMethod.CreateValue( - function(const Params: IDataValue): IDataValue + factoryMethodType.CreateValue( + function(const Params: TDataType.TValue): TDataType.TValue var - paramsRec: IDataRecordValue; + paramsRec: TDataRecordValue; begin - paramsRec := TDataValue(Params).AsRecord; - var period := TDataValue(paramsRec.Items[0]).AsOrdinal.Value; - var multiplier := TDataValue(paramsRec.Items[1]).AsFloat.Value; - var KeltnerChannels := CreateKeltnerChannels(period, multiplier); + paramsRec := Params.AsRecord; + var KeltnerChannels := + CreateKeltnerChannels( + TDataType.TValue(paramsRec.Items[0]).AsOrdinal.Value, + TDataType.TValue(paramsRec.Items[1]).AsFloat.Value + ); Result := - indicatorMethod.CreateValue( - function(const Args: IDataValue): IDataValue + indicatorMethodType.CreateValue( + function(const Args: TDataType.TValue): TDataType.TValue var - argRec, ohlcRec: IDataRecordValue; + ohlcRec: TDataRecordValue; ohlcVal: TOhlcItem; begin - argRec := TDataValue(Args).AsRecord; - ohlcRec := TDataValue(argRec.Items[0]).AsRecord; - ohlcVal.Open := TDataValue(ohlcRec.Items[0]).AsFloat.Value; - ohlcVal.High := TDataValue(ohlcRec.Items[1]).AsFloat.Value; - ohlcVal.Low := TDataValue(ohlcRec.Items[2]).AsFloat.Value; - ohlcVal.Close := TDataValue(ohlcRec.Items[3]).AsFloat.Value; - ohlcVal.Volume := TDataValue(ohlcRec.Items[4]).AsFloat.Value; + ohlcRec := Args.AsRecord; + ohlcVal.Open := TDataType.TValue(ohlcRec.Items[0]).AsFloat.Value; + ohlcVal.High := TDataType.TValue(ohlcRec.Items[1]).AsFloat.Value; + ohlcVal.Low := TDataType.TValue(ohlcRec.Items[2]).AsFloat.Value; + ohlcVal.Close := TDataType.TValue(ohlcRec.Items[3]).AsFloat.Value; + ohlcVal.Volume := TDataType.TValue(ohlcRec.Items[4]).AsFloat.Value; var res := KeltnerChannels(ohlcVal); Result := - results.CreateValue( + resultType.CreateValue( [ - TDataValue.FromFloat(res.UpperBand), - TDataValue.FromFloat(res.MiddleBand), - TDataValue.FromFloat(res.LowerBand) + TDataType.FromFloat(res.UpperBand), + TDataType.FromFloat(res.MiddleBand), + TDataType.FromFloat(res.LowerBand) ] ); end @@ -1576,35 +1526,32 @@ end; class constructor TMean.CreateClass; begin - var params := TDataType.RecordOf([]); - var args := TDataType.RecordOf([TRecordField.Create('Values', TDataType.ArrayOf(TDataType.Float))]); - var results := TDataType.RecordOf([TRecordField.Create('Mean', TDataType.Float)]); + var paramsType := TDataType.RecordOf([]); + var argsType := TDataType.ArrayOf(TDataType.Float); + var resultType := TDataType.Float; - var indicatorMethod := TDataType.MethodOf(args, results); - var factoryMethod := TDataType.MethodOf(params, indicatorMethod); + var indicatorMethodType := TDataType.MethodOf(argsType, resultType); + var factoryMethodType := TDataType.MethodOf(paramsType, indicatorMethodType); FFactory := - factoryMethod.CreateValue( - function(const Params: IDataValue): IDataValue + factoryMethodType.CreateValue( + function(const Params: TDataType.TValue): TDataType.TValue begin var Mean := CreateMean(); Result := - indicatorMethod.CreateValue( - function(const Args: IDataValue): IDataValue + indicatorMethodType.CreateValue( + function(const Args: TDataType.TValue): TDataType.TValue var i: Integer; - argsRec: IDataRecordValue; - valuesArray: IDataArrayValue; + valuesArray: TDataArrayValue; values: TArray; begin - argsRec := TDataValue(Args).AsRecord; - valuesArray := TDataValue(argsRec.Items[0]).AsArray; + valuesArray := Args.AsArray; SetLength(values, valuesArray.ElementCount); for i := 0 to valuesArray.ElementCount - 1 do - values[i] := TDataValue(valuesArray.Items[i]).AsFloat.Value; + values[i] := TDataType.TValue(valuesArray.Items[i]).AsFloat.Value; - var res := Mean(values); - Result := results.CreateValue([TDataValue.FromFloat(res)]); + Result := TDataType.FromFloat(Mean(values)); end ); end diff --git a/Src/Myc.Trade.Indicators_v2.pas b/Src/Myc.Trade.Indicators_v2.pas index 95b404e..68c1e27 100644 --- a/Src/Myc.Trade.Indicators_v2.pas +++ b/Src/Myc.Trade.Indicators_v2.pas @@ -79,7 +79,7 @@ type function GetArgType: TDataType; function GetResultType: TDataType; - function CreateIndicator(const Params: TDataValue): TConvertFunc; + function CreateIndicator(const Params: TDataType.TValue): TConvertFunc; // Provides direct access to the type information of parameters, arguments, and results. property ParamType: TDataType read GetParamType; @@ -108,7 +108,7 @@ type function GetParamType: TDataType; function GetArgType: TDataType; function GetResultType: TDataType; - function CreateIndicator(const Params: TDataValue): TConvertFunc; overload; + function CreateIndicator(const Params: TDataType.TValue): TConvertFunc; overload; class function CreateFromTemplate: TGenericIndicatorFactory; @@ -163,7 +163,7 @@ type var IndicatorRegistry: TIndicatorRegistry; -function DataValueFromTValue(const aValue: TValue): TDataValue; +function DataValueFromTValue(const aValue: TValue): TDataType.TValue; function DataTypeFromRttiType(const Ctx: TRttiContext; rttiType: TRttiType): TDataType; implementation @@ -207,20 +207,20 @@ begin end; // Converts a TValue into an IDataValue. This is the bridge from RTTI to the custom type system. -function DataValueFromTValue(const aValue: TValue): TDataValue; +function DataValueFromTValue(const aValue: TValue): TDataType.TValue; var ctx: TRttiContext; begin if aValue.IsEmpty then begin - Result := TDataValue.Create(nil); + Result := TDataType.TValue.Create(nil); exit; end; case aValue.Kind of - tkInteger, tkInt64, tkEnumeration: Result := TDataValue.FromOrdinal(aValue.AsInt64); - tkFloat: Result := TDataValue.FromFloat(aValue.AsExtended); - tkString, tkUString: Result := TDataValue.FromText(aValue.AsString); + tkInteger, tkInt64, tkEnumeration: Result := TDataType.FromOrdinal(aValue.AsInt64); + tkFloat: Result := TDataType.FromFloat(aValue.AsExtended); + tkString, tkUString: Result := TDataType.FromText(aValue.AsString); tkRecord: begin ctx := TRttiContext.Create; @@ -438,12 +438,12 @@ begin Result := FResultType; end; -function TGenericIndicatorFactory.CreateIndicator(const Params: TDataValue): TConvertFunc; +function TGenericIndicatorFactory.CreateIndicator(const Params: TDataType.TValue): TConvertFunc; var internalProc: TConvertFunc; begin internalProc := FFactoryProc(Params); - Result := function(const Args: TDataValue): TDataValue begin Result := internalProc(Args); end; + Result := function(const Args: TDataType.TValue): TDataType.TValue begin Result := internalProc(Args); end; end; function TGenericIndicatorFactory.CreateIndicator(const Params: TParams): TConvertFunc; @@ -531,7 +531,7 @@ var // Generates a field layout from a data type. function LayoutFromDataType(DataType: TDataType): TFieldLayout; var - recordType: TDataRecordType; + recordType: TDataType.TRecord; begin if DataType.Kind <> TDataKind.dkRecord then begin