Keyword mapping refactoring
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -36,8 +36,7 @@ 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}
|
||||||
|
|
||||||
|
|||||||
@@ -167,7 +167,6 @@
|
|||||||
<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>
|
||||||
|
|||||||
@@ -78,8 +78,7 @@ 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
|
||||||
@@ -499,8 +498,7 @@ begin
|
|||||||
genFields[i] := TPair<IKeyword, TDataValue>.Create(field.Key.Value, field.Value.Accept(Self));
|
genFields[i] := TPair<IKeyword, TDataValue>.Create(field.Key.Value, field.Value.Accept(Self));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
var dynRec := TDynamicRecord.Create(genFields);
|
Result := TDataValue.FromGenericRecord(TKeywordMapping<TDataValue>.Create(genFields));
|
||||||
Result := TDataValue.FromGenericRecord(dynRec);
|
|
||||||
end
|
end
|
||||||
else if Assigned(Node.ScalarDefinition) then
|
else if Assigned(Node.ScalarDefinition) then
|
||||||
begin
|
begin
|
||||||
|
|||||||
@@ -96,6 +96,19 @@ type
|
|||||||
class function Intern(const AFields: TArray<TPair<IKeyword, T>>): IKeywordMapping<T>; static;
|
class function Intern(const AFields: TArray<TPair<IKeyword, T>>): IKeywordMapping<T>; static;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
TKeywordMapping<T> = class(TInterfacedObject, IKeywordMapping<T>)
|
||||||
|
private
|
||||||
|
FFields: TArray<TPair<IKeyword, T>>;
|
||||||
|
|
||||||
|
// IKeywordMapping implementation
|
||||||
|
function GetItems(Idx: Integer): TPair<IKeyword, T>;
|
||||||
|
function GetFields(const Key: IKeyword): T;
|
||||||
|
function GetCount: Integer;
|
||||||
|
public
|
||||||
|
constructor Create(const AFields: TArray<TPair<IKeyword, T>>);
|
||||||
|
function IndexOf(const Key: IKeyword): Integer;
|
||||||
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
{ TKeywordRegistry.TKeyword }
|
{ TKeywordRegistry.TKeyword }
|
||||||
@@ -280,4 +293,49 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TKeywordMapping }
|
||||||
|
|
||||||
|
constructor TKeywordMapping<T>.Create(const AFields: TArray<TPair<IKeyword, T>>);
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
FFields := AFields;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TKeywordMapping<T>.GetCount: Integer;
|
||||||
|
begin
|
||||||
|
Result := Length(FFields);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TKeywordMapping<T>.GetFields(const Key: IKeyword): T;
|
||||||
|
var
|
||||||
|
idx: Integer;
|
||||||
|
begin
|
||||||
|
idx := IndexOf(Key);
|
||||||
|
if idx < 0 then
|
||||||
|
raise EArgumentException.CreateFmt('Field "%s" not found in dynamic record.', [Key.Name]);
|
||||||
|
Result := FFields[idx].Value;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TKeywordMapping<T>.GetItems(Idx: Integer): TPair<IKeyword, T>;
|
||||||
|
begin
|
||||||
|
Result := FFields[Idx];
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TKeywordMapping<T>.IndexOf(const Key: IKeyword): Integer;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
// Linear search (O(n)). Fast enough for typical records.
|
||||||
|
// Keyword comparison is integer-based (Idx), so this is efficient.
|
||||||
|
for i := 0 to High(FFields) do
|
||||||
|
begin
|
||||||
|
if FFields[i].Key.Idx = Key.Idx then
|
||||||
|
begin
|
||||||
|
Result := i;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
Result := -1;
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|||||||
@@ -1,73 +0,0 @@
|
|||||||
unit Myc.Data.Records;
|
|
||||||
|
|
||||||
interface
|
|
||||||
|
|
||||||
uses
|
|
||||||
System.SysUtils,
|
|
||||||
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>>;
|
|
||||||
|
|
||||||
// IKeywordMapping implementation
|
|
||||||
function GetItems(Idx: Integer): TPair<IKeyword, TDataValue>;
|
|
||||||
function GetFields(const Key: IKeyword): TDataValue;
|
|
||||||
function GetCount: Integer;
|
|
||||||
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.GetCount: Integer;
|
|
||||||
begin
|
|
||||||
Result := Length(FFields);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TDynamicRecord.GetFields(const Key: IKeyword): TDataValue;
|
|
||||||
var
|
|
||||||
idx: Integer;
|
|
||||||
begin
|
|
||||||
idx := IndexOf(Key);
|
|
||||||
if idx < 0 then
|
|
||||||
raise EArgumentException.CreateFmt('Field "%s" not found in dynamic record.', [Key.Name]);
|
|
||||||
Result := FFields[idx].Value;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TDynamicRecord.GetItems(Idx: Integer): TPair<IKeyword, TDataValue>;
|
|
||||||
begin
|
|
||||||
Result := FFields[Idx];
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TDynamicRecord.IndexOf(const Key: IKeyword): Integer;
|
|
||||||
var
|
|
||||||
i: Integer;
|
|
||||||
begin
|
|
||||||
// Linear search (O(n)). Fast enough for typical records.
|
|
||||||
// Keyword comparison is integer-based (Idx), so this is efficient.
|
|
||||||
for i := 0 to High(FFields) do
|
|
||||||
begin
|
|
||||||
if FFields[i].Key.Idx = Key.Idx then
|
|
||||||
begin
|
|
||||||
Result := i;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
Result := -1;
|
|
||||||
end;
|
|
||||||
|
|
||||||
end.
|
|
||||||
Reference in New Issue
Block a user