Ast series indexer

This commit is contained in:
Michael Schimmel
2025-09-02 16:58:52 +02:00
parent 375e64411b
commit a83bbf4f54
11 changed files with 734 additions and 79 deletions
+79 -7
View File
@@ -114,7 +114,14 @@ type
constructor Create(const AName: String; AKind: TScalarKind);
end;
TScalarRecordDefinition = TArray<TScalarRecordField>;
TScalarRecordDefinition = record
private
FFields: TArray<TScalarRecordField>;
public
constructor Create(const AFields: TArray<TScalarRecordField>);
function IndexOf(const Name: String): Integer;
property Fields: TArray<TScalarRecordField> read FFields;
end;
// A record of scalar values, based on a definition.
TScalarRecord = record
@@ -152,6 +159,20 @@ type
FItems: TSeries<TScalarValue>;
end;
TScalarMemberSeries = record
private
FDef: TScalarRecordDefinition;
FArray: TChunkArray<TScalarValue>;
FElement: Integer;
function GetCount: Int64; inline;
function GetItems(Idx: Integer): TScalarValue;
public
constructor Create(const ADef: TScalarRecordDefinition; const AArray: TChunkArray<TScalarValue>; AElement: Integer);
property Count: Int64 read GetCount;
property Element: Integer read FElement;
property Items[Idx: Integer]: TScalarValue read GetItems; default;
end;
// A time series of scalar records, optimized for memory and access speed.
TScalarRecordSeries = record
private
@@ -163,6 +184,7 @@ type
public
constructor Create(const ADef: TScalarRecordDefinition);
procedure Add(const Item: TScalarRecord; Lookback: Int64 = -1);
function CreateMemberSeries(const Field: String): TScalarMemberSeries;
property Def: TScalarRecordDefinition read GetDef;
property Items[Idx: Integer]: TScalarRecord read GetItems; default;
property TotalCount: Int64 read FTotalCount;
@@ -384,7 +406,7 @@ end;
constructor TScalarRecord.Create(const ADef: TScalarRecordDefinition; const AFields: TArray<TScalarValue>);
begin
Assert(Length(ADef) = Length(AFields), 'Field definition and value count must match.');
Assert(Length(ADef.Fields) = Length(AFields), 'Field definition and value count must match.');
FDef := ADef;
FFields := AFields;
end;
@@ -405,9 +427,9 @@ var
fieldDef: TScalarRecordField;
begin
// Find the index of the field by name (case-insensitive)
for i := 0 to Length(FDef) - 1 do
for i := 0 to High(FDef.Fields) do
begin
fieldDef := FDef[i];
fieldDef := FDef.Fields[i];
if (CompareText(fieldDef.Name, Name) = 0) then
begin
// Found it. Construct the TScalar result from the kind and value.
@@ -445,7 +467,7 @@ end;
constructor TScalarRecordSeries.Create(const ADef: TScalarRecordDefinition);
begin
Assert(Length(ADef) > 0);
Assert(Length(ADef.Fields) > 0);
FDef := ADef;
FArray := Default(TChunkArray<TScalarValue>);
FTotalCount := 0;
@@ -453,10 +475,19 @@ end;
procedure TScalarRecordSeries.Add(const Item: TScalarRecord; Lookback: Int64 = -1);
begin
FArray.Add(Item.Fields, Length(FDef) * Lookback);
FArray.Add(Item.Fields, Length(FDef.Fields) * Lookback);
inc(FTotalCount);
end;
function TScalarRecordSeries.CreateMemberSeries(const Field: String): TScalarMemberSeries;
begin
var elem := FDef.IndexOf(Field);
if elem < 0 then
raise EArgumentException.CreateFmt('Field "%s" not found in record definition.', [Field]);
Result := TScalarMemberSeries.Create(FDef, FArray, elem);
end;
function TScalarRecordSeries.GetDef: TScalarRecordDefinition;
begin
Result := FDef;
@@ -467,12 +498,53 @@ var
values: TArray<TScalarValue>;
fieldCount: Integer;
begin
fieldCount := Length(FDef);
fieldCount := Length(FDef.Fields);
SetLength(values, fieldCount);
Move(FArray.ItemRef[(FArray.Count - fieldCount) - (Idx * fieldCount)]^, values[0], sizeof(TScalarValue) * fieldCount);
Result.Create(FDef, values);
end;
constructor TScalarMemberSeries.Create(const ADef: TScalarRecordDefinition; const AArray: TChunkArray<TScalarValue>; AElement: Integer);
begin
FDef := ADef;
FArray := AArray;
FElement := AElement;
end;
function TScalarMemberSeries.GetCount: Int64;
begin
Result := FArray.Count;
end;
function TScalarMemberSeries.GetItems(Idx: Integer): TScalarValue;
var
values: TArray<TScalarValue>;
fieldCount: Integer;
begin
fieldCount := Length(FDef.Fields);
SetLength(values, fieldCount);
Result := FArray.ItemRef[(FArray.Count - fieldCount) - (Idx * fieldCount)]^;
end;
constructor TScalarRecordDefinition.Create(const AFields: TArray<TScalarRecordField>);
begin
FFields := AFields;
end;
function TScalarRecordDefinition.IndexOf(const Name: String): Integer;
var
i: Integer;
fieldDef: TScalarRecordField;
begin
// Find the index of the field by name (case-insensitive)
for i := 0 to High(FFields) do
if (CompareText(FFields[i].Name, Name) = 0) then
exit(i);
// If we get here, the field was not found.
raise EArgumentException.CreateFmt('Field "%s" not found in record definition.', [Name]);
end;
initialization
Assert(sizeof(TScalarValue) = 8);