New type system - Decimals

This commit is contained in:
Michael Schimmel
2025-08-26 13:47:38 +02:00
parent c434a151dd
commit 1ff603bd10
7 changed files with 337 additions and 197 deletions
+127
View File
@@ -0,0 +1,127 @@
unit Myc.Data.Types.Decimal;
interface
uses
Myc.Data.Types;
type
// Concrete implementation of the IDataDecimalType interface.
TImplDataDecimalType = class(TInterfacedObject, IDataDecimalType)
private
FScale: Integer;
public
constructor Create(const AScale: Integer);
// IDataType
function GetName: String;
function GetKind: TDataKind;
// IDataDecimalType
function GetScale: Integer;
function CreateValue(const AValue: Int64): IDataDecimalValue;
end;
implementation
uses
System.SysUtils,
System.Rtti,
System.Math;
type
TDataDecimalValue = class(TInterfacedObject, IDataDecimalValue)
private
FDataType: IDataDecimalType;
FValue: Int64;
public
constructor Create(const AValue: Int64; const ADataType: IDataDecimalType);
// IDataValue
function GetDataType: IDataType;
function GetAsString: string;
function AsTValue: TValue;
// IDataDecimalValue
function GetValue: Int64;
end;
{ TImplDataDecimalType }
constructor TImplDataDecimalType.Create(const AScale: Integer);
begin
inherited Create;
FScale := AScale;
end;
function TImplDataDecimalType.CreateValue(const AValue: Int64): IDataDecimalValue;
begin
Result := TDataDecimalValue.Create(AValue, Self);
end;
function TImplDataDecimalType.GetKind: TDataKind;
begin
Result := dkDecimal;
end;
function TImplDataDecimalType.GetName: String;
begin
Result := Format('Decimal(18, %d)', [FScale]);
end;
function TImplDataDecimalType.GetScale: Integer;
begin
Result := FScale;
end;
{ TDataDecimalValue }
constructor TDataDecimalValue.Create(const AValue: Int64; const ADataType: IDataDecimalType);
begin
inherited Create;
FValue := AValue;
FDataType := ADataType;
end;
function TDataDecimalValue.AsTValue: TValue;
begin
Result := TValue.From<Int64>(FValue);
end;
function TDataDecimalValue.GetAsString: string;
var
s: string;
scale: Integer;
insertPos: Integer;
begin
s := IntToStr(abs(FValue));
scale := FDataType.Scale;
if scale > 0 then
begin
if Length(s) <= scale then
s := StringOfChar('0', scale - Length(s) + 1) + s;
insertPos := Length(s) - scale;
Result := Copy(s, 1, insertPos) + '.' + Copy(s, insertPos + 1, MaxInt);
end
else
begin
Result := s;
end;
if FValue < 0 then
Result := '-' + Result;
end;
function TDataDecimalValue.GetDataType: IDataType;
begin
Result := FDataType;
end;
function TDataDecimalValue.GetValue: Int64;
begin
Result := FValue;
end;
end.
+129 -113
View File
@@ -8,8 +8,7 @@ uses
System.RTTI; System.RTTI;
type type
// Corrected dfVoid to dkVoid and added void type support TDataKind = (dkVoid, dkOrdinal, dkFloat, dkText, dkTimestamp, dkDecimal, dkRecord, dkTuple, dkArray, dkEnum, dkMethod);
TDataKind = (dkVoid, dkOrdinal, dkFloat, dkText, dkTimestamp, dkRecord, dkTuple, dkArray, dkEnum, dkMethod);
IDataType = interface IDataType = interface
{$region 'private'} {$region 'private'}
@@ -82,6 +81,23 @@ type
function CreateValue(const AValue: TDateTime): IDataTimestampValue; function CreateValue(const AValue: TDateTime): IDataTimestampValue;
end; end;
// Represents a fixed-point decimal data value.
IDataDecimalValue = interface(IDataValue)
{$region 'private'}
function GetValue: Int64;
{$endregion}
property Value: Int64 read GetValue;
end;
// Represents the type of a fixed-point decimal data value.
IDataDecimalType = interface(IDataType)
{$region 'private'}
function GetScale: Integer;
{$endregion}
function CreateValue(const AValue: Int64): IDataDecimalValue;
property Scale: Integer read GetScale;
end;
IDataEnumValue = interface(IDataValue) IDataEnumValue = interface(IDataValue)
{$region 'private'} {$region 'private'}
function GetValue: Integer; function GetValue: Integer;
@@ -190,6 +206,7 @@ type
function AsFloat: IDataFloatValue; inline; function AsFloat: IDataFloatValue; inline;
function AsText: IDataTextValue; inline; function AsText: IDataTextValue; inline;
function AsTimestamp: IDataTimestampValue; inline; function AsTimestamp: IDataTimestampValue; inline;
function AsDecimal: IDataDecimalValue; inline;
function AsRecord: IDataRecordValue; inline; function AsRecord: IDataRecordValue; inline;
function AsTuple: IDataTupleValue; inline; function AsTuple: IDataTupleValue; inline;
function AsArray: IDataArrayValue; inline; function AsArray: IDataArrayValue; inline;
@@ -204,6 +221,7 @@ type
class operator Implicit(const A: IDataFloatValue): TDataType.TValue; overload; inline; class operator Implicit(const A: IDataFloatValue): TDataType.TValue; overload; inline;
class operator Implicit(const A: IDataTextValue): TDataType.TValue; overload; inline; class operator Implicit(const A: IDataTextValue): TDataType.TValue; overload; inline;
class operator Implicit(const A: IDataTimestampValue): TDataType.TValue; overload; inline; class operator Implicit(const A: IDataTimestampValue): TDataType.TValue; overload; inline;
class operator Implicit(const A: IDataDecimalValue): TDataType.TValue; overload; inline;
class operator Implicit(const A: IDataEnumValue): TDataType.TValue; overload; inline; class operator Implicit(const A: IDataEnumValue): TDataType.TValue; overload; inline;
class operator Implicit(const A: IDataMethodValue): TDataType.TValue; overload; inline; class operator Implicit(const A: IDataMethodValue): TDataType.TValue; overload; inline;
class operator Implicit(const A: IDataRecordValue): TDataType.TValue; overload; inline; class operator Implicit(const A: IDataRecordValue): TDataType.TValue; overload; inline;
@@ -266,6 +284,33 @@ type
function CreateValue(const AValue: TDateTime): IDataTimestampValue; inline; function CreateValue(const AValue: TDateTime): IDataTimestampValue; inline;
end; end;
TDecimal = record
type
TValue = record
private
// The wrapped interface instance.
FDecimalValue: IDataDecimalValue;
function GetValue: Int64; inline;
public
constructor Create(const ADecimalValue: IDataDecimalValue);
class operator Implicit(const A: IDataDecimalValue): TDataType.TDecimal.TValue; overload; inline;
class operator Implicit(const A: TDataType.TDecimal.TValue): IDataDecimalValue; overload; inline;
property Value: Int64 read GetValue;
end;
private
FDecimalType: IDataDecimalType;
function GetScale: Integer; inline;
public
constructor Create(const ADecimalType: IDataDecimalType);
class operator Implicit(const A: IDataDecimalType): TDataType.TDecimal; overload; inline;
class operator Implicit(const A: TDataType.TDecimal): IDataDecimalType; overload; inline;
function CreateValue(const AValue: Int64): TDataType.TDecimal.TValue; inline;
property Scale: Integer read GetScale;
end;
TEnum = record TEnum = record
private private
FEnumType: IDataEnumType; FEnumType: IDataEnumType;
@@ -343,6 +388,7 @@ type
FArrayTypeRegistry: TDictionary<IDataType, IDataArrayType>; FArrayTypeRegistry: TDictionary<IDataType, IDataArrayType>;
FRecordTypeRegistry: TDictionary<TArray<TRecordField>, IDataRecordType>; FRecordTypeRegistry: TDictionary<TArray<TRecordField>, IDataRecordType>;
FMethodTypeRegistry: TDictionary<TPair<IDataType, IDataType>, IDataMethodType>; FMethodTypeRegistry: TDictionary<TPair<IDataType, IDataType>, IDataMethodType>;
FDecimalTypes: TArray<IDataDecimalType>;
class constructor CreateClass; class constructor CreateClass;
class destructor DestroyClass; class destructor DestroyClass;
public public
@@ -355,6 +401,7 @@ type
class operator Implicit(const A: TDataType.TFloat): TDataType; overload; inline; class operator Implicit(const A: TDataType.TFloat): TDataType; overload; inline;
class operator Implicit(const A: TDataType.TText): TDataType; overload; inline; class operator Implicit(const A: TDataType.TText): TDataType; overload; inline;
class operator Implicit(const A: TDataType.TTimestamp): TDataType; overload; inline; class operator Implicit(const A: TDataType.TTimestamp): TDataType; overload; inline;
class operator Implicit(const A: TDataType.TDecimal): TDataType; overload; inline;
class operator Implicit(const A: TDataType.TEnum): TDataType; overload; inline; class operator Implicit(const A: TDataType.TEnum): TDataType; overload; inline;
class operator Implicit(const A: TDataType.TMethod): TDataType; overload; inline; class operator Implicit(const A: TDataType.TMethod): TDataType; overload; inline;
class operator Implicit(const A: TDataType.TRecord): TDataType; overload; inline; class operator Implicit(const A: TDataType.TRecord): TDataType; overload; inline;
@@ -367,6 +414,7 @@ type
class function Float: TDataType.TFloat; static; inline; class function Float: TDataType.TFloat; static; inline;
class function Text: TDataType.TText; static; inline; class function Text: TDataType.TText; static; inline;
class function Timestamp: TDataType.TTimestamp; static; inline; class function Timestamp: TDataType.TTimestamp; static; inline;
class function DecimalOf(const AScale: Integer): TDataType.TDecimal; static;
class function Tuple: TDataType.TTuple; static; inline; class function Tuple: TDataType.TTuple; static; inline;
class function MethodOf(const AArgType, AResultType: IDataType): TDataType.TMethod; static; class function MethodOf(const AArgType, AResultType: IDataType): TDataType.TMethod; static;
class function ArrayOf(const AElementType: IDataType): TDataType.TArray; static; class function ArrayOf(const AElementType: IDataType): TDataType.TArray; static;
@@ -374,25 +422,6 @@ type
class function RecordOf(const Fields: array of TRecordField): 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; class function EnumOf(const AName: string; const AIdentifiers: array of string): TDataType.TEnum; static;
// Value factories
class function FromOrdinal(const AValue: Int64): IDataOrdinalValue; static; inline;
class function FromFloat(const AValue: Double): IDataFloatValue; static; inline;
class function FromText(const AValue: string): IDataTextValue; static; inline;
class function FromTimestamp(const AValue: TDateTime): IDataTimestampValue; static; inline;
class function FromTuple(const AItems: array of IDataValue): IDataTupleValue; static;
class function FromMethod(const AMethodType: TDataType.TMethod; const AValue: TMethod.TProc): IDataMethodValue; static; inline;
// Casting
function AsOrdinal: TDataType.TOrdinal; inline;
function AsFloat: TDataType.TFloat; inline;
function AsText: TDataType.TText; inline;
function AsTimestamp: TDataType.TTimestamp; inline;
function AsRecord: TDataType.TRecord; inline;
function AsTuple: TDataType.TTuple; inline;
function AsArray: TDataType.TArray; inline;
function AsEnum: TDataType.TEnum; inline;
function AsMethod: TDataType.TMethod; inline;
property DataType: IDataType read FDataType; property DataType: IDataType read FDataType;
property Name: String read GetName; property Name: String read GetName;
property Kind: TDataKind read GetKind; property Kind: TDataKind read GetKind;
@@ -408,6 +437,7 @@ uses
Myc.Data.Types.Float, Myc.Data.Types.Float,
Myc.Data.Types.Text, Myc.Data.Types.Text,
Myc.Data.Types.Timestamp, Myc.Data.Types.Timestamp,
Myc.Data.Types.Decimal,
Myc.Data.Types.Arrays, Myc.Data.Types.Arrays,
Myc.Data.Types.Records, Myc.Data.Types.Records,
Myc.Data.Types.Tuple, Myc.Data.Types.Tuple,
@@ -422,6 +452,28 @@ begin
DataType := ADataType; DataType := ADataType;
end; end;
{ TDataType.TDecimal.TValue }
constructor TDataType.TDecimal.TValue.Create(const ADecimalValue: IDataDecimalValue);
begin
FDecimalValue := ADecimalValue;
end;
function TDataType.TDecimal.TValue.GetValue: Int64;
begin
Result := FDecimalValue.Value;
end;
class operator TDataType.TDecimal.TValue.Implicit(const A: IDataDecimalValue): TDataType.TDecimal.TValue;
begin
Result.FDecimalValue := A;
end;
class operator TDataType.TDecimal.TValue.Implicit(const A: TDataType.TDecimal.TValue): IDataDecimalValue;
begin
Result := A.FDecimalValue;
end;
{ TDataType.TVoid } { TDataType.TVoid }
constructor TDataType.TVoid.Create(const AVoidType: IDataVoidType); constructor TDataType.TVoid.Create(const AVoidType: IDataVoidType);
@@ -532,6 +584,33 @@ begin
Result := A.FTimestampType; Result := A.FTimestampType;
end; end;
{ TDataType.TDecimal }
constructor TDataType.TDecimal.Create(const ADecimalType: IDataDecimalType);
begin
FDecimalType := ADecimalType;
end;
function TDataType.TDecimal.CreateValue(const AValue: Int64): TDataType.TDecimal.TValue;
begin
Result.Create(FDecimalType.CreateValue(AValue));
end;
function TDataType.TDecimal.GetScale: Integer;
begin
Result := FDecimalType.Scale;
end;
class operator TDataType.TDecimal.Implicit(const A: IDataDecimalType): TDataType.TDecimal;
begin
Result.FDecimalType := A;
end;
class operator TDataType.TDecimal.Implicit(const A: TDataType.TDecimal): IDataDecimalType;
begin
Result := A.FDecimalType;
end;
{ TDataType.TEnum } { TDataType.TEnum }
constructor TDataType.TEnum.Create(const AEnumType: IDataEnumType); constructor TDataType.TEnum.Create(const AEnumType: IDataEnumType);
@@ -710,9 +789,16 @@ begin
end; end;
class constructor TDataType.CreateClass; class constructor TDataType.CreateClass;
var
i: Integer;
begin begin
FArrayTypeRegistry := TDictionary<IDataType, IDataArrayType>.Create; FArrayTypeRegistry := TDictionary<IDataType, IDataArrayType>.Create;
FRecordTypeRegistry := TDictionary<TArray<TRecordField>, IDataRecordType>.Create(TRecordFieldComparer.Create); FRecordTypeRegistry := TDictionary<TArray<TRecordField>, IDataRecordType>.Create(TRecordFieldComparer.Create);
SetLength(FDecimalTypes, 19);
for i := 0 to 18 do
FDecimalTypes[i] := TImplDataDecimalType.Create(i);
FMethodTypeRegistry := FMethodTypeRegistry :=
TDictionary<TPair<IDataType, IDataType>, IDataMethodType>.Create( TDictionary<TPair<IDataType, IDataType>, IDataMethodType>.Create(
TEqualityComparer<TPair<IDataType, IDataType>>.Construct( TEqualityComparer<TPair<IDataType, IDataType>>.Construct(
@@ -737,6 +823,7 @@ class destructor TDataType.DestroyClass;
begin begin
FArrayTypeRegistry.Free; FArrayTypeRegistry.Free;
FRecordTypeRegistry.Free; FRecordTypeRegistry.Free;
FDecimalTypes := nil;
FMethodTypeRegistry.Free; FMethodTypeRegistry.Free;
end; end;
@@ -760,67 +847,11 @@ begin
Result.Create(res); Result.Create(res);
end; end;
function TDataType.AsArray: TDataType.TArray; class function TDataType.DecimalOf(const AScale: Integer): TDataType.TDecimal;
begin begin
if (FDataType.Kind <> dkArray) then if (AScale < 0) or (AScale > 18) then
raise EInvalidCast.Create('Array expected'); raise EArgumentException.Create('Scale for decimal must be between 0 and 18.');
Result.Create(IDataArrayType(FDataType)); Result.Create(FDecimalTypes[AScale]);
end;
function TDataType.AsEnum: TDataType.TEnum;
begin
if (FDataType.Kind <> dkEnum) then
raise EInvalidCast.Create('Enum expected');
Result.Create(IDataEnumType(FDataType));
end;
function TDataType.AsFloat: TDataType.TFloat;
begin
if (FDataType.Kind <> dkFloat) then
raise EInvalidCast.Create('Float expected');
Result.Create(IDataFloatType(FDataType));
end;
function TDataType.AsMethod: TDataType.TMethod;
begin
if (FDataType.Kind <> dkMethod) then
raise EInvalidCast.Create('Method expected');
Result.Create(IDataMethodType(FDataType));
end;
function TDataType.AsOrdinal: TDataType.TOrdinal;
begin
if (FDataType.Kind <> dkOrdinal) then
raise EInvalidCast.Create('Ordinal expected');
Result.Create(IDataOrdinalType(FDataType));
end;
function TDataType.AsRecord: TDataType.TRecord;
begin
if (FDataType.Kind <> dkRecord) then
raise EInvalidCast.Create('Record expected');
Result.Create(IDataRecordType(FDataType));
end;
function TDataType.AsText: TDataType.TText;
begin
if (FDataType.Kind <> dkText) then
raise EInvalidCast.Create('Text expected');
Result.Create(IDataTextType(FDataType));
end;
function TDataType.AsTimestamp: TDataType.TTimestamp;
begin
if (FDataType.Kind <> dkTimestamp) then
raise EInvalidCast.Create('Timestamp expected');
Result.Create(IDataTimestampType(FDataType));
end;
function TDataType.AsTuple: TDataType.TTuple;
begin
if (FDataType.Kind <> dkTuple) then
raise EInvalidCast.Create('Tuple expected');
Result.Create(IDataTupleType(FDataType));
end; end;
class function TDataType.EnumOf(const AName: string; const AIdentifiers: array of string): TDataType.TEnum; class function TDataType.EnumOf(const AName: string; const AIdentifiers: array of string): TDataType.TEnum;
@@ -833,38 +864,6 @@ begin
Result.Create(TImplDataFloatType.Singleton); Result.Create(TImplDataFloatType.Singleton);
end; end;
class function TDataType.FromFloat(const AValue: Double): IDataFloatValue;
begin
Result := TDataType.Float.CreateValue(AValue);
end;
class function TDataType.FromMethod(const AMethodType: TDataType.TMethod; const AValue: TMethod.TProc): IDataMethodValue;
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): IDataOrdinalValue;
begin
Result := TDataType.Ordinal.CreateValue(AValue);
end;
class function TDataType.FromText(const AValue: string): IDataTextValue;
begin
Result := TDataType.Text.CreateValue(AValue);
end;
class function TDataType.FromTimestamp(const AValue: TDateTime): IDataTimestampValue;
begin
Result := TDataType.Timestamp.CreateValue(AValue);
end;
class function TDataType.FromTuple(const AItems: array of IDataValue): IDataTupleValue;
begin
Result := TDataType.Tuple.CreateValue(AItems);
end;
function TDataType.GetKind: TDataKind; function TDataType.GetKind: TDataKind;
begin begin
Result := FDataType.Kind; Result := FDataType.Kind;
@@ -965,6 +964,11 @@ begin
Result.FDataType := A.FArrayType; Result.FDataType := A.FArrayType;
end; end;
class operator TDataType.Implicit(const A: TDataType.TDecimal): TDataType;
begin
Result.FDataType := A.FDecimalType;
end;
class operator TDataType.Implicit(const A: TDataType.TEnum): TDataType; class operator TDataType.Implicit(const A: TDataType.TEnum): TDataType;
begin begin
Result.FDataType := A.FEnumType; Result.FDataType := A.FEnumType;
@@ -1025,6 +1029,13 @@ begin
Result := IDataArrayValue(FDataValue); Result := IDataArrayValue(FDataValue);
end; end;
function TDataType.TValue.AsDecimal: IDataDecimalValue;
begin
if (FDataValue.DataType.Kind <> dkDecimal) then
raise EInvalidCast.Create('Decimal expected');
Result := IDataDecimalValue(FDataValue);
end;
function TDataType.TValue.AsEnum: IDataEnumValue; function TDataType.TValue.AsEnum: IDataEnumValue;
begin begin
if (FDataValue.DataType.Kind <> dkEnum) then if (FDataValue.DataType.Kind <> dkEnum) then
@@ -1106,6 +1117,11 @@ begin
Result.FDataValue := A; Result.FDataValue := A;
end; end;
class operator TDataType.TValue.Implicit(const A: IDataDecimalValue): TDataType.TValue;
begin
Result.FDataValue := A;
end;
class operator TDataType.TValue.Implicit(const A: IDataEnumValue): TDataType.TValue; class operator TDataType.TValue.Implicit(const A: IDataEnumValue): TDataType.TValue;
begin begin
Result.FDataValue := A; Result.FDataValue := A;
+57 -62
View File
@@ -86,7 +86,7 @@ begin
Assert.AreNotSame(IDataRecordType(personType1), IDataRecordType(otherType), 'Different definitions should result in different types'); Assert.AreNotSame(IDataRecordType(personType1), IDataRecordType(otherType), 'Different definitions should result in different types');
// --- 3. Test Value Creation and Access --- // --- 3. Test Value Creation and Access ---
personValue := personType1.CreateValue([TDataType.FromOrdinal(123), TDataType.FromFloat(45.67)]); personValue := personType1.CreateValue([TDataType.Ordinal.CreateValue(123), TDataType.Float.CreateValue(45.67)]);
Assert.IsNotNull(personValue, 'RecordValue should be created'); Assert.IsNotNull(personValue, 'RecordValue should be created');
Assert.AreSame(IDataRecordType(personType1), personValue.DataType, 'Value should have the correct data type'); Assert.AreSame(IDataRecordType(personType1), personValue.DataType, 'Value should have the correct data type');
@@ -111,7 +111,7 @@ begin
// Test for wrong number of items during value creation // Test for wrong number of items during value creation
Assert.WillRaise( Assert.WillRaise(
procedure begin personType1.CreateValue([TDataType.FromOrdinal(99)]); end, procedure begin personType1.CreateValue([TDataType.Ordinal.CreateValue(99)]); end,
EArgumentException, EArgumentException,
'Wrong number of items should raise exception' 'Wrong number of items should raise exception'
); );
@@ -121,7 +121,7 @@ begin
procedure procedure
begin begin
// Passing Float instead of Integer for the first item // Passing Float instead of Integer for the first item
personType1.CreateValue([TDataType.FromFloat(1.0), TDataType.FromFloat(2.0)]); personType1.CreateValue([TDataType.Float.CreateValue(1.0), TDataType.Float.CreateValue(2.0)]);
end, end,
EArgumentException, EArgumentException,
'Wrong item type should raise exception' 'Wrong item type should raise exception'
@@ -142,7 +142,8 @@ begin
TRecordField.Create('C', TDataType.Float) TRecordField.Create('C', TDataType.Float)
] ]
); );
dataValue := dataType.CreateValue([TDataType.FromOrdinal(1), TDataType.FromText('two'), TDataType.FromFloat(3.0)]); dataValue :=
dataType.CreateValue([TDataType.Ordinal.CreateValue(1), TDataType.Text.CreateValue('two'), TDataType.Float.CreateValue(3.0)]);
Assert.IsNotNull(dataValue, 'Generic record value should be created'); Assert.IsNotNull(dataValue, 'Generic record value should be created');
Assert.AreEqual(3, dataType.FieldCount, 'Generic record should have 3 fields'); Assert.AreEqual(3, dataType.FieldCount, 'Generic record should have 3 fields');
@@ -161,11 +162,11 @@ var
begin begin
// This test covers optimized implementations for 1 and 2 elements. // This test covers optimized implementations for 1 and 2 elements.
// --- 1. Setup: Create some values --- // --- 1. Setup: Create some values ---
intValue := TDataType.FromOrdinal(123); intValue := TDataType.Ordinal.CreateValue(123);
floatValue := TDataType.FromFloat(45.67); floatValue := TDataType.Float.CreateValue(45.67);
// --- 2. Test Value Creation and basic properties --- // --- 2. Test Value Creation and basic properties ---
tuple1 := TDataType.FromTuple([intValue, floatValue]); tuple1 := TDataType.Tuple.CreateValue([intValue, floatValue]);
Assert.IsNotNull(tuple1, 'Tuple value should be created'); Assert.IsNotNull(tuple1, 'Tuple value should be created');
Assert.AreEqual(2, tuple1.ItemCount, 'ItemCount should be on the value'); Assert.AreEqual(2, tuple1.ItemCount, 'ItemCount should be on the value');
@@ -174,8 +175,8 @@ begin
// --- 3. Test Singleton Type Behavior --- // --- 3. Test Singleton Type Behavior ---
// Create more tuples with different structures // Create more tuples with different structures
tuple2 := TDataType.FromTuple([TDataType.FromOrdinal(99), TDataType.FromFloat(1.1)]); tuple2 := TDataType.Tuple.CreateValue([TDataType.Ordinal.CreateValue(99), TDataType.Float.CreateValue(1.1)]);
tuple3 := TDataType.FromTuple([intValue]); tuple3 := TDataType.Tuple.CreateValue([intValue]);
// Access the DataType via the underlying interface // Access the DataType via the underlying interface
type1 := tuple1.DataType; type1 := tuple1.DataType;
@@ -196,14 +197,14 @@ var
begin begin
// Test the generic implementation for tuples with > 5 elements. // Test the generic implementation for tuples with > 5 elements.
tupleValue := tupleValue :=
TDataType.FromTuple( TDataType.Tuple.CreateValue(
[ [
TDataType.FromOrdinal(1), TDataType.Ordinal.CreateValue(1),
TDataType.FromOrdinal(2), TDataType.Ordinal.CreateValue(2),
TDataType.FromOrdinal(3), TDataType.Ordinal.CreateValue(3),
TDataType.FromOrdinal(4), TDataType.Ordinal.CreateValue(4),
TDataType.FromOrdinal(5), TDataType.Ordinal.CreateValue(5),
TDataType.FromOrdinal(6) TDataType.Ordinal.CreateValue(6)
] ]
); );
@@ -247,8 +248,8 @@ begin
Assert.AreEqual('Array<Float>', TDataType(floatArrayType).Name, 'Type name should be Array<Float>'); Assert.AreEqual('Array<Float>', TDataType(floatArrayType).Name, 'Type name should be Array<Float>');
// --- 3. Test Value Creation and Access --- // --- 3. Test Value Creation and Access ---
v1 := TDataType.FromOrdinal(10); v1 := TDataType.Ordinal.CreateValue(10);
v2 := TDataType.FromOrdinal(20); v2 := TDataType.Ordinal.CreateValue(20);
arrayValue := intArrayType1.CreateValue([v1, v2]); arrayValue := intArrayType1.CreateValue([v1, v2]);
Assert.IsNotNull(arrayValue, 'ArrayValue should be created'); Assert.IsNotNull(arrayValue, 'ArrayValue should be created');
@@ -267,7 +268,7 @@ begin
procedure procedure
begin begin
// Try to add a float value to an Array<Integer> // Try to add a float value to an Array<Integer>
intArrayType1.CreateValue([v1, TDataType.FromFloat(3.14)]); intArrayType1.CreateValue([v1, TDataType.Float.CreateValue(3.14)]);
end, end,
EArgumentException, EArgumentException,
'Wrong element type should raise an exception' 'Wrong element type should raise an exception'
@@ -290,14 +291,15 @@ begin
Assert.AreEqual('[]', empty1.AsString, 'Empty array AsString is incorrect'); Assert.AreEqual('[]', empty1.AsString, 'Empty array AsString is incorrect');
// Test optimized path for 1 element // Test optimized path for 1 element
single := arrayType.CreateValue([TDataType.FromOrdinal(42)]); single := arrayType.CreateValue([TDataType.Ordinal.CreateValue(42)]);
Assert.IsNotNull(single, 'Single element array should be created'); Assert.IsNotNull(single, 'Single element array should be created');
Assert.AreEqual(1, single.ElementCount, 'Single element array should have 1 element'); Assert.AreEqual(1, single.ElementCount, 'Single element array should have 1 element');
Assert.AreEqual(Int64(42), TDataType.TValue(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]', single.AsString, 'Single element array AsString is incorrect'); Assert.AreEqual('[42]', single.AsString, 'Single element array AsString is incorrect');
// Test generic path for > 1 elements // Test generic path for > 1 elements
generic := arrayType.CreateValue([TDataType.FromOrdinal(1), TDataType.FromOrdinal(2), TDataType.FromOrdinal(3)]); generic :=
arrayType.CreateValue([TDataType.Ordinal.CreateValue(1), TDataType.Ordinal.CreateValue(2), TDataType.Ordinal.CreateValue(3)]);
Assert.IsNotNull(generic, 'Generic array should be created'); Assert.IsNotNull(generic, 'Generic array should be created');
Assert.AreEqual(3, generic.ElementCount, 'Generic array should have 3 elements'); Assert.AreEqual(3, generic.ElementCount, 'Generic array should have 3 elements');
Assert.AreEqual('[1, 2, 3]', generic.AsString, 'Generic array AsString is incorrect'); Assert.AreEqual('[1, 2, 3]', generic.AsString, 'Generic array AsString is incorrect');
@@ -317,22 +319,22 @@ begin
Assert.AreEqual(dkText, TDataType(textType).Kind, 'Type kind should be dkText'); Assert.AreEqual(dkText, TDataType(textType).Kind, 'Type kind should be dkText');
// --- 2. Test Value Creation and Access --- // --- 2. Test Value Creation and Access ---
textValue1 := TDataType.FromText('Hello World'); textValue1 := TDataType.Text.CreateValue('Hello World');
Assert.IsNotNull(textValue1, 'TextValue should be created'); Assert.IsNotNull(textValue1, 'TextValue should be created');
Assert.AreSame(IDataType(textType), textValue1.DataType, 'Value should have the correct data type'); Assert.AreSame(IDataType(textType), textValue1.DataType, 'Value should have the correct data type');
Assert.AreEqual('Hello World', textValue1.Value, 'Value should be ''Hello World'''); Assert.AreEqual('Hello World', textValue1.Value, 'Value should be ''Hello World''');
// Test another text value // Test another text value
textValue2 := TDataType.FromText('Delphi'); textValue2 := TDataType.Text.CreateValue('Delphi');
Assert.AreEqual('Delphi', textValue2.Value, 'Value should be ''Delphi'''); Assert.AreEqual('Delphi', textValue2.Value, 'Value should be ''Delphi''');
// --- 3. Test AsText casting --- // --- 3. Test AsText casting ---
dataValue := TDataType.FromText('Test Text'); dataValue := TDataType.Text.CreateValue('Test Text');
Assert.AreEqual('Test Text', TDataType.TValue(dataValue).AsText.Value, 'AsText should return correct value'); Assert.AreEqual('Test Text', TDataType.TValue(dataValue).AsText.Value, 'AsText should return correct value');
// Test invalid cast // Test invalid cast
dataValue := TDataType.FromOrdinal(123); dataValue := TDataType.Ordinal.CreateValue(123);
Assert.WillRaise( Assert.WillRaise(
procedure begin TDataType.TValue(dataValue).AsText; end, procedure begin TDataType.TValue(dataValue).AsText; end,
EInvalidCast, EInvalidCast,
@@ -345,8 +347,8 @@ var
empty1, empty2: IDataTextValue; empty1, empty2: IDataTextValue;
begin begin
// Test the singleton implementation for the empty string. // Test the singleton implementation for the empty string.
empty1 := TDataType.FromText(''); empty1 := TDataType.Text.CreateValue('');
empty2 := TDataType.FromText(''); empty2 := TDataType.Text.CreateValue('');
Assert.IsNotNull(empty1, 'Empty text value should be created'); Assert.IsNotNull(empty1, 'Empty text value should be created');
Assert.AreSame(empty1, empty2, 'Empty text value should be a singleton'); Assert.AreSame(empty1, empty2, 'Empty text value should be a singleton');
@@ -359,22 +361,22 @@ var
zero1, zero2, nan1, nan2, generic: IDataFloatValue; zero1, zero2, nan1, nan2, generic: IDataFloatValue;
begin begin
// Test singleton for 0.0 // Test singleton for 0.0
zero1 := TDataType.FromFloat(0.0); zero1 := TDataType.Float.CreateValue(0.0);
zero2 := TDataType.FromFloat(0.0); zero2 := TDataType.Float.CreateValue(0.0);
Assert.IsNotNull(zero1, 'Zero float should be created'); Assert.IsNotNull(zero1, 'Zero float should be created');
Assert.AreSame(zero1, zero2, 'Zero float should be a singleton'); Assert.AreSame(zero1, zero2, 'Zero float should be a singleton');
Assert.AreEqual(0.0, zero1.Value, 'Value of zero float is incorrect'); Assert.AreEqual(0.0, zero1.Value, 'Value of zero float is incorrect');
// Test singleton for NaN // Test singleton for NaN
nan1 := TDataType.FromFloat(NaN); nan1 := TDataType.Float.CreateValue(NaN);
nan2 := TDataType.FromFloat(NaN); nan2 := TDataType.Float.CreateValue(NaN);
Assert.IsNotNull(nan1, 'NaN float should be created'); Assert.IsNotNull(nan1, 'NaN float should be created');
Assert.AreSame(nan1, nan2, 'NaN float should be a singleton'); Assert.AreSame(nan1, nan2, 'NaN float should be a singleton');
Assert.IsTrue(IsNaN(nan1.Value), 'Value of NaN float should be NaN'); Assert.IsTrue(IsNaN(nan1.Value), 'Value of NaN float should be NaN');
Assert.AreEqual('NaN', nan1.AsString, 'NaN AsString is incorrect'); Assert.AreEqual('NaN', nan1.AsString, 'NaN AsString is incorrect');
// Test generic path // Test generic path
generic := TDataType.FromFloat(123.45); generic := TDataType.Float.CreateValue(123.45);
Assert.IsNotNull(generic, 'Generic float should be created'); Assert.IsNotNull(generic, 'Generic float should be created');
Assert.AreNotSame(zero1, generic, 'Generic float should not be the zero singleton'); Assert.AreNotSame(zero1, generic, 'Generic float should not be the zero singleton');
Assert.AreNotSame(nan1, generic, 'Generic float should not be the NaN singleton'); Assert.AreNotSame(nan1, generic, 'Generic float should not be the NaN singleton');
@@ -397,22 +399,22 @@ begin
// --- 2. Test Value Creation and Access --- // --- 2. Test Value Creation and Access ---
now := System.Sysutils.Now; now := System.Sysutils.Now;
tsValue1 := TDataType.FromTimestamp(now); tsValue1 := TDataType.Timestamp.CreateValue(now);
Assert.IsNotNull(tsValue1, 'TimestampValue should be created'); Assert.IsNotNull(tsValue1, 'TimestampValue should be created');
Assert.AreSame(IDataType(tsType), tsValue1.DataType, 'Value should have the correct data type'); Assert.AreSame(IDataType(tsType), tsValue1.DataType, 'Value should have the correct data type');
Assert.AreEqual(now, tsValue1.Value, 'Value should be the same'); Assert.AreEqual(now, tsValue1.Value, 'Value should be the same');
// Test another text value // Test another text value
tsValue2 := TDataType.FromTimestamp(Date); tsValue2 := TDataType.Timestamp.CreateValue(Date);
Assert.AreEqual(Date, tsValue2.Value, 'Value should be the same'); Assert.AreEqual(Date, tsValue2.Value, 'Value should be the same');
// --- 3. Test AsTimestamp casting --- // --- 3. Test AsTimestamp casting ---
dataValue := TDataType.FromTimestamp(now); dataValue := TDataType.Timestamp.CreateValue(now);
Assert.AreEqual(now, TDataType.TValue(dataValue).AsTimestamp.Value, 'AsTimestamp should return correct value'); Assert.AreEqual(now, TDataType.TValue(dataValue).AsTimestamp.Value, 'AsTimestamp should return correct value');
// Test invalid cast // Test invalid cast
dataValue := TDataType.FromOrdinal(123); dataValue := TDataType.Ordinal.CreateValue(123);
Assert.WillRaise( Assert.WillRaise(
procedure begin TDataType.TValue(dataValue).AsTimestamp; end, procedure begin TDataType.TValue(dataValue).AsTimestamp; end,
EInvalidCast, EInvalidCast,
@@ -491,20 +493,20 @@ var
now: TDateTime; now: TDateTime;
begin begin
// Ordinal // Ordinal
ordinalValue := TDataType.FromOrdinal(123); ordinalValue := TDataType.Ordinal.CreateValue(123);
Assert.AreEqual('123', ordinalValue.AsString, 'Ordinal AsString incorrect'); Assert.AreEqual('123', ordinalValue.AsString, 'Ordinal AsString incorrect');
// Float // Float
floatValue := TDataType.FromFloat(45.67); floatValue := TDataType.Float.CreateValue(45.67);
Assert.AreEqual(FloatToStr(45.67), floatValue.AsString, 'Float AsString incorrect'); Assert.AreEqual(FloatToStr(45.67), floatValue.AsString, 'Float AsString incorrect');
// Text // Text
textValue := TDataType.FromText('Hello'); textValue := TDataType.Text.CreateValue('Hello');
Assert.AreEqual('Hello', textValue.AsString, 'Text AsString incorrect'); Assert.AreEqual('Hello', textValue.AsString, 'Text AsString incorrect');
// Timestamp // Timestamp
now := System.Sysutils.Now; now := System.Sysutils.Now;
tsValue := TDataType.FromTimestamp(now); tsValue := TDataType.Timestamp.CreateValue(now);
Assert.AreEqual(DateTimeToStr(now), tsValue.AsString, 'Timestamp AsString incorrect'); Assert.AreEqual(DateTimeToStr(now), tsValue.AsString, 'Timestamp AsString incorrect');
// Enum // Enum
@@ -514,16 +516,16 @@ begin
// Array // Array
intArrayType := TDataType.ArrayOf(TDataType.Ordinal); intArrayType := TDataType.ArrayOf(TDataType.Ordinal);
arrayValue := intArrayType.CreateValue([TDataType.FromOrdinal(1), TDataType.FromOrdinal(2)]); arrayValue := intArrayType.CreateValue([TDataType.Ordinal.CreateValue(1), TDataType.Ordinal.CreateValue(2)]);
Assert.AreEqual('[1, 2]', arrayValue.AsString, 'Array AsString incorrect'); Assert.AreEqual('[1, 2]', arrayValue.AsString, 'Array AsString incorrect');
// Record // Record
personType := TDataType.RecordOf([TRecordField.Create('ID', TDataType.Ordinal), TRecordField.Create('Name', TDataType.Text)]); personType := TDataType.RecordOf([TRecordField.Create('ID', TDataType.Ordinal), TRecordField.Create('Name', TDataType.Text)]);
recordValue := personType.CreateValue([TDataType.FromOrdinal(1), TDataType.FromText('Bob')]); recordValue := personType.CreateValue([TDataType.Ordinal.CreateValue(1), TDataType.Text.CreateValue('Bob')]);
Assert.AreEqual('<ID: 1, Name: Bob>', recordValue.AsString, 'Record AsString incorrect'); Assert.AreEqual('<ID: 1, Name: Bob>', recordValue.AsString, 'Record AsString incorrect');
// Tuple // Tuple
tupleValue := TDataType.FromTuple([TDataType.FromOrdinal(10), TDataType.FromText('Tuple')]); tupleValue := TDataType.Tuple.CreateValue([TDataType.Ordinal.CreateValue(10), TDataType.Text.CreateValue('Tuple')]);
Assert.AreEqual('(10, Tuple)', tupleValue.AsString, 'Tuple AsString incorrect'); Assert.AreEqual('(10, Tuple)', tupleValue.AsString, 'Tuple AsString incorrect');
end; end;
@@ -537,21 +539,21 @@ var
personType: TDataType.TRecord; personType: TDataType.TRecord;
begin begin
// --- Ordinal --- // --- Ordinal ---
dataValue := TDataType.FromOrdinal(123); dataValue := TDataType.Ordinal.CreateValue(123);
tv := dataValue.AsTValue; tv := dataValue.AsTValue;
Assert.IsFalse(tv.IsEmpty, 'Ordinal TValue should not be empty'); Assert.IsFalse(tv.IsEmpty, 'Ordinal TValue should not be empty');
Assert.AreEqual(tkInt64, tv.Kind, 'Ordinal TValue kind should be tkInt64'); Assert.AreEqual(tkInt64, tv.Kind, 'Ordinal TValue kind should be tkInt64');
Assert.AreEqual(Int64(123), tv.AsInt64, 'Ordinal TValue content is incorrect'); Assert.AreEqual(Int64(123), tv.AsInt64, 'Ordinal TValue content is incorrect');
// --- Float --- // --- Float ---
dataValue := TDataType.FromFloat(45.67); dataValue := TDataType.Float.CreateValue(45.67);
tv := dataValue.AsTValue; tv := dataValue.AsTValue;
Assert.IsFalse(tv.IsEmpty, 'Float TValue should not be empty'); Assert.IsFalse(tv.IsEmpty, 'Float TValue should not be empty');
Assert.AreEqual(tkFloat, tv.Kind, 'Float TValue kind should be tkFloat'); Assert.AreEqual(tkFloat, tv.Kind, 'Float TValue kind should be tkFloat');
Assert.AreEqual(45.67, tv.AsExtended, 'Float TValue content is incorrect'); Assert.AreEqual(45.67, tv.AsExtended, 'Float TValue content is incorrect');
// --- Text --- // --- Text ---
dataValue := TDataType.FromText('Hello'); dataValue := TDataType.Text.CreateValue('Hello');
tv := dataValue.AsTValue; tv := dataValue.AsTValue;
Assert.IsFalse(tv.IsEmpty, 'Text TValue should not be empty'); Assert.IsFalse(tv.IsEmpty, 'Text TValue should not be empty');
Assert.AreEqual(tkUString, tv.Kind, 'Text TValue kind should be tkUString'); Assert.AreEqual(tkUString, tv.Kind, 'Text TValue kind should be tkUString');
@@ -559,7 +561,7 @@ begin
// --- Timestamp --- // --- Timestamp ---
now := System.SysUtils.Now; now := System.SysUtils.Now;
dataValue := TDataType.FromTimestamp(now); dataValue := TDataType.Timestamp.CreateValue(now);
tv := dataValue.AsTValue; tv := dataValue.AsTValue;
Assert.IsFalse(tv.IsEmpty, 'Timestamp TValue should not be empty'); Assert.IsFalse(tv.IsEmpty, 'Timestamp TValue should not be empty');
Assert.AreEqual(tkFloat, tv.Kind, 'Timestamp TValue kind is incorrect'); Assert.AreEqual(tkFloat, tv.Kind, 'Timestamp TValue kind is incorrect');
@@ -575,7 +577,7 @@ begin
// --- Array --- // --- Array ---
intArrayType := TDataType.ArrayOf(TDataType.Ordinal); intArrayType := TDataType.ArrayOf(TDataType.Ordinal);
dataValue := intArrayType.CreateValue([TDataType.FromOrdinal(10), TDataType.FromOrdinal(20)]); dataValue := intArrayType.CreateValue([TDataType.Ordinal.CreateValue(10), TDataType.Ordinal.CreateValue(20)]);
tv := dataValue.AsTValue; tv := dataValue.AsTValue;
Assert.IsFalse(tv.IsEmpty, 'Array TValue should not be empty'); Assert.IsFalse(tv.IsEmpty, 'Array TValue should not be empty');
Assert.IsTrue(tv.IsArray, 'Array TValue should be an array'); Assert.IsTrue(tv.IsArray, 'Array TValue should be an array');
@@ -598,7 +600,7 @@ begin
// --- Record --- // --- Record ---
personType := TDataType.RecordOf([TRecordField.Create('ID', TDataType.Ordinal), TRecordField.Create('Name', TDataType.Text)]); personType := TDataType.RecordOf([TRecordField.Create('ID', TDataType.Ordinal), TRecordField.Create('Name', TDataType.Text)]);
dataValue := personType.CreateValue([TDataType.FromOrdinal(1), TDataType.FromText('Bob')]); dataValue := personType.CreateValue([TDataType.Ordinal.CreateValue(1), TDataType.Text.CreateValue('Bob')]);
tv := dataValue.AsTValue; tv := dataValue.AsTValue;
Assert.IsFalse(tv.IsEmpty, 'Record TValue should not be empty'); Assert.IsFalse(tv.IsEmpty, 'Record TValue should not be empty');
Assert.IsTrue(tv.IsArray, 'Record TValue should be represented as an array'); Assert.IsTrue(tv.IsArray, 'Record TValue should be represented as an array');
@@ -608,7 +610,7 @@ begin
Assert.AreEqual('Bob', tv.GetArrayElement(1).AsType<TValue>.AsString, 'Record TValue element 1 is incorrect'); Assert.AreEqual('Bob', tv.GetArrayElement(1).AsType<TValue>.AsString, 'Record TValue element 1 is incorrect');
// --- Tuple --- // --- Tuple ---
dataValue := TDataType.FromTuple([TDataType.FromOrdinal(99), TDataType.FromText('Red')]); dataValue := TDataType.Tuple.CreateValue([TDataType.Ordinal.CreateValue(99), TDataType.Text.CreateValue('Red')]);
tv := dataValue.AsTValue; tv := dataValue.AsTValue;
Assert.IsFalse(tv.IsEmpty, 'Tuple TValue should not be empty'); Assert.IsFalse(tv.IsEmpty, 'Tuple TValue should not be empty');
Assert.IsTrue(tv.IsArray, 'Tuple TValue should be represented as an array'); Assert.IsTrue(tv.IsArray, 'Tuple TValue should be represented as an array');
@@ -667,15 +669,15 @@ begin
begin begin
ordinalValue := AValue.AsOrdinal; ordinalValue := AValue.AsOrdinal;
val := ordinalValue.Value; val := ordinalValue.Value;
Result := TDataType.FromText(val.ToString); Result := TDataType.Text.CreateValue(val.ToString);
end; end;
methodValue := TDataType.FromMethod(methodType1, myFunc); methodValue := methodType1.CreateValue(myFunc);
Assert.IsNotNull(methodValue, 'MethodValue should be created'); Assert.IsNotNull(methodValue, 'MethodValue should be created');
Assert.AreSame(IDataType(methodType1), methodValue.DataType, 'Value should have the correct data type'); Assert.AreSame(IDataType(methodType1), methodValue.DataType, 'Value should have the correct data type');
// --- 4. Test Execution (Simulated) --- // --- 4. Test Execution (Simulated) ---
inputValue := TDataType.FromOrdinal(42); inputValue := TDataType.Ordinal.CreateValue(42);
// Execute the function retrieved from the value // Execute the function retrieved from the value
resultValue := methodValue.Value(inputValue); resultValue := methodValue.Value(inputValue);
@@ -692,18 +694,11 @@ begin
Assert.IsTrue(TypeInfo(TDataMethodProc) = 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 --- // --- 6. Test Validation and Error Handling ---
// Test creating a value with a nil type
Assert.WillRaise(
procedure begin TDataType.FromMethod(nil, myFunc); end,
EArgumentException,
'FromMethod with nil type should raise an exception'
);
// Test creating a value with a nil function // Test creating a value with a nil function
Assert.WillRaise( Assert.WillRaise(
procedure begin TDataType.FromMethod(methodType1, nil); end, procedure begin methodType1.CreateValue(nil); end,
EArgumentException, EArgumentException,
'FromMethod with nil function should raise an exception' 'CreateValue with nil function should raise an exception'
); );
end; end;
+18 -18
View File
@@ -367,7 +367,7 @@ begin
indicatorMethodType.CreateValue( indicatorMethodType.CreateValue(
function(const Args: TDataType.TValue): TDataType.TValue function(const Args: TDataType.TValue): TDataType.TValue
begin begin
Result := TDataType.FromFloat(SMA(Args.AsFloat.Value)); Result := TDataType.Float.CreateValue(SMA(Args.AsFloat.Value));
end end
); );
end end
@@ -466,7 +466,7 @@ begin
indicatorMethodType.CreateValue( indicatorMethodType.CreateValue(
function(const Args: TDataType.TValue): TDataType.TValue function(const Args: TDataType.TValue): TDataType.TValue
begin begin
Result := TDataType.FromFloat(EMA(Args.AsFloat.Value)); Result := TDataType.Float.CreateValue(EMA(Args.AsFloat.Value));
end end
); );
end end
@@ -549,7 +549,7 @@ begin
indicatorMethodType.CreateValue( indicatorMethodType.CreateValue(
function(const Args: TDataType.TValue): TDataType.TValue function(const Args: TDataType.TValue): TDataType.TValue
begin begin
Result := TDataType.FromFloat(WMA(Args.AsFloat.Value)); Result := TDataType.Float.CreateValue(WMA(Args.AsFloat.Value));
end end
); );
end end
@@ -644,7 +644,7 @@ begin
indicatorMethodType.CreateValue( indicatorMethodType.CreateValue(
function(const Args: TDataType.TValue): TDataType.TValue function(const Args: TDataType.TValue): TDataType.TValue
begin begin
Result := TDataType.FromFloat(HMA(Args.AsFloat.Value)); Result := TDataType.Float.CreateValue(HMA(Args.AsFloat.Value));
end end
); );
end end
@@ -712,7 +712,7 @@ begin
indicatorMethodType.CreateValue( indicatorMethodType.CreateValue(
function(const Args: TDataType.TValue): TDataType.TValue function(const Args: TDataType.TValue): TDataType.TValue
begin begin
Result := TDataType.FromFloat(RSI(Args.AsFloat.Value)); Result := TDataType.Float.CreateValue(RSI(Args.AsFloat.Value));
end end
); );
end end
@@ -837,9 +837,9 @@ begin
Result := Result :=
resultType.CreateValue( resultType.CreateValue(
[ [
TDataType.FromFloat(res.MacdLine), TDataType.Float.CreateValue(res.MacdLine),
TDataType.FromFloat(res.SignalLine), TDataType.Float.CreateValue(res.SignalLine),
TDataType.FromFloat(res.Histogram) TDataType.Float.CreateValue(res.Histogram)
] ]
); );
end end
@@ -1011,7 +1011,7 @@ begin
var res := Stochastic(ohlcVal); var res := Stochastic(ohlcVal);
Result := resultType.CreateValue([TDataType.FromFloat(res.K), TDataType.FromFloat(res.D)]); Result := resultType.CreateValue([TDataType.Float.CreateValue(res.K), TDataType.Float.CreateValue(res.D)]);
end end
); );
end end
@@ -1143,7 +1143,7 @@ begin
indicatorMethodType.CreateValue( indicatorMethodType.CreateValue(
function(const Args: TDataType.TValue): TDataType.TValue function(const Args: TDataType.TValue): TDataType.TValue
begin begin
Result := TDataType.FromFloat(StdDev(Args.AsFloat.Value)); Result := TDataType.Float.CreateValue(StdDev(Args.AsFloat.Value));
end end
); );
end end
@@ -1253,9 +1253,9 @@ begin
Result := Result :=
resultType.CreateValue( resultType.CreateValue(
[ [
TDataType.FromFloat(res.UpperBand), TDataType.Float.CreateValue(res.UpperBand),
TDataType.FromFloat(res.MiddleBand), TDataType.Float.CreateValue(res.MiddleBand),
TDataType.FromFloat(res.LowerBand) TDataType.Float.CreateValue(res.LowerBand)
] ]
); );
end end
@@ -1348,7 +1348,7 @@ begin
ohlcVal.Low := TDataType.TValue(ohlcRec.Items[2]).AsFloat.Value; ohlcVal.Low := TDataType.TValue(ohlcRec.Items[2]).AsFloat.Value;
ohlcVal.Close := TDataType.TValue(ohlcRec.Items[3]).AsFloat.Value; ohlcVal.Close := TDataType.TValue(ohlcRec.Items[3]).AsFloat.Value;
ohlcVal.Volume := TDataType.TValue(ohlcRec.Items[4]).AsFloat.Value; ohlcVal.Volume := TDataType.TValue(ohlcRec.Items[4]).AsFloat.Value;
Result := TDataType.FromFloat(ATR(ohlcVal)); Result := TDataType.Float.CreateValue(ATR(ohlcVal));
end end
); );
end end
@@ -1460,9 +1460,9 @@ begin
Result := Result :=
resultType.CreateValue( resultType.CreateValue(
[ [
TDataType.FromFloat(res.UpperBand), TDataType.Float.CreateValue(res.UpperBand),
TDataType.FromFloat(res.MiddleBand), TDataType.Float.CreateValue(res.MiddleBand),
TDataType.FromFloat(res.LowerBand) TDataType.Float.CreateValue(res.LowerBand)
] ]
); );
end end
@@ -1550,7 +1550,7 @@ begin
for i := 0 to valuesArray.ElementCount - 1 do for i := 0 to valuesArray.ElementCount - 1 do
values[i] := TDataType.TValue(valuesArray.Items[i]).AsFloat.Value; values[i] := TDataType.TValue(valuesArray.Items[i]).AsFloat.Value;
Result := TDataType.FromFloat(Mean(values)); Result := TDataType.Float.CreateValue(Mean(values));
end end
); );
end end
+3 -3
View File
@@ -218,9 +218,9 @@ begin
end; end;
case aValue.Kind of case aValue.Kind of
tkInteger, tkInt64, tkEnumeration: Result := TDataType.FromOrdinal(aValue.AsInt64); tkInteger, tkInt64, tkEnumeration: Result := TDataType.Ordinal.CreateValue(aValue.AsInt64);
tkFloat: Result := TDataType.FromFloat(aValue.AsExtended); tkFloat: Result := TDataType.Float.CreateValue(aValue.AsExtended);
tkString, tkUString: Result := TDataType.FromText(aValue.AsString); tkString, tkUString: Result := TDataType.Text.CreateValue(aValue.AsString);
tkRecord: tkRecord:
begin begin
ctx := TRttiContext.Create; ctx := TRttiContext.Create;
+2 -1
View File
@@ -32,7 +32,8 @@ uses
Myc.Data.Types.Arrays in 'Myc.Data.Types.Arrays.pas', Myc.Data.Types.Arrays in 'Myc.Data.Types.Arrays.pas',
TestDataTypes in '..\Src\Data\TestDataTypes.pas', TestDataTypes in '..\Src\Data\TestDataTypes.pas',
Myc.Data.Types.Method in '..\Src\Data\Myc.Data.Types.Method.pas', Myc.Data.Types.Method in '..\Src\Data\Myc.Data.Types.Method.pas',
Myc.Data.Types.Void in '..\Src\Data\Myc.Data.Types.Void.pas'; Myc.Data.Types.Void in '..\Src\Data\Myc.Data.Types.Void.pas',
Myc.Data.Types.Decimal in '..\Src\Data\Myc.Data.Types.Decimal.pas';
{ keep comment here to protect the following conditional from being removed by the IDE when adding a unit } { keep comment here to protect the following conditional from being removed by the IDE when adding a unit }
{$IFNDEF TESTINSIGHT} {$IFNDEF TESTINSIGHT}
+1
View File
@@ -134,6 +134,7 @@ $(PreBuildEvent)]]></PreBuildEvent>
<DCCReference Include="..\Src\Data\TestDataTypes.pas"/> <DCCReference Include="..\Src\Data\TestDataTypes.pas"/>
<DCCReference Include="..\Src\Data\Myc.Data.Types.Method.pas"/> <DCCReference Include="..\Src\Data\Myc.Data.Types.Method.pas"/>
<DCCReference Include="..\Src\Data\Myc.Data.Types.Void.pas"/> <DCCReference Include="..\Src\Data\Myc.Data.Types.Void.pas"/>
<DCCReference Include="..\Src\Data\Myc.Data.Types.Decimal.pas"/>
<BuildConfiguration Include="Base"> <BuildConfiguration Include="Base">
<Key>Base</Key> <Key>Base</Key>
</BuildConfiguration> </BuildConfiguration>