unit ASFcnMgr;
{$WARN SYMBOL_PLATFORM OFF}
{$WARN DUPLICATE_CTOR_DTOR OFF}
interface
uses
SysUtils, Types, Classes, ASKernelDefs, ASExpression, Generics.Defaults,
Generics.Collections, GenHelpers;
type
FunctionAttribute = class(TCustomAttribute)
strict private
FNames: TArray<string>;
public
constructor Create(const AName: string); overload;
constructor Create(const AName1, AName2: string); overload;
constructor Create(const AName1, AName2, AName3: string); overload;
property Names: TArray<string> read FNames;
end;
TFcnCategory = (fcSystem, fcGeneral, fcMath, fcTrigonometry, fcHyperbolic,
fcNumberTheory, fcLogic, fcSets, fcStrings, fcTables, fcLists, fcStructures,
fcDateTime, fcPixmaps, fcSounds, fcMIDI, fcBinaryData, fcVisualization);
TFcnCategoryHelper = record helper for TFcnCategory
function ToString: string;
end;
CategoryAttribute = class(TCustomAttribute)
strict private
FCategories: TArray<TFcnCategory>;
public
constructor Create(const ACat: TFcnCategory); overload;
constructor Create(const ACat1, ACat2: TFcnCategory); overload;
constructor Create(const ACat1, ACat2, ACat3: TFcnCategory); overload;
constructor Create(const ACat1, ACat2, ACat3, ACat4: TFcnCategory); overload;
constructor Create(const ACat1, ACat2, ACat3, ACat4, ACat5: TFcnCategory); overload;
property Categories: TArray<TFcnCategory> read FCategories;
end;
TFunctionMgr = record
class var Functions: TDictionary<string, TASFunctionClass>;
class var Names: TDictionary<TASFunctionClass, TArray<string>>;
class var Categories: TDictionary<TASFunctionClass, TArray<TFcnCategory>>;
class var FcnNames: TArray<string>;
class constructor ClassCreate;
class destructor ClassDestroy;
end;
implementation
uses
System.Rtti;
constructor FunctionAttribute.Create(const AName: string);
begin
FNames := [AName];
end;
constructor FunctionAttribute.Create(const AName1, AName2: string);
begin
FNames := [AName1, AName2];
end;
constructor FunctionAttribute.Create(const AName1, AName2, AName3: string);
begin
FNames := [AName1, AName2, AName3];
end;
constructor CategoryAttribute.Create(const ACat: TFcnCategory);
begin
FCategories := [ACat];
end;
constructor CategoryAttribute.Create(const ACat1, ACat2: TFcnCategory);
begin
FCategories := [ACat1, ACat2];
end;
constructor CategoryAttribute.Create(const ACat1, ACat2, ACat3: TFcnCategory);
begin
FCategories := [ACat1, ACat2, ACat3];
end;
constructor CategoryAttribute.Create(const ACat1, ACat2, ACat3,
ACat4: TFcnCategory);
begin
FCategories := [ACat1, ACat2, ACat3, ACat4];
end;
constructor CategoryAttribute.Create(const ACat1, ACat2, ACat3, ACat4,
ACat5: TFcnCategory);
begin
FCategories := [ACat1, ACat2, ACat3, ACat4, ACat5];
end;
class constructor TFunctionMgr.ClassCreate;
var
Context: TRttiContext;
&Type: TRttiType;
Attribute: TCustomAttribute;
i: Integer;
begin
Functions := TDictionary<string, TASFunctionClass>.Create;
Names := TDictionary<TASFunctionClass, TArray<string>>.Create;
Categories := TDictionary<TASFunctionClass, TArray<TFcnCategory>>.Create;
Context := TRttiContext.Create;
try
for &Type in Context.GetTypes do
if &Type.IsInstance and TRttiInstanceType(&Type).MetaclassType.InheritsFrom(TASFunction) then
for Attribute in &Type.GetAttributes do
if Attribute is FunctionAttribute then
begin
for i := 0 to High(FunctionAttribute(Attribute).Names) do
Functions.Add(
FunctionAttribute(Attribute).Names[i],
TASFunctionClass(TRttiInstanceType(&Type).MetaclassType)
);
Names.Add(
TASFunctionClass(TRttiInstanceType(&Type).MetaclassType),
FunctionAttribute(Attribute).Names
);
end
else if Attribute is CategoryAttribute then
Categories.Add(
TASFunctionClass(TRttiInstanceType(&Type).MetaclassType),
CategoryAttribute(Attribute).Categories
)
finally
Context.Free;
end;
FcnNames := Functions.Keys.ToArray;
TArray.Sort<string>(
FcnNames,
TComparer<string>.Construct(
function(const Left, Right: string): Integer
begin
Result := CompareText(Left, Right);
end
)
);
end;
class destructor TFunctionMgr.ClassDestroy;
begin
FreeAndNil(Categories);
FreeAndNil(Names);
FreeAndNil(Functions);
end;
function TFcnCategoryHelper.ToString: string;
begin
case Self of
fcSystem:
Result := 'system';
fcGeneral:
Result := 'general';
fcMath:
Result := 'math';
fcTrigonometry:
Result := 'trigonometry';
fcHyperbolic:
Result := 'hyperbolic';
fcNumberTheory:
Result := 'number theory';
fcLogic:
Result := 'logic';
fcSets:
Result := 'sets';
fcStrings:
Result := 'strings';
fcTables:
Result := 'tables';
fcLists:
Result := 'lists';
fcStructures:
Result := 'structures';
fcDateTime:
Result := 'datetime';
fcPixmaps:
Result := 'pixmaps';
fcSounds:
Result := 'sounds';
fcMIDI:
Result := 'MIDI';
fcBinaryData:
Result := 'binary data';
fcVisualization:
Result := 'visualization';
else
Result := '';
end;
end;
end.