IScalarRecord
This commit is contained in:
@@ -338,13 +338,10 @@ begin
|
|||||||
case seriesVar.Kind of
|
case seriesVar.Kind of
|
||||||
vkRecordSeries:
|
vkRecordSeries:
|
||||||
begin
|
begin
|
||||||
if (itemValue.Kind <> vkRecord) then
|
if (itemValue.Kind <> vkScalarRecord) then
|
||||||
raise EEvaluatorException.Create('Can only add record values to a TScalarRecordSeries.');
|
raise EEvaluatorException.Create('Can only add record values to a TScalarRecordSeries.');
|
||||||
|
|
||||||
with seriesVar.AsRecordSeries do
|
seriesVar.AsRecordSeries.Add(itemValue.AsScalarRecord, lookback);
|
||||||
begin
|
|
||||||
Add(itemValue.AsRecord, lookback);
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
else
|
else
|
||||||
raise EEvaluatorException.Create('"add" operation is only supported for series types.');
|
raise EEvaluatorException.Create('"add" operation is only supported for series types.');
|
||||||
@@ -414,7 +411,6 @@ var
|
|||||||
key: IKeyword;
|
key: IKeyword;
|
||||||
memberSeries: ISeries;
|
memberSeries: ISeries;
|
||||||
scalarValue: TScalar;
|
scalarValue: TScalar;
|
||||||
rec: TScalarRecord;
|
|
||||||
begin
|
begin
|
||||||
baseValue := Node.Base.Accept(Self);
|
baseValue := Node.Base.Accept(Self);
|
||||||
indexValue := Node.Index.Accept(Self);
|
indexValue := Node.Index.Accept(Self);
|
||||||
@@ -450,8 +446,7 @@ begin
|
|||||||
values[i] := scalarValue.Value;
|
values[i] := scalarValue.Value;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
rec := TScalarRecord.Create(recSeries.Def, values);
|
Result := TDataValue.FromScalarRecord(TScalarRecord.Create(recSeries.Def, values));
|
||||||
Result := TDataValue.FromRecord(rec);
|
|
||||||
end;
|
end;
|
||||||
else
|
else
|
||||||
raise EEvaluatorException.Create('Indexer `[]` is not supported for this value type.');
|
raise EEvaluatorException.Create('Indexer `[]` is not supported for this value type.');
|
||||||
@@ -466,18 +461,8 @@ begin
|
|||||||
|
|
||||||
case baseValue.Kind of
|
case baseValue.Kind of
|
||||||
vkRecordSeries: Result := TDataValue.FromSeries(baseValue.AsRecordSeries[Node.Member.Value]);
|
vkRecordSeries: Result := TDataValue.FromSeries(baseValue.AsRecordSeries[Node.Member.Value]);
|
||||||
|
vkScalarRecord: Result := TDataValue(baseValue.AsScalarRecord.Fields[Node.Member.Value]);
|
||||||
vkRecord: Result := TDataValue(baseValue.AsRecord[Node.Member.Value]);
|
vkGenericRecord: Result := TDataValue(baseValue.AsGenericRecord.Fields[Node.Member.Value]);
|
||||||
|
|
||||||
vkGenericRecord:
|
|
||||||
begin
|
|
||||||
var rec := baseValue.AsGenericRecord;
|
|
||||||
var fieldIndex := rec.IndexOf(Node.Member.Value);
|
|
||||||
if fieldIndex < 0 then
|
|
||||||
raise EEvaluatorException.CreateFmt('Member ":%s" not found in record.', [Node.Member.Value.Name]);
|
|
||||||
|
|
||||||
Result := rec.Items[fieldIndex].Value;
|
|
||||||
end;
|
|
||||||
else
|
else
|
||||||
raise EEvaluatorException.Create('Member access operator `.` is not supported for this value type.');
|
raise EEvaluatorException.Create('Member access operator `.` is not supported for this value type.');
|
||||||
end;
|
end;
|
||||||
@@ -512,8 +497,7 @@ begin
|
|||||||
values[i] := valData.AsScalar.Value;
|
values[i] := valData.AsScalar.Value;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
var rec := TScalarRecord.Create(Node.ScalarDefinition, values);
|
Result := TDataValue.FromScalarRecord(TScalarRecord.Create(Node.ScalarDefinition, values));
|
||||||
Result := TDataValue.FromRecord(rec);
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
raise EEvaluatorException.Create('RecordLiteral has no definition (Binder/TypeChecker failure).');
|
raise EEvaluatorException.Create('RecordLiteral has no definition (Binder/TypeChecker failure).');
|
||||||
|
|||||||
@@ -74,7 +74,6 @@ type
|
|||||||
FFields: TArray<TPair<IKeyword, T>>;
|
FFields: TArray<TPair<IKeyword, T>>;
|
||||||
FFirst, FLast: Integer;
|
FFirst, FLast: Integer;
|
||||||
|
|
||||||
function GetItem(Idx: Integer): TPair<IKeyword, T>;
|
|
||||||
function GetItems(Idx: Integer): TPair<IKeyword, T>;
|
function GetItems(Idx: Integer): TPair<IKeyword, T>;
|
||||||
function GetFields(const Key: IKeyword): T;
|
function GetFields(const Key: IKeyword): T;
|
||||||
function GetCount: Integer;
|
function GetCount: Integer;
|
||||||
@@ -221,12 +220,6 @@ begin
|
|||||||
Result := Length(FFields);
|
Result := Length(FFields);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Internal helper required for interface implementation match if defined in stricter mode
|
|
||||||
function TKeywordMappingRegistry<T>.TKeywordMapping.GetItem(Idx: Integer): TPair<IKeyword, T>;
|
|
||||||
begin
|
|
||||||
Result := FFields[Idx];
|
|
||||||
end;
|
|
||||||
|
|
||||||
// Interface method for Items property
|
// Interface method for Items property
|
||||||
function TKeywordMappingRegistry<T>.TKeywordMapping.GetItems(Idx: Integer): TPair<IKeyword, T>;
|
function TKeywordMappingRegistry<T>.TKeywordMapping.GetItems(Idx: Integer): TPair<IKeyword, T>;
|
||||||
begin
|
begin
|
||||||
|
|||||||
@@ -146,20 +146,18 @@ type
|
|||||||
IScalarRecord = IKeywordMapping<TScalar>;
|
IScalarRecord = IKeywordMapping<TScalar>;
|
||||||
TScalarRecordRegistry = TKeywordMappingRegistry<TScalar.TKind>;
|
TScalarRecordRegistry = TKeywordMappingRegistry<TScalar.TKind>;
|
||||||
|
|
||||||
// A record of scalar values, based on a definition.
|
TScalarRecord = class(TInterfacedObject, IScalarRecord)
|
||||||
TScalarRecord = record
|
private
|
||||||
public
|
|
||||||
constructor Create(const ADef: IScalarRecordDefinition; const AFields: TArray<TScalar.TValue>);
|
|
||||||
function GetDef: IScalarRecordDefinition; inline;
|
|
||||||
function GetFields: TArray<TScalar.TValue>; inline;
|
|
||||||
function GetKeys(const Key: IKeyword): TScalar;
|
|
||||||
property Def: IScalarRecordDefinition read GetDef;
|
|
||||||
property Fields: TArray<TScalar.TValue> read GetFields;
|
|
||||||
property Keys[const Key: IKeyword]: TScalar read GetKeys; default;
|
|
||||||
strict private
|
|
||||||
FDef: IScalarRecordDefinition;
|
FDef: IScalarRecordDefinition;
|
||||||
FFields: TArray<TScalar.TValue>;
|
FData: TArray<TScalar.TValue>;
|
||||||
end deprecated;
|
|
||||||
|
function IndexOf(const Key: IKeyword): Integer;
|
||||||
|
function GetCount: Integer;
|
||||||
|
function GetItems(Idx: Integer): TPair<IKeyword, TScalar>;
|
||||||
|
function GetFields(const Key: IKeyword): TScalar;
|
||||||
|
public
|
||||||
|
constructor Create(const ADef: IScalarRecordDefinition; const AData: TArray<TScalar.TValue>);
|
||||||
|
end;
|
||||||
|
|
||||||
ISeries = interface
|
ISeries = interface
|
||||||
{$region 'private'}
|
{$region 'private'}
|
||||||
@@ -197,7 +195,7 @@ type
|
|||||||
function GetTotalCount: Int64;
|
function GetTotalCount: Int64;
|
||||||
function GetFields(const Key: IKeyword): ISeries;
|
function GetFields(const Key: IKeyword): ISeries;
|
||||||
{$endregion}
|
{$endregion}
|
||||||
procedure Add(const Item: TScalarRecord; Lookback: Int64 = -1);
|
procedure Add(const Item: IScalarRecord; Lookback: Int64 = -1);
|
||||||
procedure AddRaw(const Data; Lookback: Int64 = -1);
|
procedure AddRaw(const Data; Lookback: Int64 = -1);
|
||||||
property Count: Int64 read GetCount;
|
property Count: Int64 read GetCount;
|
||||||
property Def: IScalarRecordDefinition read GetDef;
|
property Def: IScalarRecordDefinition read GetDef;
|
||||||
@@ -233,7 +231,7 @@ type
|
|||||||
public
|
public
|
||||||
constructor Create(const ADef: IScalarRecordDefinition);
|
constructor Create(const ADef: IScalarRecordDefinition);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
procedure Add(const Item: TScalarRecord; Lookback: Int64 = -1);
|
procedure Add(const Item: IScalarRecord; Lookback: Int64 = -1);
|
||||||
|
|
||||||
// Copies data directly from the Data reference (zero-copy wrapper)
|
// Copies data directly from the Data reference (zero-copy wrapper)
|
||||||
procedure AddRaw(const Data; Lookback: Int64 = -1);
|
procedure AddRaw(const Data; Lookback: Int64 = -1);
|
||||||
@@ -801,36 +799,6 @@ begin
|
|||||||
Items := AItems;
|
Items := AItems;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TScalarRecord }
|
|
||||||
|
|
||||||
constructor TScalarRecord.Create(const ADef: IScalarRecordDefinition; const AFields: TArray<TScalar.TValue>);
|
|
||||||
begin
|
|
||||||
Assert(ADef.Count = Length(AFields), 'Field definition and value count must match.');
|
|
||||||
FDef := ADef;
|
|
||||||
FFields := AFields;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TScalarRecord.GetDef: IScalarRecordDefinition;
|
|
||||||
begin
|
|
||||||
Result := FDef;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TScalarRecord.GetFields: TArray<TScalar.TValue>;
|
|
||||||
begin
|
|
||||||
Result := FFields;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TScalarRecord.GetKeys(const Key: IKeyword): TScalar;
|
|
||||||
var
|
|
||||||
idx: Integer;
|
|
||||||
begin
|
|
||||||
idx := FDef.IndexOf(Key);
|
|
||||||
if idx < 0 then
|
|
||||||
raise EArgumentException.CreateFmt('Field ":%s" not found in record definition.', [Key.Name]);
|
|
||||||
|
|
||||||
Result.Create(FDef[idx].Value, FFields[idx]);
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ TScalarRecordSeries }
|
{ TScalarRecordSeries }
|
||||||
|
|
||||||
constructor TScalarRecordSeries.Create(const ADef: IScalarRecordDefinition);
|
constructor TScalarRecordSeries.Create(const ADef: IScalarRecordDefinition);
|
||||||
@@ -850,22 +818,23 @@ begin
|
|||||||
inherited;
|
inherited;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TScalarRecordSeries.Add(const Item: TScalarRecord; Lookback: Int64 = -1);
|
procedure TScalarRecordSeries.Add(const Item: IScalarRecord; Lookback: Int64 = -1);
|
||||||
begin
|
begin
|
||||||
FArray.Add(Item.Fields, FDef.Count * Integer(Lookback));
|
var lb := FDef.Count * Integer(Lookback);
|
||||||
|
for var i := 0 to FDef.Count - 1 do
|
||||||
|
FArray.Add(Item[i].Value.Value, lb);
|
||||||
inc(FTotalCount);
|
inc(FTotalCount);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TScalarRecordSeries.AddRaw(const Data; Lookback: Int64 = -1);
|
procedure TScalarRecordSeries.AddRaw(const Data; Lookback: Int64 = -1);
|
||||||
type
|
|
||||||
TValueArr = array[0..MaxInt div SizeOf(TScalar.TValue) - 1] of TScalar.TValue;
|
|
||||||
PValueArr = ^TValueArr;
|
|
||||||
var
|
|
||||||
len: Integer;
|
|
||||||
begin
|
begin
|
||||||
len := FDef.Count;
|
var lb := FDef.Count * Integer(Lookback);
|
||||||
// Use Slice to pass the raw data as an open array without copying.
|
var P: TScalar.PValue := @Data;
|
||||||
FArray.Add(Slice(PValueArr(@Data)^, len), len * Integer(Lookback));
|
for var i := 0 to FDef.Count - 1 do
|
||||||
|
begin
|
||||||
|
FArray.Add(P^, lb);
|
||||||
|
inc(P);
|
||||||
|
end;
|
||||||
inc(FTotalCount);
|
inc(FTotalCount);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -1042,6 +1011,45 @@ begin
|
|||||||
Result := TScalar.FromInt64(sourceIndex);
|
Result := TScalar.FromInt64(sourceIndex);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TScalarRecord }
|
||||||
|
|
||||||
|
constructor TScalarRecord.Create(const ADef: IScalarRecordDefinition; const AData: TArray<TScalar.TValue>);
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
FDef := ADef;
|
||||||
|
FData := AData;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TScalarRecord.GetCount: Integer;
|
||||||
|
begin
|
||||||
|
Result := FDef.Count;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TScalarRecord.GetFields(const Key: IKeyword): TScalar;
|
||||||
|
var
|
||||||
|
idx: Integer;
|
||||||
|
begin
|
||||||
|
idx := FDef.IndexOf(Key);
|
||||||
|
if idx < 0 then
|
||||||
|
exit(Default(TScalar));
|
||||||
|
|
||||||
|
// Return the raw TValue at the offset
|
||||||
|
Result.Kind := FDef[idx].Value;
|
||||||
|
Result.Value := FData[idx];
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TScalarRecord.GetItems(Idx: Integer): TPair<IKeyword, TScalar>;
|
||||||
|
begin
|
||||||
|
Result.Key := FDef[Idx].Key;
|
||||||
|
Result.Value.Kind := FDef[idx].Value;
|
||||||
|
Result.Value.Value := FData[idx];
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TScalarRecord.IndexOf(const Key: IKeyword): Integer;
|
||||||
|
begin
|
||||||
|
Result := FDef.IndexOf(Key);
|
||||||
|
end;
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
Assert(sizeof(TScalar.TValue) = 8);
|
Assert(sizeof(TScalar.TValue) = 8);
|
||||||
|
|
||||||
|
|||||||
+17
-17
@@ -9,7 +9,8 @@ uses
|
|||||||
Myc.Utils,
|
Myc.Utils,
|
||||||
Myc.Data.Scalar,
|
Myc.Data.Scalar,
|
||||||
Myc.Data.Series,
|
Myc.Data.Series,
|
||||||
Myc.Data.Keyword;
|
Myc.Data.Keyword,
|
||||||
|
Myc.Trade.DataFeed;
|
||||||
|
|
||||||
type
|
type
|
||||||
TDataValueKind = (
|
TDataValueKind = (
|
||||||
@@ -18,7 +19,7 @@ type
|
|||||||
vkText,
|
vkText,
|
||||||
vkSeries,
|
vkSeries,
|
||||||
vkRecordSeries,
|
vkRecordSeries,
|
||||||
vkRecord,
|
vkScalarRecord,
|
||||||
vkGenericRecord,
|
vkGenericRecord,
|
||||||
vkManagedObject,
|
vkManagedObject,
|
||||||
vkMethod,
|
vkMethod,
|
||||||
@@ -78,7 +79,7 @@ type
|
|||||||
class function Map(const SourceSeries: ISeries; const MapperFunc: TFunc): ISeries; static;
|
class function Map(const SourceSeries: ISeries; const MapperFunc: TFunc): ISeries; static;
|
||||||
|
|
||||||
class function FromRecordSeries(const AValue: IRecordSeries): TDataValue; static; inline;
|
class function FromRecordSeries(const AValue: IRecordSeries): TDataValue; static; inline;
|
||||||
class function FromRecord(const [ref] AValue: TScalarRecord): TDataValue; static; inline;
|
class function FromScalarRecord(const AValue: IScalarRecord): TDataValue; static; inline;
|
||||||
class function FromGenericRecord(const AValue: IKeywordMapping<TDataValue>): TDataValue; static; inline;
|
class function FromGenericRecord(const AValue: IKeywordMapping<TDataValue>): TDataValue; static; inline;
|
||||||
class function FromSeries(const AValue: ISeries): TDataValue; static; inline;
|
class function FromSeries(const AValue: ISeries): TDataValue; static; inline;
|
||||||
|
|
||||||
@@ -86,7 +87,7 @@ type
|
|||||||
function AsMethod: TFunc; inline;
|
function AsMethod: TFunc; inline;
|
||||||
function AsText: String; inline;
|
function AsText: String; inline;
|
||||||
function AsRecordSeries: IRecordSeries; inline;
|
function AsRecordSeries: IRecordSeries; inline;
|
||||||
function AsRecord: TScalarRecord; inline;
|
function AsScalarRecord: IScalarRecord; inline;
|
||||||
function AsGenericRecord: IKeywordMapping<TDataValue>; inline;
|
function AsGenericRecord: IKeywordMapping<TDataValue>; inline;
|
||||||
function AsSeries: ISeries; inline;
|
function AsSeries: ISeries; inline;
|
||||||
function AsObject: TObject; overload; inline;
|
function AsObject: TObject; overload; inline;
|
||||||
@@ -190,11 +191,11 @@ begin
|
|||||||
Result := Pointer(FScalar.Value.AsInt64);
|
Result := Pointer(FScalar.Value.AsInt64);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDataValue.AsRecord: TScalarRecord;
|
function TDataValue.AsScalarRecord: IScalarRecord;
|
||||||
begin
|
begin
|
||||||
if (FKind <> vkRecord) then
|
if (FKind <> vkScalarRecord) then
|
||||||
raise EInvalidCast.Create('Cannot read value as Record.');
|
raise EInvalidCast.Create('Cannot read value as Record.');
|
||||||
Result := (FInterface as TVal<TScalarRecord>).Value;
|
Result := IScalarRecord(FInterface);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDataValue.AsGenericRecord: IKeywordMapping<TDataValue>;
|
function TDataValue.AsGenericRecord: IKeywordMapping<TDataValue>;
|
||||||
@@ -253,10 +254,10 @@ begin
|
|||||||
Result.FInterface := AValue;
|
Result.FInterface := AValue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TDataValue.FromRecord(const [ref] AValue: TScalarRecord): TDataValue;
|
class function TDataValue.FromScalarRecord(const AValue: IScalarRecord): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result.FKind := vkRecord;
|
Result.FKind := vkScalarRecord;
|
||||||
Result.FInterface := TVal<TScalarRecord>.Create(AValue);
|
Result.FInterface := AValue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TDataValue.FromGenericRecord(const AValue: IKeywordMapping<TDataValue>): TDataValue;
|
class function TDataValue.FromGenericRecord(const AValue: IKeywordMapping<TDataValue>): TDataValue;
|
||||||
@@ -333,24 +334,23 @@ begin
|
|||||||
sb.Free;
|
sb.Free;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
vkRecord:
|
vkScalarRecord:
|
||||||
begin
|
begin
|
||||||
var rec := AsRecord;
|
var rec := AsScalarRecord;
|
||||||
sb := TStringBuilder.Create;
|
sb := TStringBuilder.Create;
|
||||||
try
|
try
|
||||||
sb.Append('{');
|
sb.Append('{');
|
||||||
first := True;
|
first := True;
|
||||||
for i := 0 to rec.Def.Count - 1 do
|
for i := 0 to rec.Count - 1 do
|
||||||
begin
|
begin
|
||||||
if not first then
|
if not first then
|
||||||
sb.Append(',');
|
sb.Append(',');
|
||||||
field := rec.Def[i];
|
sb.Append(rec[i].Key.Name);
|
||||||
sb.Append(field.Key.Name);
|
|
||||||
first := False;
|
first := False;
|
||||||
end;
|
end;
|
||||||
sb.Append('}');
|
sb.Append('}');
|
||||||
// Add field names for records
|
// Add field names for records
|
||||||
Result := Format('<record%s>', [sb.ToString]);
|
Result := Format('<scalar_record%s>', [sb.ToString]);
|
||||||
finally
|
finally
|
||||||
sb.Free;
|
sb.Free;
|
||||||
end;
|
end;
|
||||||
@@ -434,7 +434,7 @@ begin
|
|||||||
vkText: Result := 'Text';
|
vkText: Result := 'Text';
|
||||||
vkSeries: Result := 'Series';
|
vkSeries: Result := 'Series';
|
||||||
vkRecordSeries: Result := 'RecordSeries';
|
vkRecordSeries: Result := 'RecordSeries';
|
||||||
vkRecord: Result := 'Record';
|
vkScalarRecord: Result := 'ScalarRecord';
|
||||||
vkGenericRecord: Result := 'GenericRecord';
|
vkGenericRecord: Result := 'GenericRecord';
|
||||||
vkMethod: Result := 'Method';
|
vkMethod: Result := 'Method';
|
||||||
vkInterface: Result := 'Interface';
|
vkInterface: Result := 'Interface';
|
||||||
|
|||||||
Reference in New Issue
Block a user