Keywords
This commit is contained in:
@@ -11,7 +11,9 @@ uses
|
||||
type
|
||||
// The runtime representation of an interned keyword
|
||||
IKeyword = interface(IInterface)
|
||||
function GetIdx: Integer;
|
||||
function GetName: string;
|
||||
property Idx: Integer read GetIdx;
|
||||
property Name: string read GetName;
|
||||
end;
|
||||
|
||||
@@ -22,9 +24,11 @@ type
|
||||
TKeyword = class(TInterfacedObject, IKeyword)
|
||||
private
|
||||
FName: string;
|
||||
FIdx: Integer;
|
||||
function GetName: string;
|
||||
function GetIdx: Integer;
|
||||
public
|
||||
constructor Create(const AName: string);
|
||||
constructor Create(const AName: string; AIdx: Integer);
|
||||
end;
|
||||
strict private
|
||||
class var
|
||||
@@ -38,14 +42,38 @@ type
|
||||
class function Intern(const AName: string): IKeyword; static;
|
||||
end;
|
||||
|
||||
TKeywordMapping<T> = record
|
||||
type
|
||||
TField = record
|
||||
Key: IKeyword;
|
||||
Value: T;
|
||||
public
|
||||
constructor Create(const AKey: IKeyword; const AValue: T);
|
||||
end;
|
||||
private
|
||||
FMap: TArray<Integer>;
|
||||
FFields: TArray<TField>;
|
||||
FFirst, FLast: Integer;
|
||||
public
|
||||
constructor Create(const AFields: TArray<TField>);
|
||||
function IndexOf(const Key: IKeyword): Integer;
|
||||
property Fields: TArray<TField> read FFields;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
{ TKeywordRegistry.TKeyword }
|
||||
|
||||
constructor TKeywordRegistry.TKeyword.Create(const AName: string);
|
||||
constructor TKeywordRegistry.TKeyword.Create(const AName: string; AIdx: Integer);
|
||||
begin
|
||||
inherited Create;
|
||||
FName := AName;
|
||||
FIdx := AIdx;
|
||||
end;
|
||||
|
||||
function TKeywordRegistry.TKeyword.GetIdx: Integer;
|
||||
begin
|
||||
Result := FIdx;
|
||||
end;
|
||||
|
||||
function TKeywordRegistry.TKeyword.GetName: string;
|
||||
@@ -72,7 +100,7 @@ begin
|
||||
try
|
||||
if not FRegistry.TryGetValue(AName, Result) then
|
||||
begin
|
||||
Result := TKeyword.Create(AName);
|
||||
Result := TKeyword.Create(AName, FRegistry.Count);
|
||||
FRegistry.Add(AName, Result);
|
||||
end;
|
||||
finally
|
||||
@@ -80,4 +108,47 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TKeywordMapping }
|
||||
|
||||
constructor TKeywordMapping<T>.Create(const AFields: TArray<TField>);
|
||||
begin
|
||||
FFields := AFields;
|
||||
FFirst := 0;
|
||||
FLast := -1;
|
||||
if Length(FFields) = 0 then
|
||||
exit;
|
||||
|
||||
FFirst := FFields[0].Key.Idx;
|
||||
FLast := FFirst;
|
||||
for var i := 1 to High(FFields) do
|
||||
begin
|
||||
var idx := FFields[i].Key.Idx;
|
||||
if FFirst > idx then
|
||||
FFirst := idx;
|
||||
if FLast < idx then
|
||||
FLast := idx;
|
||||
end;
|
||||
|
||||
SetLength(FMap, FLast - FFirst + 1);
|
||||
for var i := 0 to High(FMap) do
|
||||
FMap[i] := -1;
|
||||
for var i := 0 to High(FFields) do
|
||||
FMap[FFirst + FFields[i].Key.Idx] := i;
|
||||
end;
|
||||
|
||||
function TKeywordMapping<T>.IndexOf(const Key: IKeyword): Integer;
|
||||
begin
|
||||
var idx := Key.Idx - FFirst;
|
||||
if (idx < 0) or (Idx > High(FMap)) then
|
||||
exit(-1);
|
||||
|
||||
Result := FMap[idx];
|
||||
end;
|
||||
|
||||
constructor TKeywordMapping<T>.TField.Create(const AKey: IKeyword; const AValue: T);
|
||||
begin
|
||||
Key := AKey;
|
||||
Value := AValue;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
@@ -24,8 +24,9 @@ type
|
||||
implementation
|
||||
|
||||
uses
|
||||
System.Generics.Collections,
|
||||
Myc.Data.Decimal,
|
||||
System.Generics.Collections;
|
||||
Myc.Data.Keyword;
|
||||
|
||||
{ TRttiAstHelper }
|
||||
|
||||
@@ -35,7 +36,8 @@ var
|
||||
fieldsArray: TJSONArray;
|
||||
i: Integer;
|
||||
fieldObj: TJSONObject;
|
||||
kindStr: string;
|
||||
kindStr, fieldName: string;
|
||||
fieldKey: IKeyword;
|
||||
fields: TArray<TScalarRecordField>;
|
||||
begin
|
||||
jsonValue := TJSONObject.ParseJSONValue(AJson);
|
||||
@@ -55,9 +57,11 @@ begin
|
||||
if not Assigned(fieldObj) then
|
||||
continue;
|
||||
|
||||
fields[i].Name := fieldObj.GetValue<string>('name');
|
||||
fieldName := fieldObj.GetValue<string>('name');
|
||||
fieldKey := TKeywordRegistry.Intern(fieldName);
|
||||
kindStr := fieldObj.GetValue<string>('kind');
|
||||
fields[i].Kind := TScalar.TKind(GetEnumValue(TypeInfo(TScalar.TKind), kindStr));
|
||||
|
||||
fields[i] := TScalarRecordField.Create(fieldKey, TScalar.TKind(GetEnumValue(TypeInfo(TScalar.TKind), kindStr)));
|
||||
end;
|
||||
Result := TScalarRecordDefinition.Create(fields);
|
||||
finally
|
||||
|
||||
@@ -5,7 +5,8 @@ interface
|
||||
uses
|
||||
System.SysUtils,
|
||||
Myc.Data.Decimal,
|
||||
Myc.Data.Series;
|
||||
Myc.Data.Series,
|
||||
Myc.Data.Keyword;
|
||||
|
||||
{$SCOPEDENUMS ON}
|
||||
|
||||
@@ -91,20 +92,8 @@ type
|
||||
TScalarTuple = TArray<TScalar>;
|
||||
|
||||
// A field definition for a scalar record.
|
||||
TScalarRecordField = record
|
||||
Name: String;
|
||||
Kind: TScalar.TKind;
|
||||
constructor Create(const AName: String; AKind: TScalar.TKind);
|
||||
end;
|
||||
|
||||
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;
|
||||
TScalarRecordField = TKeywordMapping<TScalar.TKind>.TField;
|
||||
TScalarRecordDefinition = TKeywordMapping<TScalar.TKind>;
|
||||
|
||||
// A record of scalar values, based on a definition.
|
||||
TScalarRecord = record
|
||||
@@ -112,10 +101,10 @@ type
|
||||
constructor Create(const ADef: TScalarRecordDefinition; const AFields: TArray<TScalar.TValue>);
|
||||
function GetDef: TScalarRecordDefinition; inline;
|
||||
function GetFields: TArray<TScalar.TValue>; inline;
|
||||
function GetItems(const Name: String): TScalar;
|
||||
function GetKeys(const Key: IKeyword): TScalar;
|
||||
property Def: TScalarRecordDefinition read GetDef;
|
||||
property Fields: TArray<TScalar.TValue> read GetFields;
|
||||
property Items[const Name: String]: TScalar read GetItems; default;
|
||||
property Keys[const Key: IKeyword]: TScalar read GetKeys; default;
|
||||
strict private
|
||||
FDef: TScalarRecordDefinition;
|
||||
FFields: TArray<TScalar.TValue>;
|
||||
@@ -158,7 +147,7 @@ type
|
||||
function GetTotalCount: Int64;
|
||||
{$endregion}
|
||||
procedure Add(const Item: TScalarRecord; Lookback: Int64 = -1);
|
||||
function CreateMemberSeries(const Field: String): ISeries;
|
||||
function CreateMemberSeries(const Key: IKeyword): ISeries;
|
||||
property Count: Int64 read GetCount;
|
||||
property Def: TScalarRecordDefinition read GetDef;
|
||||
property Items[Idx: Integer]: TScalarRecord read GetItems; default;
|
||||
@@ -192,7 +181,7 @@ type
|
||||
public
|
||||
constructor Create(const ADef: TScalarRecordDefinition);
|
||||
procedure Add(const Item: TScalarRecord; Lookback: Int64 = -1);
|
||||
function CreateMemberSeries(const Field: String): ISeries;
|
||||
function CreateMemberSeries(const Key: IKeyword): ISeries;
|
||||
property Count: Int64 read GetCount;
|
||||
property Def: TScalarRecordDefinition read GetDef;
|
||||
property Items[Idx: Integer]: TScalarRecord read GetItems; default;
|
||||
@@ -528,14 +517,6 @@ begin
|
||||
Items := AItems;
|
||||
end;
|
||||
|
||||
{ TScalarRecordField }
|
||||
|
||||
constructor TScalarRecordField.Create(const AName: String; AKind: TScalar.TKind);
|
||||
begin
|
||||
Name := AName;
|
||||
Kind := AKind;
|
||||
end;
|
||||
|
||||
{ TScalarRecord }
|
||||
|
||||
constructor TScalarRecord.Create(const ADef: TScalarRecordDefinition; const AFields: TArray<TScalar.TValue>);
|
||||
@@ -555,34 +536,15 @@ begin
|
||||
Result := FFields;
|
||||
end;
|
||||
|
||||
function TScalarRecord.GetItems(const Name: String): TScalar;
|
||||
function TScalarRecord.GetKeys(const Key: IKeyword): TScalar;
|
||||
var
|
||||
idx: Integer;
|
||||
begin
|
||||
idx := FDef.IndexOf(Name);
|
||||
idx := FDef.IndexOf(Key);
|
||||
if idx < 0 then
|
||||
raise EArgumentException.CreateFmt('Field "%s" not found in record definition.', [Name]);
|
||||
raise EArgumentException.CreateFmt('Field ":%s" not found in record definition.', [Key.Name]);
|
||||
|
||||
Result.Create(FDef.Fields[idx].Kind, FFields[idx]);
|
||||
end;
|
||||
|
||||
{ TScalarRecordDefinition }
|
||||
|
||||
constructor TScalarRecordDefinition.Create(const AFields: TArray<TScalarRecordField>);
|
||||
begin
|
||||
FFields := AFields;
|
||||
end;
|
||||
|
||||
function TScalarRecordDefinition.IndexOf(const Name: String): Integer;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
for i := 0 to High(FFields) do
|
||||
begin
|
||||
if (CompareText(FFields[i].Name, Name) = 0) then
|
||||
exit(i);
|
||||
end;
|
||||
Result := -1;
|
||||
Result.Create(FDef.Fields[idx].Value, FFields[idx]);
|
||||
end;
|
||||
|
||||
{ TScalarRecordSeries }
|
||||
@@ -600,11 +562,11 @@ begin
|
||||
inc(FTotalCount);
|
||||
end;
|
||||
|
||||
function TScalarRecordSeries.CreateMemberSeries(const Field: String): ISeries;
|
||||
function TScalarRecordSeries.CreateMemberSeries(const Key: IKeyword): ISeries;
|
||||
begin
|
||||
var elem := FDef.IndexOf(Field);
|
||||
var elem := FDef.IndexOf(Key);
|
||||
if elem < 0 then
|
||||
raise EArgumentException.CreateFmt('Field "%s" not found in record definition.', [Field]);
|
||||
raise EArgumentException.CreateFmt('Field ":%s" not found in record definition.', [Key.Name]);
|
||||
|
||||
Result := TMemberSeries.Create(Self, elem);
|
||||
end;
|
||||
@@ -686,7 +648,7 @@ begin
|
||||
inherited Create;
|
||||
FRecordSeries := ARecordSeries;
|
||||
FRecordSeries._AddRef;
|
||||
FKind := FRecordSeries.FDef.FFields[AElementIdx].Kind;
|
||||
FKind := FRecordSeries.FDef.Fields[AElementIdx].Value;
|
||||
FOffset := sizeof(TScalar.TValue) * AElementIdx;
|
||||
end;
|
||||
|
||||
|
||||
@@ -82,12 +82,12 @@ type
|
||||
class function FromRecordSeries(const AValue: IRecordSeries): TDataValue; static; inline;
|
||||
class function FromRecord(const [ref] AValue: TScalarRecord): TDataValue; static; inline;
|
||||
class function FromSeries(const AValue: ISeries): TDataValue; static; inline;
|
||||
class function FromKeyword(const AValue: IKeyword): TDataValue; static; inline; // Added
|
||||
class function FromKeyword(const AValue: IKeyword): TDataValue; static; inline;
|
||||
|
||||
function AsScalar: TScalar; inline;
|
||||
function AsMethod: TFunc; inline;
|
||||
function AsText: String; inline;
|
||||
function AsKeyword: IKeyword; inline; // Added
|
||||
function AsKeyword: IKeyword; inline;
|
||||
function AsRecordSeries: IRecordSeries; inline;
|
||||
function AsRecord: TScalarRecord; inline;
|
||||
function AsSeries: ISeries; inline;
|
||||
@@ -264,7 +264,7 @@ begin
|
||||
TInterlocked.CompareExchange(FScalar.Value.AsInt64, NewValue.AsScalar.Value.AsInt64, Expected.AsScalar.Value.AsInt64)
|
||||
= Expected.AsScalar.Value.AsInt64;
|
||||
|
||||
vkText, vkKeyword, vkSeries, vkRecordSeries, vkRecord, vkManagedObject, vkMethod, vkInterface, vkGeneric: // Added vkKeyword
|
||||
vkText, vkKeyword, vkSeries, vkRecordSeries, vkRecord, vkManagedObject, vkMethod, vkInterface, vkGeneric:
|
||||
Result := IntfCompareExchange(FInterface, NewValue.FInterface, Expected.FInterface) = Expected.FInterface;
|
||||
end;
|
||||
end;
|
||||
@@ -369,7 +369,7 @@ begin
|
||||
end;
|
||||
vkPointer: Result := TInterlocked.Exchange(FScalar.Value.AsInt64, NewValue.AsScalar.Value.AsInt64);
|
||||
|
||||
vkText, vkKeyword, vkSeries, vkRecordSeries, vkRecord, vkManagedObject, vkMethod, vkInterface, vkGeneric: // Added vkKeyword
|
||||
vkText, vkKeyword, vkSeries, vkRecordSeries, vkRecord, vkManagedObject, vkMethod, vkInterface, vkGeneric:
|
||||
begin
|
||||
Result.FKind := FKind;
|
||||
Result.FInterface := IntfExchange(FInterface, NewValue.FInterface);
|
||||
@@ -386,7 +386,7 @@ begin
|
||||
case FKind of
|
||||
vkScalar: Result := FScalar.ToString;
|
||||
vkText: Result := '"' + AsText + '"';
|
||||
vkKeyword: Result := ':' + AsKeyword.Name; // Added
|
||||
vkKeyword: Result := ':' + AsKeyword.Name;
|
||||
vkSeries:
|
||||
begin
|
||||
var series := AsSeries;
|
||||
@@ -404,7 +404,7 @@ begin
|
||||
begin
|
||||
if not first then
|
||||
sb.Append(',');
|
||||
sb.Append(field.Name);
|
||||
sb.Append(field.Key.Name);
|
||||
first := False;
|
||||
end;
|
||||
sb.Append('}');
|
||||
@@ -425,7 +425,7 @@ begin
|
||||
begin
|
||||
if not first then
|
||||
sb.Append(',');
|
||||
sb.Append(field.Name);
|
||||
sb.Append(field.Key.Name);
|
||||
first := False;
|
||||
end;
|
||||
sb.Append('}');
|
||||
@@ -490,7 +490,7 @@ begin
|
||||
vkVoid: Result := 'Void';
|
||||
vkScalar: Result := 'Scalar';
|
||||
vkText: Result := 'Text';
|
||||
vkKeyword: Result := 'Keyword'; // Added
|
||||
vkKeyword: Result := 'Keyword';
|
||||
vkSeries: Result := 'Series';
|
||||
vkRecordSeries: Result := 'RecordSeries';
|
||||
vkRecord: Result := 'Record';
|
||||
|
||||
Reference in New Issue
Block a user