Extracted TDynamicRecord

This commit is contained in:
Michael Schimmel
2025-12-08 10:21:25 +01:00
parent 1d13d0cdaa
commit 95de9a155e
5 changed files with 54 additions and 38 deletions
File diff suppressed because one or more lines are too long
+2 -1
View File
@@ -36,7 +36,8 @@ uses
Myc.Fmx.AstEditor.Handlers.Lists in '..\Src\AST\Myc.Fmx.AstEditor.Handlers.Lists.pas', Myc.Fmx.AstEditor.Handlers.Lists in '..\Src\AST\Myc.Fmx.AstEditor.Handlers.Lists.pas',
Myc.Fmx.AstEditor.Handlers.Primitives in '..\Src\AST\Myc.Fmx.AstEditor.Handlers.Primitives.pas', Myc.Fmx.AstEditor.Handlers.Primitives in '..\Src\AST\Myc.Fmx.AstEditor.Handlers.Primitives.pas',
Myc.Fmx.AstEditor.Handlers.Control in '..\Src\AST\Myc.Fmx.AstEditor.Handlers.Control.pas', Myc.Fmx.AstEditor.Handlers.Control in '..\Src\AST\Myc.Fmx.AstEditor.Handlers.Control.pas',
Myc.Fmx.AstEditor.Handlers.Data in '..\Src\AST\Myc.Fmx.AstEditor.Handlers.Data.pas'; Myc.Fmx.AstEditor.Handlers.Data in '..\Src\AST\Myc.Fmx.AstEditor.Handlers.Data.pas',
Myc.Data.Records in '..\Src\Data\Myc.Data.Records.pas';
{$R *.res} {$R *.res}
+1
View File
@@ -167,6 +167,7 @@
<DCCReference Include="..\Src\AST\Myc.Fmx.AstEditor.Handlers.Primitives.pas"/> <DCCReference Include="..\Src\AST\Myc.Fmx.AstEditor.Handlers.Primitives.pas"/>
<DCCReference Include="..\Src\AST\Myc.Fmx.AstEditor.Handlers.Control.pas"/> <DCCReference Include="..\Src\AST\Myc.Fmx.AstEditor.Handlers.Control.pas"/>
<DCCReference Include="..\Src\AST\Myc.Fmx.AstEditor.Handlers.Data.pas"/> <DCCReference Include="..\Src\AST\Myc.Fmx.AstEditor.Handlers.Data.pas"/>
<DCCReference Include="..\Src\Data\Myc.Data.Records.pas"/>
<BuildConfiguration Include="Base"> <BuildConfiguration Include="Base">
<Key>Base</Key> <Key>Base</Key>
</BuildConfiguration> </BuildConfiguration>
+2 -36
View File
@@ -78,7 +78,8 @@ uses
Myc.Data.Decimal, Myc.Data.Decimal,
Myc.Data.Series, Myc.Data.Series,
Myc.Data.Scalar.JSON, Myc.Data.Scalar.JSON,
Myc.Ast.Types; Myc.Ast.Types,
Myc.Data.Records;
// Helper type for TCO via trampolining. // Helper type for TCO via trampolining.
type type
@@ -96,41 +97,6 @@ begin
Recur := ARecur; Recur := ARecur;
end; end;
{ TDynamicRecord }
type
// Runtime implementation for generic records using linear search
TDynamicRecord = class(TInterfacedObject, IKeywordMapping<TDataValue>)
private
FFields: TArray<TPair<IKeyword, TDataValue>>;
function GetFields: TArray<TPair<IKeyword, TDataValue>>;
public
constructor Create(const AFields: TArray<TPair<IKeyword, TDataValue>>);
function IndexOf(const Key: IKeyword): Integer;
end;
constructor TDynamicRecord.Create(const AFields: TArray<TPair<IKeyword, TDataValue>>);
begin
inherited Create;
FFields := AFields;
end;
function TDynamicRecord.GetFields: TArray<TPair<IKeyword, TDataValue>>;
begin
Result := FFields;
end;
function TDynamicRecord.IndexOf(const Key: IKeyword): Integer;
begin
// Linear search (O(n)) as requested
for Result := 0 to High(FFields) do
begin
if FFields[Result].Key.Idx = Key.Idx then
exit;
end;
Result := -1;
end;
{ TEvaluatorVisitor } { TEvaluatorVisitor }
constructor TEvaluatorVisitor.Create(const AScope: IExecutionScope); constructor TEvaluatorVisitor.Create(const AScope: IExecutionScope);
+48
View File
@@ -0,0 +1,48 @@
unit Myc.Data.Records;
interface
uses
system.generics.collections,
Myc.Data.Keyword,
Myc.Data.Value;
type
// Runtime implementation for generic records using linear search (optimized for small record sizes)
TDynamicRecord = class(TInterfacedObject, IKeywordMapping<TDataValue>)
private
FFields: TArray<TPair<IKeyword, TDataValue>>;
function GetFields: TArray<TPair<IKeyword, TDataValue>>;
public
constructor Create(const AFields: TArray<TPair<IKeyword, TDataValue>>);
function IndexOf(const Key: IKeyword): Integer;
end;
implementation
{ TDynamicRecord }
constructor TDynamicRecord.Create(const AFields: TArray<TPair<IKeyword, TDataValue>>);
begin
inherited Create;
FFields := AFields;
end;
function TDynamicRecord.GetFields: TArray<TPair<IKeyword, TDataValue>>;
begin
Result := FFields;
end;
function TDynamicRecord.IndexOf(const Key: IKeyword): Integer;
begin
// Linear search (O(n)). Fast enough for typical records.
// Keyword comparison is integer-based (Idx), so this is efficient.
for Result := 0 to High(FFields) do
begin
if FFields[Result].Key.Idx = Key.Idx then
exit;
end;
Result := -1;
end;
end.